Skip to content

Commit 5b91ace

Browse files
jcoc611-microsoftJuan Osorio
andauthored
MarkdownTextBlock: Rewrite lists to be text-based (#684)
* MarkdownTextBlock: Rewrite lists to be text-based * Remove unnecessary properties --------- Co-authored-by: Juan Osorio <juosori@microsoft.com>
1 parent 1f6cda0 commit 5b91ace

8 files changed

Lines changed: 136 additions & 144 deletions

File tree

components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ private void Build()
106106

107107
// Default block renderers
108108
_renderer.ObjectRenderers.Add(new CodeBlockRenderer());
109-
_renderer.ObjectRenderers.Add(new ListRenderer());
109+
_renderer.ObjectRenderers.Add(new ListRenderer());
110+
_renderer.ObjectRenderers.Add(new ListItemRenderer());
110111
_renderer.ObjectRenderers.Add(new HeadingRenderer());
111112
_renderer.ObjectRenderers.Add(new ParagraphRenderer());
112113
_renderer.ObjectRenderers.Add(new QuoteBlockRenderer());
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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.Renderers.ObjectRenderers;
8+
9+
internal class ListItemRenderer : UWPObjectRenderer<ListItemBlock>
10+
{
11+
protected override void Write(WinUIRenderer renderer, ListItemBlock listItem)
12+
{
13+
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
14+
if (listItem == null) throw new ArgumentNullException(nameof(listItem));
15+
16+
renderer.WriteChildren(listItem);
17+
}
18+
}

components/MarkdownTextBlock/src/Renderers/ObjectRenderers/ListRenderer.cs

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,73 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using Markdig.Syntax;
5+
using System.Globalization;
66
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.TextElements;
7+
using Markdig.Syntax;
8+
using RomanNumerals;
79

810
namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers;
911

1012
internal class ListRenderer : UWPObjectRenderer<ListBlock>
1113
{
14+
public const string UnorderedListDot = "• ";
15+
1216
protected override void Write(WinUIRenderer renderer, ListBlock listBlock)
1317
{
14-
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
15-
if (listBlock == null) throw new ArgumentNullException(nameof(listBlock));
16-
17-
var list = new MyList(listBlock);
18+
int index = 1;
19+
bool isOrdered = false;
20+
BulletType bulletType = BulletType.Circle;
21+
if (listBlock.IsOrdered)
22+
{
23+
isOrdered = true;
24+
bulletType = ToOrderedBulletType(listBlock.BulletType);
1825

19-
renderer.Push(list);
26+
if (listBlock.OrderedStart != null && listBlock.DefaultOrderedStart != listBlock.OrderedStart)
27+
{
28+
int.TryParse(listBlock.OrderedStart, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out index);
29+
}
30+
}
2031

21-
foreach (var item in listBlock)
32+
foreach (var listItem in listBlock)
2233
{
23-
var listItemBlock = (ListItemBlock)item;
24-
var listItem = new MyBlockContainer(listItemBlock);
25-
renderer.Push(listItem);
26-
renderer.WriteChildren(listItemBlock);
27-
renderer.Pop();
34+
renderer.PushListBullet(GetBulletString(isOrdered, bulletType, index));
35+
renderer.Write(listItem);
36+
renderer.PopListBullet();
37+
index++;
2838
}
39+
}
40+
41+
internal static BulletType ToOrderedBulletType(char bullet)
42+
{
43+
return bullet switch
44+
{
45+
'1' => BulletType.Number,
46+
'a' => BulletType.LowerAlpha,
47+
'A' => BulletType.UpperAlpha,
48+
'i' => BulletType.LowerRoman,
49+
'I' => BulletType.UpperRoman,
50+
_ => BulletType.Number,
51+
};
52+
}
2953

30-
renderer.Pop();
54+
private static string GetBulletString(bool isOrdered, BulletType bulletType, int index)
55+
{
56+
if (isOrdered)
57+
{
58+
return bulletType switch
59+
{
60+
BulletType.Number => $"{index}. ",
61+
BulletType.LowerAlpha => $"{index.ToAlphabetical()}. ",
62+
BulletType.UpperAlpha => $"{index.ToAlphabetical().ToUpper(CultureInfo.CurrentCulture)}. ",
63+
BulletType.LowerRoman => $"{index.ToRomanNumerals().ToLower(CultureInfo.CurrentCulture)} ",
64+
BulletType.UpperRoman => $"{index.ToRomanNumerals().ToUpper(CultureInfo.CurrentCulture)} ",
65+
BulletType.Circle => UnorderedListDot,
66+
_ => $"{index}. "
67+
};
68+
}
69+
else
70+
{
71+
return UnorderedListDot;
72+
}
3173
}
3274
}

components/MarkdownTextBlock/src/Renderers/ObjectRenderers/ParagraphRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protected override void Write(WinUIRenderer renderer, ParagraphBlock obj)
1414
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
1515
if (obj == null) throw new ArgumentNullException(nameof(obj));
1616

17-
var paragraph = new MyParagraph(obj);
17+
var paragraph = new MyParagraph(obj, renderer);
1818
// set style
1919
renderer.Push(paragraph);
2020
renderer.WriteLeafInline(obj);

components/MarkdownTextBlock/src/Renderers/WinUIRenderer.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public class WinUIRenderer : RendererBase
1717
private readonly Stack<IAddChild> _stack = new Stack<IAddChild>();
1818
private char[] _buffer;
1919
private MarkdownConfig _config = MarkdownConfig.Default;
20+
private readonly Stack<string> _listBullets = new();
21+
2022
public MyFlowDocument FlowDocument { get; private set; }
2123
public MarkdownConfig Config
2224
{
@@ -134,6 +136,29 @@ public void WriteText(string? text, int offset, int length)
134136
}
135137
}
136138

