public virtual IMarkdownToken TryMatch(IMarkdownParser parser, IMarkdownParsingContext context)
        {
            var match = OrderList.Match(context.CurrentMarkdown);

            if (match.Length == 0)
            {
                match = UnorderList.Match(context.CurrentMarkdown);
                if (match.Length == 0)
                {
                    return(null);
                }
            }
            var sourceInfo = context.Consume(match.Length);

            var bull = match.Groups[2].Value;

            var cap = match.Groups[0].Value.Match(Item);

            var next       = false;
            var l          = cap.Length;
            int i          = 0;
            var tokens     = new List <IMarkdownToken>();
            var lineOffset = 0;
            var lines      = 0;

            for (; i < l; i++)
            {
                var item = cap[i];
                lines = CountLine(item);
                // Remove the list item's bullet
                // so it is seen as the next token.
                var space = item.Length;
                item = item.ReplaceRegex(Regexes.Lexers.LeadingBullet, string.Empty);

                // Outdent whatever the
                // list item contains. Hacky.
                if (item.IndexOf("\n ") > -1)
                {
                    space -= item.Length;
                    item   = !parser.Options.Pedantic
                      ? Regex.Replace(item, "^ {1," + space + "}", "", RegexOptions.Multiline)
                      : Regex.Replace(item, @"^ {1,4}", "", RegexOptions.Multiline);
                }

                // Determine whether item is loose or not.
                // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
                // for discount behavior.
                var loose = next || Regex.IsMatch(item, @"\n\n(?!\s*$)");
                if (i != l - 1 && item.Length != 0)
                {
                    next = item[item.Length - 1] == '\n';
                    if (!loose)
                    {
                        loose = next;
                    }
                }

                tokens.Add(
                    new TwoPhaseBlockToken(
                        this,
                        parser.Context,
                        sourceInfo.Copy(item, lineOffset),
                        (p, t) =>
                {
                    var c = p.SwitchContext(MarkdownBlockContext.IsTop, false);
                    if (!loose)
                    {
                        var bc = (MarkdownBlockContext)p.Context;
                        c      = p.SwitchContext(
                            bc.SetRules(
                                ImmutableList.Create <IMarkdownRule>(
                                    this,
                                    new MarkdownNewLineBlockRule(),
                                    new MarkdownTextBlockRule())));
                    }
                    var blockTokens = p.Tokenize(t.SourceInfo.Copy(item));
                    p.SwitchContext(c);
                    blockTokens = TokenHelper.ParseInlineToken(p, this, blockTokens, loose, t.SourceInfo);
                    return(new MarkdownListItemBlockToken(t.Rule, t.Context, blockTokens, loose, t.SourceInfo));
                }));
                lineOffset += lines;
            }

            return(new MarkdownListBlockToken(this, parser.Context, tokens.ToImmutableArray(), bull.Length > 1, sourceInfo));
        }
示例#2
0
        public virtual IMarkdownToken TryMatch(IMarkdownParser parser, ref string source)
        {
            var match = Regexes.Block.List.Match(source);

            if (match.Length == 0)
            {
                return(null);
            }
            source = source.Substring(match.Length);

            var bull = match.Groups[2].Value;

            var cap = match.Groups[0].Value.Match(Item);

            var next   = false;
            var l      = cap.Length;
            int i      = 0;
            var tokens = new List <IMarkdownToken>();

            for (; i < l; i++)
            {
                var item = cap[i];

                // Remove the list item's bullet
                // so it is seen as the next token.
                var space = item.Length;
                item = item.ReplaceRegex(Regexes.Lexers.LeadingBullet, string.Empty);

                // Outdent whatever the
                // list item contains. Hacky.
                if (item.IndexOf("\n ") > -1)
                {
                    space -= item.Length;
                    item   = !parser.Options.Pedantic
                      ? Regex.Replace(item, "^ {1," + space + "}", "", RegexOptions.Multiline)
                      : Regex.Replace(item, @"^ {1,4}", "", RegexOptions.Multiline);
                }

                // Determine whether the next list item belongs here.
                // Backpedal if it does not belong in this list.
                if (parser.Options.SmartLists && i != l - 1)
                {
                    var b = Bullet.Apply(cap[i + 1])[0]; // !!!!!!!!!!!
                    if (bull != b && !(bull.Length > 1 && b.Length > 1))
                    {
                        source = string.Join("\n", cap.Skip(i + 1)) + source;
                        i      = l - 1;
                    }
                }

                // Determine whether item is loose or not.
                // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
                // for discount behavior.
                var loose = next || Regex.IsMatch(item, @"\n\n(?!\s*$)");
                if (i != l - 1 && item.Length != 0)
                {
                    next = item[item.Length - 1] == '\n';
                    if (!loose)
                    {
                        loose = next;
                    }
                }

                var c           = parser.SwitchContext(MarkdownBlockContext.IsTop, false);
                var blockTokens = parser.Tokenize(item);
                blockTokens = TokenHelper.ParseInlineToken(parser, this, blockTokens, loose);
                tokens.Add(new MarkdownListItemBlockToken(this, parser.Context, blockTokens, loose, item));
                parser.SwitchContext(c);
            }

            return(new MarkdownListBlockToken(this, parser.Context, tokens.ToImmutableArray(), bull.Length > 1, match.Value));
        }
示例#3
0
        public StringBuffer Mark(SourceInfo sourceInfo, IMarkdownContext context)
        {
            var result = StringBuffer.Empty;
            var parser = Parser;

            if (context != null)
            {
                parser.SwitchContext(context);
            }
            var preprocessedSourceInfo = sourceInfo.Copy(Preprocess(sourceInfo.Markdown));

            var tokens = parser.Tokenize(preprocessedSourceInfo);

            if (parser.Context is MarkdownBlockContext)
            {
                tokens = TokenHelper.CreateParagraghs(
                    parser,
                    MarkdownParagraphBlockRule.Instance,
                    tokens,
                    true,
                    preprocessedSourceInfo);
            }

            // resolve two phase token
            tokens = RewriteTokens(
                tokens,
                sourceInfo.File,
                new MarkdownRewriteEngine(
                    this,
                    MarkdownTokenRewriterFactory.Loop(
                        MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, TwoPhaseBlockToken>(
                            (e, t) => t.Extract(parser)),
                        MaxExtractCount + 1)));

            // Aggregate tokens.
            foreach (var agg in TokenAggregators)
            {
                tokens = RewriteTokens(
                    tokens,
                    sourceInfo.File,
                    new MarkdownAggregateEngine(
                        this,
                        agg));
            }

            // customized rewriter.
            tokens = RewriteTokens(
                tokens,
                sourceInfo.File,
                RewriteEngine);

            if (Options.ShouldFixId)
            {
                // fix id.
                var idTable = new Dictionary <string, int>();
                tokens = RewriteTokens(
                    tokens,
                    sourceInfo.File,
                    new MarkdownRewriteEngine(
                        this,
                        MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, MarkdownHeadingBlockToken>(
                            (e, t) => t.RewriteId(idTable))));
            }

            if (TokenTreeValidator != null)
            {
                TokenTreeValidator.Validate(tokens);
            }

            var renderer = Renderer;

            foreach (var token in tokens)
            {
                result += renderer.Render(token);
            }
            return(result);
        }