예제 #1
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.Title.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not a block title");
            }

            var title = new Title(match.Groups["title"].Value);

            if (attributes != null)
            {
                attributes.Add(title);
            }
            else
            {
                attributes = new AttributeList {
                    title
                }
            };

            reader.ReadLine();
        }
    }
예제 #2
0
 public static bool ContainBlockName(this AttributeList attributes, string blockName)
 {
     if (attributes == null || attributes.Count == 0)
     {
         return(false);
     }
     return(attributes.Any(a => a.Name.Equals(blockName)));
 }
예제 #3
0
 public static bool ContainBlockName(this AttributeList attributes, string[] blockNames)
 {
     if (attributes == null || attributes.Count == 0)
     {
         return(false);
     }
     return(attributes.Any(a => blockNames.Contains(a.Name, StringComparer.OrdinalIgnoreCase)));
 }
예제 #4
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.Include.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not an include");
            }

            var include         = new Include(match.Groups["path"].Value);
            var attributesValue = match.Groups["attributes"].Value;

            if (!string.IsNullOrEmpty(attributesValue))
            {
                var attributeValues = SplitOnCharacterOutsideQuotes(attributesValue);
                foreach (var attributeValue in attributeValues)
                {
                    var attributeMatch = PatternMatcher.AttributeNameValue.Match(attributeValue);
                    if (attributeMatch.Success)
                    {
                        switch (attributeMatch.Groups["name"].Value.ToLowerInvariant())
                        {
                        case "leveloffset":
                            if (int.TryParse(attributeMatch.Groups["value"].Value, out var offset))
                            {
                                include.LevelOffset = offset;
                            }
                            break;

                        case "lines":
                            include.Lines = attributeMatch.Groups["value"].Value;
                            break;

                        case "tag":
                        case "tags":
                            include.Tags = attributeMatch.Groups["value"].Value;
                            break;

                        case "indent":
                            if (int.TryParse(attributeMatch.Groups["value"].Value, out var indent))
                            {
                                include.Indent = indent;
                            }
                            break;

                        default:
                            throw new NotImplementedException("TODO: add attribute to include attribute list");
                        }
                    }
                }
            }

            container.Add(include);
            attributes = null;

            reader.ReadLine();
        }
예제 #5
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.ElementAttribute.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not a block attribute");
            }

            var attributesValue = match.Groups["attributes"].Value.Trim();

            if (attributes == null)
            {
                attributes = new AttributeList();
            }

            if (attributesValue.IndexOf(",", StringComparison.Ordinal) == -1)
            {
                switch (attributesValue)
                {
                case "float":
                    attributes.IsFloating = true;
                    reader.ReadLine();
                    return;

                case "discrete":
                    attributes.IsDiscrete = true;
                    reader.ReadLine();
                    return;

                default:
                    attributes.Add(ParseElementAttributesWithPosition(attributesValue, 0));
                    reader.ReadLine();
                    return;
                }
            }

            var inputs = SplitOnCharacterOutsideQuotes(attributesValue);

            if (inputs[0] == "quote" || inputs[0] == "verse")
            {
                for (var index = 0; index < inputs.Length; index++)
                {
                    var i = inputs[index];
                    attributes.Add(new Attribute(i, true));
                }
                reader.ReadLine();
                return;
            }

            var attributeLists = inputs.Select(ParseElementAttributesWithPosition);

            attributes = attributeLists.Aggregate(attributes, (first, second) => first.Add(second));

            reader.ReadLine();
        }
예제 #6
0
        /// <summary>
        /// Parses text from <see cref="IDocumentReader"/> into an <see cref="Document"/>
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns>An new instance of <see cref="Document"/></returns>
        public Document Parse(IDocumentReader reader)
        {
            var           document   = new Document(reader.Path);
            var           buffer     = new List <string>(8);
            AttributeList attributes = null;

            Parse(document, reader, null, ref buffer, ref attributes);
            return(document);
        }
예제 #7
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var comment = new Comment(reader.Line.Substring(2));

            container.Add(comment);

            reader.ReadLine();
        }
