Skip to content

Commit 519358d

Browse files
authored
Merge pull request CommunityToolkit#603 from jcoc611-microsoft/user/juosori/ConfigureBuiltInExtensions
MarkdownTextBlock: Enable/Disable built in extensions
2 parents 55af261 + 10cc885 commit 519358d

File tree

4 files changed

+218
-80
lines changed

4 files changed

+218
-80
lines changed

components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
<controls:MarkdownTextBlock x:Name="MarkdownTextBlock2"
4242
Grid.Row="3"
4343
Config="{x:Bind MarkdownConfig, Mode=OneTime}"
44-
Text="{x:Bind Text, Mode=OneTime}" />
44+
Text="{x:Bind Text, Mode=OneTime}"
45+
UseAutoLinks="True"
46+
UseEmphasisExtras="True"
47+
UseListExtras="True"
48+
UsePipeTables="True"
49+
UseTaskLists="True" />
4550
</Grid>
4651
</Page>
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Markdig.Syntax;
6+
7+
namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock;
8+
9+
public partial class MarkdownTextBlock
10+
{
11+
/// <summary>
12+
/// Identifies the <see cref="Config"/> dependency property.
13+
/// </summary>
14+
private static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(
15+
nameof(Config),
16+
typeof(MarkdownConfig),
17+
typeof(MarkdownTextBlock),
18+
new PropertyMetadata(null, OnConfigChanged)
19+
);
20+
21+
/// <summary>
22+
/// Identifies the <see cref="Text"/> dependency property.
23+
/// </summary>
24+
private static readonly DependencyProperty TextProperty = DependencyProperty.Register(
25+
nameof(Text),
26+
typeof(string),
27+
typeof(MarkdownTextBlock),
28+
new PropertyMetadata(null, OnTextChanged));
29+
30+
/// <summary>
31+
/// Identifies the <see cref="UseEmphasisExtras"/> dependency property.
32+
/// </summary>
33+
private static readonly DependencyProperty UseEmphasisExtrasProperty = DependencyProperty.Register(
34+
nameof(UseEmphasisExtras),
35+
typeof(bool),
36+
typeof(MarkdownTextBlock),
37+
new PropertyMetadata(false));
38+
39+
/// <summary>
40+
/// Identifies the <see cref="UsePipeTables"/> dependency property.
41+
/// </summary>
42+
private static readonly DependencyProperty UsePipeTablesProperty = DependencyProperty.Register(
43+
nameof(UsePipeTables),
44+
typeof(bool),
45+
typeof(MarkdownTextBlock),
46+
new PropertyMetadata(false));
47+
48+
/// <summary>
49+
/// Identifies the <see cref="UseListExtras"/> dependency property.
50+
/// </summary>
51+
private static readonly DependencyProperty UseListExtrasProperty = DependencyProperty.Register(
52+
nameof(UseListExtras),
53+
typeof(bool),
54+
typeof(MarkdownTextBlock),
55+
new PropertyMetadata(false));
56+
57+
/// <summary>
58+
/// Identifies the <see cref="UseTaskLists"/> dependency property.
59+
/// </summary>
60+
private static readonly DependencyProperty UseTaskListsProperty = DependencyProperty.Register(
61+
nameof(UseTaskLists),
62+
typeof(bool),
63+
typeof(MarkdownTextBlock),
64+
new PropertyMetadata(false));
65+
66+
/// <summary>
67+
/// Identifies the <see cref="UseAutoLinks"/> dependency property.
68+
/// </summary>
69+
private static readonly DependencyProperty UseAutoLinksProperty = DependencyProperty.Register(
70+
nameof(UseAutoLinks),
71+
typeof(bool),
72+
typeof(MarkdownTextBlock),
73+
new PropertyMetadata(false));
74+
75+
/// <summary>
76+
/// Identifies the <see cref="UseSoftlineBreakAsHardlineBreak"/> dependency property.
77+
/// </summary>
78+
private static readonly DependencyProperty UseSoftlineBreakAsHardlineBreakProperty = DependencyProperty.Register(
79+
nameof(UseSoftlineBreakAsHardlineBreak),
80+
typeof(bool),
81+
typeof(MarkdownTextBlock),
82+
new PropertyMetadata(false));
83+
84+
/// <summary>
85+
/// Identifies the <see cref="MarkdownDocument"/> dependency property.
86+
/// </summary>
87+
private static readonly DependencyProperty MarkdownDocumentProperty = DependencyProperty.Register(
88+
nameof(MarkdownDocument),
89+
typeof(MarkdownDocument),
90+
typeof(MarkdownTextBlock),
91+
new PropertyMetadata(null));
92+
93+
public MarkdownConfig Config
94+
{
95+
get => (MarkdownConfig)GetValue(ConfigProperty);
96+
set => SetValue(ConfigProperty, value);
97+
}
98+
99+
/// <summary>
100+
/// Gets or sets the markdown text to display.
101+
/// </summary>
102+
public string Text
103+
{
104+
get => (string)GetValue(TextProperty);
105+
set => SetValue(TextProperty, value);
106+
}
107+
108+
/// <summary>
109+
/// If true, adds support for strikethroughs, superscript, subscript, inserted, and marked text.
110+
/// </summary>
111+
public bool UseEmphasisExtras
112+
{
113+
get => (bool)GetValue(UseEmphasisExtrasProperty);
114+
set => SetValue(UseEmphasisExtrasProperty, value);
115+
}
116+
117+
/// <summary>
118+
/// If true, adds support for GitHub-style pipe tables.
119+
/// </summary>
120+
public bool UsePipeTables
121+
{
122+
get => (bool)GetValue(UsePipeTablesProperty);
123+
set => SetValue(UsePipeTablesProperty, value);
124+
}
125+
126+
/// <summary>
127+
/// If true, adds support for alphabetic and roman numbering in lists.
128+
/// </summary>
129+
public bool UseListExtras
130+
{
131+
get => (bool)GetValue(UseListExtrasProperty);
132+
set => SetValue(UseListExtrasProperty, value);
133+
}
134+
135+
/// <summary>
136+
/// If true, adds support for GitHub-style task lists using the [ ] and [x] syntax.
137+
/// </summary>
138+
public bool UseTaskLists
139+
{
140+
get => (bool)GetValue(UseTaskListsProperty);
141+
set => SetValue(UseTaskListsProperty, value);
142+
}
143+
144+
/// <summary>
145+
/// If true, parses text that looks like URIs into hyperlinks (e.g. https://...).
146+
/// </summary>
147+
public bool UseAutoLinks
148+
{
149+
get => (bool)GetValue(UseAutoLinksProperty);
150+
set => SetValue(UseAutoLinksProperty, value);
151+
}
152+
153+
/// <summary>
154+
/// If true, considers single newlines as hardline breaks.
155+
/// </summary>
156+
public bool UseSoftlineBreakAsHardlineBreak
157+
{
158+
get => (bool)GetValue(UseSoftlineBreakAsHardlineBreakProperty);
159+
set => SetValue(UseSoftlineBreakAsHardlineBreakProperty, value);
160+
}
161+
162+
/// <summary>
163+
/// Gets the parsed markdown document. May be null if the document has not been parsed yet.
164+
/// </summary>
165+
public MarkdownDocument? MarkdownDocument
166+
{
167+
get => (MarkdownDocument)GetValue(MarkdownDocumentProperty);
168+
private set => SetValue(MarkdownDocumentProperty, value);
169+
}
170+
}

