From 4179e2b2775ccc97ceb11abd5ca3df18af209528 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 24 Jan 2025 13:48:54 +0100 Subject: [PATCH 1/7] Add custom DisableHtmlWithExceptions extension --- .../DisableHtmlWithExceptionsExtension.cs | 25 +++++++++ .../RestrictedAutolinkInlineParser.cs | 54 +++++++++++++++++++ src/Elastic.Markdown/Myst/MarkdownParser.cs | 25 +++++---- .../Elastic.Markdown.Tests.csproj | 4 ++ .../Inline/RestrictedAutolinkinlineTests.cs | 31 +++++++++++ 5 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs create mode 100644 src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs create mode 100644 tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs diff --git a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs new file mode 100644 index 000000000..58b806858 --- /dev/null +++ b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs @@ -0,0 +1,25 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using Elastic.Markdown.Myst.InlineParsers; +using Markdig; +using Markdig.Parsers; +using Markdig.Parsers.Inlines; + +namespace Elastic.Markdown.Myst.Extensions; + +public static class MarkdownPipelineBuilderExtensions +{ + public static MarkdownPipelineBuilder DisableHtmlWithExceptions(this MarkdownPipelineBuilder pipeline, HashSet exceptions) + { + var parser = pipeline.BlockParsers.Find(); + if (parser != null) + { + pipeline.BlockParsers.Remove(parser); + } + + pipeline.InlineParsers.ReplaceOrAdd(new RestrictedAutolinkInlineParser { AllowedTags = exceptions }); + return pipeline; + } +} diff --git a/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs b/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs new file mode 100644 index 000000000..7e84464b6 --- /dev/null +++ b/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs @@ -0,0 +1,54 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections.ObjectModel; +using Markdig; +using Markdig.Helpers; +using Markdig.Parsers; +using Markdig.Parsers.Inlines; +using Markdig.Syntax; +using Markdig.Syntax.Inlines; + +namespace Elastic.Markdown.Myst.InlineParsers; + +// This class is a copy of the AutolinkInlineParser with the addition of a check for allowed tags +public class RestrictedAutolinkInlineParser : InlineParser +{ + + public RestrictedAutolinkInlineParser() => OpeningCharacters = ['<']; + + public required IReadOnlySet AllowedTags { get; init; } + + public override bool Match(InlineProcessor processor, ref StringSlice slice) + { + var saved = slice; + int line; + int column; + if (LinkHelper.TryParseAutolink(ref slice, out var link, out var isEmail)) + { + processor.Inline = new AutolinkInline(link) + { + IsEmail = isEmail, + Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), + Line = line, + Column = column + }; + } + else + { + slice = saved; + if (!HtmlHelper.TryParseHtmlTag(ref slice, out var htmlTag)) + return false; + if (!AllowedTags.Contains(htmlTag)) + return false; + processor.Inline = new HtmlInline(htmlTag) + { + Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), + Line = line, + Column = column + }; + } + return true; + } +} diff --git a/src/Elastic.Markdown/Myst/MarkdownParser.cs b/src/Elastic.Markdown/Myst/MarkdownParser.cs index 152fb62a4..c8706c7b6 100644 --- a/src/Elastic.Markdown/Myst/MarkdownParser.cs +++ b/src/Elastic.Markdown/Myst/MarkdownParser.cs @@ -9,6 +9,7 @@ using Elastic.Markdown.Myst.CodeBlocks; using Elastic.Markdown.Myst.Comments; using Elastic.Markdown.Myst.Directives; +using Elastic.Markdown.Myst.Extensions; using Elastic.Markdown.Myst.FrontMatter; using Elastic.Markdown.Myst.InlineParsers; using Elastic.Markdown.Myst.Substitution; @@ -26,16 +27,6 @@ public class MarkdownParser( { public IDirectoryInfo SourcePath { get; } = sourcePath; - private BuildContext Context { get; } = context; - - public static MarkdownPipeline MinimalPipeline { get; } = - new MarkdownPipelineBuilder() - .UseYamlFrontMatter() - .UseInlineAnchors() - .UseHeadingsWithSlugs() - .UseDirectives() - .Build(); - public static MarkdownPipeline Pipeline { get; } = new MarkdownPipelineBuilder() .EnableTrackTrivia() @@ -52,7 +43,17 @@ public class MarkdownParser( .UsePipeTables() .UseDirectives() .UseEnhancedCodeBlocks() - .DisableHtml() + .DisableHtmlWithExceptions(["
"]) + .Build(); + + private BuildContext Context { get; } = context; + + public static MarkdownPipeline MinimalPipeline { get; } = + new MarkdownPipelineBuilder() + .UseYamlFrontMatter() + .UseInlineAnchors() + .UseHeadingsWithSlugs() + .UseDirectives() .Build(); public ConfigurationFile Configuration { get; } = configuration; @@ -107,6 +108,4 @@ public MarkdownDocument Parse(string yaml, IFileInfo parent, YamlFrontMatter? ma var markdownDocument = Markdig.Markdown.Parse(yaml, Pipeline, context); return markdownDocument; } - - } diff --git a/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj b/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj index d3b123dc7..700e0e440 100644 --- a/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj +++ b/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj @@ -28,4 +28,8 @@ + + + + diff --git a/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs b/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs new file mode 100644 index 000000000..c321486bb --- /dev/null +++ b/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs @@ -0,0 +1,31 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using FluentAssertions; +using Xunit.Abstractions; + +namespace Elastic.Markdown.Tests.Inline; + +public class AllowBRTagTest(ITestOutputHelper output) + : InlineTest(output, + "Hello,
World!") +{ + [Fact] + public void GeneratesHtml() => + Html.Should().Contain( + "

