Ejemplo n.º 1
0
        protected IList <IInlineElement> ProcessInlineElements(string block, InlineElementType elementType = InlineElementType.All)
        {
            var elements = new List <IInlineElement>();

            if (string.IsNullOrWhiteSpace(block))
            {
                return(elements);
            }

            var matches = new List <InlineElementRuleMatch>();

            foreach (var rule in PatternMatcher.InlineElementRules.Where(r => elementType.HasFlag(r.ElementType)))
            {
                if (rule.Regex.IsMatch(block))
                {
                    var currentRule  = rule;
                    var outerMatches = matches;
                    block = currentRule.Regex.Replace(block, match =>
                    {
                        switch (currentRule.ElementType)
                        {
                        case InlineElementType.Emphasis:
                        case InlineElementType.EmphasisDouble:
                            var emphasis = CreateInlineElement <Emphasis>(match, currentRule.Constraint);

                            if (currentRule.ElementType == InlineElementType.EmphasisDouble)
                            {
                                emphasis.Element.DoubleDelimited = true;
                            }

                            outerMatches.Add(emphasis);
                            break;

                        case InlineElementType.Strong:
                        case InlineElementType.StrongDouble:
                            var strong = CreateContainerInlineElement <Strong>(match, currentRule.Constraint);

                            if (currentRule.ElementType == InlineElementType.StrongDouble)
                            {
                                strong.Element.DoubleDelimited = true;
                            }

                            outerMatches.Add(strong);
                            break;

                        case InlineElementType.Monospace:
                        case InlineElementType.MonospaceDouble:
                            var monospace = CreateContainerInlineElement <Monospace>(match, currentRule.Constraint);
                            if (currentRule.ElementType == InlineElementType.MonospaceDouble)
                            {
                                monospace.Element.DoubleDelimited = true;
                            }

                            outerMatches.Add(monospace);
                            break;

                        case InlineElementType.Subscript:
                            var subscript = CreateInlineElement <Subscript>(match, currentRule.Constraint);
                            outerMatches.Add(subscript);

                            break;

                        case InlineElementType.Superscript:
                            var superscript = CreateInlineElement <Superscript>(match, currentRule.Constraint);
                            outerMatches.Add(superscript);

                            break;

                        case InlineElementType.Quotation:
                        case InlineElementType.QuotationDouble:
                            var quotation = CreateContainerInlineElement <QuotationMark>(match, currentRule.Constraint);
                            if (currentRule.ElementType == InlineElementType.QuotationDouble)
                            {
                                quotation.Element.DoubleDelimited = true;
                            }

                            outerMatches.Add(quotation);
                            break;

                        case InlineElementType.Mark:
                        case InlineElementType.MarkDouble:
                            var mark = CreateContainerInlineElement <Mark>(match, currentRule.Constraint);

                            if (currentRule.ElementType == InlineElementType.MarkDouble)
                            {
                                mark.Element.DoubleDelimited = true;
                            }

                            outerMatches.Add(mark);
                            break;

                        case InlineElementType.InternalAnchor:
                            var internalAnchorParts = match.Groups[1].Value;
                            InternalAnchor anchor;
                            if (internalAnchorParts.IndexOf(",", StringComparison.OrdinalIgnoreCase) > -1)
                            {
                                var parts = internalAnchorParts.Split(',');
                                // TODO: Process inline elements of parts[1]
                                anchor = new InternalAnchor(parts[0], parts[1]);
                            }
                            else
                            {
                                anchor = new InternalAnchor(internalAnchorParts);
                            }

                            outerMatches.Add(new InlineElementRuleMatch(anchor, match.Index, match.Index + match.Length, new string(' ', match.Length)));
                            break;

                        case InlineElementType.InlineAnchor:
                            var inlineAnchorId = match.Groups[1].Value;
                            var xRefLabel      = match.Groups[2].Value;

                            // TODO: process inline elements of xRefLabel
                            var inlineAnchor = !string.IsNullOrEmpty(xRefLabel)
                                    ? new InlineAnchor(inlineAnchorId, xRefLabel)
                                    : new InlineAnchor(inlineAnchorId);

                            outerMatches.Add(new InlineElementRuleMatch(inlineAnchor, match.Index, match.Index + match.Length, new string(' ', match.Length)));
                            break;

                        case InlineElementType.AttributeReference:
                            var text = match.Groups[2].Value;
                            var attributeReference = new AttributeReference(text);
                            outerMatches.Add(new InlineElementRuleMatch(attributeReference, match.Index, match.Index + match.Length, new string(' ', match.Length)));
                            break;

                        case InlineElementType.ImplicitLink:
                            // TODO: split attributes out
                            var attributes = match.Groups["attributes"].Success
                                            ? match.Groups["attributes"].Value
                                            : null;
                            var href = match.Groups["href"].Value;
                            var link = new Link(href, attributes);
                            outerMatches.Add(new InlineElementRuleMatch(link, match.Index + match.Groups[1].Length, match.Index + match.Length, match.Groups[1].Value + new string(' ', match.Length - match.Groups[1].Length)));
                            break;
                        }

                        // replace any matches with the match replacement value TODO: This could be optimized
                        return(outerMatches[outerMatches.Count - 1].Replacement);
                    });
                }
            }

            if (matches.Any())
            {
                matches.Sort((match1, match2) => match1.StartIndex.CompareTo(match2.StartIndex));
                for (int i = 0; i < matches.Count; i++)
                {
                    var match       = matches[i];
                    var isLastMatch = i == matches.Count - 1;

                    if (i == 0 && match.StartIndex > 0)
                    {
                        elements.Add(new TextLiteral(block.Substring(0, matches[0].StartIndex)));
                    }

                    elements.Add(match.Element);

                    if (!isLastMatch)
                    {
                        // is there a literal between where this match ends and next one begins
                        var nextMatch = matches[i + 1];
                        var length    = nextMatch.StartIndex - match.EndIndex;
                        if (length > 0)
                        {
                            elements.Add(new TextLiteral(block.Substring(match.EndIndex, length)));
                        }
                    }
                    else
                    {
                        if (match.EndIndex < block.Length)
                        {
                            elements.Add(new TextLiteral(block.Substring(match.EndIndex)));
                        }
                    }
                }
            }
            else
            {
                elements.Add(new TextLiteral(block));
            }

            return(elements);
        }