예제 #8
0
        protected void ProcessBuffer(Container container, ref List <string> buffer, ref AttributeList attributes)
        {
            if (buffer.Count > 0)
            {
                if (attributes.ContainBlockName("quote"))
                {
                    ProcessLine <Quote>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("pass"))
                {
                    ProcessSimple <Passthrough>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("example"))
                {
                    ProcessLine <Example>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("stem"))
                {
                    ProcessSimple <Stem>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("sidebar"))
                {
                    ProcessLine <Sidebar>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("source"))
                {
                    ProcessSimple <Source>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("listing"))
                {
                    ProcessSimple <Listing>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("literal"))
                {
                    ProcessSimple <Literal>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("comment"))
                {
                    ProcessSimple <Comment>(container, ref buffer, ref attributes);
                }
                else if (attributes.ContainBlockName("verse"))
                {
                    ProcessLine <Verse>(container, ref buffer, ref attributes);
                }
                else
                {
                    ProcessParagraph(container, ref buffer, ref attributes);
                }

                buffer = new List <string>(8);
            }

            attributes = null;
        }
예제 #9
0
        protected void ProcessParagraph(Container parent, ref List <string> buffer, ref AttributeList attributes)
        {
            if (buffer.Count > 0 && !buffer.All(string.IsNullOrWhiteSpace))
            {
                var inlineElements = ProcessInlineElements(string.Join(Environment.NewLine, buffer));
                var paragraph      = new Paragraph(inlineElements);
                paragraph.Attributes.Add(attributes);
                parent.Add(paragraph);

                attributes = null;
                buffer     = new List <string>(8);
            }
        }
예제 #10
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var listingRegex = PatternMatcher.GetDelimiterRegexFor <TElement>();
            var isDelimiter  = listingRegex.IsMatch(reader.Line);

            if (isDelimiter)
            {
                ProcessParagraph(container, ref buffer);
                reader.ReadLine();
                while (reader.Line != null && !listingRegex.IsMatch(reader.Line))
                {
                    buffer.Add(reader.Line);
                    reader.ReadLine();
                }
            }
            else
            {
                buffer.Add(reader.Line);
                reader.ReadLine();
                while (reader.Line != null && !PatternMatcher.BlankCharacters.IsMatch(reader.Line))
                {
                    buffer.Add(reader.Line);
                    reader.ReadLine();
                }
            }

            var element = new TElement {
                Text = string.Join(Environment.NewLine, buffer)
            };

            element.Attributes.Add(attributes);

            reader.ReadLine();
            if (isDelimiter)
            {
                while (reader.Line != null && PatternMatcher.Callout.IsMatch(reader.Line))
                {
                    ParseCallout(element, reader.Line);
                    reader.ReadLine();
                }
            }

            container.Add(element);
            attributes = null;
            buffer     = new List <string>(8);
        }
예제 #11
0
        public void Parse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                          ref AttributeList attributes)
        {
            var document = (Document)container;

            ParseDocumentTitle(document, reader, ref attributes);

            reader.ReadLine();

            if (reader.Line == null)
            {
                return;
            }

            ParseAuthors(document, reader.Line);

            reader.ReadLine();
        }
예제 #12
0
        /// <summary>
        /// Visits the attribute list.
        /// </summary>
        /// <param name="attributes">The attributes.</param>
        public virtual void VisitAttributeList(AttributeList attributes)
        {
            if (attributes == null)
            {
                return;
            }
            if (attributes.HasAnchor)
            {
                attributes.Anchor.Accept(this);
            }

            if (attributes.IsDiscrete)
            {
                _writer.WriteLine("[discrete]");
            }
            else if (attributes.IsFloating)
            {
                _writer.WriteLine("[float]");
            }

            if (attributes.Any())
            {
                _writer.Write("[");
                for (int index = 0; index < attributes.Count; index++)
                {
                    var lastAttribute  = index == attributes.Count - 1;
                    var asciiAttribute = attributes[index];
                    asciiAttribute.Accept(this);

                    if (!lastAttribute)
                    {
                        _writer.Write(",");
                    }
                }
                _writer.WriteLine("]");
            }

            if (attributes.HasTitle)
            {
                attributes.Title.Accept(this);
            }
        }
예제 #13
0
        // TODO: based on html output, a section title should define a section block element into which all proceeding elements should be added, until the next section Title is hit
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.SectionTitle.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not a section title");
            }

            var title          = match.Groups["title"].Value;
            var inlineElements = ProcessInlineElements(title);
            var level          = match.Groups["level"].Value.Length;
            var sectionTitle   = new SectionTitle(inlineElements, level);

            sectionTitle.Attributes.Add(attributes);
            container.Add(sectionTitle);
            attributes = null;

            reader.ReadLine();
        }