Hello,
World!

" + ); +} + +public class DisallowSpanTag(ITestOutputHelper output) + : InlineTest(output, + "Hello,World!") +{ + [Fact] + // span tag is rendered as text + public void GeneratesHtml() => + Html.Should().Contain( + "

Hello,<span>World!</span>

" + ); +} From 184f2d2a91f9f52effa5fab787c71365e4dcc55d Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 24 Jan 2025 13:49:33 +0100 Subject: [PATCH 2/7] format --- .../DisableHtmlWithExceptionsExtension.cs | 10 +-- .../RestrictedAutolinkInlineParser.cs | 66 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs index 58b806858..6dd599c02 100644 --- a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs +++ b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs @@ -14,12 +14,12 @@ public static class MarkdownPipelineBuilderExtensions public static MarkdownPipelineBuilder DisableHtmlWithExceptions(this MarkdownPipelineBuilder pipeline, HashSet exceptions) { var parser = pipeline.BlockParsers.Find(); - if (parser != null) - { - pipeline.BlockParsers.Remove(parser); - } + if (parser != null) + { + pipeline.BlockParsers.Remove(parser); + } - pipeline.InlineParsers.ReplaceOrAdd(new RestrictedAutolinkInlineParser { AllowedTags = exceptions }); + pipeline.InlineParsers.ReplaceOrAdd(new RestrictedAutolinkInlineParser { AllowedTags = exceptions }); return pipeline; } } diff --git a/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs b/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs index 7e84464b6..d8f4c9f8e 100644 --- a/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs +++ b/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs @@ -16,39 +16,39 @@ namespace Elastic.Markdown.Myst.InlineParsers; public class RestrictedAutolinkInlineParser : InlineParser { - public RestrictedAutolinkInlineParser() => OpeningCharacters = ['<']; + public RestrictedAutolinkInlineParser() => OpeningCharacters = ['<']; - public required IReadOnlySet AllowedTags { get; init; } + public required IReadOnlySet AllowedTags { get; init; } - public override bool Match(InlineProcessor processor, ref StringSlice slice) - { - var saved = slice; - int line; - int column; - if (LinkHelper.TryParseAutolink(ref slice, out var link, out var isEmail)) - { - processor.Inline = new AutolinkInline(link) - { - IsEmail = isEmail, - Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), - Line = line, - Column = column - }; - } - else - { - slice = saved; - if (!HtmlHelper.TryParseHtmlTag(ref slice, out var htmlTag)) - return false; - if (!AllowedTags.Contains(htmlTag)) - return false; - processor.Inline = new HtmlInline(htmlTag) - { - Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), - Line = line, - Column = column - }; - } - return true; - } + public override bool Match(InlineProcessor processor, ref StringSlice slice) + { + var saved = slice; + int line; + int column; + if (LinkHelper.TryParseAutolink(ref slice, out var link, out var isEmail)) + { + processor.Inline = new AutolinkInline(link) + { + IsEmail = isEmail, + Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), + Line = line, + Column = column + }; + } + else + { + slice = saved; + if (!HtmlHelper.TryParseHtmlTag(ref slice, out var htmlTag)) + return false; + if (!AllowedTags.Contains(htmlTag)) + return false; + processor.Inline = new HtmlInline(htmlTag) + { + Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), + Line = line, + Column = column + }; + } + return true; + } } From 8e082593b4f5b67f79b1c9021033942328997fe4 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 24 Jan 2025 13:52:38 +0100 Subject: [PATCH 3/7] Move property position back --- src/Elastic.Markdown/Myst/MarkdownParser.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Elastic.Markdown/Myst/MarkdownParser.cs b/src/Elastic.Markdown/Myst/MarkdownParser.cs index c8706c7b6..95baf3cac 100644 --- a/src/Elastic.Markdown/Myst/MarkdownParser.cs +++ b/src/Elastic.Markdown/Myst/MarkdownParser.cs @@ -27,6 +27,16 @@ public class MarkdownParser( { public IDirectoryInfo SourcePath { get; } = sourcePath; + private BuildContext Context { get; } = context; + + public static MarkdownPipeline MinimalPipeline { get; } = + new MarkdownPipelineBuilder() + .UseYamlFrontMatter() + .UseInlineAnchors() + .UseHeadingsWithSlugs() + .UseDirectives() + .Build(); + public static MarkdownPipeline Pipeline { get; } = new MarkdownPipelineBuilder() .EnableTrackTrivia() @@ -46,16 +56,6 @@ public class MarkdownParser( .DisableHtmlWithExceptions(["
"]) .Build(); - private BuildContext Context { get; } = context; - - public static MarkdownPipeline MinimalPipeline { get; } = - new MarkdownPipelineBuilder() - .UseYamlFrontMatter() - .UseInlineAnchors() - .UseHeadingsWithSlugs() - .UseDirectives() - .Build(); - public ConfigurationFile Configuration { get; } = configuration; public Task MinimalParseAsync(IFileInfo path, Cancel ctx) From 9e89ea592e7564bd18ecb3e46dd3d1c56b44d06e Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 24 Jan 2025 13:54:38 +0100 Subject: [PATCH 4/7] Add comment --- .../Myst/Extensions/DisableHtmlWithExceptionsExtension.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs index 6dd599c02..7117d4c93 100644 --- a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs +++ b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs @@ -11,6 +11,10 @@ namespace Elastic.Markdown.Myst.Extensions; public static class MarkdownPipelineBuilderExtensions { + // This is a copy of the DisableHtml extension method with the addition of a HashSet of exceptions + // to allow certain HTML tags to be parsed. + // However, as of now it only supports inline HTML tags. + // If you need to support block HTML tags, you will need to add a custom HtmlBlockParser. public static MarkdownPipelineBuilder DisableHtmlWithExceptions(this MarkdownPipelineBuilder pipeline, HashSet exceptions) { var parser = pipeline.BlockParsers.Find(); @@ -18,7 +22,6 @@ public static MarkdownPipelineBuilder DisableHtmlWithExceptions(this MarkdownPip { pipeline.BlockParsers.Remove(parser); } - pipeline.InlineParsers.ReplaceOrAdd(new RestrictedAutolinkInlineParser { AllowedTags = exceptions }); return pipeline; } From 8ce5ba0cb9ed3350bea76735e0e3ec1df413f120 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Fri, 24 Jan 2025 15:18:51 +0100 Subject: [PATCH 5/7] Remove `DisableHtmlWithExceptions` and implement `UseHardBreaks`. The `DisableHtmlWithExceptions` logic was removed and replaced with a simpler `UseHardBreaks` implementation for handling `
` tags. This refactor simplifies the markdown pipeline and improves maintainability while retaining support for hard breaks. --- .../DisableHtmlWithExceptionsExtension.cs | 28 -------- .../Myst/InlineParsers/HardBreakParser.cs | 65 +++++++++++++++++++ .../RestrictedAutolinkInlineParser.cs | 54 --------------- src/Elastic.Markdown/Myst/MarkdownParser.cs | 4 +- .../Inline/RestrictedAutolinkinlineTests.cs | 13 +++- 5 files changed, 79 insertions(+), 85 deletions(-) delete mode 100644 src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs create mode 100644 src/Elastic.Markdown/Myst/InlineParsers/HardBreakParser.cs delete mode 100644 src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs diff --git a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs b/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs deleted file mode 100644 index 7117d4c93..000000000 --- a/src/Elastic.Markdown/Myst/Extensions/DisableHtmlWithExceptionsExtension.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using Elastic.Markdown.Myst.InlineParsers; -using Markdig; -using Markdig.Parsers; -using Markdig.Parsers.Inlines; - -namespace Elastic.Markdown.Myst.Extensions; - -public static class MarkdownPipelineBuilderExtensions -{ - // This is a copy of the DisableHtml extension method with the addition of a HashSet of exceptions - // to allow certain HTML tags to be parsed. - // However, as of now it only supports inline HTML tags. - // If you need to support block HTML tags, you will need to add a custom HtmlBlockParser. - public static MarkdownPipelineBuilder DisableHtmlWithExceptions(this MarkdownPipelineBuilder pipeline, HashSet exceptions) - { - var parser = pipeline.BlockParsers.Find(); - if (parser != null) - { - pipeline.BlockParsers.Remove(parser); - } - pipeline.InlineParsers.ReplaceOrAdd(new RestrictedAutolinkInlineParser { AllowedTags = exceptions }); - return pipeline; - } -} diff --git a/src/Elastic.Markdown/Myst/InlineParsers/HardBreakParser.cs b/src/Elastic.Markdown/Myst/InlineParsers/HardBreakParser.cs new file mode 100644 index 000000000..1ec836ed6 --- /dev/null +++ b/src/Elastic.Markdown/Myst/InlineParsers/HardBreakParser.cs @@ -0,0 +1,65 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using Markdig; +using Markdig.Helpers; +using Markdig.Parsers; +using Markdig.Parsers.Inlines; +using Markdig.Renderers; +using Markdig.Renderers.Html; +using Markdig.Renderers.Html.Inlines; +using Markdig.Syntax.Inlines; + +namespace Elastic.Markdown.Myst.InlineParsers; + +public static class HardBreakBuilderExtensions +{ + public static MarkdownPipelineBuilder UseHardBreaks(this MarkdownPipelineBuilder pipeline) + { + pipeline.Extensions.AddIfNotAlready(); + return pipeline; + } +} + +public class HardBreakBuilderExtension : IMarkdownExtension +{ + public void Setup(MarkdownPipelineBuilder pipeline) => + pipeline.InlineParsers.InsertBefore(new HardBreakParser()); + + public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) => + renderer.ObjectRenderers.InsertAfter(new HardBreakRenderer()); +} + +public class HardBreakParser : InlineParser +{ + public HardBreakParser() => OpeningCharacters = ['<']; + + public override bool Match(InlineProcessor processor, ref StringSlice slice) + { + var span = slice.AsSpan(); + if (!span.StartsWith("'); + // we allow + if (closingStart != 0) + return false; + + processor.Inline = new HardBreak(); + + var sliceEnd = slice.Start + 4; //
+ while (slice.Start != sliceEnd) + slice.SkipChar(); + + return true; + } +} + +public class HardBreak : LeafInline; + +public class HardBreakRenderer : HtmlObjectRenderer +{ + protected override void Write(HtmlRenderer renderer, HardBreak obj) => + renderer.Write("
"); +} diff --git a/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs b/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs deleted file mode 100644 index d8f4c9f8e..000000000 --- a/src/Elastic.Markdown/Myst/InlineParsers/RestrictedAutolinkInlineParser.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using System.Collections.ObjectModel; -using Markdig; -using Markdig.Helpers; -using Markdig.Parsers; -using Markdig.Parsers.Inlines; -using Markdig.Syntax; -using Markdig.Syntax.Inlines; - -namespace Elastic.Markdown.Myst.InlineParsers; - -// This class is a copy of the AutolinkInlineParser with the addition of a check for allowed tags -public class RestrictedAutolinkInlineParser : InlineParser -{ - - public RestrictedAutolinkInlineParser() => OpeningCharacters = ['<']; - - public required IReadOnlySet AllowedTags { get; init; } - - public override bool Match(InlineProcessor processor, ref StringSlice slice) - { - var saved = slice; - int line; - int column; - if (LinkHelper.TryParseAutolink(ref slice, out var link, out var isEmail)) - { - processor.Inline = new AutolinkInline(link) - { - IsEmail = isEmail, - Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), - Line = line, - Column = column - }; - } - else - { - slice = saved; - if (!HtmlHelper.TryParseHtmlTag(ref slice, out var htmlTag)) - return false; - if (!AllowedTags.Contains(htmlTag)) - return false; - processor.Inline = new HtmlInline(htmlTag) - { - Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)), - Line = line, - Column = column - }; - } - return true; - } -} diff --git a/src/Elastic.Markdown/Myst/MarkdownParser.cs b/src/Elastic.Markdown/Myst/MarkdownParser.cs index 95baf3cac..e6ce64f69 100644 --- a/src/Elastic.Markdown/Myst/MarkdownParser.cs +++ b/src/Elastic.Markdown/Myst/MarkdownParser.cs @@ -9,7 +9,6 @@ using Elastic.Markdown.Myst.CodeBlocks; using Elastic.Markdown.Myst.Comments; using Elastic.Markdown.Myst.Directives; -using Elastic.Markdown.Myst.Extensions; using Elastic.Markdown.Myst.FrontMatter; using Elastic.Markdown.Myst.InlineParsers; using Elastic.Markdown.Myst.Substitution; @@ -53,7 +52,8 @@ public class MarkdownParser( .UsePipeTables() .UseDirectives() .UseEnhancedCodeBlocks() - .DisableHtmlWithExceptions(["
"]) + .DisableHtml() + .UseHardBreaks() .Build(); public ConfigurationFile Configuration { get; } = configuration; diff --git a/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs b/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs index c321486bb..1d761c8c0 100644 --- a/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs +++ b/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs @@ -7,7 +7,7 @@ namespace Elastic.Markdown.Tests.Inline; -public class AllowBRTagTest(ITestOutputHelper output) +public class AllowBrTagTest(ITestOutputHelper output) : InlineTest(output, "Hello,
World!") { @@ -18,6 +18,17 @@ public void GeneratesHtml() => ); } +public class BrTagNeedsToBeExact(ITestOutputHelper output) + : InlineTest(output, + "Hello,
World
!") +{ + [Fact] + public void GeneratesHtml() => + Html.Should().Contain( + "

Hello,<br >World<br />!

" + ); +} + public class DisallowSpanTag(ITestOutputHelper output) : InlineTest(output, "Hello,World!") From 10dca0011806e3ea75a38ca99ee0aeb6afda2948 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Fri, 24 Jan 2025 15:23:54 +0100 Subject: [PATCH 6/7] remove folder from Tests csproj --- tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj b/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj index 700e0e440..d3b123dc7 100644 --- a/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj +++ b/tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj @@ -28,8 +28,4 @@ - - - - From 5469d689326efa1c2da2dc376116ade04b0a91e9 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 24 Jan 2025 15:54:06 +0100 Subject: [PATCH 7/7] Rename file --- .../{RestrictedAutolinkinlineTests.cs => HardBreakTests.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/Elastic.Markdown.Tests/Inline/{RestrictedAutolinkinlineTests.cs => HardBreakTests.cs} (100%) diff --git a/tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs b/tests/Elastic.Markdown.Tests/Inline/HardBreakTests.cs similarity index 100% rename from tests/Elastic.Markdown.Tests/Inline/RestrictedAutolinkinlineTests.cs rename to tests/Elastic.Markdown.Tests/Inline/HardBreakTests.cs