Skip to content

Commit 92c8dd6

Browse files
authored
[llvm] add support for mustache templating language (#105893)
Adds Support for the Mustache Templating Language. See specs here: https://mustache.github.io/mustache.5.html This patch implements support+tests for majority of the features of the language including: - Variables - Comments - Lambdas - Sections This meant as a library to support places where we have to generate HTML, such as in clang-doc.
1 parent aeae366 commit 92c8dd6

File tree

5 files changed

+2146
-0
lines changed

5 files changed

+2146
-0
lines changed

llvm/include/llvm/Support/Mustache.h

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===--- Mustache.h ---------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Implementation of the Mustache templating language supports version 1.4.2
10+
// currently relies on llvm::json::Value for data input.
11+
// See the Mustache spec for more information
12+
// (https://mustache.github.io/mustache.5.html).
13+
//
14+
// Current Features Supported:
15+
// - Variables
16+
// - Sections
17+
// - Inverted Sections
18+
// - Partials
19+
// - Comments
20+
// - Lambdas
21+
// - Unescaped Variables
22+
//
23+
// Features Not Supported:
24+
// - Set Delimiter
25+
// - Blocks
26+
// - Parents
27+
// - Dynamic Names
28+
//
29+
// The Template class is a container class that outputs the Mustache template
30+
// string and is the main class for users. It stores all the lambdas and the
31+
// ASTNode Tree. When the Template is instantiated it tokenizes the Template
32+
// String and creates a vector of Tokens. Then it calls a basic recursive
33+
// descent parser to construct the ASTNode Tree. The ASTNodes are all stored
34+
// in an arena allocator which is freed once the template class goes out of
35+
// scope.
36+
//
37+
// Usage:
38+
// \code
39+
// // Creating a simple template and rendering it
40+
// auto Template = Template("Hello, {{name}}!");
41+
// Value Data = {{"name", "World"}};
42+
// std::string Out;
43+
// raw_string_ostream OS(Out);
44+
// T.render(Data, OS);
45+
// // Out == "Hello, World!"
46+
//
47+
// // Creating a template with a partial and rendering it
48+
// auto Template = Template("{{>partial}}");
49+
// Template.registerPartial("partial", "Hello, {{name}}!");
50+
// Value Data = {{"name", "World"}};
51+
// std::string Out;
52+
// raw_string_ostream OS(Out);
53+
// T.render(Data, OS);
54+
// // Out == "Hello, World!"
55+
//
56+
// // Creating a template with a lambda and rendering it
57+
// Value D = Object{};
58+
// auto T = Template("Hello, {{lambda}}!");
59+
// Lambda L = []() -> llvm::json::Value { return "World"; };
60+
// T.registerLambda("lambda", L);
61+
// std::string Out;
62+
// raw_string_ostream OS(Out);
63+
// T.render(D, OS);
64+
// // Out == "Hello, World!"
65+
// \endcode
66+
//
67+
//===----------------------------------------------------------------------===//
68+
69+
#ifndef LLVM_SUPPORT_MUSTACHE
70+
#define LLVM_SUPPORT_MUSTACHE
71+
72+
#include "Error.h"
73+
#include "llvm/ADT/StringMap.h"
74+
#include "llvm/Support/Allocator.h"
75+
#include "llvm/Support/JSON.h"
76+
#include "llvm/Support/StringSaver.h"
77+
#include <functional>
78+
#include <vector>
79+
80+
namespace llvm::mustache {
81+
82+
using Lambda = std::function<llvm::json::Value()>;
83+
using SectionLambda = std::function<llvm::json::Value(std::string)>;
84+
85+
class ASTNode;
86+
87+
// A Template represents the container for the AST and the partials
88+
// and Lambdas that are registered with it.
89+
class Template {
90+
public:
91+
Template(StringRef TemplateStr);
92+
93+
Template(const Template &) = delete;
94+
95+
Template &operator=(const Template &) = delete;
96+
97+
Template(Template &&Other) noexcept;
98+
99+
Template &operator=(Template &&Other) noexcept;
100+
101+
void render(const llvm::json::Value &Data, llvm::raw_ostream &OS);
102+
103+
void registerPartial(std::string Name, std::string Partial);
104+
105+
void registerLambda(std::string Name, Lambda Lambda);
106+
107+
void registerLambda(std::string Name, SectionLambda Lambda);
108+
109+
// By default the Mustache Spec Specifies that HTML special characters
110+
// should be escaped. This function allows the user to specify which
111+
// characters should be escaped.
112+
void overrideEscapeCharacters(DenseMap<char, std::string> Escapes);
113+
114+
private:
115+
StringMap<ASTNode *> Partials;
116+
StringMap<Lambda> Lambdas;
117+
StringMap<SectionLambda> SectionLambdas;
118+
DenseMap<char, std::string> Escapes;
119+
// The allocator for the ASTNode Tree
120+
llvm::BumpPtrAllocator AstAllocator;
121+
// Allocator for each render call resets after each render
122+
llvm::BumpPtrAllocator RenderAllocator;
123+
ASTNode *Tree;
124+
};
125+
} // namespace llvm::mustache
126+
127+
#endif // LLVM_SUPPORT_MUSTACHE

llvm/lib/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ add_llvm_component_library(LLVMSupport
220220
MD5.cpp
221221
MSP430Attributes.cpp
222222
MSP430AttributeParser.cpp
223+
Mustache.cpp
223224
NativeFormatting.cpp
224225
OptimizedStructLayout.cpp
225226
Optional.cpp

0 commit comments

Comments
 (0)