Skip to content
This repository was archived by the owner on Feb 25, 2026. It is now read-only.
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,9 @@ private void RenderInline(InlineCollection inlineCollection, MarkdownInline elem
case MarkdownInlineType.Bold:
RenderBoldRun(inlineCollection, (BoldTextInline)element, context);
break;
case MarkdownInlineType.BoldItalic:
RenderBoldItalicRun(inlineCollection, (BoldItalicTextInline)element, context);
break;
case MarkdownInlineType.MarkdownLink:
RenderMarkdownLink(inlineCollection, (MarkdownLinkInline)element, parent, context);
break;
Expand Down Expand Up @@ -1027,6 +1030,28 @@ private void RenderItalicRun(InlineCollection inlineCollection, ItalicTextInline
inlineCollection.Add(italicSpan);
}

/// <summary>
/// Renders a text run element.
/// </summary>
/// <param name="inlineCollection"> The list to add to. </param>
/// <param name="element"> The parsed inline element to render. </param>
/// <param name="context"> Persistent state. </param>
private void RenderBoldItalicRun(InlineCollection inlineCollection, BoldItalicTextInline element, RenderContext context)
{
// Create the text run
Span bolditalicSpan = new Span
{
FontWeight = FontWeights.Bold,
FontStyle = FontStyle.Italic
};

// Render the children into the italic inline.
RenderInlineChildren(bolditalicSpan.Inlines, element.Inlines, bolditalicSpan, context);

// Add it to the current inlines
inlineCollection.Add(bolditalicSpan);
}

/// <summary>
/// Renders a strikethrough element.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ internal enum InlineParseMethod
/// </summary>
Italic,

/// <summary>
/// An bold and italic block
/// </summary>
BoldItalic,

/// <summary>
/// A link block
/// </summary>
Expand Down Expand Up @@ -106,6 +111,7 @@ internal class InlineTripCharHelper

static Common()
{
BoldItalicTextInline.AddTripChars(_triggerList);
BoldTextInline.AddTripChars(_triggerList);
ItalicTextInline.AddTripChars(_triggerList);
MarkdownLinkInline.AddTripChars(_triggerList);
Expand Down Expand Up @@ -219,6 +225,9 @@ private static InlineParseResult FindNextInlineElement(string markdown, int star
InlineParseResult parseResult = null;
switch (currentTripChar.Method)
{
case InlineParseMethod.BoldItalic:
parseResult = BoldItalicTextInline.Parse(markdown, pos, end);
break;
case InlineParseMethod.Bold:
parseResult = BoldTextInline.Parse(markdown, pos, end);
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System.Collections.Generic;
using Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Helpers;

namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Parse
{
/// <summary>
/// Represents a span containing bold italic text.
/// </summary>
internal class BoldItalicTextInline : MarkdownInline, IInlineContainer
{
/// <summary>
/// Initializes a new instance of the <see cref="BoldItalicTextInline"/> class.
/// </summary>
public BoldItalicTextInline()
: base(MarkdownInlineType.BoldItalic)
{
}

/// <summary>
/// Gets or sets the contents of the inline.
/// </summary>
public IList<MarkdownInline> Inlines { get; set; }

/// <summary>
/// Returns the chars that if found means we might have a match.
/// </summary>
internal static void AddTripChars(List<Common.InlineTripCharHelper> tripCharHelpers)
{
tripCharHelpers.Add(new Common.InlineTripCharHelper() { FirstChar = '*', Method = Common.InlineParseMethod.BoldItalic });
tripCharHelpers.Add(new Common.InlineTripCharHelper() { FirstChar = '_', Method = Common.InlineParseMethod.BoldItalic });
}

/// <summary>
/// Attempts to parse a bold text span.
/// </summary>
/// <param name="markdown"> The markdown text. </param>
/// <param name="start"> The location to start parsing. </param>
/// <param name="maxEnd"> The location to stop parsing. </param>
/// <returns> A parsed bold text span, or <c>null</c> if this is not a bold text span. </returns>
internal static Common.InlineParseResult Parse(string markdown, int start, int maxEnd)
{
if (start >= maxEnd - 1)
{
return null;
}

// Check the start sequence.
string startSequence = markdown.Substring(start, 3);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes an Exception when at the start of the document, and writing asterisks. Ensure markdown is at least length 6.

if (startSequence != "***" && startSequence != "___")
{
return null;
}

// Find the end of the span. The end sequence (either '***' or '___') must be the same
// as the start sequence.
var innerStart = start + 3;
int innerEnd = Common.IndexOf(markdown, startSequence, innerStart, maxEnd);
if (innerEnd == -1)
{
return null;
}

// The span must contain at least one character.
if (innerStart == innerEnd)
{
return null;
}

// The first character inside the span must NOT be a space.
if (Common.IsWhiteSpace(markdown[innerStart]))
{
return null;
}

// The last character inside the span must NOT be a space.
if (Common.IsWhiteSpace(markdown[innerEnd - 1]))
{
return null;
}

// We found something!
var result = new BoldItalicTextInline();
Copy link
Contributor

@WilliamABradley WilliamABradley Jan 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should instead be:

var bold = new BoldTextInline();
var italic = new ItalicTextInline();
bold.Inlines.Add(italic);
italic.Inlines = Common.ParseInlineChildren(markdown, innerStart, innerEnd);
return new Common.InlineParseResult(bold, start, innerEnd + 3);

result.Inlines = Common.ParseInlineChildren(markdown, innerStart, innerEnd);
return new Common.InlineParseResult(result, start, innerEnd + 3);
}

/// <summary>
/// Converts the object into it's textual representation.
/// </summary>
/// <returns> The textual representation of this object. </returns>
public override string ToString()
{
if (Inlines == null)
{
return base.ToString();
}

return "***" + string.Join(string.Empty, Inlines) + "***";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ internal enum MarkdownInlineType
/// </summary>
MarkdownLink,

/// <summary>
/// An bold and italic block
/// </summary>
BoldItalic,

/// <summary>
/// A raw hyper link
/// </summary>
Expand Down