Skip to content

Commit 4179e2b

Browse files
committed
Add custom DisableHtmlWithExceptions extension
1 parent 6f7552d commit 4179e2b

File tree

5 files changed

+126
-13
lines changed

5 files changed

+126
-13
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using Elastic.Markdown.Myst.InlineParsers;
6+
using Markdig;
7+
using Markdig.Parsers;
8+
using Markdig.Parsers.Inlines;
9+
10+
namespace Elastic.Markdown.Myst.Extensions;
11+
12+
public static class MarkdownPipelineBuilderExtensions
13+
{
14+
public static MarkdownPipelineBuilder DisableHtmlWithExceptions(this MarkdownPipelineBuilder pipeline, HashSet<string> exceptions)
15+
{
16+
var parser = pipeline.BlockParsers.Find<HtmlBlockParser>();
17+
if (parser != null)
18+
{
19+
pipeline.BlockParsers.Remove(parser);
20+
}
21+
22+
pipeline.InlineParsers.ReplaceOrAdd<AutolinkInlineParser>(new RestrictedAutolinkInlineParser { AllowedTags = exceptions });
23+
return pipeline;
24+
}
25+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Collections.ObjectModel;
6+
using Markdig;
7+
using Markdig.Helpers;
8+
using Markdig.Parsers;
9+
using Markdig.Parsers.Inlines;
10+
using Markdig.Syntax;
11+
using Markdig.Syntax.Inlines;
12+
13+
namespace Elastic.Markdown.Myst.InlineParsers;
14+
15+
// This class is a copy of the AutolinkInlineParser with the addition of a check for allowed tags
16+
public class RestrictedAutolinkInlineParser : InlineParser
17+
{
18+
19+
public RestrictedAutolinkInlineParser() => OpeningCharacters = ['<'];
20+
21+
public required IReadOnlySet<string> AllowedTags { get; init; }
22+
23+
public override bool Match(InlineProcessor processor, ref StringSlice slice)
24+
{
25+
var saved = slice;
26+
int line;
27+
int column;
28+
if (LinkHelper.TryParseAutolink(ref slice, out var link, out var isEmail))
29+
{
30+
processor.Inline = new AutolinkInline(link)
31+
{
32+
IsEmail = isEmail,
33+
Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)),
34+
Line = line,
35+
Column = column
36+
};
37+
}
38+
else
39+
{
40+
slice = saved;
41+
if (!HtmlHelper.TryParseHtmlTag(ref slice, out var htmlTag))
42+
return false;
43+
if (!AllowedTags.Contains(htmlTag))
44+
return false;
45+
processor.Inline = new HtmlInline(htmlTag)
46+
{
47+
Span = new SourceSpan(processor.GetSourcePosition(saved.Start, out line, out column), processor.GetSourcePosition(slice.Start - 1)),
48+
Line = line,
49+
Column = column
50+
};
51+
}
52+
return true;
53+
}
54+
}

src/Elastic.Markdown/Myst/MarkdownParser.cs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Elastic.Markdown.Myst.CodeBlocks;
1010
using Elastic.Markdown.Myst.Comments;
1111
using Elastic.Markdown.Myst.Directives;
12+
using Elastic.Markdown.Myst.Extensions;
1213
using Elastic.Markdown.Myst.FrontMatter;
1314
using Elastic.Markdown.Myst.InlineParsers;
1415
using Elastic.Markdown.Myst.Substitution;
@@ -26,16 +27,6 @@ public class MarkdownParser(
2627
{
2728
public IDirectoryInfo SourcePath { get; } = sourcePath;
2829

29-
private BuildContext Context { get; } = context;
30-
31-
public static MarkdownPipeline MinimalPipeline { get; } =
32-
new MarkdownPipelineBuilder()
33-
.UseYamlFrontMatter()
34-
.UseInlineAnchors()
35-
.UseHeadingsWithSlugs()
36-
.UseDirectives()
37-
.Build();
38-
3930
public static MarkdownPipeline Pipeline { get; } =
4031
new MarkdownPipelineBuilder()
4132
.EnableTrackTrivia()
@@ -52,7 +43,17 @@ public class MarkdownParser(
5243
.UsePipeTables()
5344
.UseDirectives()
5445
.UseEnhancedCodeBlocks()
55-
.DisableHtml()
46+
.DisableHtmlWithExceptions(["<br>"])
47+
.Build();
48+
49+
private BuildContext Context { get; } = context;
50+
51+
public static MarkdownPipeline MinimalPipeline { get; } =
52+
new MarkdownPipelineBuilder()
53+
.UseYamlFrontMatter()
54+
.UseInlineAnchors()
55+
.UseHeadingsWithSlugs()
56+
.UseDirectives()
5657
.Build();
5758

5859
public ConfigurationFile Configuration { get; } = configuration;
@@ -107,6 +108,4 @@ public MarkdownDocument Parse(string yaml, IFileInfo parent, YamlFrontMatter? ma
107108
var markdownDocument = Markdig.Markdown.Parse(yaml, Pipeline, context);
108109
return markdownDocument;
109110
}
110-
111-
112111
}

tests/Elastic.Markdown.Tests/Elastic.Markdown.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,8 @@
2828
<Using Include="Xunit"/>
2929
</ItemGroup>
3030

31+
<ItemGroup>
32+
<Folder Include="Extensions\" />
33+
</ItemGroup>
34+
3135
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using FluentAssertions;
6+
using Xunit.Abstractions;
7+
8+
namespace Elastic.Markdown.Tests.Inline;
9+
10+
public class AllowBRTagTest(ITestOutputHelper output)
11+
: InlineTest(output,
12+
"Hello,<br>World!")
13+
{
14+
[Fact]
15+
public void GeneratesHtml() =>
16+
Html.Should().Contain(
17+
"<p>Hello,<br>World!</p>"
18+
);
19+
}
20+
21+
public class DisallowSpanTag(ITestOutputHelper output)
22+
: InlineTest(output,
23+
"Hello,<span>World!</span>")
24+
{
25+
[Fact]
26+
// span tag is rendered as text
27+
public void GeneratesHtml() =>
28+
Html.Should().Contain(
29+
"<p>Hello,&lt;span&gt;World!&lt;/span&gt;</p>"
30+
);
31+
}

0 commit comments

Comments
 (0)