/// <summary> /// Attempts to parse a list item marker (bullet or enumerated). /// On success, returns length of the marker, and populates /// data with the details. On failure, returns 0. /// </summary> /// <remarks>Original: int parse_list_marker(string ln, int pos, ref ListData dataptr)</remarks> private static int ParseListMarker(string ln, int pos, bool interruptsParagraph, out ListData data) { char c; int startpos; data = null; var len = ln.Length; startpos = pos; c = ln[pos]; if (c == '+' || c == '•' || ((c == '*' || c == '-') && 0 == Scanner.scan_thematic_break(ln, pos, len))) { pos++; if (pos == len || !Utilities.IsWhitespace(ln[pos])) { return(0); } if (interruptsParagraph && Scanner.scan_spacechars(ln, pos + 1, ln.Length) == ln.Length - pos - 1) { return(0); } data = new ListData(); data.BulletChar = c; data.Start = 1; } else if (c >= '0' && c <= '9') { int start = c - '0'; while (pos < len - 1) { c = ln[++pos]; // We limit to 9 digits to avoid overflow, This also seems to be the limit for 'start' in some browsers. if (c >= '0' && c <= '9' && start < 100000000) { start = start * 10 + (c - '0'); } else { break; } } if (pos >= len - 1 || (c != '.' && c != ')')) { return(0); } pos++; if (pos == len || !Utilities.IsWhitespace(ln[pos])) { return(0); } if (interruptsParagraph && (start != 1 || Scanner.scan_spacechars(ln, pos + 1, ln.Length) == ln.Length - pos - 1)) { return(0); } data = new ListData(); data.ListType = ListType.Ordered; data.BulletChar = '\0'; data.Start = start; data.Delimiter = (c == '.' ? ListDelimiter.Period : ListDelimiter.Parenthesis); } else { return(0); } return(pos - startpos); }
// Parse a link or the link portion of an image, or return a fallback. static Reference ParseLinkDetails(Subject subj) { int n; int sps; int endlabel, starturl, endurl, starttitle, endtitle, endall; string url, title; endlabel = subj.Position; var c = peek_char(subj); if (c == '(' && ((sps = Scanner.scan_spacechars(subj.Buffer, subj.Position + 1, subj.Length)) > -1) && ((n = Scanner.scan_link_url(subj.Buffer, subj.Position + 1 + sps, subj.Length)) > -1)) { // try to parse an explicit link: starturl = subj.Position + 1 + sps; // after ( endurl = starturl + n; starttitle = endurl + Scanner.scan_spacechars(subj.Buffer, endurl, subj.Length); // ensure there are spaces btw url and title endtitle = (starttitle == endurl) ? starttitle : starttitle + Scanner.scan_link_title(subj.Buffer, starttitle, subj.Length); endall = endtitle + Scanner.scan_spacechars(subj.Buffer, endtitle, subj.Length); if (endall < subj.Length && subj.Buffer[endall] == ')') { subj.Position = endall + 1; url = subj.Buffer.Substring(starturl, endurl - starturl); url = CleanUrl(url); title = subj.Buffer.Substring(starttitle, endtitle - starttitle); title = CleanTitle(title); return(new Reference() { Title = title, Url = url }); } } else if (c == '[' || c == ' ' || c == '\n') { var label = ParseReferenceLabel(subj); if (label != null) { if (label.Value.Length == 0) { return(Reference.SelfReference); } var details = LookupReference(subj.ReferenceMap, label.Value); if (details != null) { return(details); } // rollback the subject but return InvalidReference so that the caller knows not to // parse 'foo' from [foo][bar]. subj.Position = endlabel; return(Reference.InvalidReference); } } // rollback the subject position because didn't match anything. subj.Position = endlabel; return(null); }