예제 #14
0
        protected void DescendingParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                       ref AttributeList attributes)
        {
            while (reader.Line != null)
            {
                if (predicate != null && predicate(reader.Line))
                {
                    ProcessParagraph(container, ref buffer, ref attributes);
                    return;
                }

                var parsed = false;
                for (var index = 0; index < Parsers.Length; index++)
                {
                    var parser = Parsers[index];
                    if (parser.IsMatch(reader, container, attributes))
                    {
                        parser.Parse(container, reader, predicate, ref buffer, ref attributes);
                        parsed = true;
                        break;
                    }
                }

                if (!parsed)
                {
                    if (PatternMatcher.BlankCharacters.IsMatch(reader.Line))
                    {
                        ProcessBuffer(container, ref buffer, ref attributes);
                    }
                    else
                    {
                        buffer.Add(reader.Line);
                    }

                    reader.ReadLine();
                }
            }

            ProcessBuffer(container, ref buffer, ref attributes);
        }
예제 #15
0
        /// <summary>
        /// Visits the attribute list.
        /// </summary>
        /// <param name="attributes">The attributes.</param>
        public virtual void VisitAttributeList(AttributeList attributes)
        {
            if (attributes == null)
            {
                return;
            }

            if (attributes.HasAnchor)
            {
                attributes.Anchor.Accept(this);
            }

            if (attributes.HasTitle)
            {
                attributes.Title.Accept(this);
            }

            foreach (var attribute in attributes)
            {
                attribute.Accept(this);
            }
        }
예제 #16
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var attributeEntry = ParseAttributeEntry(reader.Line);
            var document       = container as Document;

            if (document != null)
            {
                if (document.Count == 0)
                {
                    document.Attributes.Add(attributeEntry);
                }
                else
                {
                    document.Add(attributeEntry);
                }
            }
            else
            {
                container.Add(attributeEntry);
            }

            reader.ReadLine();
        }
예제 #17
0
        public override void Parse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                   ref AttributeList attributes)
        {
            var delimiterRegex = PatternMatcher.GetDelimiterRegexFor <TElement>();
            var element        = new TElement();

            element.Attributes.Add(attributes);
            if (delimiterRegex.IsMatch(reader.Line))
            {
                ProcessParagraph(container, ref buffer);
                reader.ReadLine();
                Parse(element, reader, delimiterRegex);
            }
            else
            {
                ProcessParagraph(element, ref buffer);
                Parse(element, reader, PatternMatcher.BlankCharacters);
            }

            container.Add(element);
            attributes = null;

            reader.ReadLine();
        }
예제 #18
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.OrderedListItem.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not an ordered list item");
            }

            var level           = match.Groups["level"].Value;
            var orderedListItem = new OrderedListItem(level.Length);

            orderedListItem.Attributes.Add(attributes);

            var number     = match.Groups["number"].Value;
            var upperAlpha = match.Groups["upperalpha"].Value;
            var lowerAlpha = match.Groups["loweralpha"].Value;
            var upperRoman = match.Groups["upperRoman"].Value;
            var lowerRoman = match.Groups["lowerRoman"].Value;

            if (!string.IsNullOrEmpty(number))
            {
                orderedListItem.Number = int.Parse(number);
            }
            else if (!string.IsNullOrEmpty(upperAlpha))
            {
                orderedListItem.Numbering = NumberStyle.UpperAlpha;
                orderedListItem.Number    = Array.IndexOf(Patterns.UpperAlphabet, upperAlpha) + 1;
            }
            else if (!string.IsNullOrEmpty(lowerAlpha))
            {
                orderedListItem.Numbering = NumberStyle.LowerAlpha;
                orderedListItem.Number    = Array.IndexOf(Patterns.LowerAlphabet, lowerAlpha) + 1;
            }
            else if (!string.IsNullOrEmpty(upperRoman))
            {
                orderedListItem.Numbering = NumberStyle.UpperRoman;
                orderedListItem.Number    = RomanNumerals.ToInt(upperRoman);
            }
            else if (!string.IsNullOrEmpty(lowerRoman))
            {
                orderedListItem.Numbering = NumberStyle.LowerRoman;
                orderedListItem.Number    = RomanNumerals.ToInt(lowerRoman);
            }

            var text = match.Groups["text"].Value;

            buffer.Add(text);
            reader.ReadLine();

            attributes = null;

            while (reader.Line != null &&
                   !PatternMatcher.BlankCharacters.IsMatch(reader.Line) &&
                   !PatternMatcher.OrderedListItem.IsMatch(reader.Line) &&
                   (predicate == null || !predicate(reader.Line)))
            {
                if (PatternMatcher.ListItemContinuation.IsMatch(reader.Line))
                {
                    ProcessBuffer(orderedListItem, ref buffer, ref attributes);
                    reader.ReadLine();
                    DescendingParse(
                        orderedListItem,
                        reader,
                        line => PatternMatcher.BlankCharacters.IsMatch(line) || PatternMatcher.OrderedListItem.IsMatch(line),
                        ref buffer,
                        ref attributes);
                }
                else
                {
                    buffer.Add(reader.Line);
                    reader.ReadLine();
                }
            }

            ProcessBuffer(orderedListItem, ref buffer, ref attributes);

            OrderedList orderedList;

            if (container.Count > 0)
            {
                orderedList = container[container.Count - 1] as OrderedList;

                if (orderedList != null && orderedList.Items.Count > 0 && orderedList.Items[0].Level == orderedListItem.Level)
                {
                    orderedList.Items.Add(orderedListItem);
                }
                else
                {
                    orderedList = new OrderedList {
                        Items = { orderedListItem }
                    };
                    container.Add(orderedList);
                }
            }
            else
            {
                orderedList = new OrderedList {
                    Items = { orderedListItem }
                };
                container.Add(orderedList);
            }

            attributes = null;
        }
