<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sempare Limited</title>
    <description>The latest articles on DEV Community by Sempare Limited (@sempare).</description>
    <link>https://dev.to/sempare</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2221051%2F8f77d145-589a-489f-a023-64740c62aa81.png</url>
      <title>DEV Community: Sempare Limited</title>
      <link>https://dev.to/sempare</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sempare"/>
    <language>en</language>
    <item>
      <title>Building Ultra-Lightweight Docker Images with Free Pascal: From Scratch in just over 1MB! 🚀</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Mon, 25 Aug 2025 12:15:26 +0000</pubDate>
      <link>https://dev.to/sempare/building-ultra-lightweight-docker-images-with-free-pascal-from-scratch-in-just-over-1mb-ia5</link>
      <guid>https://dev.to/sempare/building-ultra-lightweight-docker-images-with-free-pascal-from-scratch-in-just-over-1mb-ia5</guid>
      <description>&lt;p&gt;Ever wondered how small you can make a Docker image for Free Pascal based of Docker scratch? In this article I'll show you how to create a fully functional application using Free Pascal and containerise it that fits in just &lt;strong&gt;1.24MB&lt;/strong&gt; - smaller than most profile pictures!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;In the world of microservices and containerised applications, image size matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster deployments&lt;/strong&gt; - Less data to transfer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced storage costs&lt;/strong&gt; - Especially important at scale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved security&lt;/strong&gt; - Smaller attack surface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better performance&lt;/strong&gt; - Less memory footprint&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Magic: Docker's &lt;code&gt;scratch&lt;/code&gt; Image
&lt;/h2&gt;

&lt;p&gt;Docker's &lt;code&gt;scratch&lt;/code&gt; image is literally empty - it contains absolutely nothing. This makes it the ultimate starting point for minimal containers, but it also means your binary needs to be completely self-contained.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;Here's what we're working with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;hello.pas&lt;/strong&gt; - A simple Free Pascal program that makes an HTTP request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
    &lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;fphttpclient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TFPCustomHTTPClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SimpleGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'http://www.somedomain.com'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;fpc.cfg&lt;/strong&gt; - Compiler configuration for static linking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-O4 
-Os 
-Xs 
-XX 
-XS 
-k-static
-Fu/usr/lib/fpc/3.2.2/units/aarch64-linux/fcl-net
-Fu/usr/lib/fpc/3.2.2/units/aarch64-linux/fcl-web 
-Fu/usr/lib/fpc/3.2.2/units/aarch64-linux/fcl-base
-Fu/usr/lib/fpc/3.2.2/units/aarch64-linux/rtl-extra 
-Fu/usr/lib/fpc/
-Fu/usr/lib/fpc/3.2.2/units/aarch64-linux/rtl-objpas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key compiler flags explained:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-O4 -Os&lt;/code&gt;: Maximum optimization for size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-Xs -XX -XS&lt;/code&gt;: Strip symbols and create smart-linked executable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-k-static&lt;/code&gt;: Static linking (crucial for scratch containers)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Multi-Stage Dockerfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;freepascal/fpc:3.2.2-alpine-3.19-full&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; musl-dev 

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /build

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /build&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; fpc.cfg /etc/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; hello.pas /build/&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;fpc hello.pas 

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; scratch&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /build/hello /app/hello&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/app/hello"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses a &lt;strong&gt;multi-stage build&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1&lt;/strong&gt;: Use the full Free Pascal Alpine image to compile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2&lt;/strong&gt;: Copy only the compiled binary to scratch&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Building and Testing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build the image&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; hello-fpc &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Check the size&lt;/span&gt;
docker images hello-fpc
&lt;span class="c"&gt;# Output: hello-fpc latest 1.24MB&lt;/span&gt;

&lt;span class="c"&gt;# Run it&lt;/span&gt;
docker run hello-fpc
&lt;span class="c"&gt;# Output: Full HTML response from the test site!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This is So Cool
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Incredible Size Efficiency&lt;/strong&gt;: At 1.24MB, this is smaller than:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single high-resolution photo&lt;/li&gt;
&lt;li&gt;Most JavaScript frameworks&lt;/li&gt;
&lt;li&gt;Basic Python/Node.js containers (often 100MB+)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security Benefits&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No shell, package manager, or unnecessary tools&lt;/li&gt;
&lt;li&gt;Minimal attack surface&lt;/li&gt;
&lt;li&gt;Only contains your application&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightning-fast container startup&lt;/li&gt;
&lt;li&gt;Minimal memory usage&lt;/li&gt;
&lt;li&gt;Perfect for serverless/edge computing &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Free Pascal Advantages
&lt;/h2&gt;

&lt;p&gt;Free Pascal shines in this use case because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static compilation&lt;/strong&gt;: Creates self-contained binaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small runtime&lt;/strong&gt;: No large runtime environment needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast execution&lt;/strong&gt;: Compiled code runs efficiently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich libraries&lt;/strong&gt;: Full HTTP client capabilities built-in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform&lt;/strong&gt;: Same code works on multiple architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison with Other Languages
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Typical Container Size&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free Pascal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.24MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;This example&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;5-20MB&lt;/td&gt;
&lt;td&gt;With scratch base&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;10-30MB&lt;/td&gt;
&lt;td&gt;With alpine/scratch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;150-300MB&lt;/td&gt;
&lt;td&gt;Even with Alpine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;100-500MB&lt;/td&gt;
&lt;td&gt;Various base images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;200-400MB&lt;/td&gt;
&lt;td&gt;JRE required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Real-World Applications
&lt;/h2&gt;

