-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Markdown Conversion: Remove hard dependency on deprecated library and replace with IMarkdownToHtmlConverter abstraction (closes #21238 and #19500)
#21242
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
Merged
AndyButland
merged 5 commits into
main
from
v17/feature/provide-markdown-to-html-converter-abstraction
Jan 6, 2026
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
c93aff5
Add IMarkdownToHtmlConverter abstraction with Markdig and HeyRed impl…
AndyButland 9338e80
Apply suggestions from code review
AndyButland 38e02f6
Apply suggestions from code review
AndyButland 319a691
Merge branch 'main' into v17/feature/provide-markdown-to-html-convert…
AndyButland c74c38d
Apply suggestion from code review.
AndyButland File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| namespace Umbraco.Cms.Core.Strings; | ||
|
|
||
| /// <summary> | ||
| /// Defines a service that converts Markdown-formatted text to HTML. | ||
| /// </summary> | ||
| public interface IMarkdownToHtmlConverter | ||
| { | ||
| /// <summary> | ||
| /// Converts the specified Markdown-formatted text to an HTML-encoded string. | ||
| /// </summary> | ||
| /// <param name="markdown">The input string containing Markdown syntax to be converted.</param> | ||
| /// <returns>A string containing the HTML representation of the input Markdown.</returns> | ||
| public string ToHtml(string markdown); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 13 additions & 3 deletions
16
src/Umbraco.Infrastructure/HealthChecks/MarkdownToHtmlConverter.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/Umbraco.Infrastructure/Strings/HeyRedMarkdownToHtmlConverter.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| using HeyRed.MarkdownSharp; | ||
| using Umbraco.Cms.Core.Strings; | ||
|
|
||
| namespace Umbraco.Cms.Infrastructure.Strings; | ||
|
|
||
| // TODO (V19): Remove this class along with the HeyRed.MarkdownSharp library entirely (remove reference from Directory.props and .csproj, and remove from NOTICES.txt). | ||
|
|
||
| /// <summary> | ||
| /// Implements a service that converts Markdown-formatted text to HTML using the HeyRed.MarkdownSharp library. | ||
| /// </summary> | ||
| [Obsolete("Uses the deprecated HeyRed.MarkdownSharp library which will continue to be provided for the lifetime of Umbraco 17 as the default implementation of IMarkdownToHtmlConverter. The default will be changed to MarkdigMarkdownToHtmlConverter for Umbraco 18. Scheduled for removal along with the HeyRed.MarkdownSharp library in Umbraco 19.")] | ||
| public class HeyRedMarkdownToHtmlConverter : IMarkdownToHtmlConverter | ||
| { | ||
| private static readonly Markdown _markdownConverter = new(); | ||
|
|
||
| /// <inheritdoc/> | ||
| public string ToHtml(string markdown) => _markdownConverter.Transform(markdown); | ||
| } |
15 changes: 15 additions & 0 deletions
15
src/Umbraco.Infrastructure/Strings/MarkdigMarkdownToHtmlConverter.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| using Markdig; | ||
| using Umbraco.Cms.Core.Strings; | ||
|
|
||
| namespace Umbraco.Cms.Infrastructure.Strings; | ||
|
|
||
| /// <summary> | ||
| /// Implements a service that converts Markdown-formatted text to HTML using the Markdig library. | ||
| /// </summary> | ||
| public class MarkdigMarkdownToHtmlConverter : IMarkdownToHtmlConverter | ||
| { | ||
| private static readonly MarkdownPipeline _markdownPipeline = new MarkdownPipelineBuilder().Build(); | ||
|
|
||
| /// <inheritdoc/> | ||
| public string ToHtml(string markdown) => Markdown.ToHtml(markdown, _markdownPipeline); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
...braco.Tests.UnitTests/Umbraco.Infrastructure/HealthChecks/MarkdownToHtmlConverterTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| // Copyright (c) Umbraco. | ||
| // See LICENSE for more details. | ||
|
|
||
| using NUnit.Framework; | ||
| using Umbraco.Cms.Core.HealthChecks; | ||
| using Umbraco.Cms.Infrastructure.HealthChecks; | ||
| using Umbraco.Cms.Infrastructure.Strings; | ||
|
|
||
| namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HealthChecks; | ||
|
|
||
| [TestFixture] | ||
| public class MarkdownToHtmlConverterTests | ||
| { | ||
| [HealthCheck("CFD6FC34-59C9-4402-B55F-C8BC96B628A1", "Stub check")] | ||
| public abstract class StubHealthCheck : HealthCheck | ||
| { | ||
| private readonly string _message; | ||
| private readonly StatusResultType _resultType; | ||
|
|
||
| protected StubHealthCheck(StatusResultType resultType, string message) | ||
| { | ||
| _resultType = resultType; | ||
| _message = message; | ||
| } | ||
|
|
||
| public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public override Task<IEnumerable<HealthCheckStatus>> GetStatusAsync() => | ||
| Task.FromResult<IEnumerable<HealthCheckStatus>>([new(_message) { ResultType = _resultType }]); | ||
| } | ||
|
|
||
| [HealthCheck("CFD6FC34-59C9-4402-B55F-C8BC96B628A1", "Success Check")] | ||
| public class SuccessHealthCheck : StubHealthCheck | ||
| { | ||
| public SuccessHealthCheck() | ||
| : base(StatusResultType.Success, "Check passed") | ||
| { | ||
| } | ||
| } | ||
|
|
||
| [HealthCheck("CFD6FC34-59C9-4402-B55F-C8BC96B628A2", "Warning Check")] | ||
| public class WarningHealthCheck : StubHealthCheck | ||
| { | ||
| public WarningHealthCheck() | ||
| : base(StatusResultType.Warning, "Check has warnings") | ||
| { | ||
| } | ||
| } | ||
|
|
||
| [HealthCheck("CFD6FC34-59C9-4402-B55F-C8BC96B628A3", "Error Check")] | ||
| public class ErrorHealthCheck : StubHealthCheck | ||
| { | ||
| public ErrorHealthCheck() | ||
| : base(StatusResultType.Error, "Check failed") | ||
| { | ||
| } | ||
| } | ||
|
|
||
| #pragma warning disable CS0618 // Type or member is obsolete | ||
| private static MarkdownToHtmlConverter CreateConverter() => | ||
| new(new HeyRedMarkdownToHtmlConverter()); | ||
| #pragma warning restore CS0618 // Type or member is obsolete | ||
|
|
||
| [Test] | ||
| public async Task ToHtml_WithSuccessResult_AppliesGreenHighlighting() | ||
| { | ||
| var checks = new List<HealthCheck> { new SuccessHealthCheck() }; | ||
| var results = await HealthCheckResults.Create(checks); | ||
| var converter = CreateConverter(); | ||
|
|
||
| var html = converter.ToHtml(results, HealthCheckNotificationVerbosity.Summary); | ||
|
|
||
| Assert.That(html, Does.Contain("<span style=\"color: #5cb85c\">Success</span>")); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task ToHtml_WithWarningResult_AppliesOrangeHighlighting() | ||
| { | ||
| var checks = new List<HealthCheck> { new WarningHealthCheck() }; | ||
| var results = await HealthCheckResults.Create(checks); | ||
| var converter = CreateConverter(); | ||
|
|
||
| var html = converter.ToHtml(results, HealthCheckNotificationVerbosity.Summary); | ||
|
|
||
| Assert.That(html, Does.Contain("<span style=\"color: #f0ad4e\">Warning</span>")); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task ToHtml_WithErrorResult_AppliesRedHighlighting() | ||
| { | ||
| var checks = new List<HealthCheck> { new ErrorHealthCheck() }; | ||
| var results = await HealthCheckResults.Create(checks); | ||
| var converter = CreateConverter(); | ||
|
|
||
| var html = converter.ToHtml(results, HealthCheckNotificationVerbosity.Summary); | ||
|
|
||
| Assert.That(html, Does.Contain("<span style=\"color: #d9534f\">Error</span>")); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task ToHtml_WithMixedResults_AppliesCorrectHighlightingForEachStatus() | ||
| { | ||
| var checks = new List<HealthCheck> | ||
| { | ||
| new SuccessHealthCheck(), | ||
| new WarningHealthCheck(), | ||
| new ErrorHealthCheck(), | ||
| }; | ||
| var results = await HealthCheckResults.Create(checks); | ||
| var converter = CreateConverter(); | ||
|
|
||
| var html = converter.ToHtml(results, HealthCheckNotificationVerbosity.Summary); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(html, Does.Contain("<span style=\"color: #5cb85c\">Success</span>"), "Success should have green highlighting"); | ||
| Assert.That(html, Does.Contain("<span style=\"color: #f0ad4e\">Warning</span>"), "Warning should have orange highlighting"); | ||
| Assert.That(html, Does.Contain("<span style=\"color: #d9534f\">Error</span>"), "Error should have red highlighting"); | ||
| }); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task ToHtml_WithDetailedVerbosity_IncludesMessageInOutput() | ||
| { | ||
| var checks = new List<HealthCheck> { new SuccessHealthCheck() }; | ||
| var results = await HealthCheckResults.Create(checks); | ||
| var converter = CreateConverter(); | ||
|
|
||
| var html = converter.ToHtml(results, HealthCheckNotificationVerbosity.Detailed); | ||
|
|
||
| Assert.That(html, Does.Contain("Check passed")); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task ToHtml_WithSummaryVerbosity_DoesNotIncludeSuccessMessageInOutput() | ||
| { | ||
| var checks = new List<HealthCheck> { new SuccessHealthCheck() }; | ||
| var results = await HealthCheckResults.Create(checks); | ||
| var converter = CreateConverter(); | ||
|
|
||
| var html = converter.ToHtml(results, HealthCheckNotificationVerbosity.Summary); | ||
|
|
||
| Assert.That(html, Does.Not.Contain("Check passed")); | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.