예제 #19
0
 public virtual void Visit(AttributeList attributes)
 {
 }
예제 #20
0
 public override bool IsMatch(IDocumentReader reader, Container container, AttributeList attributes) =>
 PatternMatcher.CheckListItem.IsMatch(reader.Line);
예제 #21
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.CheckListItem.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not a check list item");
            }

            var level     = match.Groups["level"].Value;
            var isChecked = !string.IsNullOrWhiteSpace(match.Groups["checked"].Value);
            var text      = match.Groups["text"].Value;

            var listItem = new CheckListItem(level.Length, isChecked);

            listItem.Attributes.Add(attributes);

            buffer.Add(text);
            reader.ReadLine();

            attributes = null;

            while (reader.Line != null &&
                   !PatternMatcher.ListItemContinuation.IsMatch(reader.Line) &&
                   !PatternMatcher.BlankCharacters.IsMatch(reader.Line) &&
                   !PatternMatcher.CheckListItem.IsMatch(reader.Line) &&
                   !PatternMatcher.ListItem.IsMatch(reader.Line) &&
                   (predicate == null || !predicate(reader.Line)))
            {
                if (PatternMatcher.ListItemContinuation.IsMatch(reader.Line))
                {
                    ProcessBuffer(listItem, ref buffer, ref attributes);
                    reader.ReadLine();
                    DescendingParse(
                        listItem,
                        reader,
                        line => PatternMatcher.BlankCharacters.IsMatch(line) ||
                        PatternMatcher.ListItem.IsMatch(line) ||
                        PatternMatcher.CheckListItem.IsMatch(reader.Line),
                        ref buffer,
                        ref attributes);
                }
                else
                {
                    buffer.Add(reader.Line);
                    reader.ReadLine();
                }
            }

            ProcessBuffer(listItem, ref buffer, ref attributes);

            UnorderedList unorderedList;

            if (container.Count > 0)
            {
                unorderedList = container[container.Count - 1] as UnorderedList;

                if (unorderedList != null && unorderedList.Items.Count > 0 && unorderedList.Items[0].Level == listItem.Level)
                {
                    unorderedList.Items.Add(listItem);
                }
                else
                {
                    unorderedList = new UnorderedList {
                        Items = { listItem }
                    };
                    container.Add(unorderedList);
                }
            }
            else
            {
                unorderedList = new UnorderedList {
                    Items = { listItem }
                };
                container.Add(unorderedList);
            }

            attributes = null;
        }