&lt;p&gt;This approach is perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microservices&lt;/strong&gt;: Minimal overhead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge computing&lt;/strong&gt;: Fast deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IoT applications&lt;/strong&gt;: Resource constraints
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless functions&lt;/strong&gt;: Quick cold starts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health check services&lt;/strong&gt;: Minimal footprint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API gateways&lt;/strong&gt;: High performance needs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips for Success
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Always use static linking&lt;/strong&gt; (&lt;code&gt;-k-static&lt;/code&gt; flag)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize for size&lt;/strong&gt; (&lt;code&gt;-Os&lt;/code&gt;, &lt;code&gt;-O4&lt;/code&gt; flags)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strip symbols&lt;/strong&gt; (&lt;code&gt;-Xs&lt;/code&gt;, &lt;code&gt;-XX&lt;/code&gt; flags)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test thoroughly&lt;/strong&gt; - No debugging tools in scratch!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle errors gracefully&lt;/strong&gt; - No shell for troubleshooting&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Free Pascal + Docker scratch images = &lt;strong&gt;Ultimate efficiency&lt;/strong&gt;! &lt;/p&gt;

&lt;p&gt;At just 1.24MB, we've created a fully functional web client that's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Secure by design
&lt;/li&gt;
&lt;li&gt;✅ Lightning fast&lt;/li&gt;
&lt;li&gt;✅ Resource efficient&lt;/li&gt;
&lt;li&gt;✅ Secured intellectual property&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach proves that modern applications don't need to be bloated. Not bad when working with with your daddy's pascal! ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you to our supporters!
&lt;/h2&gt;