139+
public void PushListBullet(string bullet)
140+
{
141+
_listBullets.Push(bullet);
142+
}
143+
144+
public string PeekListBullet()
145+
{
146+
return _listBullets.Count > 0 ? _listBullets.Peek() : string.Empty;
147+
}
148+
149+
public int GetListBulletCount()
150+
{
151+
return _listBullets.Count;
152+
}
153+
154+
public void PopListBullet()
155+
{
156+
if (_listBullets.Count > 0)
157+
{
158+
_listBullets.Pop();
159+
}
160+
}
161+
137162
private static void AddInline(IAddChild parent, IAddChild inline)
138163
{
139164
parent.AddChild(inline);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock.TextElements;
6+
7+
internal enum BulletType
8+
{
9+
Circle,
10+
Number,
11+
LowerAlpha,
12+
UpperAlpha,
13+
LowerRoman,
14+
UpperRoman
15+
}

components/MarkdownTextBlock/src/TextElements/MyList.cs

Lines changed: 0 additions & 128 deletions
This file was deleted.

components/MarkdownTextBlock/src/TextElements/MyParagraph.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers;
56
using Markdig.Syntax;
67

78
namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock.TextElements;
89

910
internal class MyParagraph : IAddChild
1011
{
12+
private readonly WinUIRenderer _renderer;
1113
private ParagraphBlock _paragraphBlock;
1214
private Paragraph _paragraph;
1315

@@ -16,10 +18,27 @@ public TextElement TextElement
1618
get => _paragraph;
1719
}
1820

19-
public MyParagraph(ParagraphBlock paragraphBlock)
21+
public MyParagraph(ParagraphBlock paragraphBlock, WinUIRenderer renderer)
2022
{
2123
_paragraphBlock = paragraphBlock;
2224
_paragraph = new Paragraph();
25+
_renderer = renderer;
26+
27+
// Lists are plain Paragraph_s, one per item.
28+
// This is so that you can select across list items.
29+
Thickness margin = new Thickness(0, 8, 0, 8); // renderer.Config.Themes.BlockMargin;
30+
int bulletCount = renderer.GetListBulletCount();
31+
margin.Left += 30 * bulletCount;
32+
_paragraph.Margin = margin;
33+
34+
if (bulletCount != 0)
35+
{
36+
string bullet = renderer.PeekListBullet();
37+
Run bulletRun = new Run { Text = bullet + "\t" };
38+
39+
_paragraph.Inlines.Add(bulletRun);
40+
_paragraph.TextIndent = -30;
41+
}
2342
}
2443

2544
public void AddChild(IAddChild child)

0 commit comments

Comments
 (0)