예제 #22
0
        public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                           ref AttributeList attributes)
        {
            var match = PatternMatcher.LabeledListItem.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not a labeled list item");
            }

            var label = match.Groups["label"].Value;
            var level = match.Groups["level"].Value.Length;

            // levels start at 0
            if (level > 0)
            {
                level -= 2;
            }

            var labeledListItem = new LabeledListItem(label, level);

            labeledListItem.Attributes.Add(attributes);
            attributes = null;

            var text = match.Groups["text"].Value;

            // labeled lists are lenient with whitespace so can have whitespace after the label
            // and before any content.
            if (!string.IsNullOrWhiteSpace(text))
            {
                buffer.Add(text);
                reader.ReadLine();
            }
            else
            {
                reader.ReadLine();
                while (reader.Line != null &&
                       PatternMatcher.BlankCharacters.IsMatch(reader.Line))
                {
                    reader.ReadLine();
                }
            }

            while (reader.Line != null &&
                   !PatternMatcher.BlankCharacters.IsMatch(reader.Line) &&
                   !PatternMatcher.LabeledListItem.IsMatch(reader.Line) &&
                   (predicate == null || !predicate(reader.Line)))
            {
                if (PatternMatcher.ListItemContinuation.IsMatch(reader.Line))
                {
                    ProcessBuffer(labeledListItem, ref buffer, ref attributes);
                    reader.ReadLine();
                    DescendingParse(
                        labeledListItem,
                        reader,
                        line => PatternMatcher.BlankCharacters.IsMatch(line) ||
                        PatternMatcher.LabeledListItem.IsMatch(line),
                        ref buffer,
                        ref attributes);
                }
                else
                {
                    buffer.Add(reader.Line);
                    reader.ReadLine();
                }
            }

            ProcessBuffer(labeledListItem, ref buffer, ref attributes);

            LabeledList labeledList;

            if (container.Count > 0)
            {
                labeledList = container[container.Count - 1] as LabeledList;

                if (labeledList != null && labeledList.Items.Count > 0 && labeledList.Items[0].Level == labeledListItem.Level)
                {
                    labeledList.Items.Add(labeledListItem);
                }
                else
                {
                    labeledList = new LabeledList {
                        Items = { labeledListItem }
                    };
                    container.Add(labeledList);
                }
            }
            else
            {
                labeledList = new LabeledList {
                    Items = { labeledListItem }
                };
                container.Add(labeledList);
            }

            attributes = null;
        }
예제 #23
0
 public bool IsMatch(IDocumentReader reader, Container container, AttributeList attributes) =>
 PatternMatcher.DocumentTitle.IsMatch(reader.Line) &&
 (reader.LineNumber == 1 || container.GetType() == typeof(Document) && container.All(e => e is Comment));
예제 #24
0
        private static void ParseDocumentTitle(Document document, IDocumentReader reader, ref AttributeList attributes)
        {
            var match = PatternMatcher.DocumentTitle.Match(reader.Line);

            if (!match.Success)
            {
                throw new ArgumentException("not a document title");
            }

            var title          = match.Groups["title"].Value;
            var lastColonIndex = title.LastIndexOf(":", StringComparison.OrdinalIgnoreCase);
            var documentTitle  = lastColonIndex > -1
                ? new DocumentTitle(title.Substring(0, lastColonIndex), title.Substring(lastColonIndex + 1))
                : new DocumentTitle(title);

            documentTitle.Attributes.Add(attributes);
            document.Title = documentTitle;

            attributes = null;
        }
예제 #25
0
 public abstract bool IsMatch(IDocumentReader reader, Container container, AttributeList attributes);
예제 #26
0
 public bool IsMatch(IDocumentReader reader, Container container, AttributeList attributes) =>
 PatternMatcher.Anchor.IsMatch(reader.Line);
예제 #27
0
 public override void InternalParse(Container container, IDocumentReader reader, Func <string, bool> predicate, ref List <string> buffer,
                                    ref AttributeList attributes)
 {
     throw new NotImplementedException("TODO");
 }