&lt;p&gt;We need your help to maintain our Sempare Template Engine (&lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Support us via GitHub Sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or Stripe (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Some interesting developments are coming regarding our Sempare Boot framework with native support in Free Pascal (currently self funded).&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's the smallest Docker image you've ever created?&lt;/em&gt;    &lt;/p&gt;

</description>
      <category>sempare</category>
      <category>webdev</category>
      <category>pascal</category>
      <category>freepascal</category>
    </item>
    <item>
      <title>The Sempare Template Engine for Delphi: Advanced Template Registry Features</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 20 Nov 2024 18:21:28 +0000</pubDate>
      <link>https://dev.to/sempare/the-sempare-template-engine-advanced-template-registry-features-29o9</link>
      <guid>https://dev.to/sempare/the-sempare-template-engine-advanced-template-registry-features-29o9</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. Having been around since 2019, the template engine has matured into a robust tool with many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this article, we will explore the various ways in which templates can be accessed using the Template Registry that accompanies the Sempare Template Engine.&lt;/p&gt;

&lt;p&gt;This article assumes you are already familiar with the template engine and are interested in some of its more advanced features. Introductory topics on the engine are covered elsewhere and in other articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: Why Use a Template Registry?
&lt;/h2&gt;

&lt;p&gt;Managing templates in larger applications often leads to repetitive boilerplate code, especially when dealing with multiple sources like files, streams, or resources. This can make the process error-prone and time-consuming. The Template Registry addresses this challenge by offering a general and consistent approach for template access management.&lt;/p&gt;

&lt;p&gt;The Sempare Template Engine’s main entry point is the Template helper class. Under the hood, it leverages several components, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A lexer to tokenize text streams.&lt;/li&gt;
&lt;li&gt;A parser to process tokens based on the template language grammar.&lt;/li&gt;
&lt;li&gt;An Abstract Syntax Tree (AST) with a visitor pattern, enabling loose coupling between evaluation, pretty printing, and other functionalities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Template helper class provides overloaded methods to parse and evaluate templates seamlessly, whether you’re working with strings, byte arrays, or streams.&lt;/p&gt;

&lt;p&gt;Here’s an example of parsing and evaluating a simple template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'hello &amp;lt;% _ %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;LOutput&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also load templates from a stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LStream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TStream&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;TBufferedFileStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'hello.tpl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmOpenRead&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LStream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;LOutput&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While these examples demonstrate the basics, scaling this approach to manage many templates often results in different developers re-implementing the same type of solution. This is where the Template Registry shines - providing a centralized, thread-safe mechanism for managing templates efficiently.&lt;/p&gt;

&lt;p&gt;The Template Registry assumes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single context contains the core configuration.&lt;/li&gt;
&lt;li&gt;Templates are uniquely named.&lt;/li&gt;
&lt;li&gt;Templates are loaded lazily and parsed only once.&lt;/li&gt;
&lt;li&gt;Template access is thread-safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Template Helper Class
&lt;/h2&gt;

&lt;p&gt;The Template helper class includes a Resolver method and several overloaded Resolve methods for accessing templates through the registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;Template&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
    &lt;span class="c1"&gt;// ...
&lt;/span&gt;
    &lt;span class="c1"&gt;// TEMPLATE REGISTRY
&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;TTemplateRegistry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;procedure&lt;/span&gt; &lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATemplateName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AOutputStream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TStream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATemplateName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;procedure&lt;/span&gt; &lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATemplateName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AOutputStream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TStream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATemplateName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// ...
&lt;/span&gt;  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;

&lt;p&gt;Using the Template.Resolve methods simplifies template usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'hello.tpl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, outputting directly to a stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;LStream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TStringStream&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;TStringStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;
  &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'hello.tpl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LStream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;
  &lt;span class="n"&gt;LStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Load Strategy
&lt;/h3&gt;

&lt;p&gt;The TTemplateRegistry.LoadStrategy property determines how templates are loaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TTemplateLoadStrategy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tlsLoadResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tlsLoadFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tlsLoadCustom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadStrategy&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tlsLoadFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tlsLoadResource&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means the registry first attempts to load from files, falling back to resources if the file isn’t found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Resources
&lt;/h3&gt;

&lt;p&gt;When embedding templates as resources, naming conventions matter. Resource keys do not support slashes, so a default resolver replaces slashes (/ or \) with underscores (_). For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello_tpl RCDATA "templates\\hello.tpl"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default ResourceNameResolver transforms names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="n"&gt;FResourceNameResolver&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToUpper&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rfReplaceAll&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'\'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rfReplaceAll&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rfReplaceAll&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rfReplaceAll&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, FileNameResolver adjusts paths for the target platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="n"&gt;FFileNameResolver&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;TPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TemplateRootFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;{$IFDEF MSWINDOWS}&lt;/span&gt;
    &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'\'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="cm"&gt;{$ELSE}&lt;/span&gt;
    &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'\'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="cm"&gt;{$ENDIF}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Custom Loading
&lt;/h3&gt;

&lt;p&gt;For advanced use cases, templates can be loaded from external sources like databases or APIs. Add tlsLoadCustom to the load strategy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadStrategy&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tlsFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tlsLoadCustom&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define a custom loader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomTemplateLoader&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt;
  &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AResolveContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TTemplateValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;ACacheInContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="c1"&gt;// Load template from a custom source
&lt;/span&gt;  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automatic Refresh
&lt;/h3&gt;

&lt;p&gt;During development, templates can automatically refresh in debug mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AutomaticRefresh&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RefreshIntervalS&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This background feature detects and reloads modified templates, ensuring changes are reflected immediately. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Sempare Template Engine eliminates boilerplate and offers robust template management for Delphi developers. Its flexibility, ease of use, and advanced features, like the Template Registry, make it an indispensable tool for projects requiring dynamic text generation.&lt;/p&gt;

&lt;p&gt;Unlike frameworks tied to specific ecosystems, the Sempare Template Engine is framework-agnostic, allowing you to use it anywhere templates are needed.&lt;/p&gt;

&lt;p&gt;We are proud to hear from our users that the Sempare Template Engine is the most feature-rich template engine for Delphi. We hope it enhances your productivity as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you to our supporters!
&lt;/h2&gt;

&lt;p&gt;We need your help to maintain the project. Support us via GitHub Sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or Stripe (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors gain access to exclusive features like our RAD Studio IDE wizard.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>templating</category>
      <category>sempare</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using the ternary expression in the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Mon, 28 Oct 2024 13:58:51 +0000</pubDate>
      <link>https://dev.to/sempare/using-the-ternary-expression-in-the-sempare-template-engine-for-delphi-2ne</link>
      <guid>https://dev.to/sempare/using-the-ternary-expression-in-the-sempare-template-engine-for-delphi-2ne</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;Sometimes, you may want an inline ternary expression to simplify more verbose if-expressions.&lt;/p&gt;

&lt;p&gt;e.g. You may have something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% x := 123 %&amp;gt;
&amp;lt;% if x &amp;gt; 100 %&amp;gt;
   a big value
&amp;lt;% else %&amp;gt;
   a low value
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could convert the above into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% x := 123 %&amp;gt;
&amp;lt;% print('a big value' if x &amp;gt; 100 else 'a low value') %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The above tutorial illustrated how a ternary expression could&lt;/p&gt;

&lt;p&gt;The Sempare Template Engine is very flexible, configurable and extensible, allowing for a good seperation of concerns between your business logic that will access data, and the templating engine that will render/present your data as required.&lt;/p&gt;

&lt;p&gt;The template engine is available on &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and via Embarcadero GetIt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>templating</category>
    </item>
    <item>
      <title>Eliminating whitespace in Sempare Template Engine for Delphi templates</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Thu, 24 Oct 2024 18:19:24 +0000</pubDate>
      <link>https://dev.to/sempare/eliminating-whitespace-in-sempare-template-engine-for-delphi-templates-3e0o</link>
      <guid>https://dev.to/sempare/eliminating-whitespace-in-sempare-template-engine-for-delphi-templates-3e0o</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will illustrate how whitespace (space and newlines) can be eliminated from templates managed by the Sempare Template Engine.&lt;/p&gt;

&lt;p&gt;Typically, when using templates, there may be more whitespace and newlines in a template that you really want. Let's explore a few options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% ignorews %&amp;gt;
  no more spaces
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nomorespaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, there is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% ignorenl %&amp;gt;
this.
is.
a.
test.
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.is.a.test.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are a bit crude. &lt;/p&gt;

&lt;p&gt;When it comes to the normal statements, we have a better alternative that you can simply add a - immediately after the script open tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;%- if true %&amp;gt;
    this will be displayed
    &amp;lt;% else %&amp;gt;
    this won't
    &amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    this will be displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The behaviour of the &amp;lt;%- is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the whitesapce before the '&amp;lt;%-' will be removed&lt;/li&gt;
&lt;li&gt;the whitespace including the newline after true '%&amp;gt;' will be removed&lt;/li&gt;
&lt;li&gt;the whitespace before and after, including newline around &amp;lt;% else %&amp;gt; will be removed&lt;/li&gt;
&lt;li&gt;the whitespace before and after, including newline around &amp;lt;% end %&amp;gt; will be removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nested statements will need to have the hint applied as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;ul&amp;gt;
    &amp;lt;%- for x := 1 to 3 %&amp;gt;
       &amp;lt;%- y := x + 1 %&amp;gt;
       &amp;lt;li&amp;gt;&amp;lt;%- y %&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;% end %&amp;gt;
    &amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the hints, you will see output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;ul&amp;gt;


      &amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;

      &amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;

      &amp;lt;li&amp;gt;4&amp;lt;/li&amp;gt;


    &amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the hint, we will get a cleaner output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;ul&amp;gt;
      &amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;4&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, the template engine provides a few alternatives to help minimise the whitespace generated by templates.&lt;/p&gt;

&lt;p&gt;The Sempare Template Engine is very flexible, configurable and extensible, allowing for a good seperation of concerns between your business logic that will access data, and the templating engine that will render/present your data as required.&lt;/p&gt;

&lt;p&gt;The template engine is available on &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and via Embarcadero GetIt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>template</category>
      <category>sempare</category>
    </item>
    <item>
      <title>Creating helper functions for the Sempare Template Engine</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Thu, 17 Oct 2024 13:24:44 +0000</pubDate>
      <link>https://dev.to/sempare/creating-helper-functions-for-the-sempare-template-engine-3nla</link>
      <guid>https://dev.to/sempare/creating-helper-functions-for-the-sempare-template-engine-3nla</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore how to add helper functions to the template engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Builtin functions
&lt;/h2&gt;

&lt;p&gt;The template engine has a number of builtin functions as described on &lt;a href="https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/builtin-functions.md" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/builtin-functions.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, we will describe you you can use your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling functions
&lt;/h2&gt;

&lt;p&gt;Lets start by illustrating how to call a builtin function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;fmtdt&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;yyyy-mm-dd&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="na"&gt;dtnow&lt;/span&gt;&lt;span class="err"&gt;())&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling a custom helper function is no different, except that the builtin functions have been pre-packaged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining functions
&lt;/h2&gt;

&lt;p&gt;Defining functions is done by defining static class methods on a class and binding them to a context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;THelperMethods&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BValue&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;THelperMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BValue&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;AValue&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;BValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The nice thing about Delphi's RTTI system is that we can map the parameters provided to to the template to the methods using normal types, rather than variadic alternatives and utilising the type system available to us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing context information
&lt;/h2&gt;

&lt;p&gt;If your function requires access to the template context, it may be presented as the first parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;DoSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AValue&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Registering your functions
&lt;/h2&gt;

&lt;p&gt;Registering your functions is done through a Template Context and accessing it is a simple as illustrated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LContext&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;THelperMethods&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LOutput&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;% Add(1,2) %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Support for overloaded methods is not robust at present. We do have a patch on the way to improve overloaded support, but it is heavier on the system, so would rather advise having methods with unique names that are not overloaded.&lt;/p&gt;

&lt;p&gt;Support for variadic parameters is also going to be improved. e.g. a signature such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AValues&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TArray&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, the template engine has no context of default parameters on methods. Unfortunately, you will have to ensure all parameters are passed through correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Sempare Template Engine offers you many options to extend and offer richness to your templates. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>template</category>
    </item>
    <item>
      <title>Accessing a FireDAC dataset from the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Thu, 17 Oct 2024 11:32:37 +0000</pubDate>
      <link>https://dev.to/sempare/accessing-a-firedac-dataset-from-the-sempare-template-engine-for-delphi-4j3g</link>
      <guid>https://dev.to/sempare/accessing-a-firedac-dataset-from-the-sempare-template-engine-for-delphi-4j3g</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this article, we will explore how a FireDAC TDataSet can be enumerated from a Sempare Template Engine template.&lt;/p&gt;

&lt;p&gt;The code for this tutorial is available at &lt;a href="https://github.com/sempare/sempare-devto-examples/tree/dev/FireDACInMemory" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-devto-examples/tree/dev/FireDACInMemory&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a mock dataset
&lt;/h2&gt;

&lt;p&gt;We normally get a TDataSet back from a database query. In this tutorial, I'll construct a TFDMemTable which we can use later in a template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;CreateMockUsersTable&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;TFDMemTable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="k"&gt;procedure&lt;/span&gt; &lt;span class="n"&gt;AddPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;AAge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'weight'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;AWeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;TFDMemTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldDefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ftWideString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldDefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ftInteger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldDefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'weight'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ftFloat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateDataSet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;AddPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'joe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;67&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;AddPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'pete'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;87&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;AddPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'jane'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;47&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the function above, we create a TFDMemTable containing 3 users. We first define the fields and then add the users.&lt;/p&gt;

&lt;p&gt;templates/users.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Users&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;idx&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;Users&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;idx&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;Users.name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;Users.age&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;Users.weight&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;onbegin&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;No&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Age&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Width&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;onend&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;onempty&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;There are no users&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above template, we use some of the additional 'events' on loops to control various aspects around when the header, body and footer is created, as well as what to output when there is no data. During each iteration, the the loop will dereference the various fields from the dataset, as we see with 'Users.name' as an example.&lt;/p&gt;

&lt;p&gt;Now to pull it all together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;FireDACInMemoryExample&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;FireDAC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Comp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;CreateMockUsersTable&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;TFDMemTable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="k"&gt;begin&lt;/span&gt; 
  &lt;span class="c1"&gt;// code from above
&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TTemplateData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
    &lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TDataSet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;LTemplateData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TTemplateData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;LTemplateData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;CreateMockUsersTable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'users.tpl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LTemplateData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
  &lt;span class="k"&gt;finally&lt;/span&gt;
    &lt;span class="n"&gt;LTemplateData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give us a simple HTML table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Users&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;No&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Age&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Width&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;joe&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;20&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;67&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;2&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;pete&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;19&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;87&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;3&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;jane&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;23&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;47&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;Something to be aware of. When enumerating using the &lt;em&gt;for&lt;/em&gt; statement, the index variable returns an offset into the data set, starting from 1. &lt;/p&gt;

&lt;p&gt;We dereference fields directory off the dataset as shown above. If there are spaces in the field name, you can use array dereferencing style. e.g. In the above Users.name and Users['name'] are equivalent. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The above example has illustrated how a simple HTML report can be generated with an in memory FireDAC table.&lt;/p&gt;

&lt;p&gt;The Sempare Template Engine is very flexible, configurable and extensible, allowing for a good seperation of concerns between your business logic that will access data, and the templating engine that will render/present your data as required.&lt;/p&gt;

&lt;p&gt;The template engine is available on &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and via Embarcadero GetIt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>template</category>
      <category>firedac</category>
    </item>
    <item>
      <title>Introducing the Sempare Template Engine Playground Wizard for the Delphi RAD Studio IDE</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 16 Oct 2024 23:12:37 +0000</pubDate>
      <link>https://dev.to/sempare/introducing-the-sempare-template-engine-playground-wizard-for-the-delphi-rad-studio-ide-1jmn</link>
      <guid>https://dev.to/sempare/introducing-the-sempare-template-engine-playground-wizard-for-the-delphi-rad-studio-ide-1jmn</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this article, I’m excited to present a preview of the Sempare Template Engine Playground Wizard for the Delphi IDE. This tool enables developers to work with templates using mock data, eliminating the need for a running application or server.&lt;/p&gt;

&lt;p&gt;Recently, we transitioned the licensing of the Sempare Template Engine from GPL to a dual-license model under the Apache 2.0 and the Sempare Commercial License.&lt;/p&gt;

&lt;p&gt;Unlike some competitors, we’ve had limited financial backing to support our R&amp;amp;D efforts, relying primarily on our own resources. While other templating products may not necessarily offer more features, increased competition has made it necessary for us to expand our user base. However, there’s a growing expectation for free tools, despite the common understanding that, while we have freedom of speech, there’s no such thing as free beer when it comes to Open Source.&lt;/p&gt;

&lt;p&gt;As a result, we’ve decided that the IDE integration will be available to our commercial supporters once it is finalized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo using the Horse framework
&lt;/h2&gt;

&lt;p&gt;Horse (&lt;a href="https://github.com/HashLoad/horse" rel="noopener noreferrer"&gt;https://github.com/HashLoad/horse&lt;/a&gt;) is a small webframework based on the Indy Project (&lt;a href="https://www.indyproject.org" rel="noopener noreferrer"&gt;https://www.indyproject.org&lt;/a&gt;). I won't go into the details of installing the framework as this can be done easily through GetIt or from GitHub. Indy should be available with the RAD Studio.&lt;/p&gt;

&lt;p&gt;The source for this demo is available on &lt;a href="https://github.com/sempare/sempare-devto-examples/tree/dev/HorseDemo" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-devto-examples/tree/dev/HorseDemo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HorseDemo.dpr&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;HorseDemo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;{$APPTYPE CONSOLE}&lt;/span&gt;
&lt;span class="cm"&gt;{$R *.res}&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Horse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TIndexData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TArray&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="n"&gt;THorseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KeepConnectionAlive&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;THorse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;procedure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;THorseRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;Res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;THorseResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;var&lt;/span&gt;
        &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TIndexData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'Sempare Template Engine'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;THorse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/page2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;procedure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;THorseRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;Res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;THorseResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;var&lt;/span&gt;
        &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TIndexData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'Sempare Template Engine'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Ian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Macro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'David'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;Res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'page2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;THorse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;procedure&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="n"&gt;TTemplateRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Finalize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;except&lt;/span&gt;
    &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;': '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above we can see in a few lines of code we have created a small web server running on port 8080, exposing endpoints / and /page2.&lt;/p&gt;

&lt;p&gt;Below are some templates for the demo. We describe the template constructs in some of the other tutorials. These are just for reference for now, as we want you to see the IDE integration below.&lt;/p&gt;

&lt;p&gt;templates/index.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;extends&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;title&amp;gt;&lt;/span&gt;Index&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This is the index page &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;templates/page2.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;extends&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;title&amp;gt;&lt;/span&gt;Page2&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt; &lt;span class="na"&gt;of&lt;/span&gt; &lt;span class="na"&gt;users&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;betweenitems&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;templates/layout.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333333&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="nt"&gt;block&lt;/span&gt; &lt;span class="s2"&gt;'style'&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="nt"&gt;end&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Default Content&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Preview the layout
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1plzroavv87u1odkiw64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1plzroavv87u1odkiw64.png" alt="The Layout" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the bottom panel, we can see a docked panel containing 3 sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mock data editor&lt;/li&gt;
&lt;li&gt;template editor&lt;/li&gt;
&lt;li&gt;preview (raw text and html)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the preview, we can see the layout being rendered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preview the index page
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftujg4rbkadxzhmlrue7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftujg4rbkadxzhmlrue7w.png" alt="The Index Page" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see that the body placeholder is being replaced in the layout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preview page2
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5dxujqgqxygcok86u72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5dxujqgqxygcok86u72.png" alt="Page2" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we see the header placeholder being filled with an HTML title. In the body, we have our mock data being rendered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preview page 2 with one user
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3yz9kxrvjlofb70one6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3yz9kxrvjlofb70one6.png" alt="Page2 with one user" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preview page 2 with no users
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffifwxv3pcn52sfzh1mwh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffifwxv3pcn52sfzh1mwh.png" alt="Page2 with no users" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Errors are instantly highlighted
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2s9oaa4uqgfii8jhxta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2s9oaa4uqgfii8jhxta.png" alt="Parsing error" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above screenshot, we can see how removing the &amp;gt; on line 5 yields the error message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the demo and opening Page2 in Edge
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj0iyi7od5a0v03nnnwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj0iyi7od5a0v03nnnwd.png" alt="Page2 demo in Edge" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pressing F9 and running the app, we are in a position to launch Edge and open &lt;a href="http://localhost:8080/page2" rel="noopener noreferrer"&gt;http://localhost:8080/page2&lt;/a&gt;. Note the output matches the mock data with users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While Delphi hasn’t historically been a common choice for web development, the availability of more tools and libraries is making it a viable option for such projects. As a dialect of Pascal, one of Delphi’s strengths is its compiler, which generates cross-platform native code (Linux, Windows, Android, macOS, iOS). The language is type-safe, classified as memory safe, and highly approachable for new users, with language features that are intuitive and easy to grasp without extensive manual reading—though diving into the documentation can unlock even more advanced capabilities.&lt;/p&gt;

&lt;p&gt;This is still in the early stages of development, but with additional commercial sponsorship, we aim to further evolve this wizard and continue supporting the underlying project.&lt;/p&gt;

&lt;p&gt;Thank you in advance for your support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blogs.embarcadero.com/is-delphi-a-memory-safe-language/" rel="noopener noreferrer"&gt;Is Delphi a memory safe language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://media.defense.gov/2023/Apr/27/2003210083/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY_V1.1.PDF" rel="noopener noreferrer"&gt;NSA - Cybersecurity Information Sheet - Memory Safety&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>template</category>
      <category>sempare</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Configuring the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 16 Oct 2024 23:12:11 +0000</pubDate>
      <link>https://dev.to/sempare/configuring-the-sempare-template-engine-for-delphi-27pn</link>
      <guid>https://dev.to/sempare/configuring-the-sempare-template-engine-for-delphi-27pn</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore some of the options to configure a template context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safe web development
&lt;/h2&gt;

&lt;p&gt;We know we are in an unsafe world! Attacks are occurring continually. SQL injection, HTML injection just to name the most obvious...&lt;/p&gt;

&lt;p&gt;The Sempare Template Engine has features to ensure your web app is safe and responsive. Two features that are important are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;max run times&lt;/li&gt;
&lt;li&gt;automatic HTML encoding&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Max run times
&lt;/h3&gt;

&lt;p&gt;By default, the max runtime is set to 1 minute.&lt;/p&gt;

&lt;p&gt;This can be customised:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MaxRunTimeMs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automatic HTML encoding
&lt;/h3&gt;

&lt;p&gt;This can be customised:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LCtx&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseHtmlVariableEncoder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say we have the following scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;
   &lt;span class="n"&gt;TTemplateData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
      &lt;span class="n"&gt;DataField&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TTemplateData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataField&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;script&amp;gt;alert("hello world");&amp;lt;/script&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Unsafe: &amp;lt;% DataField %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Safe: &amp;lt;% DataField %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;Unsafe: &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
Safe: &lt;span class="ni"&gt;&amp;amp;lt;&lt;/span&gt;script&lt;span class="ni"&gt;&amp;amp;gt;&lt;/span&gt;alert(&lt;span class="ni"&gt;&amp;amp;quot;&lt;/span&gt;hello world&lt;span class="ni"&gt;&amp;amp;quot;&lt;/span&gt;);&lt;span class="ni"&gt;&amp;amp;lt;&lt;/span&gt;/script&lt;span class="ni"&gt;&amp;amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you have HTML encoding enabled, you may have scenarios where you want to evaluate raw HTML. You can use the &lt;em&gt;print&lt;/em&gt; statement to do this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;DataField&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     vs
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;DataField&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Changing the script tags
&lt;/h2&gt;

&lt;p&gt;By default, template scripting is done between the &amp;lt;% and %&amp;gt; tags.&lt;/p&gt;

&lt;p&gt;This can be changed as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LCtx&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartToken&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'{{'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EndToken&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'}}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'{{ if true }}hello{{else}}bye{{end}}'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Embedded error messages
&lt;/h2&gt;

&lt;p&gt;By default, errors in the template evaluation results in a template Exception being raised.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;% a := ["a"; "b"] %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example will raise an exception stating that a comma (,) is expected, rather than the semicolon (;).&lt;/p&gt;

&lt;p&gt;We can change the behaviour as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LCtx&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;eoEmbedException&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;% a := ["a"; "b"] %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example will produce output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;(Line 1, Column 14) Parsing error. Expecting: ,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;The documentation for the context is available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/configuration.md" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/configuration.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are many configuration options available for manipulating the behaviour of the template engine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>template</category>
    </item>
    <item>
      <title>Functional templates with the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 16 Oct 2024 23:10:58 +0000</pubDate>
      <link>https://dev.to/sempare/functional-templates-with-the-sempare-template-engine-for-delphi-2p3d</link>
      <guid>https://dev.to/sempare/functional-templates-with-the-sempare-template-engine-for-delphi-2p3d</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore how templates can behave like functions and all the super powers of 'include'.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

&lt;p&gt;We can define inline templates and use them as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;template&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;person&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;#&lt;/span&gt; &lt;span class="na"&gt;this&lt;/span&gt; &lt;span class="na"&gt;is&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="na"&gt;comment&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;#&lt;/span&gt; &lt;span class="na"&gt;we&lt;/span&gt; &lt;span class="na"&gt;can&lt;/span&gt; &lt;span class="na"&gt;define&lt;/span&gt; &lt;span class="na"&gt;dictionaries&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;people&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;
     &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;conrad&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;},&lt;/span&gt;
     &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;ian&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;},&lt;/span&gt;
     &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;richard&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;
   &lt;span class="err"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;person&lt;/span&gt; &lt;span class="na"&gt;of&lt;/span&gt; &lt;span class="na"&gt;people&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;include&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;person&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="na"&gt;person&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, we define a template name 'person' - containing some HTML div tags.&lt;/p&gt;

&lt;p&gt;Then we have a for loop enumerating over the people array. Using the inline data is useful when mocking data, as we can test it without having a server running, either using the demo Playground app, or using the IDE Wizard which will be discussed in another tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are functional templates?
&lt;/h2&gt;

&lt;p&gt;As we have seen, the 'include' statement behaves like a function. However, there is an alternative syntax for including templates, which makes it appear more functional. Let us illustrate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;person&lt;/span&gt; &lt;span class="na"&gt;of&lt;/span&gt; &lt;span class="na"&gt;people&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;person&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;person.name&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets try something different to illustrate it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;template&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;:&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;% id %&amp;gt;"&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;name="&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;"&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;gt;
   &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/signup"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"First Name"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"fn"&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Last Name"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"lastname"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ln"&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"E-mail"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the 'functional include' syntax is slightly different to the dictionary format illustrated above with the mock data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this interesting? Maybe Atomic Design?
&lt;/h2&gt;

&lt;p&gt;Lets say you like styling with TailwindCSS (&lt;a href="https://tailwindcss.com" rel="noopener noreferrer"&gt;https://tailwindcss.com&lt;/a&gt;). We can create a template library, either standalone or inline, with 'atomic' components that we can define with whatever granularity we require. We can build up more complex components by including others as required.&lt;/p&gt;

&lt;p&gt;We can build styled templates for buttons, inputs, grids, etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The Sempare Template Engine offers a lot of rich functionality, allowing you to manipulate text output to fit your needs. &lt;/p&gt;

&lt;h1&gt;
  
  
  Further reading
&lt;/h1&gt;

&lt;p&gt;Have a look at &lt;a href="https://bradfrost.com/blog/post/atomic-web-design" rel="noopener noreferrer"&gt;https://bradfrost.com/blog/post/atomic-web-design&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>template</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating layouts using the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 16 Oct 2024 23:07:37 +0000</pubDate>
      <link>https://dev.to/sempare/creating-layouts-using-the-sempare-template-engine-3ah8</link>
      <guid>https://dev.to/sempare/creating-layouts-using-the-sempare-template-engine-3ah8</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will explore how layouts can be created using the Sempare Template Engine.&lt;/p&gt;

&lt;p&gt;This can be done in different ways, depending on the requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use 'include' statements&lt;/li&gt;
&lt;li&gt;use 'extends' and 'block' statements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the examples below, we will assume we are working on server side rendering of HTML pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using include statements
&lt;/h2&gt;

&lt;p&gt;Using include statements can be used for layouts, but doesn't scale very well. We will investigate the include statement in another tutorial as it has some super powers. For now, lets say we have an index page. We know there is a header, body and footer. A simple approach is as follows:&lt;/p&gt;

&lt;p&gt;header.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;footer.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;index.tpl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;include&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   This is my index page
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;include&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;footer&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, you will note that it may be more complex to manage the layout consistently. We will consider an improved approach in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a layout
&lt;/h2&gt;

&lt;p&gt;Considering you may be doing server side rendering, we can create a layout.tpl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="nt"&gt;block&lt;/span&gt; &lt;span class="s2"&gt;'style'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="nt"&gt;end&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="err"&gt;';&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Default Content&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The nice thing about the above approach is that we get a good sense of the template above compared to the 'include' approach. Placeholders named style, header and body are defined. The body placeholder block has default content, where the others are empty.&lt;/p&gt;

&lt;p&gt;Now we could have an index.tpl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% extends 'layout' %&amp;gt;
   &amp;lt;% block 'header %&amp;gt;
       &amp;lt;title&amp;gt;Index&amp;lt;/title&amp;gt;
   &amp;lt;% end %&amp;gt;
   &amp;lt;% block 'body' %&amp;gt;
      This is the index page.
   &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the above will reference the layout template and replace the header and body placeholder blocks with the content in this template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing state and layout from your code
&lt;/h2&gt;

&lt;p&gt;Now lets say you have two different layouts, one for being an anonymous user, and another for being a signed in user.&lt;/p&gt;

&lt;p&gt;Our template could reference the layout via a variable such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;extends&lt;/span&gt; &lt;span class="na"&gt;layoutTpl&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Index&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      This is the index page.
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We may have Delphi/Object Pascal that uses a structure such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TIndexData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
     &lt;span class="n"&gt;LayoutTpl&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;GetIndexData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TIndexData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;SignedIn&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
     &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LayoutTpl&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'layout_authenticaetd.tpl'&lt;/span&gt;
   &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LayoutTpl&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'layout_guest.tpl'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Controlling the layout can be done in the same way we return data to the template engine.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The Sempare Template Engine offers flexibility in the way layouts can be managed, allowing you to maintain your output according to your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>template</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using loops in the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 16 Oct 2024 23:07:15 +0000</pubDate>
      <link>https://dev.to/sempare/using-loops-in-the-sempare-template-engine-for-delphi-417m</link>
      <guid>https://dev.to/sempare/using-loops-in-the-sempare-template-engine-for-delphi-417m</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial we will review some of the looping statements, namely &lt;em&gt;for&lt;/em&gt; and &lt;em&gt;while&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic for loops
&lt;/h2&gt;

&lt;p&gt;The basics, as we do in pascal, we can loop over a fixed range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="err"&gt;10&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will produce the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;2&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
     ... 3 to 8 ommitted ...
     &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;9&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;10&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets make it more interesting, and use variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;start_idx&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;1;&lt;/span&gt; &lt;span class="na"&gt;end_idx&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;start_idx&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="na"&gt;end_idx&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us assume the variables are driven by user input, rather than being set in the template. Now we need to also cater for the scenario that no values are present. So we could devise a script like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;start_idx&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;= 0) and (end_idx &amp;gt; 0) %&amp;gt;
     &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;start_idx&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="na"&gt;end_idx&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;else&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;There are no values&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This could be translated to the following using extension to the &lt;em&gt;for loop grammar&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;     &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;start_idx&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="na"&gt;end_idx&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;onbegin&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;onend&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;onempty&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;There are no values&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enumerable for loops
&lt;/h2&gt;

&lt;p&gt;For loops are flexible and can enumerate over different structures such as arrays, lists, dictionaries, JSON arrays, and can be extended to enumerate over custom types as well.&lt;/p&gt;

&lt;p&gt;When it comes to enumeration, there are also two variations of the for loop, namely 'for in' and 'for of'. Lets have a quick look at some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;arr&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt; &lt;span class="err"&gt;5,&lt;/span&gt; &lt;span class="err"&gt;4,&lt;/span&gt; &lt;span class="err"&gt;3,&lt;/span&gt; &lt;span class="err"&gt;2,&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt; &lt;span class="err"&gt;]&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;arr&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;betweenitems&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;0, 1, 2, 3, 4, 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very similar to JavaScript behaviour.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;arr&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt; &lt;span class="err"&gt;5,&lt;/span&gt; &lt;span class="err"&gt;4,&lt;/span&gt; &lt;span class="err"&gt;3,&lt;/span&gt; &lt;span class="err"&gt;2,&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt; &lt;span class="err"&gt;]&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;of&lt;/span&gt; &lt;span class="na"&gt;arr&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;betweenitems&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will yield:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;5, 4, 3, 2, 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Looping over dictionaries
&lt;/h2&gt;

