Skip to content

Commit

Permalink
Add CSharpToColouredHtml.Core (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
wbaldoumas authored Feb 13, 2024
1 parent 41c4d38 commit b4bb8b6
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 8 deletions.
6 changes: 5 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ dotnet_diagnostic.SA1642.severity = none

# require XML documentation
dotnet_diagnostic.SA1600.severity = none
dotnet_diagnostic.CS1591.severity = none
dotnet_diagnostic.CS1591.severity = none

[*.{csproj,targets,props}]
indent_style = space
indent_size = 2
3 changes: 3 additions & 0 deletions .github/workflows/publish-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
- name: Pack NuGet
run: dotnet pack src/Markdown.ColorCode/Markdown.ColorCode.csproj --no-build --configuration Release /p:Version=${VERSION} --output src

- name: Pack NuGet
run: dotnet pack src/Markdown.ColorCode.CSharpToColoredHtml/Markdown.ColorCode.CSharpToColoredHtml.csproj --no-build --configuration Release /p:Version=${VERSION} --output src

- name: Publish NuGet
run: dotnet nuget push src/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${NUGET_KEY}
env:
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ jobs:
with:
PROJECT_FILE_PATH: src/Markdown.ColorCode/Markdown.ColorCode.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}

- name: Publish NuGet
uses: alirezanet/[email protected]
with:
PROJECT_FILE_PATH: src/Markdown.ColorCode.CSharpToColoredHtml/Markdown.ColorCode.CSharpToColoredHtml.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
3 changes: 2 additions & 1 deletion .markdownlint.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"MD024": {
"siblings_only": true
},
"MD041": false
"MD041": false,
"MD034": false
}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.2.0] - 2024-02-12

### Changed

- Introduced a new `Markdown.ColorCode.CSharpToColoredHtml` package that provides improved syntax highlighting for C# code blocks. See the [README](README.md) for more information.

## [2.1.0] - 2023-11-15