components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
// See the LICENSE file in the project root for more information.
44

55
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers;
6+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers;
7+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers.Extensions;
8+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers.Inlines;
69
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.TextElements;
710
using Markdig;
811
using Markdig.Syntax;
@@ -14,47 +17,10 @@ public partial class MarkdownTextBlock : Control
1417
{
1518
private const string MarkdownContainerName = "MarkdownContainer";
1619
private Grid? _container;
17-
private MarkdownPipeline _pipeline;
20+
private MarkdownPipeline _pipeline = null!;
1821
private MyFlowDocument _document;
1922
private WinUIRenderer? _renderer;
2023

21-
private static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(
22-
nameof(Config),
23-
typeof(MarkdownConfig),
24-
typeof(MarkdownTextBlock),
25-
new PropertyMetadata(null, OnConfigChanged)
26-
);
27-
28-
private static readonly DependencyProperty TextProperty = DependencyProperty.Register(
29-
nameof(Text),
30-
typeof(string),
31-
typeof(MarkdownTextBlock),
32-
new PropertyMetadata(null, OnTextChanged));
33-
34-
private static readonly DependencyProperty MarkdownDocumentProperty = DependencyProperty.Register(
35-
nameof(MarkdownDocument),
36-
typeof(MarkdownDocument),
37-
typeof(MarkdownTextBlock),
38-
new PropertyMetadata(null));
39-
40-
public MarkdownConfig Config
41-
{
42-
get => (MarkdownConfig)GetValue(ConfigProperty);
43-
set => SetValue(ConfigProperty, value);
44-
}
45-
46-
public string Text
47-
{
48-
get => (string)GetValue(TextProperty);
49-
set => SetValue(TextProperty, value);
50-
}
51-
52-
public MarkdownDocument? MarkdownDocument
53-
{
54-
get => (MarkdownDocument)GetValue(MarkdownDocumentProperty);
55-
private set => SetValue(MarkdownDocumentProperty, value);
56-
}
57-
5824
public event EventHandler<LinkClickedEventArgs>? OnLinkClicked;
5925

6026
internal void RaiseLinkClickedEvent(Uri uri) => OnLinkClicked?.Invoke(this, new LinkClickedEventArgs(uri));
@@ -79,17 +45,24 @@ public MarkdownTextBlock()
7945
{
8046
this.DefaultStyleKey = typeof(MarkdownTextBlock);
8147
_document = new MyFlowDocument();
82-
_pipeline = new MarkdownPipelineBuilder()
83-
.UseEmphasisExtras()
84-
.UseAutoLinks()
85-
.UseTaskLists()
86-
.UsePipeTables()
87-
.Build();
8848
}
8949

9050
protected override void OnApplyTemplate()
9151
{
9252
base.OnApplyTemplate();
53+
54+
var pipelineBuilder = new MarkdownPipelineBuilder();
55+
56+
// NOTE: Order matters here
57+
if (UseEmphasisExtras) pipelineBuilder = pipelineBuilder.UseEmphasisExtras();
58+
if (UsePipeTables) pipelineBuilder = pipelineBuilder.UsePipeTables();
59+
if (UseListExtras) pipelineBuilder = pipelineBuilder.UseListExtras();
60+
if (UseTaskLists) pipelineBuilder = pipelineBuilder.UseTaskLists();
61+
if (UseAutoLinks) pipelineBuilder = pipelineBuilder.UseAutoLinks();
62+
if (UseSoftlineBreakAsHardlineBreak) pipelineBuilder = pipelineBuilder.UseSoftlineBreakAsHardlineBreak();
63+
64+
_pipeline = pipelineBuilder.Build();
65+
9366
_container = (Grid)GetTemplateChild(MarkdownContainerName);
9467
_container.Children.Clear();
9568
_container.Children.Add(_document.RichTextBlock);
@@ -128,6 +101,31 @@ private void Build()
128101
if (_renderer == null)
129102
{
130103
_renderer = new WinUIRenderer(_document, Config, this);
104+
105+
// Default block renderers
106+
_renderer.ObjectRenderers.Add(new CodeBlockRenderer());
107+
_renderer.ObjectRenderers.Add(new ListRenderer());
108+
_renderer.ObjectRenderers.Add(new HeadingRenderer());
109+
_renderer.ObjectRenderers.Add(new ParagraphRenderer());
110+
_renderer.ObjectRenderers.Add(new QuoteBlockRenderer());
111+
_renderer.ObjectRenderers.Add(new ThematicBreakRenderer());
112+
_renderer.ObjectRenderers.Add(new HtmlBlockRenderer());
113+
114+
// Default inline renderers
115+
if (UseAutoLinks) _renderer.ObjectRenderers.Add(new AutoLinkInlineRenderer());
116+
_renderer.ObjectRenderers.Add(new CodeInlineRenderer());
117+
_renderer.ObjectRenderers.Add(new DelimiterInlineRenderer());
118+
_renderer.ObjectRenderers.Add(new EmphasisInlineRenderer());
119+
_renderer.ObjectRenderers.Add(new HtmlEntityInlineRenderer());
120+
_renderer.ObjectRenderers.Add(new LineBreakInlineRenderer());
121+
_renderer.ObjectRenderers.Add(new LinkInlineRenderer());
122+
_renderer.ObjectRenderers.Add(new LiteralInlineRenderer());
123+
_renderer.ObjectRenderers.Add(new ContainerInlineRenderer());
124+
125+
// Extension renderers
126+
if (UsePipeTables) _renderer.ObjectRenderers.Add(new TableRenderer());
127+
if (UseTaskLists) _renderer.ObjectRenderers.Add(new TaskListRenderer());
128+
_renderer.ObjectRenderers.Add(new HtmlInlineRenderer());
131129
}
132130
_pipeline.Setup(_renderer);
133131
ApplyText(false);

components/MarkdownTextBlock/src/Renderers/WinUIRenderer.cs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ public WinUIRenderer(MyFlowDocument document, MarkdownConfig config, MarkdownTex
3333
FlowDocument = document;
3434
// set style
3535
_stack.Push(FlowDocument);
36-
LoadOverridenRenderers();
37-
}
38-
39-
private void LoadOverridenRenderers()
40-
{
41-
LoadRenderers();
4236
}
4337

4438
public override object Render(MarkdownObject markdownObject)
@@ -52,7 +46,6 @@ public void ReloadDocument()
5246
_stack.Clear();
5347
FlowDocument.RichTextBlock.Blocks.Clear();
5448
_stack.Push(FlowDocument);
55-
LoadOverridenRenderers();
5649
}
5750

5851
public void WriteLeafInline(LeafBlock leafBlock)
@@ -145,32 +138,4 @@ private static void AddInline(IAddChild parent, IAddChild inline)
145138
{
146139
parent.AddChild(inline);
147140
}
148-
149-
protected virtual void LoadRenderers()
150-
{
151-
// Default block renderers
152-
ObjectRenderers.Add(new CodeBlockRenderer());
153-
ObjectRenderers.Add(new ListRenderer());
154-
ObjectRenderers.Add(new HeadingRenderer());
155-
ObjectRenderers.Add(new ParagraphRenderer());
156-
ObjectRenderers.Add(new QuoteBlockRenderer());
157-
ObjectRenderers.Add(new ThematicBreakRenderer());
158-
ObjectRenderers.Add(new HtmlBlockRenderer());
159-
160-
// Default inline renderers
161-
ObjectRenderers.Add(new AutoLinkInlineRenderer());
162-
ObjectRenderers.Add(new CodeInlineRenderer());
163-
ObjectRenderers.Add(new DelimiterInlineRenderer());
164-
ObjectRenderers.Add(new EmphasisInlineRenderer());
165-
ObjectRenderers.Add(new HtmlEntityInlineRenderer());
166-
ObjectRenderers.Add(new LineBreakInlineRenderer());
167-
ObjectRenderers.Add(new LinkInlineRenderer());
168-
ObjectRenderers.Add(new LiteralInlineRenderer());
169-
ObjectRenderers.Add(new ContainerInlineRenderer());
170-
171-
// Extension renderers
172-
ObjectRenderers.Add(new TableRenderer());
173-
ObjectRenderers.Add(new TaskListRenderer());
174-
ObjectRenderers.Add(new HtmlInlineRenderer());
175-
}
176141
}

0 commit comments

Comments
 (0)