-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[llvm] add support for mustache templating language #105893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 21 commits
ac1c7b5
bcc4b0d
5fe47ca
28fb40f
0d150ea
e5e70b8
1c4f631
b8f3f9c
bb98aad
c60e2b5
0a20de8
8290c38
07d31b4
6e893c0
976593e
6a60eab
6a1fcc8
f1c27af
eb1e1a6
8ff1100
f4b0520
7ffaeec
746fb97
4944435
bcc86fe
2ceb0b0
95ad7a6
bb3b1ac
d8aa85c
0534a05
06da7a5
f713198
6b4f5cd
d400c29
8fa5fd7
fd7c106
29bba68
7eed82f
e73454d
b58fbcb
bb4ba40
b0ce196
561c7eb
96f6990
a247423
a0e7d48
4165fec
5b0a20a
ba4a6db
362728f
74d69b3
5281dc4
569df38
91547a5
a50461b
e596a5a
7eb288d
b0f2f02
adb2534
0bc60a6
a97beca
40cbec9
e8bd889
91d4217
1198d3d
ba8ee26
9895f9d
03ad2f4
3649ae6
72343f4
4729743
a780958
c9f0cc6
0c9bc1c
dc49fd7
c6a9935
ec452cf
254bf2e
83f95f0
d5f380b
b5f43b7
f6d18b7
d6bf982
1e62179
2191e67
ac8d17f
345012b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| //===--- Mustache.h ---------------------------------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Implementation of the Mustache templating language supports version 1.4.2 | ||
| // currently relies on llvm::json::Value for data input | ||
| // see the Mustache spec for more information | ||
| // (https://mustache.github.io/mustache.5.html). | ||
PeterChou1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // | ||
| // Current Features Supported: | ||
| // - Variables | ||
| // - Sections | ||
| // - Inverted Sections | ||
| // - Partials | ||
| // - Comments | ||
| // - Lambdas | ||
| // - Unescaped Variables | ||
| // | ||
| // Features Not Supported: | ||
| // - Set Delimiter | ||
| // - Blocks | ||
| // - Parents | ||
| // - Dynamic Names | ||
| // | ||
| // Usage: | ||
PeterChou1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // \code | ||
| // // Creating a simple template and rendering it | ||
| // auto Template = Template::createTemplate("Hello, {{name}}!"); | ||
| // Value Data = {{"name", "World"}}; | ||
| // StringRef Rendered = Template.render(Data); | ||
| // // Rendered == "Hello, World!" | ||
| // | ||
| // // Creating a template with a partial and rendering it | ||
| // auto Template = Template::createTemplate("{{>partial}}"); | ||
| // Template.registerPartial("partial", "Hello, {{name}}!"); | ||
| // Value Data = {{"name", "World"}}; | ||
| // StringRef Rendered = Template.render(Data); | ||
| // // Rendered == "Hello, World!" | ||
| // | ||
| // // Creating a template with a lambda and rendering it | ||
| // auto Template = Template::createTemplate("{{#lambda}}Hello, | ||
| // {{name}}!{{/lambda}}"); | ||
| // Template.registerLambda("lambda", []() { return true; }); | ||
| // Value Data = {{"name", "World"}}; | ||
| // StringRef Rendered = Template.render(Data); | ||
| // // Rendered == "Hello, World!" | ||
| // \endcode | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_SUPPORT_MUSTACHE | ||
| #define LLVM_SUPPORT_MUSTACHE | ||
|
|
||
| #include "Error.h" | ||
| #include "llvm/ADT/StringMap.h" | ||
| #include "llvm/Support/JSON.h" | ||
| #include <vector> | ||
|
|
||
| namespace llvm { | ||
| namespace mustache { | ||
PeterChou1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| using Accessor = std::vector<SmallString<128>>; | ||
PeterChou1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| using Lambda = std::function<llvm::json::Value()>; | ||
| using SectionLambda = std::function<llvm::json::Value(StringRef)>; | ||
|
|
||
| class Token { | ||
| public: | ||
| enum class Type { | ||
| Text, | ||
| Variable, | ||
| Partial, | ||
| SectionOpen, | ||
| SectionClose, | ||
| InvertSectionOpen, | ||
| UnescapeVariable, | ||
| Comment, | ||
| }; | ||
|
|
||
| Token(StringRef Str); | ||
|
|
||
| Token(StringRef RawBody, StringRef Str, char Identifier); | ||
|
|
||
| StringRef getTokenBody() const { return TokenBody; }; | ||
|
|
||
| StringRef getRawBody() const { return RawBody; }; | ||
|
|
||
| void setTokenBody(SmallString<128> NewBody) { TokenBody = NewBody; }; | ||
PeterChou1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Accessor getAccessor() const { return Accessor; }; | ||
|
|
||
| Type getType() const { return TokenType; }; | ||
|
|
||
| static Type getTokenType(char Identifier); | ||
|
|
||
| private: | ||
| Type TokenType; | ||
| SmallString<128> RawBody; | ||
| Accessor Accessor; | ||
| SmallString<128> TokenBody; | ||
| }; | ||
|
|
||
| class ASTNode { | ||
| public: | ||
| enum Type { | ||
| Root, | ||
| Text, | ||
| Partial, | ||
| Variable, | ||
| UnescapeVariable, | ||
| Section, | ||
| InvertSection, | ||
| }; | ||
|
|
||
| ASTNode() : T(Type::Root), LocalContext(nullptr) {}; | ||
|
|
||
| ASTNode(StringRef Body, std::shared_ptr<ASTNode> Parent) | ||
| : T(Type::Text), Body(Body), Parent(Parent), LocalContext(nullptr) {}; | ||
|
|
||
| // Constructor for Section/InvertSection/Variable/UnescapeVariable | ||
| ASTNode(Type T, Accessor Accessor, std::shared_ptr<ASTNode> Parent) | ||
| : T(T), Accessor(Accessor), Parent(Parent), LocalContext(nullptr), | ||
| Children({}) {}; | ||
|
|
||
| void addChild(std::shared_ptr<ASTNode> Child) { | ||
| Children.emplace_back(Child); | ||
| }; | ||
|
|
||
| SmallString<128> getBody() const { return Body; }; | ||
|
|
||
| void setBody(StringRef NewBody) { Body = NewBody; }; | ||
|
|
||
| void setRawBody(StringRef NewBody) { RawBody = NewBody; }; | ||
|
|
||
| std::shared_ptr<ASTNode> getLastChild() const { | ||
| return Children.empty() ? nullptr : Children.back(); | ||
| }; | ||
|
|
||
| SmallString<128> | ||
|
||
| render(llvm::json::Value Data, | ||
| DenseMap<StringRef, std::shared_ptr<ASTNode>> &Partials, | ||
| DenseMap<StringRef, Lambda> &Lambdas, | ||
| DenseMap<StringRef, SectionLambda> &SectionLambdas, | ||
| DenseMap<char, StringRef> &Escapes); | ||
|
|
||
| private: | ||
| llvm::json::Value findContext(); | ||
| Type T; | ||
| SmallString<128> RawBody; | ||
| SmallString<128> Body; | ||
| std::weak_ptr<ASTNode> Parent; | ||
| std::vector<std::shared_ptr<ASTNode>> Children; | ||
PeterChou1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const Accessor Accessor; | ||
| llvm::json::Value LocalContext; | ||
| }; | ||
|
|
||
| // A Template represents the container for the AST and the partials | ||
| // and Lambdas that are registered with it. | ||
| class Template { | ||
| public: | ||
| static Template createTemplate(StringRef TemplateStr); | ||
|
|
||
| SmallString<128> render(llvm::json::Value Data); | ||
|
|
||
| void registerPartial(StringRef Name, StringRef Partial); | ||
|
|
||
| void registerLambda(StringRef Name, Lambda Lambda); | ||
|
|
||
| void registerLambda(StringRef Name, SectionLambda Lambda); | ||
|
|
||
| // By default the Mustache Spec Specifies that HTML special characters | ||
| // should be escaped. This function allows the user to specify which | ||
| // characters should be escaped. | ||
ilovepi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| void registerEscape(DenseMap<char, StringRef> Escapes); | ||
|
|
||
| private: | ||
| Template(std::shared_ptr<ASTNode> Tree) : Tree(Tree){}; | ||
| DenseMap<StringRef, std::shared_ptr<ASTNode>> Partials; | ||
| DenseMap<StringRef, Lambda> Lambdas; | ||
| DenseMap<StringRef, SectionLambda> SectionLambdas; | ||
| DenseMap<char, StringRef> Escapes; | ||
| std::shared_ptr<ASTNode> Tree; | ||
| }; | ||
|
|
||
| } // namespace mustache | ||
| } // end namespace llvm | ||
PeterChou1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #endif // LLVM_SUPPORT_MUSTACHE | ||
PeterChou1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Uh oh!
There was an error while loading. Please reload this page.