### Changed
Expand Down
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ public interface FooService {
### Package Manager

```text
Install-Package Markdown.ColorCode -Version 2.1.0
Install-Package Markdown.ColorCode -Version 2.2.0
```

### .NET CLI

```text
dotnet add package Markdown.ColorCode --version 2.1.0
dotnet add package Markdown.ColorCode --version 2.2.0
```

## Usage
Expand Down Expand Up @@ -102,6 +102,28 @@ var pipeline = new MarkdownPipelineBuilder()
var colorizedHtml = Markdig.Markdown.ToHtml(someMarkdown, pipeline);
```

### Improved C# Syntax Highlighting

For an improved experience with C# code blocks, consider using the `Markdown.ColorCode.CSharpToColoredHtml` package. This package provides a more robust syntax highlighting experience for C# code blocks by leveraging [CSharpToColouredHtml.Core](https://github.com/Swiftly1/CsharpToColouredHTML).

```cs
var pipeline = new MarkdownPipelineBuilder()
.UseAdvancedExtensions()
.UseColorCodeWithCSharpToColoredHtml(
HtmlFormatterType.Style, // use style-based colorization (default)
myCustomStyleDictionary, // use a custom colorization style dictionary
myHtmlEmitterSettings, // configures CSharpToColouredHtml's HTML emitter
myAdditionalLanguages, // augment the built-in language support
myCustomLanguageId // set a default language ID to fall back to
)
.Build();

var colorizedHtml = Markdig.Markdown.ToHtml(someMarkdown, pipeline);
```

> [!CAUTION]
> The `CsharpToColouredHTML` package introduces dependencies which will not work well with Blazor WebAssembly projects. Either generate the HTML on the server side and send it to the client or use the base `Markdown.ColorCode` package if you are working with Blazor WebAssembly. See https://github.com/dotnet/aspnetcore/issues/27373 and https://github.com/dotnet/aspnetcore/issues/26724 for more details on the problem.
## Roadmap

See the [open issues](https://github.com/wbaldoumas/markdown-colorcode/issues) for a list of proposed features (and known issues).
Expand Down
9 changes: 9 additions & 0 deletions src/Markdown.ColorCode.CSharpToColoredHtml/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
global using ColorCode;
global using ColorCode.Styling;
global using Markdig;
global using CsharpToColouredHTML.Core;
global using Markdown.ColorCode.CSharpToColoredHtml.Internal;
global using Markdown.ColorCode.Internal;
global using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Markdown.ColorCode.CSharpToColoredHtml")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Diagnostics.CodeAnalysis;
using ColorCode.Common;

namespace Markdown.ColorCode.CSharpToColoredHtml.Internal;

/// <inheritdoc cref="IHtmlFormatter"/>
[ExcludeFromCodeCoverage]
internal sealed class CSharpToColoredHtmlFormatter : IHtmlFormatter
{
private readonly IHtmlFormatter _internalFormatter;

private readonly HTMLEmitterSettings _htmlEmitterSettings;

private readonly CsharpColourer _csharpColorer;

/// <summary>
/// Create a new <see cref="CSharpToColoredHtmlFormatter"/>.
/// </summary>
/// <param name="internalFormatter">The internal formatter to use.</param>
/// <param name="htmlEmitterSettings">The HTML emitter settings to use.</param>
public CSharpToColoredHtmlFormatter(IHtmlFormatter internalFormatter, HTMLEmitterSettings htmlEmitterSettings)
{
_internalFormatter = internalFormatter;
_htmlEmitterSettings = htmlEmitterSettings;
_csharpColorer = new CsharpColourer();
}

/// <inheritdoc />
public string? GetHtmlString(string sourceCode, ILanguage language) => language.Id == LanguageId.CSharp
? _csharpColorer.ProcessSourceCode(sourceCode, new HTMLEmitter(_htmlEmitterSettings))
: _internalFormatter.GetHtmlString(sourceCode, language);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Diagnostics.CodeAnalysis;

namespace Markdown.ColorCode.CSharpToColoredHtml.Internal;

/// <inheritdoc cref="IHtmlFormatterFactory"/>
[ExcludeFromCodeCoverage]
internal sealed class HtmlFormatterFactoryWithCSharpToColoredHtml : IHtmlFormatterFactory
{
private readonly StyleDictionary _styleDictionary;

private readonly HTMLEmitterSettings _htmlEmitterSettings;

/// <summary>
/// Create a new <see cref="HtmlFormatterFactoryWithCSharpToColoredHtml"/>.
/// </summary>
/// <param name="styleDictionary">The <see cref="StyleDictionary"/> to use with the returned <see cref="IHtmlFormatter"/>s.</param>
/// <param name="htmlEmitterSettings">The <see cref="HTMLEmitterSettings"/> to use with the returned <see cref="IHtmlFormatter"/>s.</param>
public HtmlFormatterFactoryWithCSharpToColoredHtml(StyleDictionary styleDictionary, HTMLEmitterSettings htmlEmitterSettings)
{
_styleDictionary = styleDictionary;
_htmlEmitterSettings = htmlEmitterSettings;
}

/// <inheritdoc />
public IHtmlFormatter Get(HtmlFormatterType htmlFormatterType) => htmlFormatterType switch
{
HtmlFormatterType.Style => new HtmlStyleFormatter(_styleDictionary),
HtmlFormatterType.Css => new HtmlCssFormatter(_styleDictionary),
HtmlFormatterType.StyleWithCSharpToColoredHtml => new CSharpToColoredHtmlFormatter(new HtmlStyleFormatter(_styleDictionary), _htmlEmitterSettings),
HtmlFormatterType.CssWithCSharpToColoredHtml => new CSharpToColoredHtmlFormatter(new HtmlCssFormatter(_styleDictionary), _htmlEmitterSettings),
_ => throw new ArgumentOutOfRangeException(nameof(htmlFormatterType), htmlFormatterType, null)
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>2.2.0</Version>
<Authors>William Baldoumas</Authors>
<Description>An extension for Markdig that adds syntax highlighting to code through the power of ColorCode, boosted with the CsharpToColouredHTML.Core package.</Description>
<Copyright>Copyright ©2024 William Baldoumas</Copyright>
<PackageProjectUrl>https://wbaldoumas.github.io/markdown-colorcode/index.html</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/wbaldoumas/markdown-colorcode</RepositoryUrl>
<PackageTags>markdig;markdown;html;colorcode;colorize;highlight;renderer</PackageTags>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageIcon>icon.png</PackageIcon>
<PackageId>Markdown.ColorCode.CSharpToColoredHtml</PackageId>
</PropertyGroup>

<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json" Link="stylecop.json" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\assets\images\icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\..\CHANGELOG.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="ColorCode.Core" Version="2.0.15" />
<PackageReference Include="CsharpToColouredHTML.Core" Version="1.0.41" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Markdown.ColorCode\Markdown.ColorCode.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace Markdown.ColorCode.CSharpToColoredHtml;

/// <summary>
/// Extensions for adding ColorCode code colorization to the Markdig <see cref="MarkdownPipelineBuilder"/>.
/// </summary>
public static class MarkdownPipelineBuilderExtensions
{
/// <summary>
/// Use ColorCode + CsharpToColouredHTML.Core to colorize HTML generated from Markdown.
/// </summary>
/// <param name="markdownPipelineBuilder">The <see cref="MarkdownPipelineBuilder"/> to configure.</param>
/// <param name="htmlFormatterType">Optional. The type of HTML formatter to use when generating HTML from Markdown.</param>
/// <param name="htmlEmitterSettings">Optional. The HTML emitter settings to use with CsharpToColouredHtml.Core.</param>
/// <param name="styleDictionary">Optional. The styles to use when generating HTML from Markdown.</param>
/// <param name="additionalLanguages">Optional. Additional languages used to augment the built-in languages provided by ColorCode-Universal.</param>
/// <param name="defaultLanguageId">Optional. The default language to use if a given language can't be found.</param>
/// <returns>The <see cref="MarkdownPipelineBuilder"/> configured with ColorCode.</returns>
public static MarkdownPipelineBuilder UseColorCodeWithCSharpToColoredHtml(
this MarkdownPipelineBuilder markdownPipelineBuilder,
HtmlFormatterType htmlFormatterType = HtmlFormatterType.Style,
HTMLEmitterSettings? htmlEmitterSettings = null,
StyleDictionary? styleDictionary = null,
IEnumerable<ILanguage>? additionalLanguages = null,
string? defaultLanguageId = null)
{
var languageExtractor = new LanguageExtractor(
additionalLanguages ?? Enumerable.Empty<ILanguage>(),
defaultLanguageId ?? string.Empty
);

var codeExtractor = new CodeExtractor();
var htmlFormatterFactory = new HtmlFormatterFactoryWithCSharpToColoredHtml(styleDictionary ?? StyleDictionary.DefaultDark, htmlEmitterSettings ?? new HTMLEmitterSettings());
var htmlFormatter = htmlFormatterFactory.Get(htmlFormatterType);
var colorCodeExtension = new ColorCodeExtension(languageExtractor, codeExtractor, htmlFormatter);

markdownPipelineBuilder.Extensions.Add(colorCodeExtension);

return markdownPipelineBuilder;
}
}
6 changes: 6 additions & 0 deletions src/Markdown.ColorCode.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdown.ColorCode", "Markd
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdown.ColorCode.UnitTests", "..\tests\Markdown.ColorCode.UnitTests\Markdown.ColorCode.UnitTests.csproj", "{C4A4653F-275A-42AC-8425-51D99F843511}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Markdown.ColorCode.CSharpToColoredHtml", "Markdown.ColorCode.CSharpToColoredHtml\Markdown.ColorCode.CSharpToColoredHtml.csproj", "{9EB3A952-F898-43D7-B159-2B3A01BC204F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +23,10 @@ Global
{C4A4653F-275A-42AC-8425-51D99F843511}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4A4653F-275A-42AC-8425-51D99F843511}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4A4653F-275A-42AC-8425-51D99F843511}.Release|Any CPU.Build.0 = Release|Any CPU
{9EB3A952-F898-43D7-B159-2B3A01BC204F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9EB3A952-F898-43D7-B159-2B3A01BC204F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EB3A952-F898-43D7-B159-2B3A01BC204F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EB3A952-F898-43D7-B159-2B3A01BC204F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions src/Markdown.ColorCode/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
global using System.Text;

[assembly: InternalsVisibleTo("Markdown.ColorCode.UnitTests")]
[assembly: InternalsVisibleTo("Markdown.ColorCode.CSharpToColoredHtml")]
12 changes: 11 additions & 1 deletion src/Markdown.ColorCode/HtmlFormatterType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,15 @@ public enum HtmlFormatterType
/// <summary>
/// Use the ColorCode <see cref="HtmlClassFormatter"/> to format the code using CSS classes.
/// </summary>
Css
Css,

/// <summary>
/// Use the ColorCode <see cref="HtmlFormatter"/> to format the code using inline style attributes, boosted with CsharpToColouredHTML.Core. Only usable with Markdown.ColorCode.CSharpToColoredHtml.
/// </summary>
StyleWithCSharpToColoredHtml,

/// <summary>
/// Use the ColorCode <see cref="HtmlClassFormatter"/> to format the code using CSS classes, boosted with CsharpToColouredHTML.Core. Only usable with Markdown.ColorCode.CSharpToColoredHtml.
/// </summary>
CssWithCSharpToColoredHtml
}
7 changes: 6 additions & 1 deletion src/Markdown.ColorCode/Internal/HtmlFormatterFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace Markdown.ColorCode.Internal;
using System.Diagnostics.CodeAnalysis;

namespace Markdown.ColorCode.Internal;

/// <inheritdoc cref="IHtmlFormatterFactory"/>
[ExcludeFromCodeCoverage]
internal sealed class HtmlFormatterFactory : IHtmlFormatterFactory
{
private readonly StyleDictionary _styleDictionary;
Expand All @@ -16,6 +19,8 @@ internal sealed class HtmlFormatterFactory : IHtmlFormatterFactory
{
HtmlFormatterType.Style => new HtmlStyleFormatter(_styleDictionary),
HtmlFormatterType.Css => new HtmlCssFormatter(_styleDictionary),
HtmlFormatterType.StyleWithCSharpToColoredHtml => throw new NotSupportedException("In order to use StyleWithCSharpToColoredHtml you must install Markdown.ColorCode.CSharpToColoredHtml and invoke UseColorCodeWithCSharpToColoredHtml."),
HtmlFormatterType.CssWithCSharpToColoredHtml => throw new NotSupportedException("In order to use CssWithCSharpToColoredHtml you must install Markdown.ColorCode.CSharpToColoredHtml and invoke UseColorCodeWithCSharpToColoredHtml."),
_ => throw new ArgumentOutOfRangeException(nameof(htmlFormatterType), htmlFormatterType, null)
};
}
4 changes: 2 additions & 2 deletions src/Markdown.ColorCode/Markdown.ColorCode.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>2.1.0</Version>
<Version>2.2.0</Version>
<Authors>William Baldoumas</Authors>
<Description>An extension for Markdig that adds syntax highlighting to code through the power of ColorCode.</Description>
<Copyright>Copyright ©2022 William Baldoumas</Copyright>
<Copyright>Copyright ©2024 William Baldoumas</Copyright>
<PackageProjectUrl>https://wbaldoumas.github.io/markdown-colorcode/index.html</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryType>git</RepositoryType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,18 @@ public void TestGetHtmlFormatter_InvalidType_ThrowsArgumentOutOfRangeException()
.Throw<ArgumentOutOfRangeException>()
.And.ParamName.Should().Be("htmlFormatterType");
}

[Test]
[TestCase(HtmlFormatterType.StyleWithCSharpToColoredHtml)]
[TestCase(HtmlFormatterType.CssWithCSharpToColoredHtml)]
public void TestGetHtmlFormatter_UnsupportedType_ThrowsNotSupportedException(HtmlFormatterType unsupportedType)
{
// act
var act = () => _factory.Get(unsupportedType);

// assert
act.Should()
.Throw<NotSupportedException>()
.WithMessage($"In order to use {unsupportedType} you must install Markdown.ColorCode.CSharpToColoredHtml and invoke UseColorCodeWithCSharpToColoredHtml.");
}
}

0 comments on commit b4bb8b6

Please sign in to comment.