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); }
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); }
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); }
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--; } }