Пример #1
0
        /// <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);
        }
Пример #2
0
        // 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);
        }