Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
167 changes: 167 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# All files
[*]
charset = utf-8
end_of_line = crlf
insert_final_newline = true
trim_trailing_whitespace = true

# Code files
[*.{cs,csx,vb,vbx}]
indent_style = space
indent_size = 4

# XML project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_style = space
indent_size = 2

# XML files
[*.{xml,stylecop,resx,ruleset}]
indent_style = space
indent_size = 2

# JSON files
[*.{json,json5,webmanifest}]
indent_style = space
indent_size = 2

# YAML files
[*.{yml,yaml}]
indent_style = space
indent_size = 2

# Markdown files
[*.md]
trim_trailing_whitespace = false

# Web files
[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
indent_style = space
indent_size = 2

# Bash scripts
[*.sh]
end_of_line = lf

# PowerShell files
[*.{ps1,psm1,psd1}]
indent_style = space
indent_size = 4

# C# code style rules
[*.cs]

# Organize usings
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false

# this. preferences
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion

# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion

# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent

# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_readonly_field = true:suggestion

# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent

# C# preferences
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent

# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = false:suggestion

# Inlined variable declarations
csharp_style_inlined_variable_declaration = true:suggestion

# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion

# C# formatting rules
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true

# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left

# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false

# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true

# Code analysis rules
[*.cs]
# CA1303: Do not pass literals as localized parameters
dotnet_diagnostic.CA1303.severity = none

# CA1062: Validate arguments of public methods
dotnet_diagnostic.CA1062.severity = suggestion

# CA1031: Do not catch general exception types
dotnet_diagnostic.CA1031.severity = suggestion

# CA2007: Consider calling ConfigureAwait on the awaited task
dotnet_diagnostic.CA2007.severity = none
142 changes: 142 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<!--
Use this file to provide workspace-specific custom instructions to Copilot.
For more details, visit https://code.visualstudio.com/docs/copilot/copilot-customization#_use-a-githubcopilotinstructionsmd-file

https://github.com/github/awesome-copilot/blob/main/instructions/csharp.instructions.md

-->

---
description: 'Guidelines for building C# applications'
applyTo: '**/*.cs'
---

# C# Development

## C# Instructions
- Always use the latest version C#, currently C# 13 features.
- Write clear and concise comments for each function.

## General Instructions
- Make only high confidence suggestions when reviewing code changes.
- Write code with good maintainability practices, including comments on why certain design decisions were made.
- Handle edge cases and write clear exception handling.
- For libraries or external dependencies, mention their usage and purpose in comments.

## Naming Conventions

- Follow PascalCase for component names, method names, and public members.
- Use camelCase for private fields and local variables.
- Prefix interface names with "I" (e.g., IUserService).

## Formatting

- Apply code-formatting style defined in `.editorconfig`.
- Prefer file-scoped namespace declarations and single-line using directives.
- Insert a newline before the opening curly brace of any code block (e.g., after `if`, `for`, `while`, `foreach`, `using`, `try`, etc.).
- Ensure that the final return statement of a method is on its own line.
- Use pattern matching and switch expressions wherever possible.
- Use `nameof` instead of string literals when referring to member names.
- Ensure that XML doc comments are created for any public APIs. When applicable, include `<example>` and `<code>` documentation in the comments.

## Project Setup and Structure

- Guide users through creating a new .NET project with the appropriate templates.
- Explain the purpose of each generated file and folder to build understanding of the project structure.
- Demonstrate how to organize code using feature folders or domain-driven design principles.
- Show proper separation of concerns with models, services, and data access layers.
- Explain the Program.cs and configuration system in ASP.NET Core 9 including environment-specific settings.

## Nullable Reference Types

- Declare variables non-nullable, and check for `null` at entry points.
- Always use `is null` or `is not null` instead of `== null` or `!= null`.
- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.

## Data Access Patterns

- Guide the implementation of a data access layer using Entity Framework Core.
- Explain different options (SQL Server, SQLite, In-Memory) for development and production.
- Demonstrate repository pattern implementation and when it's beneficial.
- Show how to implement database migrations and data seeding.
- Explain efficient query patterns to avoid common performance issues.

## Authentication and Authorization

- Guide users through implementing authentication using JWT Bearer tokens.
- Explain OAuth 2.0 and OpenID Connect concepts as they relate to ASP.NET Core.
- Show how to implement role-based and policy-based authorization.
- Demonstrate integration with Microsoft Entra ID (formerly Azure AD).
- Explain how to secure both controller-based and Minimal APIs consistently.

## Validation and Error Handling

- Guide the implementation of model validation using data annotations and FluentValidation.
- Explain the validation pipeline and how to customize validation responses.
- Demonstrate a global exception handling strategy using middleware.
- Show how to create consistent error responses across the API.
- Explain problem details (RFC 7807) implementation for standardized error responses.

## API Versioning and Documentation

- Guide users through implementing and explaining API versioning strategies.
- Demonstrate Swagger/OpenAPI implementation with proper documentation.
- Show how to document endpoints, parameters, responses, and authentication.
- Explain versioning in both controller-based and Minimal APIs.
- Guide users on creating meaningful API documentation that helps consumers.

## Logging and Monitoring

- Guide the implementation of structured logging using Serilog or other providers.
- Explain the logging levels and when to use each.
- Demonstrate integration with Application Insights for telemetry collection.
- Show how to implement custom telemetry and correlation IDs for request tracking.
- Explain how to monitor API performance, errors, and usage patterns.

## Testing

- Always include test cases for critical paths of the application.
- Guide users through creating unit tests.
- Do not emit "Act", "Arrange" or "Assert" comments.
- Copy existing style in nearby files for test method names and capitalization.
- Explain integration testing approaches for API endpoints.
- Demonstrate how to mock dependencies for effective testing.
- Show how to test authentication and authorization logic.
- Explain test-driven development principles as applied to API development.

## Performance Optimization

- Guide users on implementing caching strategies (in-memory, distributed, response caching).
- Explain asynchronous programming patterns and why they matter for API performance.
- Demonstrate pagination, filtering, and sorting for large data sets.
- Show how to implement compression and other performance optimizations.
- Explain how to measure and benchmark API performance.

## Deployment and DevOps

- Guide users through containerizing their API using .NET's built-in container support (`dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer`).
- Explain the differences between manual Dockerfile creation and .NET's container publishing features.
- Explain CI/CD pipelines for NET applications.
- Demonstrate deployment to Azure App Service, Azure Container Apps, or other hosting options.
- Show how to implement health checks and readiness probes.
- Explain environment-specific configurations for different deployment stages.


### Target Framework
- **Target**: .NET 8.0 (`net8.0`)
- **Language Version**: C# 13.0 (latest features enabled)
- **Compatibility**: PowerShell 7.4+
- **Benefits**: Modern performance, latest C# features, advanced optimization

## Development Guidelines

### PowerShell Best Practices
- Use proper PowerShell parameter validation attributes
- Include comprehensive help text for all parameters
- Handle errors gracefully with meaningful error messages
- Support pipeline input where appropriate (`ValueFromPipeline`, `ValueFromPipelineByPropertyName`), alias parameters where applicable to match property names on input objects
- Use `WriteVerbose` for debugging information
- Use `WriteWarning` for non-fatal issues
- Use `WriteError` for proper error handling with `ErrorRecord`
- Support `-WhatIf` and `-Confirm` parameters for cmdlets that modify state
- Use `OutputType` attribute to specify the type of output returned by cmdlets
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ src/obj/*
src/.vs/*
Module/lib
debug.md
output/*
*/obj/*
*/bin/*
4 changes: 2 additions & 2 deletions Module/PSTextMate.format.ps1xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
<TableColumnItems>
<TableColumnItem>
<ScriptBlock>
return 'Line {0}, Index {1}' -f $_.Index[0], ($_.Index[1,2] -join '-')
return 'Line {0}, Index {1}' -f $_.LineIndex, ($_.StartIndex, $_.EndIndex -join '-')
</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
Expand All @@ -82,7 +82,7 @@
<View>
<Name>TextMateDebug</Name>
<ViewSelectedBy>
<TypeName>PwshSpectreConsole.TextMate.Test+TokenDebug</TypeName>
<TypeName>PwshSpectreConsole.TextMate.Core.TokenDebugInfo</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
Expand Down
4 changes: 2 additions & 2 deletions Module/PSTextMate.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
Copyright = '(c) trackd. All rights reserved.'
PowerShellVersion = '7.4'
CompatiblePSEditions = 'Core'
CmdletsToExport = 'Show-TextMate', 'Test-SupportedTextMate', 'Get-SupportedTextMate', 'Debug-TextMate', 'Debug-TextMateTokens'
CmdletsToExport = 'Show-TextMate', 'Test-SupportedTextMate', 'Get-SupportedTextMate', 'Debug-TextMate', 'Debug-TextMateTokens','Debug-SixelSupport','Test-ImageRendering'
AliasesToExport = '*'
RequiredAssemblies = './lib/TextMateSharp.dll', './lib/TextMateSharp.Grammars.dll', './lib/Onigwrap.dll'
RequiredAssemblies = './lib/TextMateSharp.dll', './lib/TextMateSharp.Grammars.dll', './lib/Onigwrap.dll', 'Markdig.Signed.dll'
FormatsToProcess = 'PSTextMate.format.ps1xml'
RequiredModules = @(
@{
Expand Down
24 changes: 17 additions & 7 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
#Requires -Version 7.4
if (-Not $PSScriptRoot) {
return 'Run this script from the root of the project'
}
$ErrorActionPreference = 'Stop'
Push-Location $PSScriptRoot

dotnet clean
dotnet restore

$moduleLibFolder = Join-Path $PSScriptRoot 'Module' 'lib'
$ModuleFilesFolder = Join-Path -Path $PSScriptRoot -ChildPath 'Module'
if (-Not (Test-Path $ModuleFilesFolder)) {
$null = New-Item -ItemType Directory -Path $ModuleFilesFolder -Force
}
Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Output') -File -Recurse | Remove-Item -Force

$moduleLibFolder = Join-Path -Path $PSScriptRoot -ChildPath 'Output' | Join-Path -ChildPath 'lib'
if (-Not (Test-Path $moduleLibFolder)) {
$null = New-Item -ItemType Directory -Path $moduleLibFolder -Force
}

$csproj = Get-Item (Join-Path $PSScriptRoot 'src' 'PSTextMate.csproj')
$outputfolder = Join-Path $PSScriptRoot 'packages'
$csproj = Get-Item (Join-Path -Path $PSScriptRoot -ChildPath 'src' | Join-Path -ChildPath 'PSTextMate.csproj')
$outputfolder = Join-Path -Path $PSScriptRoot -ChildPath 'packages'
if (-Not (Test-Path -Path $outputfolder)) {
$null = New-Item -ItemType Directory -Path $outputfolder -Force
}

dotnet publish $csproj.FullName -c Release -o $outputfolder
Copy-Item -Path $ModuleFilesFolder/* -Destination (Join-Path -Path $PSScriptRoot -ChildPath 'Output') -Force -Recurse -Include '*.psd1', '*.psm1', '*.ps1xml'

Get-ChildItem -Path $moduleLibFolder -File | Remove-Item -Force


Get-ChildItem -Path (Join-Path $outputfolder 'runtimes' 'win-x64' 'native') -Filter *.dll | Move-Item -Destination $moduleLibFolder -Force
Get-ChildItem -Path (Join-Path $outputfolder 'runtimes' 'osx' 'native') -Filter *.dylib | Move-Item -Destination $moduleLibFolder -Force
Get-ChildItem -Path (Join-Path $outputfolder 'runtimes' 'linux-x64' 'native') -Filter *.so | Copy-Item -Destination $moduleLibFolder -Force
Move-Item (Join-Path $outputfolder 'PSTextMate.dll') -Destination (Split-Path $moduleLibFolder) -Force
Get-ChildItem -Path (Join-Path -Path $outputfolder -ChildPath 'runtimes' | Join-Path -ChildPath 'win-x64' | Join-Path -ChildPath 'native') -Filter *.dll | Move-Item -Destination $moduleLibFolder -Force
Get-ChildItem -Path (Join-Path -Path $outputfolder -ChildPath 'runtimes' | Join-Path -ChildPath 'osx' | Join-Path -ChildPath 'native') -Filter *.dylib | Move-Item -Destination $moduleLibFolder -Force
Get-ChildItem -Path (Join-Path -Path $outputfolder -ChildPath 'runtimes' | Join-Path -ChildPath 'linux-x64' | Join-Path -ChildPath 'native') -Filter *.so | Copy-Item -Destination $moduleLibFolder -Force
Move-Item (Join-Path -Path $outputfolder -ChildPath 'PSTextMate.dll') -Destination (Split-Path $moduleLibFolder) -Force
Get-ChildItem -Path $outputfolder -File |
Where-Object { -Not $_.Name.StartsWith('System.Text') -And $_.Extension -notin '.json','.pdb' } |
Move-Item -Destination $moduleLibFolder -Force
Expand Down
Loading
Loading