Skip to content

Conversation

@avknaidu
Copy link
Member

Issue: #1221

PR Type

What kind of change does this PR introduce?

[ ] Bugfix
[x] Feature
[ ] Code style update (formatting)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build or CI related changes
[ ] Documentation content changes
[ ] Sample app changes
[ ] Other... Please describe:

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?

[ ] Yes
[x] No

Other information

@avknaidu avknaidu changed the title Bold italic1163 Implementing Simultaneous Bold and Italic in MarkdownTextBlock Dec 18, 2017
@nmetulev nmetulev self-requested a review December 18, 2017 19:45
@nmetulev
Copy link
Contributor

This is amazing, thank you for submitting this. Most likely will review this after the holidays :)

@WilliamABradley
Copy link
Contributor

@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:

**_Bold Italic text_**

Which produces:
Bold Italic text

@avknaidu
Copy link
Member Author

avknaidu commented Jan 2, 2018

@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 * and _ in 2 different parsing scenario's. _**blah**_ and **_blah_**. Also with this change the parser works both ways. See below.

image

Let me know your thoughts.

@WilliamABradley
Copy link
Contributor

@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.

@avknaidu
Copy link
Member Author

avknaidu commented Jan 4, 2018

@WilliamABradley I was looking at what you said but the definition of RenderBoldRun and RenderItalicRun explicitly looks for for BoldTextInline and ItalicTextInline. I would recommend using a separate method for itself instead of fiddling with current methods. Advise otherwise.

@WilliamABradley WilliamABradley self-requested a review January 17, 2018 00:29
Copy link
Contributor

@WilliamABradley WilliamABradley left a 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();
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);

@WilliamABradley
Copy link
Contributor

@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) + "***";
        }
    }
}

@WilliamABradley
Copy link
Contributor

ping @avknaidu can you implement this?

@avknaidu
Copy link
Member Author

@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);
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.

Copy link
Contributor

@WilliamABradley WilliamABradley left a 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.

@nmetulev nmetulev merged commit 83a7dca into CommunityToolkit:master Jan 30, 2018
@windowstoolkitbot
Copy link

This PR is linked to unclosed issues. Please check if one of these issues should be closed: #1221

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants