-
Couldn't load subscription status.
- Fork 1.4k
Implementing Simultaneous Bold and Italic in MarkdownTextBlock #1710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Updating my fork
Update Fork.
Updating fork from Root
|
This is amazing, thank you for submitting this. Most likely will review this after the holidays :) |
|
@avknaidu Wouldn't it be better to convert three (*) symbols into an Italic Run inside of a Bold Run, that way you don't need to create a new rendering function. It should be able to be done, since you can achieve the same effect by using: Which produces: |
|
@WilliamABradley That was my initial thought. But The parser runs based on Markdown.Type and there is no additional property to set this as a flag. Also if i use the same BoldInline parser class, I need to handle Let me know your thoughts. |
|
@avknaidu What I am saying, is that you can add three *s as a BoldItalic Trip Char set, but then when caught, wrap an Italic Run inside of a Bold Run. That way you can still use the RenderBoldRun, and RenderItalicRun methods and achieve the same result, rather than RenderBoldItalicRun which does the same thing. |
|
@WilliamABradley I was looking at what you said but the definition of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can get rid of RenderBoldItalic run if you use this in BoldItalicTextInline.Parse():
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);Then it would be picked up by RenderBoldRun, because it has the type of BoldTextInline, and then it's inner element of italic will be rendered when the content of the Span is rendered.
If you follow how the Static Parse method is used, it can be used properly this way.
| } | ||
|
|
||
| // We found something! | ||
| var result = new BoldItalicTextInline(); |
There was a problem hiding this comment.
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);|
@avknaidu I have tested on my end, and this code works, you can now get rid of the Render methods, and BoldItalicTextInline from the Enum: // ******************************************************************
// 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.Bold)
{
}
/// <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;
}
if (markdown == null || markdown.Length < 6)
{
return null;
}
// Check the start sequence.
string startSequence = markdown.Substring(start, 3);
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 bold = new BoldTextInline
{
Inlines = new List<MarkdownInline>
{
new ItalicTextInline
{
Inlines = Common.ParseInlineChildren(markdown, innerStart, innerEnd)
}
}
};
return new Common.InlineParseResult(bold, 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) + "***";
}
}
} |
|
ping @avknaidu can you implement this? |
|
@WilliamABradley I made the necessary changes. Also I added an example in sample page. All ready for your review. |
| } | ||
|
|
||
| // Check the start sequence. | ||
| string startSequence = markdown.Substring(start, 3); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will still cause an exception if the string is less than 6 chars, you forgot to add that check.
|
This PR is linked to unclosed issues. Please check if one of these issues should be closed: #1221 |

Issue: #1221
PR Type
What kind of change does this PR introduce?
What is the current behavior?
PR Checklist
Please check if your PR fulfills the following requirements:
What is the new behavior?
Does this PR introduce a breaking change?
Other information