예제 #1
0
        private static Inline HandleTilde(Subject subj)
        {
            bool canOpen, canClose;
            var  numdelims = ScanEmphasisDelimeters(subj, '~', out canOpen, out canClose);

            if (numdelims == 1)
            {
                return(new Inline("~", subj.Position - 1, subj.Position));
            }

            if (canClose)
            {
                // walk the stack and find a matching opener, if there is one
                var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Emphasis, '~', out canClose);
                if (istack != null)
                {
                    MatchInlineStack(istack, subj, numdelims, null, null, InlineTag.Strikethrough);

                    // if the closer was not fully used, move back a char or two and try again.
                    if (numdelims > 2)
                    {
                        subj.Position = subj.Position - numdelims + 2;

                        // use recursion only if it will not be very deep.
                        if (numdelims < 10)
                        {
                            return(HandleTilde(subj));
                        }
                    }

                    return(null);
                }
            }

            var inlText = new Inline(subj.Buffer, subj.Position - numdelims, numdelims,
                                     subj.Position - numdelims, subj.Position);

            if (canOpen || canClose)
            {
                var istack = new InlineStack();
                istack.DelimeterCount = numdelims;
                istack.Delimeter      = '~';
                istack.StartingInline = inlText;
                istack.Priority       = InlineStack.InlineStackPriority.Emphasis;
                istack.Flags          = (canOpen ? InlineStack.InlineStackFlags.Opener : 0)
                                        | (canClose ? InlineStack.InlineStackFlags.Closer : 0);

                InlineStack.AppendStackEntry(istack, subj);
            }

            return(inlText);
        }
예제 #2
0
        private static Inline HandleOpenerCloser(Subject subj, InlineTag singleCharTag, InlineTag doubleCharTag)
        {
            bool canOpen, canClose;
            var  c         = subj.Buffer[subj.Position];
            var  numdelims = ScanEmphasisDelimiters(subj, c, out canOpen, out canClose);

            if (canClose)
            {
                // walk the stack and find a matching opener, if there is one
                var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Emphasis, c, numdelims, canOpen, out canClose);
                if (istack != null)
                {
                    var useDelims = MatchInlineStack(istack, subj, numdelims, null, singleCharTag, doubleCharTag);

                    if (useDelims > 0)
                    {
                        // if the closer was not fully used, move back a char or two and try again.
                        if (useDelims < numdelims)
                        {
                            subj.Position = subj.Position - numdelims + useDelims;

                            // use recursion only if it will not be very deep.
                            // however it cannot be used if the single char will not be parsed.
                            if (numdelims < 10)
                            {
                                return(HandleOpenerCloser(subj, singleCharTag, doubleCharTag));
                            }
                        }

                        return(null);
                    }
                }
            }

            var inlText = new Inline(subj.Buffer, subj.Position - numdelims, numdelims, subj.Position - numdelims, subj.Position, c);

            if (canOpen || canClose)
            {
                var istack = new InlineStack();
                istack.DelimiterCount = numdelims;
                istack.Delimiter      = c;
                istack.StartingInline = inlText;
                istack.Priority       = InlineStack.InlineStackPriority.Emphasis;
                istack.Flags          = (canOpen ? InlineStack.InlineStackFlags.Opener : 0)
                                        | (canClose ? (InlineStack.InlineStackFlags.Closer | InlineStack.InlineStackFlags.CloserOriginally) : 0);

                InlineStack.AppendStackEntry(istack, subj);
            }

            return(inlText);
        }
예제 #3
0
        private static Inline HandleRightSquareBracket(Subject subj)
        {
            // move past ']'
            subj.Position++;

            bool canClose;
            var  istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Links, '[', out canClose);

            if (istack != null)
            {
                // if the opener is "inactive" then it means that there was a nested link
                if (istack.DelimeterCount == -1)
                {
                    InlineStack.RemoveStackEntry(istack, subj, istack);
                    return(new Inline("]", subj.Position - 1, subj.Position));
                }

                var endpos = subj.Position;

                // try parsing details for '[foo](/url "title")' or '[foo][bar]'
                var details = ParseLinkDetails(subj);

                // try lookup of the brackets themselves
                if (details == null || details == Reference.SelfReference)
                {
                    var startpos = istack.StartPosition;
                    var label    = new StringPart(subj.Buffer, startpos, endpos - startpos - 1);

                    details = LookupReference(subj.ReferenceMap, label);
                }

                if (details == Reference.InvalidReference)
                {
                    details = null;
                }

                MatchSquareBracketStack(istack, subj, details);
                return(null);
            }

            var inlText = new Inline("]", subj.Position - 1, subj.Position);

            if (canClose)
            {
                // note that the current implementation will not work if there are other inlines with priority
                // higher than Links.
                // to fix this the parsed link details should be added to the closer element in the stack.

                throw new NotSupportedException("It is not supported to have inline stack priority higher than Links.");

                ////istack = new InlineStack();
                ////istack.Delimeter = '[';
                ////istack.StartingInline = inlText;
                ////istack.StartPosition = subj.Position;
                ////istack.Priority = InlineStack.InlineStackPriority.Links;
                ////istack.Flags = InlineStack.InlineStackFlags.Closer;

                ////InlineStack.AppendStackEntry(istack, subj);
            }

            return(inlText);
        }
예제 #4
0
        public static void PostProcessInlineStack(Subject subj, InlineStack first, InlineStack last, InlineStackPriority ignorePriority)
        {
            while (ignorePriority > 0)
            {
                var istack = first;
                while (istack != null)
                {
                    if (istack.Priority >= ignorePriority)
                    {
                        InlineStack.RemoveStackEntry(istack, subj, istack);
                    }
                    else if (0 != (istack.Flags & InlineStackFlags.Closer))
                    {
                        bool canClose;
                        var  iopener = InlineStack.FindMatchingOpener(istack.Previous, istack.Priority, istack.Delimeter, out canClose);
                        if (iopener != null)
                        {
                            bool retry = false;
                            if (iopener.Delimeter == '~')
                            {
                                InlineMethods.MatchInlineStack(iopener, subj, istack.DelimeterCount, istack, null, InlineTag.Strikethrough);
                                if (istack.DelimeterCount > 1)
                                {
                                    retry = true;
                                }
                            }
                            else
                            {
                                var useDelims = InlineMethods.MatchInlineStack(iopener, subj, istack.DelimeterCount, istack, InlineTag.Emphasis, InlineTag.Strong);
                                if (istack.DelimeterCount > 0)
                                {
                                    retry = true;
                                }
                            }

                            if (retry)
                            {
                                // remove everything between opened and closer (not inclusive).
                                if (iopener.Next != istack.Previous)
                                {
                                    InlineStack.RemoveStackEntry(iopener.Next, subj, istack.Previous);
                                }

                                continue;
                            }
                            else
                            {
                                // remove opener, everything in between, and the closer
                                InlineStack.RemoveStackEntry(iopener, subj, istack);
                            }
                        }
                        else if (!canClose)
                        {
                            // this case means that a matching opener does not exist
                            // remove the Closer flag so that a future Opener can be matched against it.
                            istack.Flags &= ~InlineStackFlags.Closer;
                        }
                    }

                    if (istack == last)
                    {
                        break;
                    }

                    istack = istack.Next;
                }

                ignorePriority--;
            }
        }