Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .husky/commit-msg
100644 → 100755
Empty file.
Empty file modified .husky/pre-commit
100644 → 100755
Empty file.
8 changes: 4 additions & 4 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ the community.
## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available
[here](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
version 2.0,
[available here](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
the [FAQ](https://www.contributor-covenant.org/faq). Translations are available
[here](https://www.contributor-covenant.org/translations).
the [FAQ](https://www.contributor-covenant.org/faq). Translations are
[available here](https://www.contributor-covenant.org/translations).
42 changes: 42 additions & 0 deletions Cutout.Docs/articles/file-templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# File Templates

The templates can also be stored in external files.

To get started, create a '.editorconfig' file in your project.

In this, connect static files to valid methods in your project.

For example, if you have a template called 'my-template.txt',
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
you can connect it to the 'MyTemplate' method.

First, add the template to the project.

```xml
<Project>
<ItemGroup>
<AdditionalFiles Include="my-template.txt" />
</ItemGroup>
</Project>
```

Create the template method.

```c#
using My.Project;

public static partial class Templates
{
[FileTemplate] // required
public static partial void MyTemplate(this StringBuilder sb, string name);
}
```

Then link the 2 together in the '.editorconfig' file.

```editorconfig
[my-template.txt]
template_method = My.Project.Templates.MyTemplate
```

Now you can externalize your templates and set your editor of choice up to
enable syntax highlighting and other features.
2 changes: 2 additions & 0 deletions Cutout.Docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ items:
href: index.md
- name: Getting Started
href: articles/getting-started.md
- name: File Templates
href: articles/file-templates.md
- name: Template
href: articles/template/
- name: Analyser Rules
Expand Down
2 changes: 2 additions & 0 deletions Cutout.Sample/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[SampleTemplate.cs.liquid]
template_method = Cutout.Sample.Examples.Test4
3 changes: 3 additions & 0 deletions Cutout.Sample/Cutout.Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@
ReferenceOutputAssembly="false"
/>
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="SampleTemplate.cs.liquid" />
</ItemGroup>
</Project>
7 changes: 7 additions & 0 deletions Cutout.Sample/Examples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,11 @@ show this text instead
public static partial void Test3(this StringBuilder builder, string parameter);

#endregion

#region ExampleWithExternalFileTemplate

[FileTemplate]
public static partial void Test4(this StringBuilder builder, string parameter);

#endregion
}
10 changes: 10 additions & 0 deletions Cutout.Sample/SampleTemplate.cs.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Some.Test;

// Some example code
public class {{parameter}}
{
public string Hello(string name)
{
return $"Hello {name} from {{parameter}}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
builder.Append(@"Some text before ");
Case2(builder, product);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
builder.Append(@"Some text before ");
Case2(builder, product);
Case2(builder, product, whitespace);
}
}
29 changes: 29 additions & 0 deletions Cutout.Tests/CallStatementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@

private const string CallExample1 = "Some text before {% call Case2(product.Title) %}";

[Template(CallExample1)]

Check warning on line 12 in Cutout.Tests/CallStatementTests.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

The type 'TemplateAttribute' in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs' conflicts with the imported type 'TemplateAttribute' in 'Cutout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs'.
public static partial void Case1(this StringBuilder builder, Product product);

private const string CallExample2 = "The product title is {{ title }}";

[Template(CallExample2)]

Check warning on line 17 in Cutout.Tests/CallStatementTests.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

The type 'TemplateAttribute' in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs' conflicts with the imported type 'TemplateAttribute' in 'Cutout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs'.
public static partial void Case2(this StringBuilder builder, string title);

private const string CallExample3 = """
Expand All @@ -24,7 +24,7 @@
```
""";

[Template(CallExample3)]

Check warning on line 27 in Cutout.Tests/CallStatementTests.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

The type 'TemplateAttribute' in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs' conflicts with the imported type 'TemplateAttribute' in 'Cutout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs'.
public static partial void Case3(this StringBuilder builder, Product product);

private const string CallExample4 = """
Expand All @@ -33,8 +33,17 @@
{{ product.Title.ToLowerInvariant() }}
""";

[Template(CallExample4)]

Check warning on line 36 in Cutout.Tests/CallStatementTests.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

The type 'TemplateAttribute' in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs' conflicts with the imported type 'TemplateAttribute' in 'Cutout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs'.
public static partial void Case4(this StringBuilder builder, Product product);

[Template(

Check warning on line 39 in Cutout.Tests/CallStatementTests.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

The type 'TemplateAttribute' in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs' conflicts with the imported type 'TemplateAttribute' in 'Cutout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in '/home/runner/work/Cutout/Cutout/Cutout.Tests/obj/Debug/net8.0/Cutout/Cutout.TemplateSourceGenerator/TemplateAttribute.g.cs'.
"""
This is an example more than one level of nesting,

{% call Case3(product) %}
"""
)]
public static partial void Case5(this StringBuilder builder, Product product);
}

public sealed class CallStatementTests
Expand Down Expand Up @@ -71,4 +80,24 @@
builder.ToString()
);
}

[Fact(DisplayName = "A nested call statement with leading whitespace can used")]
public void Case3()
{
var builder = new StringBuilder();
builder.Case5(new CallTemplates.Product("Awesome Shoes"));
Assert.Equal(
"""
This is an example more than one level of nesting,

This is an example with a call with leading whitespace,
```
The title in two calls,
Awesome Shoes
awesome shoes
```
""",
builder.ToString()
);
}
}
7 changes: 6 additions & 1 deletion Cutout.Tests/Extensions/GeneratorDriverExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ internal static class Test

internal static SettingsTask IgnoreStandardSupportCode(this SettingsTask settings)
{
return settings.IgnoreGeneratedResult(x => x.HintName is "TemplateAttribute.g.cs");
return settings.IgnoreGeneratedResult(x =>
x.HintName
is "TemplateAttribute.g.cs"
or "FileTemplateAttribute.g.cs"
or "RenderUtilities.g.cs"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
builder.Append(@"This is a test for tags [");
foreach (var tag in product.Tags )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,12 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
builder.Append(@"This is a test for tags [");
foreach (var tag in product.Tags )
{
builder.Append(tag);
if ((tag).ToString().IndexOf('\n') != -1)
{
builder.Append(whitespace);
}
builder.Append(Cutout.RenderUtilities.ApplyExtraWhitespace(tag, whitespace));
builder.Append(@"; ");
}
builder.Append(@"] which is cool.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
builder.Append(@"This is a test for tags [");
while ( i < product.Tags.Length )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,14 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
builder.Append(@"This is a test for tags [");
while ( i < product.Tags.Length )
{
builder.Append(i + 1);
if ((i + 1).ToString().IndexOf('\n') != -1)
{
builder.Append(whitespace);
}
builder.Append(Cutout.RenderUtilities.ApplyExtraWhitespace(i + 1, whitespace));
builder.Append(@". ");
builder.Append( product.Tags[i++] );
if (( product.Tags[i++] ).ToString().IndexOf('\n') != -1)
{
builder.Append(whitespace);
}
builder.Append(Cutout.RenderUtilities.ApplyExtraWhitespace( product.Tags[i++] , whitespace));
}
builder.Append(@"] which is cool.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
builder.Append(@"This is a test for tags [");
for (var i = 0; i < product.Tags.Length; i++ )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
builder.Append(@"This is a test for tags [");
for (var i = 0; i < product.Tags.Length; i++ )
Expand All @@ -23,17 +23,9 @@ internal static void Test(this StringBuilder builder, String product, string whi
{
break;
}
builder.Append(i + 1);
if ((i + 1).ToString().IndexOf('\n') != -1)
{
builder.Append(whitespace);
}
builder.Append(Cutout.RenderUtilities.ApplyExtraWhitespace(i + 1, whitespace));
builder.Append(@". ");
builder.Append( product.Tags[i] );
if (( product.Tags[i] ).ToString().IndexOf('\n') != -1)
{
builder.Append(whitespace);
}
builder.Append(Cutout.RenderUtilities.ApplyExtraWhitespace( product.Tags[i] , whitespace));
}
builder.Append(@"] which is cool.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
if ( product == "Awesome Shoes" )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
if ( product == "Awesome Shoes" )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
if ( product == "Awesome Shoes" )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
if ( product == "Awesome Shoes" )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static partial void Test(this StringBuilder builder, String product)
internal static partial void Test(this StringBuilder builder, string product)
{
if ( product == "Awesome Shoes" )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace <global namespace>;

internal static partial class Test
{
internal static void Test(this StringBuilder builder, String product, string whitespace)
internal static void Test(this StringBuilder builder, string product, string whitespace)
{
if ( product == "Awesome Shoes" )
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//HintName: FileTemplateAttribute.g.cs
#if !CUTOUT_EXCLUDE_ATTRIBUTES

// <auto-generated/>
#nullable enable

namespace Cutout;

/// <summary>
/// Marks a method as a template generator based on an external file, this method will be implemented to write
/// into a string builder like object, based on a template defined in an external file
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
internal sealed class FileTemplateAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="FileTemplateAttribute"/> class
/// </summary>
public FileTemplateAttribute() {}
}

#endif
25 changes: 25 additions & 0 deletions Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//HintName: RenderUtilities.g.cs
// <auto-generated/>
#nullable enable

using System;

namespace Cutout;

/// <summary>
/// Utility methods for use in generated render methods
/// </summary>
internal static class RenderUtilities
{
internal static string? ApplyExtraWhitespace<T>(T value, string whitespace)
{
string? str = value switch
{
null => null,
string str1 => str1,
_ => value.ToString()
};

return str is null ? null : str.Replace("\n", "\n" + whitespace);
}
}
Loading
Loading