diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..5cd79ab --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "husky": { + "version": "0.7.2", + "commands": [ + "husky" + ] + }, + "csharpier": { + "version": "1.0.3", + "commands": [ + "csharpier" + ] + } + } +} \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..8babb0b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @bmazzarol \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..654ba62 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '…' +2. Click on '…' +3. Scroll down to '…' +4. See error. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..5f43738 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when (...) + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml new file mode 100644 index 0000000..85c55d5 --- /dev/null +++ b/.github/workflows/build-deploy-docs.yml @@ -0,0 +1,17 @@ +name: Build and Deploy Docs + +on: + push: + branches: [main] + +jobs: + build-and-deploy-docs: + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + steps: + - uses: bmazzarol/bmazzarol/.github/actions/build-deploy-docs@main + with: + docsProjectPath: Cutout.Docs + csProjFileName: Cutout.Docs.csproj diff --git a/.github/workflows/cd-build.yml b/.github/workflows/cd-build.yml new file mode 100644 index 0000000..7ae2866 --- /dev/null +++ b/.github/workflows/cd-build.yml @@ -0,0 +1,23 @@ +name: CD Build + +on: + workflow_dispatch: + inputs: + version: + description: Release Version + required: true + release: + types: [published] + +env: + PACKAGE_VERSION: ${{ github.event.inputs.version || github.event.release.tag_name }} + +jobs: + publish: + name: Publish to Nuget + runs-on: ubuntu-latest + steps: + - uses: bmazzarol/bmazzarol/.github/actions/cd-build@main + with: + version: ${{ env.PACKAGE_VERSION }} + nugetKey: ${{ secrets.NUGET_API_KEY }} diff --git a/.github/workflows/check-code-format.yml b/.github/workflows/check-code-format.yml new file mode 100644 index 0000000..89f0122 --- /dev/null +++ b/.github/workflows/check-code-format.yml @@ -0,0 +1,12 @@ +name: Check C# Formatting + +on: + pull_request: + branches: [main] + +jobs: + check_formatting: + runs-on: ubuntu-latest + name: Check C# Formatting + steps: + - uses: bmazzarol/bmazzarol/.github/actions/check-code-format@main diff --git a/.github/workflows/check-commit-message.yml b/.github/workflows/check-commit-message.yml new file mode 100644 index 0000000..6250ed2 --- /dev/null +++ b/.github/workflows/check-commit-message.yml @@ -0,0 +1,12 @@ +name: Check Commit Message + +on: + pull_request: + branches: [main] + +jobs: + commitlint: + if: ${{ github.actor != 'dependabot[bot]' }} + runs-on: ubuntu-latest + steps: + - uses: bmazzarol/bmazzarol/.github/actions/check-commit-message@main diff --git a/.github/workflows/check-docs.yml b/.github/workflows/check-docs.yml new file mode 100644 index 0000000..47a10d8 --- /dev/null +++ b/.github/workflows/check-docs.yml @@ -0,0 +1,14 @@ +name: Check the Docfx site + +on: + pull_request: + branches: [main] + +jobs: + check-docs: + runs-on: ubuntu-latest + steps: + - uses: bmazzarol/bmazzarol/.github/actions/check-docs@main + with: + docsProjectPath: Cutout.Docs + csProjFileName: Cutout.Docs.csproj diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml new file mode 100644 index 0000000..4379dd8 --- /dev/null +++ b/.github/workflows/check-markdown.yml @@ -0,0 +1,21 @@ +name: Check Markdown + +on: + push: + branches: [main] + paths: + - "**/*.md" + - .github/workflows/check-markdown.yml + pull_request: + branches: [main] + +jobs: + lint: + runs-on: ubuntu-latest + permissions: + statuses: write + steps: + - uses: bmazzarol/bmazzarol/.github/actions/check-markdown@main + with: + targetMdFiles: | + "Cutout*/**/*.md" "Cutout.Docs/**/*.md" "*.md" "!LICENSE.md" \ No newline at end of file diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml new file mode 100644 index 0000000..a436f4c --- /dev/null +++ b/.github/workflows/ci-build.yml @@ -0,0 +1,22 @@ +name: CI Build + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + if: ${{ github.actor != 'dependabot[bot]' }} + name: Build and analyze + runs-on: ubuntu-latest + permissions: + checks: write + pull-requests: write + steps: + - uses: bmazzarol/bmazzarol/.github/actions/ci-build@main + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} + sonarToken: ${{ secrets.SONAR_TOKEN }} + sonarProjectKey: bmazzarol_Cutout \ No newline at end of file diff --git a/.github/workflows/test-reporter.yml b/.github/workflows/test-reporter.yml new file mode 100644 index 0000000..0aed7fb --- /dev/null +++ b/.github/workflows/test-reporter.yml @@ -0,0 +1,18 @@ +name: Test Reporter + +on: + workflow_run: + workflows: [CI Build] + types: [completed] + +jobs: + report: + runs-on: ubuntu-latest + steps: + - uses: dorny/test-reporter@v1 + with: + artifact: test-results + name: Test Results + path: | + **/*.trx + reporter: dotnet-trx diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..fd2e998 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,22 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +## husky task runner examples ------------------- +## Note : for local installation use 'dotnet' prefix. e.g. 'dotnet husky' + +## run all tasks +#husky run + +### run all tasks with group: 'group-name' +#husky run --group group-name + +## run task with name: 'task-name' +#husky run --name task-name + +## pass hook arguments to task +#husky run --args "$1" "$2" + +## or put your custom commands ------------------- +#echo 'Husky.Net is awesome!' + +npx --no -- commitlint --edit ${1} diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..fd85d23 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,22 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +## husky task runner examples ------------------- +## Note : for local installation use 'dotnet' prefix. e.g. 'dotnet husky' + +## run all tasks +#husky run + +### run all tasks with group: 'group-name' +#husky run --group group-name + +## run task with name: 'task-name' +#husky run --name task-name + +## pass hook arguments to task +#husky run --args "$1" "$2" + +## or put your custom commands ------------------- +#echo 'Husky.Net is awesome!' + +dotnet husky run diff --git a/.husky/task-runner.json b/.husky/task-runner.json new file mode 100644 index 0000000..ed079de --- /dev/null +++ b/.husky/task-runner.json @@ -0,0 +1,39 @@ +{ + "tasks": [ + { + "name": "Format C# Code", + "command": "dotnet", + "args": [ + "csharpier", + "format", + "." + ] + }, + { + "name": "Lint Markdown", + "command": "npx", + "args": [ + "markdownlint-cli2", + "Cutout*/**/*.md", + "Cutout.Docs/**/*.md", + "*.md", + "!LICENSE.md" + ] + }, + { + "name": "Test C# Code", + "command": "dotnet", + "args": [ + "test" + ] + }, + { + "name": "Lint Docs", + "command": "dotnet", + "args": [ + "build", + "Cutout.Docs/Cutout.Docs.csproj" + ] + } + ] +} diff --git a/Cutout.Docs/.config/dotnet-tools.json b/Cutout.Docs/.config/dotnet-tools.json new file mode 100644 index 0000000..6e7d362 --- /dev/null +++ b/Cutout.Docs/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "docfx": { + "version": "2.78.2", + "commands": [ + "docfx" + ] + } + } +} \ No newline at end of file diff --git a/Cutout.Docs/.gitignore b/Cutout.Docs/.gitignore new file mode 100644 index 0000000..9ebe008 --- /dev/null +++ b/Cutout.Docs/.gitignore @@ -0,0 +1,3 @@ +_site +api +doctests \ No newline at end of file diff --git a/Cutout.Docs/Cutout.Docs.csproj b/Cutout.Docs/Cutout.Docs.csproj new file mode 100644 index 0000000..445083c --- /dev/null +++ b/Cutout.Docs/Cutout.Docs.csproj @@ -0,0 +1,3 @@ + + + diff --git a/Cutout.Docs/articles/getting-started.md b/Cutout.Docs/articles/getting-started.md new file mode 100644 index 0000000..d1ea31e --- /dev/null +++ b/Cutout.Docs/articles/getting-started.md @@ -0,0 +1,25 @@ +# Getting Started + +To use this library, simply include `Cutout.dll` in your project or grab +it from [NuGet](https://www.nuget.org/packages/Cutout/), and add a reference to it. + +```xml + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + +``` + +Then use the `Cutout.Template` attribute to define a template method. + +[!code-csharp[](../../Cutout.Sample/Examples.cs#ParameterExample)] + +The first parameter is the `StringBuilder`-like type to write to. Everything +else passed can be used in the template. + +The template must be a compile-time constant string, so it can be defined +as a `const` field or inline in the attribute. + +[!code-csharp[](../../Cutout.Sample/Examples.cs#ExampleWithConditionAndConstTemplate)] diff --git a/Cutout.Docs/articles/rules/CUTOUT001.md b/Cutout.Docs/articles/rules/CUTOUT001.md new file mode 100644 index 0000000..3751111 --- /dev/null +++ b/Cutout.Docs/articles/rules/CUTOUT001.md @@ -0,0 +1,9 @@ +# CUTOUT001 - Invalid Template + +The template used is not valid in some way. This could be due to a syntax +error, or it could be that the template is not compatible with the Cutout +version of the liquid language. + +The error will indicate the line number and position where the parser +encountered the issue. The user should review the template string and +resolve the problem. diff --git a/Cutout.Docs/articles/rules/toc.yml b/Cutout.Docs/articles/rules/toc.yml new file mode 100644 index 0000000..a6bb6c5 --- /dev/null +++ b/Cutout.Docs/articles/rules/toc.yml @@ -0,0 +1,3 @@ +items: + - name: (CUTOUT001) Invalid Template + href: CUTOUT001.md diff --git a/Cutout.Docs/articles/template/break.md b/Cutout.Docs/articles/template/break.md new file mode 100644 index 0000000..8eaa20e --- /dev/null +++ b/Cutout.Docs/articles/template/break.md @@ -0,0 +1,21 @@ +# Break Statement + +The `break` statement can be used inside loops to exit the loop early, +just like in C#. + +## Syntax + +```c# +{% break %} +``` + +## Example + +```c# +{% for i = 0; i < 10; i++ %} + {% if i == 5 %} + {% break %} + {% end %} + Value: {{ i }} +{% end %} +``` diff --git a/Cutout.Docs/articles/template/call.md b/Cutout.Docs/articles/template/call.md new file mode 100644 index 0000000..3c37b96 --- /dev/null +++ b/Cutout.Docs/articles/template/call.md @@ -0,0 +1,16 @@ +# Call Statement + +The `call` statement allows you to invoke other template methods decorated +with `[Cutout.Template]`. + +## Syntax + +```c# +{% call MethodName(arg1, arg2) %} +``` + +## Example + +```c# +{% call RenderHeader("Title") %} +``` diff --git a/Cutout.Docs/articles/template/continue.md b/Cutout.Docs/articles/template/continue.md new file mode 100644 index 0000000..6e8819f --- /dev/null +++ b/Cutout.Docs/articles/template/continue.md @@ -0,0 +1,21 @@ +# Continue Statement + +The `continue` statement can be used inside loops to skip to the next iteration +, just like in C#. + +## Syntax + +```c# +{% continue %} +``` + +## Example + +```c# +{% for i = 0; i < 10; i++ %} + {% if i % 2 == 0 %} + {% continue %} + {% end %} + Odd: {{ i }} +{% end %} +``` diff --git a/Cutout.Docs/articles/template/for.md b/Cutout.Docs/articles/template/for.md new file mode 100644 index 0000000..c126822 --- /dev/null +++ b/Cutout.Docs/articles/template/for.md @@ -0,0 +1,19 @@ +# For Statement + +The `for` statement allows you to write C#-style for loops in your template. + +## Syntax + +```c# +{% for i = 0; i < items.Count; i++ %} + ... +{% end %} +``` + +## Example + +```c# +{% for i = 0; i < items.Count; i++ %} +Item: {{ items[i] }} +{% end %} +``` diff --git a/Cutout.Docs/articles/template/foreach.md b/Cutout.Docs/articles/template/foreach.md new file mode 100644 index 0000000..46fbb26 --- /dev/null +++ b/Cutout.Docs/articles/template/foreach.md @@ -0,0 +1,20 @@ +# Foreach Statement + +The `foreach` statement allows you to iterate over collections in your template +using C# syntax. + +## Syntax + +```c# +{% foreach item in items %} + ... +{% end %} +``` + +## Example + +```c# +{% foreach item in items %} +Item: {{ item }} +{% end %} +``` diff --git a/Cutout.Docs/articles/template/if.md b/Cutout.Docs/articles/template/if.md new file mode 100644 index 0000000..1469369 --- /dev/null +++ b/Cutout.Docs/articles/template/if.md @@ -0,0 +1,26 @@ +# If/Else Statement + +The `if` statement allows conditional rendering in templates. +The condition must be a valid C# boolean expression. + +## Syntax + +```c# +{% if condition %} + ... +{% elseif otherCondition %} + ... +{% else %} + ... +{% end %} +``` + +## Example + +```c# +{% if name == "Bob" %} +Hello Bob +{% else %} +Hello {{ name }} +{% end %} +``` diff --git a/Cutout.Docs/articles/template/return.md b/Cutout.Docs/articles/template/return.md new file mode 100644 index 0000000..a052110 --- /dev/null +++ b/Cutout.Docs/articles/template/return.md @@ -0,0 +1,19 @@ +# Return Statement + +The `return` statement can be used to exit from a template method early, +similar to C#. + +## Syntax + +```c# +{% return %} +``` + +## Example + +```c# +{% if shouldExit %} + {% return %} +{% end %} +Continue rendering... +``` diff --git a/Cutout.Docs/articles/template/syntax.md b/Cutout.Docs/articles/template/syntax.md new file mode 100644 index 0000000..ff9b3ee --- /dev/null +++ b/Cutout.Docs/articles/template/syntax.md @@ -0,0 +1,61 @@ +# Template Definition + +Cutout templates use a syntax inspired +by [Liquid](https://shopify.github.io/liquid/), but support C# expressions +instead of the custom language that Liquid uses. This allows you to write +templates that are both powerful and easy to read, while leveraging the full +capabilities of C#. + +## Syntax Overview + +* **Literals:** Any text outside of `{{ ... }}` or `{% ... %}` is treated as a + string literal and written directly to the output. +* **Expressions:** Use `{{ ... }}` to insert the value of any valid C# + expression. +* **Blocks:** Use `{% ... %}` for control flow (e.g., if, for, foreach, while) + and function calls. +* **Whitespace Control:** Whitespace can be managed using the `-` character, + similar to Liquid. For example, `{%- ... -%}` trims whitespace around the + block. + +### Example + +```csharp +private const string Template = """ + {% if name == "Bob" %} + Hello Bob + {% else %} + Hello {{ name }} + {% end %} + """; + +[Cutout.Template(Template)] +public static partial void MyTemplateMethod(StringBuilder sb, string name); +``` + +## Whitespace Handling + +Cutout supports whitespace control similar to +[Liquid's whitespace basics](https://shopify.github.io/liquid/basics/whitespace/) +: + +* `{% ... %}`: Preserves whitespace around the block. +* `{%- ... %}`: Trims whitespace before the block. +* `{% ... -%}`: Trims whitespace after the block. +* `{%- ... -%}`: Trims whitespace both before and after the block. +* The same applies to output tags: `{{ ... }}`, `{{- ... }}`, `{{ ... -}}`, + `{{- ... -}}`. + +This allows for fine-grained control over the formatting of generated code, +making it easier to maintain correct indentation and spacing. + +## Deviations from Liquid Standard + +| Feature | Cutout Implementation | Liquid Standard | +|--------------------|-------------------------------------------------|---------------------------------------------------| +| End Block | Single `{% end %}` for all blocks | Specific `{% endif %}`, `{% endfor %}` etc. | +| Expressions | Must be valid C# expressions | Liquid expressions | +| Function Calls | `{% call Function(args) %}` | Not supported in Liquid | +| Loop Syntax | C# style (`for`, `foreach`, `while`) | Liquid style (`for ... in ...`) | +| Whitespace Control | Same as Liquid (`-` modifier) | Liquid whitespace control | +| Conditionals | Only one conditional statement (`if`) supported | Multiple conditional types (`if`, `unless`, etc.) | diff --git a/Cutout.Docs/articles/template/toc.yml b/Cutout.Docs/articles/template/toc.yml new file mode 100644 index 0000000..052e332 --- /dev/null +++ b/Cutout.Docs/articles/template/toc.yml @@ -0,0 +1,21 @@ +items: + - name: Syntax + href: syntax.md + - name: If/Else + href: if.md + - name: For + href: for.md + - name: Foreach + href: foreach.md + - name: While + href: while.md + - name: Call + href: call.md + - name: Var + href: var.md + - name: Continue + href: continue.md + - name: Break + href: break.md + - name: Return + href: return.md diff --git a/Cutout.Docs/articles/template/var.md b/Cutout.Docs/articles/template/var.md new file mode 100644 index 0000000..59c45f1 --- /dev/null +++ b/Cutout.Docs/articles/template/var.md @@ -0,0 +1,17 @@ +# Var Statement + +The `var` statement allows you to declare variables within your template +using C# syntax. + +## Syntax + +```c# +{% var x = 10 %} +``` + +## Example + +```c# +{% var greeting = "Hello" %} +{{ greeting }} +``` diff --git a/Cutout.Docs/articles/template/while.md b/Cutout.Docs/articles/template/while.md new file mode 100644 index 0000000..bbb868f --- /dev/null +++ b/Cutout.Docs/articles/template/while.md @@ -0,0 +1,19 @@ +# While Statement + +The `while` statement allows you to write C#-style while loops in your template. + +## Syntax + +```c# +{% while condition %} + ... +{% end %} +``` + +## Example + +```c# +{% while i < 10 %} +Value: {{ i }} +{% end %} +``` diff --git a/Cutout.Docs/docfx.json b/Cutout.Docs/docfx.json new file mode 100644 index 0000000..e89aae7 --- /dev/null +++ b/Cutout.Docs/docfx.json @@ -0,0 +1,37 @@ +{ + "metadata": [], + "build": { + "content": [ + { + "files": [ + "articles/**.md", + "articles/**.yml", + "toc.yml", + "*.md" + ] + } + ], + "resource": [ + { + "files": [ + "images/**" + ] + } + ], + "postProcessors": [ + "ExtractSearchIndex" + ], + "template": [ + "default", + "modern", + "template" + ], + "output": "_site", + "globalMetadata": { + "_appName": "Cutout", + "_appLogoPath": "images/scissors-icon.png", + "_appFaviconPath": "images/favicon.ico", + "_appFooter": "Created By Ben Mazzarol" + } + } +} \ No newline at end of file diff --git a/Cutout.Docs/images/favicon.ico b/Cutout.Docs/images/favicon.ico new file mode 100644 index 0000000..c4097a9 Binary files /dev/null and b/Cutout.Docs/images/favicon.ico differ diff --git a/Cutout.Docs/images/scissors-icon.png b/Cutout.Docs/images/scissors-icon.png new file mode 100644 index 0000000..5c546e5 Binary files /dev/null and b/Cutout.Docs/images/scissors-icon.png differ diff --git a/Cutout.Docs/index.md b/Cutout.Docs/index.md new file mode 100644 index 0000000..44406ac --- /dev/null +++ b/Cutout.Docs/index.md @@ -0,0 +1,40 @@ + +
+ +Cutout + +# Cutout + +--- + +[![Nuget](https://img.shields.io/nuget/v/Cutout)](https://www.nuget.org/packages/Cutout/) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=bmazzarol_Cutout&metric=coverage)](https://sonarcloud.io/summary/new_code?id=bmazzarol_Cutout) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=bmazzarol_Cutout&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=bmazzarol_Cutout) +[![CD Build](https://github.com/bmazzarol/Cutout/actions/workflows/cd-build.yml/badge.svg)](https://github.com/bmazzarol/Cutout/actions/workflows/cd-build.yml) +[![Check Markdown](https://github.com/bmazzarol/Cutout/actions/workflows/check-markdown.yml/badge.svg)](https://github.com/bmazzarol/Cutout/actions/workflows/check-markdown.yml) + +Zero cost :muscle: source generated templating for .NET + +--- + +
+ +## Why? + +When building source generators there is a requirement to generate source code +as a string that has indentation managed correctly. The code also needs to be +as fast as possible to not impact users in large repositories. + +The recommended approach is to use +the [IndentedTextWriter](https://learn.microsoft.com/en-us/dotnet/api/system.codedom.compiler.indentedtextwriter?view=net-9.0) +. This class is simple to use, but is low level. + +A standard template engine is a better approach from a code maintenance +perspective, but the performance is not as good. + +This aims to provide the best of both worlds. + +It's a source generator, so can be used in other source generators without +incurring a dependency on a template engine, and it lets you use a simplified +version of [liquid](https://shopify.github.io/liquid/) and any type that +implements the basic StringBuilder API. diff --git a/Cutout.Docs/template/public/main.css b/Cutout.Docs/template/public/main.css new file mode 100644 index 0000000..4228cef --- /dev/null +++ b/Cutout.Docs/template/public/main.css @@ -0,0 +1,18 @@ +#logo { + margin-right: 1em; + height: 2.5em; +} + +.navbar { + background-color: var(--bs-border-color); +} + +body > footer { + background-color: var(--bs-tertiary-bg); + height: auto; + padding: 0.5em; +} + +body > footer.border-top { + border-top-color: var(--bs-tertiary-bg); +} diff --git a/Cutout.Docs/template/public/main.js b/Cutout.Docs/template/public/main.js new file mode 100644 index 0000000..0c99bf7 --- /dev/null +++ b/Cutout.Docs/template/public/main.js @@ -0,0 +1,9 @@ +export default { + iconLinks: [ + { + icon: 'github', + href: 'https://github.com/bmazzarol/Cutout', + title: 'GitHub' + } + ] +} \ No newline at end of file diff --git a/Cutout.Docs/toc.yml b/Cutout.Docs/toc.yml new file mode 100644 index 0000000..045380b --- /dev/null +++ b/Cutout.Docs/toc.yml @@ -0,0 +1,9 @@ +items: + - name: About + href: index.md + - name: Getting Started + href: articles/getting-started.md + - name: Template + href: articles/template/ + - name: Analyser Rules + href: articles/rules/ diff --git a/Cutout.Sample/Examples.cs b/Cutout.Sample/Examples.cs index deff70e..d62b7eb 100644 --- a/Cutout.Sample/Examples.cs +++ b/Cutout.Sample/Examples.cs @@ -6,4 +6,30 @@ public static partial class Examples { [Template("This is a very simple example")] public static partial void Test(this StringBuilder builder); + + #region ParameterExample + + [Template("This is a very simple example with a {{parameter}} parameter")] + public static partial void Test2(this StringBuilder builder, string parameter); + + #endregion + + #region ExampleWithConditionAndConstTemplate + + private const string TemplateExample = """ + A multi-line template example + with a {{parameter}} parameter. + + It also has a conditional section, + {%- if parameter == "INVALID" -%} + show this text + {%- else -%} + show this text instead + {%- end -%} + """; + + [Template(TemplateExample)] + public static partial void Test3(this StringBuilder builder, string parameter); + + #endregion } diff --git a/Cutout.sln b/Cutout.sln index 1db3910..4f05841 100644 --- a/Cutout.sln +++ b/Cutout.sln @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cutout.Sample", "Cutout.Sam EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cutout.Tests", "Cutout.Tests\Cutout.Tests.csproj", "{EA3D7126-C006-47DE-AF88-AEC0F5FD485E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cutout.Docs", "Cutout.Docs\Cutout.Docs.csproj", "{8D842E29-21B3-4D8A-9EA5-581795C0132A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +26,9 @@ Global {EA3D7126-C006-47DE-AF88-AEC0F5FD485E}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA3D7126-C006-47DE-AF88-AEC0F5FD485E}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA3D7126-C006-47DE-AF88-AEC0F5FD485E}.Release|Any CPU.Build.0 = Release|Any CPU + {8D842E29-21B3-4D8A-9EA5-581795C0132A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D842E29-21B3-4D8A-9EA5-581795C0132A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D842E29-21B3-4D8A-9EA5-581795C0132A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D842E29-21B3-4D8A-9EA5-581795C0132A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Cutout/README.md b/Cutout/README.md index 3b7209f..90bacbc 100644 --- a/Cutout/README.md +++ b/Cutout/README.md @@ -51,7 +51,7 @@ public static partial class MyTemplate ## Template Language -Everything that is not between `{{` or `{@` and `}}` or `%}` is treated as a +Everything that is not between `{{` or `{@` and `}}` or `%}` is treated as a string literal. Any valid C# expression can be used in the template as it is compiled to C# diff --git a/README.md b/README.md index dd09a14..433e719 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ public static partial class MyTemplate ## Template Language -Everything that is not between `{{` or `{@` and `}}` or `%}` is treated as a +Everything that is not between `{{` or `{@` and `}}` or `%}` is treated as a string literal. Any valid C# expression can be used in the template as it is compiled to C# diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..de8425d --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,15 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + "subject-case": [0, 'never'], + "subject-max-length": [2, "always", 100], + "scope-enum": _ => [ + 2, + "always", + [ + "deps", + "docs" + ] + ] + } +}