<commit_before>// Copyright (c) <NAME>. All rights reserved.
// This file is licensed under the BSD-Clause 2 license. 
// See the license.txt file in the project root for more information.

using System.Collections.Generic;
using Markdig.Helpers;
using Markdig.Parsers;
using Markdig.Renderers.Html;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;

namespace Markdig.Extensions.GenericAttributes
{
    /// <summary>
    /// An inline parser used to parse a HTML attributes that can be attached to the previous <see cref="Inline"/> or current <see cref="Block"/>.
    /// </summary>
    /// <seealso cref="Markdig.Parsers.InlineParser" />
    public class GenericAttributesParser : InlineParser
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GenericAttributesParser"/> class.
        /// </summary>
        public GenericAttributesParser()
        {
            OpeningCharacters = new[] { '{' };
        }

        public override bool Match(InlineProcessor processor, ref StringSlice slice)
        {
            HtmlAttributes attributes;
            var startPosition = slice.Start;
            if (TryParse(ref slice, out attributes))
            {
                var inline = processor.Inline;

                // If the curent object to attach is either a literal or delimiter
                // try to find a suitable parent, otherwise attach the html attributes to the block
                if (inline is LiteralInline)
                {
                    while (true)
                    {
                        inline = inline.Parent;
                        if (!(inline is DelimiterInline))
                        {
                            break;
                        }
                    }
                }
                var objectToAttach = inline == null || inline == processor.Root ? (MarkdownObject) processor.Block : inline;

                // If the current block is a Paragraph, but only the HtmlAttributes is used,
                // Try to attach the attributes to the following block
                var paragraph = objectToAttach as ParagraphBlock;
                if (paragraph != null && paragraph.Inline.FirstChild == null && processor.Inline == null && slice.IsEmptyOrWhitespace())
                {
                    var parent = paragraph.Parent;
                    var indexOfParagraph = parent.IndexOf(paragraph);
                    if (indexOfParagraph + 1 < parent.Count)
                    {
                        objectToAttach = parent[indexOfParagraph + 1];
                        // We can remove the paragraph as it is empty
                        parent.RemoveAt(indexOfParagraph);
                    }
                }

                var currentHtmlAttributes = objectToAttach.GetAttributes();
                attributes.CopyTo(currentHtmlAttributes, false, false);

                // Update the position of the attributes
                int line;
                int column;
                currentHtmlAttributes.Span.Start = processor.GetSourcePosition(startPosition, out line, out column);
                currentHtmlAttributes.Line = line;
                currentHtmlAttributes.Column = column;
                currentHtmlAttributes.Span.End = currentHtmlAttributes.Span.Start + slice.Start - startPosition - 1;

                // We don't set the processor.Inline as we don't want to add attach attributes to a particular entity
                return true;
            }

            return false;
        }
<commit_msg>fixes issue where using special attributes overwites element id, even when id is not specified<commit_after>// Copyright (c) <NAME>. All rights reserved.
// This file is licensed under the BSD-Clause 2 license. 
// See the license.txt file in the project root for more information.

using System.Collections.Generic;
using Markdig.Helpers;
using Markdig.Parsers;
using Markdig.Renderers.Html;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;

namespace Markdig.Extensions.GenericAttributes
{
    /// <summary>
    /// An inline parser used to parse a HTML attributes that can be attached to the previous <see cref="Inline"/> or current <see cref="Block"/>.
    /// </summary>
    /// <seealso cref="Markdig.Parsers.InlineParser" />
    public class GenericAttributesParser : InlineParser
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GenericAttributesParser"/> class.
        /// </summary>
        public GenericAttributesParser()
        {
            OpeningCharacters = new[] { '{' };
        }

        public override bool Match(InlineProcessor processor, ref StringSlice slice)
        {
            HtmlAttributes attributes;
            var startPosition = slice.Start;
            if (TryParse(ref slice, out attributes))
            {
                var inline = processor.Inline;

                // If the curent object to attach is either a literal or delimiter
                // try to find a suitable parent, otherwise attach the html attributes to the block
                if (inline is LiteralInline)
                {
                    while (true)
                    {
                        inline = inline.Parent;
                        if (!(inline is DelimiterInline))
                        {
                            break;
                        }
                    }
                }
                var objectToAttach = inline == null || inline == processor.Root ? (MarkdownObject) processor.Block : inline;

                // If the current block is a Paragraph, but only the HtmlAttributes is used,
                // Try to attach the attributes to the following block
                var paragraph = objectToAttach as ParagraphBlock;
                if (paragraph != null && paragraph.Inline.FirstChild == null && processor.Inline == null && slice.IsEmptyOrWhitespace())
                {
                    var parent = paragraph.Parent;
                    var indexOfParagraph = parent.IndexOf(paragraph);
                    if (indexOfParagraph + 1 < parent.Count)
                    {
                        objectToAttach = parent[indexOfParagraph + 1];
                        // We can remove the paragraph as it is empty
                        parent.RemoveAt(indexOfParagraph);
                    }
                }

                var currentHtmlAttributes = objectToAttach.GetAttributes();
                attributes.CopyTo(currentHtmlAttributes, true, false);

                // Update the position of the attributes
                int line;
                int column;
                currentHtmlAttributes.Span.Start = processor.GetSourcePosition(startPosition, out line, out column);
                currentHtmlAttributes.Line = line;
                currentHtmlAttributes.Column = column;
                currentHtmlAttributes.Span.End = currentHtmlAttributes.Span.Start + slice.Start - startPosition - 1;

                // We don't set the processor.Inline as we don't want to add attach attributes to a particular entity
                return true;
            }

            return false;
        }

{'fraction_non_alphanumeric': 0.07575334821428571, 'fraction_numerical': 0.0011160714285714285, 'mean_word_length': 1.6192911947387651, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6889732', 'n_tokens_mistral': 1645, 'n_tokens_neox': 1564, 'n_words': 544}