&lt;p&gt;Assume we have the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;
   &lt;span class="n"&gt;TPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
     &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LUsers&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TDictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TPerson&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;string&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'...'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// listed below
//
&lt;/span&gt;&lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LUsers&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;_&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Email: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Name: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;_&lt;/span&gt;&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="err"&gt;].&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic _ references the TDictionary passed to the template.&lt;/p&gt;

&lt;p&gt;Consider we may only be interested in the names, we could change the template to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt; &lt;span class="na"&gt;person&lt;/span&gt; &lt;span class="na"&gt;of&lt;/span&gt; &lt;span class="na"&gt;_&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Name: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;person.Name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More documentation is available at: &lt;a href="https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/statements.md#for" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/statements.md#for&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  While loops
&lt;/h2&gt;

&lt;p&gt;A while statement is a loop based on a condition being true.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="na"&gt;:= &lt;/span&gt;&lt;span class="s"&gt;0;&lt;/span&gt; &lt;span class="na"&gt;while&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt; &lt;span class="err"&gt;10;&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="na"&gt;betweenitems&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking out of a loop
&lt;/h2&gt;

&lt;p&gt;As in Pascal, we can use the &lt;em&gt;break&lt;/em&gt; statement to break out of a &lt;em&gt;for&lt;/em&gt; or &lt;em&gt;while&lt;/em&gt; loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   &amp;lt;% for i := 1 to 10 %&amp;gt;
      &amp;lt;% if i = 5 ; break ; end %&amp;gt;
      &amp;lt;% i %&amp;gt;
   &amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will show the values 1 to 4.&lt;/p&gt;

