AzureLiquid 1.3.0
dotnet add package AzureLiquid --version 1.3.0
NuGet\Install-Package AzureLiquid -Version 1.3.0
<PackageReference Include="AzureLiquid" Version="1.3.0" />
paket add AzureLiquid --version 1.3.0
#r "nuget: AzureLiquid, 1.3.0"
// Install AzureLiquid as a Cake Addin #addin nuget:?package=AzureLiquid&version=1.3.0 // Install AzureLiquid as a Cake Tool #tool nuget:?package=AzureLiquid&version=1.3.0
Azure Liquid
The project was primarily built to aid in developing and testing Liquid template parsing solutions for Microsoft Azure cloud services.
The Liquid template engine that is used in Microsoft Azure is based on the DotLiquid library.
DotLiquid is a .Net port of the popular Ruby Liquid templating language. It is a separate project that aims to retain the same template syntax as the original, while using .NET coding conventions where possible. For more information about the original Liquid project, see https://shopify.github.io/liquid/.
This library uses my .NET 6.0 port of the same library, to allow for cross-platform compilation and tooling support.
Azure uses a set of predefined feature uses of DotLiquid. For example, an Azure Logic App mapping service uses the " content" accessor for any data submitted using a workflow action. The LiquidParser class exposes a set of SetContent methods used to either set:
- objects (will render down to JSON)
- JSON string
- XML string (will parse as XDocument then to JSON)
The object can then be accessed under the "content" variable in the Liquid template.
{% assign albums = content.CATALOG.CD -%} [{%- for album in albums limit:3 %}
{ "artist": "{{ album.ARTIST }}", "title": "{{ album.TITLE}}" }{% if
forloop.last == false %},{% endif %} {%- endfor -%} ]
Our object data is in this case XML, and has been added as a hierarchical selector object, here named "CATALOG", containing an array of "CD" objects. These are loaded under the hood by parsing text to an XmlDocument then back to JSON using the SetContentXml method.
Similarly, we can load JSON data either using a string with the SetContentJson method, or using object serialization with the SetContent method. Note this method's parameter forceCamlCase allows us to ensure that camel JSON formatting is preserved in the selectors.
Azure Specific Differences
For example, an Azure LogicApp mapping service uses the content accessor. The LiquidParser exposes a set of SetContent methods used to either set:
- objects (will render down to JSON)
- JSON string
- XML string (will parse as XDocument then to JSON)
The object can then be accessed under the 'content' variable in the Liquid template. This is implemented by using the LiquidParser object and using it for unit testing or for live previews/file rendering.
A key within this project is that I created it to be as compatible and usable for Azure implementations as possible. Therefore, it is important to understand how the DotLiquid and Azure implementations of the library differ from Shopify Liquid.
Liquid templates follow the file size limits for maps in Azure Logic Apps.
When using the date filter, DotLiquid supports both Ruby and .NET date format strings (but not both at the same time). By default, it will use .NET date format strings.
The JSON filter from the Shopify extension filters is currently not implemented in DotLiquid.
The standard Replace filter in the DotLiquid implementation uses regular expression (RegEx) matching, while the Shopify implementation uses simple string matching.
Liquid by default uses Ruby casing for output fields and filters such as {{ some_field | escape }}. The Azure implementation of DotLiquid uses C# naming convention, in which case output fields and filters would be referenced like so {{ SomeField | Escape }}.
For further details, see the Microsoft documentation.
How To Unit Test Liquid
There are a few different examples made:
// Arrange
var myObj = new MyObj( Title = "Title here");
// Act
var result = new LiquidParser()
.SetContent(myObj, true) // 'true' => camelCase property names
.Parse("{{ content.title }}")
.Render();
// Assert
result.Should().NotBeEmpty("A result should have been returned");
result.Should().Be(myObj.Title, "The expected result should be returned");
Another example can be made where we use a string body to transform the data.
/// <summary>
/// Ensures loading JSON from a file and parsing with a liquid file template works.
/// </summary>
[Fact]
public void EnsureJsonBodyTemplateParsing()
{
// Arrange
var parser = new LiquidParser()
.SetContentJson(Resources.JsonTestContent)
.Parse(Resources.JsonTestLiquidTemplate)
var expected = Resources.TestExpectedOutput;
// Act
var result = parser.Render();
// Assert
result.Should().NotBeEmpty("A result should have been returned");
result.Should().Be(expected, "The expected result should be returned");
}
You could similarly load the content and templates from a set of file. See the full test project for several such examples.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. |
-
net9.0
- DotLiquid-Net6 (>= 1.0.15)
- Newtonsoft.Json (>= 13.0.3)
- Roslynator.Core (>= 4.12.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.