예제 #28
0
        private static AttributeList ParseElementAttributesWithPosition(string input, int position)
        {
            var attributes = new AttributeList();

            input = input.Trim();
            var start = 0;

            for (var index = 0; index < input.Length; index++)
            {
                var currentChar = input[index];
                var last        = index == input.Length - 1;

                if (currentChar == '%')
                {
                    var options           = new List <string>();
                    var optionsStartIndex = index + 1;

                    for (int i = optionsStartIndex; i < input.Length; i++)
                    {
                        var lastChar = i == input.Length - 1;

                        if (input[i] == '%')
                        {
                            options.Add(input.Substring(optionsStartIndex, i - optionsStartIndex));
                            optionsStartIndex = i + 1;
                        }
                        else if (lastChar || input[i] == '#' || input[i] == '.' || input[i] == '=')
                        {
                            options.Add(lastChar
                                ? input.Substring(optionsStartIndex, i - (optionsStartIndex - 1))
                                : input.Substring(optionsStartIndex, i - 1));

                            attributes.Add(new OptionsAttribute(options.ToArray(), false));
                            index = i;
                            start = i;
                            break;
                        }
                    }
                }
                else if (currentChar == '#')
                {
                    var startIdIndex = index + 1;
                    for (var i = startIdIndex; i < input.Length; i++)
                    {
                        var lastChar = i == input.Length - 1;

                        if (lastChar)
                        {
                            var value = input.Substring(startIdIndex);
                            attributes.Add(new IdAttribute(value, false));
                            index = i;
                            start = i;
                            break;
                        }
                        if (input[i] == '.' || input[i] == '%' || input[i] == '=')
                        {
                            var value = input.Substring(startIdIndex, i - 1);
                            attributes.Add(new IdAttribute(value, false));
                            index = i - 1;
                            start = i - 1;
                            break;
                        }
                    }
                }
                else if (currentChar == '.')
                {
                    var options        = new List <string>();
                    var roleStartIndex = index + 1;

                    for (var i = roleStartIndex; i < input.Length; i++)
                    {
                        var lastChar = i == input.Length - 1;

                        if (input[i] == '.')
                        {
                            options.Add(input.Substring(roleStartIndex, i - roleStartIndex));
                            roleStartIndex = i + 1;
                        }
                        else if (lastChar || input[i] == '#' || input[i] == '%' || input[i] == '=')
                        {
                            options.Add(lastChar
                                ? input.Substring(roleStartIndex, i - (roleStartIndex - 1))
                                : input.Substring(roleStartIndex, i - 1));

                            attributes.Add(new RoleAttribute(options, false));
                            index = i;
                            start = i;
                            break;
                        }
                    }
                }
                else if (currentChar == '=')
                {
                    var name = input.Substring(start, index);
                    for (int i = index + 1; i < input.Length; i++)
                    {
                        var lastChar = i == input.Length - 1;

                        if (lastChar || input[i] == '#' || input[i] == '%' || input[i] == '.')
                        {
                            var singleQuoted = input[index + 1] == '\'';

                            var value = singleQuoted || input[index + 1] == '"'
                                ? input.Substring(index + 2, i - (name.Length + 2))
                                : input.Substring(index + 1, i - name.Length);

                            // TODO: handle known named elements
                            switch (name.ToLowerInvariant())
                            {
                            case "id":
                                if (value.IndexOf(",", StringComparison.OrdinalIgnoreCase) > -1)
                                {
                                    var valueParts = value.Split(',');
                                    attributes.Add(new IdAttribute(valueParts[0], valueParts[1], singleQuoted));
                                }
                                else
                                {
                                    attributes.Add(new IdAttribute(value, singleQuoted));
                                }
                                break;

                            case "role":
                                attributes.Add(new RoleAttribute(value, singleQuoted));
                                break;

                            case "options":
                            case "opts":
                                attributes.Add(new OptionsAttribute(value, singleQuoted));
                                break;

                            case "subs":
                                attributes.Add(new SubstitutionsAttribute(value));
                                break;

                            default:
                                attributes.Add(new NamedAttribute(name, value, singleQuoted));
                                break;
                            }

                            index = i;
                            start = i;
                            break;
                        }
                    }
                }
                else if (index == 0 && position == 0)
                {
                    var hashIndex    = input.IndexOf("#", StringComparison.OrdinalIgnoreCase);
                    var dotIndex     = input.IndexOf(".", StringComparison.OrdinalIgnoreCase);
                    var percentIndex = input.IndexOf("%", StringComparison.OrdinalIgnoreCase);

                    if (hashIndex > -1 || dotIndex > -1 || percentIndex > -1)
                    {
                        var minIndex = new[] { hashIndex, dotIndex, percentIndex }.Where(i => i != -1).Min();
                        if (minIndex > 1)
                        {
                            var name = input.Substring(0, minIndex);
                            attributes.Add(new Attribute(name));
                            index = minIndex - 1;
                            start = minIndex - 1;
                        }
                    }
                }
                else if (last)
                {
                    var name = input.Substring(start);
                    attributes.Add(new Attribute(name));
                }
            }

            return(attributes);
        }
예제 #29
0
 public override bool IsMatch(IDocumentReader reader, Container container, AttributeList attrtibutes) =>
 PatternMatcher.SectionTitle.IsMatch(reader.Line);
예제 #30
0
 /// <summary>
 /// Determines whether the specified <see cref="AttributeList" />, is equal to this instance.
 /// </summary>
 /// <param name="other">The other.</param>
 /// <returns>true if equal; otherwise, false</returns>
 protected bool Equals(AttributeList other) =>
 Equals(Anchor, other.Anchor) &&
 Equals(Title, other.Title) &&
 AttributesEqual(_attributes, other._attributes);