&lt;p&gt;More documentation is available at: &lt;a href="https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/statements.md#while" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/statements.md#while&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Skipping iterations
&lt;/h2&gt;

&lt;p&gt;Similar to the above, we can use the &lt;em&gt;continue&lt;/em&gt; statement to skip iterations in &lt;em&gt;for&lt;/em&gt; or &lt;em&gt;while&lt;/em&gt; loops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   &amp;lt;% for i := 1 to 10 %&amp;gt;
      &amp;lt;% if i mod 2 == 0 ; continue ; end %&amp;gt;
      &amp;lt;% i %&amp;gt;
   &amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will show all the odd numbers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The Sempare Template Engine offers a lot of rich functionality, allowing you to manipulate text output to fit your needs. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>delphi</category>
      <category>sempare</category>
      <category>templating</category>
      <category>pascal</category>
    </item>
    <item>
      <title>Accessing data from the Sempare Template Engine for Delphi</title>
      <dc:creator>Sempare Limited</dc:creator>
      <pubDate>Wed, 16 Oct 2024 23:05:45 +0000</pubDate>
      <link>https://dev.to/sempare/accessing-data-from-the-sempare-template-engine-for-delphi-5dg8</link>
      <guid>https://dev.to/sempare/accessing-data-from-the-sempare-template-engine-for-delphi-5dg8</guid>
      <description>&lt;p&gt;The Sempare Template Engine (available at &lt;a href="https://github.com/sempare/sempare-delphi-template-engine" rel="noopener noreferrer"&gt;https://github.com/sempare/sempare-delphi-template-engine&lt;/a&gt; and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.&lt;/p&gt;

&lt;p&gt;In this tutorial we will explore the various ways in which data can be accessed by Sempare Template Engine templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The template engine provides numerous ways for data to be accessed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data passed to the template&lt;/li&gt;
&lt;li&gt;Data passed upfront in the context&lt;/li&gt;
&lt;li&gt;Data queried on demand &lt;/li&gt;
&lt;li&gt;Data queried by static helper functions&lt;/li&gt;
&lt;li&gt;Data queried by helper methods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This tutorial assumes you have installed the template engine following the instructions discussed elsewhere.&lt;/p&gt;

&lt;p&gt;Let us explore each of these approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data passed to the template&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the simplest approach where we pass data while evaluating the template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TTemplateData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TTemplateData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'Joe'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Hello &amp;lt;% name %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data passed upfront in the context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, the Template helper methods will create a new context if you do not provide one. A context allows us to provide bespoke configuration that changes the way the template engine behaves. We can use this to also store global variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; 
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Variable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Company'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'Sempare Limited'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Variable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'CopyrightYear'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Copyright &amp;lt;% Company %&amp;gt;, &amp;lt;% CopyrightYear %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data queried on demand&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rather than injecting values into the context, we can provide an anonymous function that allows for values to be resolved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; 
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VariableResolver&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;AResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TValue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'Company'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="n"&gt;AResult&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;'Sempare Limited'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;AName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'CopyrightYear'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="n"&gt;AResult&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;AResult&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Copyright &amp;lt;% Company %&amp;gt;, &amp;lt;% CopyrightYear %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, the resolver must return true if it is able to find the result. The AResult is a TValue from the RTTI unit which can store anything. &lt;/p&gt;

&lt;p&gt;Note that if you allocate memory, you must deallocate memory yourself after the template has been evaluated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data queried by static helper functions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;THelperMethods&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;GetCompany&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;GetCopyrightYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;THelperMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetCompany&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Sempare Limited'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;THelperMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetCopyrightYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; 
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;THelperMethods&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Copyright &amp;lt;% GetCompany() %&amp;gt;, &amp;lt;% GetCopyrightYear() %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, we have illustrated how we add static functions and procedures. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data queried by helper methods&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Sempare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TCompanyInfo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;GetCompany&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;GetCopyrightYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="k"&gt;property&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt; &lt;span class="k"&gt;read&lt;/span&gt; &lt;span class="n"&gt;GetCompany&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;property&lt;/span&gt; &lt;span class="n"&gt;CopyrightYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;read&lt;/span&gt; &lt;span class="n"&gt;GetCopyrightYear&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;TCompanyInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetCompany&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Sempare Limited'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;TCompanyInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetCopyrightYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; 
  &lt;span class="n"&gt;LCompanyInfo&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TCompanyInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplateContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;LCompanyInfo&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;TCompanyInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="n"&gt;LContext&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Variables&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'company'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;LCompanyInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;LTemplate&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Copyright &amp;lt;% _.Company %&amp;gt;, &amp;lt;% _.CopyrightYear %&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;finally&lt;/span&gt;
    &lt;span class="n"&gt;LCompanyInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, we also use '_' which is a &lt;em&gt;magic&lt;/em&gt; variable that is an alias for the data being passed into the template. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we have seen above, the Sempare Template Engine is very flexible and allows you to access data in many ways, allowing you to use it according to your usage pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sponsorship Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please help us maintain the project by supporting Sempare via GitHub sponsors (&lt;a href="https://github.com/sponsors/sempare" rel="noopener noreferrer"&gt;https://github.com/sponsors/sempare&lt;/a&gt;) or via our payment link (&lt;a href="https://buy.stripe.com/aEU7t61N88pffQIdQQ" rel="noopener noreferrer"&gt;https://buy.stripe.com/aEU7t61N88pffQIdQQ&lt;/a&gt;). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>delphi</category>
      <category>sempare</category>
      <category>template</category>
    </item>
  </channel>
</rss>
