Example #1
0
        /// <summary>
        /// Determines if element contains given position
        /// </summary>
        /// <param name="position">Position in a text buffer</param>
        public override bool Contains(int position)
        {
            if (base.Contains(position))
            {
                return(true);
            }

            if (StartTag.Contains(position))
            {
                return(true);
            }

            if (EndTag != null)
            {
                if (EndTag.Contains(position))
                {
                    return(true);
                }
            }
            else
            {
                if (position == VirtualEnd && !IsShorthand() && !IsSelfClosing())
                {
                    return(true);
                }
            }

            return(false);
        }
Example #2
0
        /// <summary>
        /// Shifts node components that are located at or beyond given start point by the specified range
        /// </summary>
        /// <param name="start">Start point</param>
        /// <param name="offset">Offset to shift by</param>
        public override void ShiftStartingFrom(int start, int offset)
        {
            // short-circuit in the case where the shift starts after our end
            if (start > End)
            {
                return;
            }

            // if tag is not closed and change is right at the end,
            // e need to grow start tag rather than element inner range

            if (StartTag.Contains(start) || StartTag.Start >= start || (!StartTag.IsClosed && start == StartTag.End))
            {
                StartTag.ShiftStartingFrom(start, offset);
            }

            if (EndTag != null && (EndTag.Contains(start) || EndTag.Start >= start))
            {
                EndTag.ShiftStartingFrom(start, offset);
            }

            if (OrphanedEndTagsCollection != null)
            {
                OrphanedEndTagsCollection.ShiftStartingFrom(start, offset);
            }

            if (VirtualEnd >= start)
            {
                VirtualEnd = Math.Max(start, VirtualEnd + offset);
            }

            int count = Children.Count;

            for (int i = 0; i < count; i++)
            {
                Children[i].ShiftStartingFrom(start, offset);
            }
        }
Example #3
0
        /// <summary>
        /// Determines position type and enclosing element node for a given position in the document text.
        /// </summary>
        /// <param name="position">Position in the document text</param>
        /// <param name="element">Element that contains position</param>
        /// <param name="attribute">Attribute that contains position (may be null)</param>
        /// <returns>Position type as a set of flags combined via OR operation</returns>
        public virtual HtmlPositionType GetPositionElement(int position, out ElementNode element, out AttributeNode attribute)
        {
            element   = null;
            attribute = null;

            // If start tag is not closed, consider end position to be inside it
            // so user can continue getting attribute intellisense, like in <a href=|<a ...></a>
            if (StartTag.Contains(position) || (position == StartTag.End && !StartTag.IsClosed))
            {
                // If position is right at the start, it is actually before the tag (in parent's content),
                // as if when caret position is like this: <table>|<tr></tr><table>
                if (position == StartTag.Start)
                {
                    element = this.Parent;
                    return(HtmlPositionType.InContent);
                }

                if (position >= QualifiedNameRange.Start && position <= StartTag.QualifiedNameRange.End)
                {
                    element = this;
                    return(HtmlPositionType.ElementName);
                }

                element = this;

                for (int i = 0; i < Attributes.Count; i++)
                {
                    var  attrNode        = Attributes[i];
                    bool hasClosingQuote = false;

                    var valueToken = attrNode.ValueToken;
                    hasClosingQuote = (valueToken != null) && (valueToken.CloseQuote != '\0');

                    if (position == attrNode.End && hasClosingQuote)
                    {
                        break;
                    }

                    if (position > attrNode.End)
                    {
                        continue;
                    }

                    if (position < attrNode.Start)
                    {
                        break;
                    }

                    if (attrNode.Contains(position) || (position == attrNode.End && !hasClosingQuote))
                    {
                        attribute = attrNode;
                        return(attrNode.GetPositionType(position));
                    }
                }

                return(HtmlPositionType.InStartTag);
            }

            if (!this.Contains(position))
            {
                return(HtmlPositionType.Undefined);
            }

            for (int i = 0; i < this.Children.Count; i++)
            {
                var child = Children[i];

                if (position < child.Start)
                {
                    break;
                }

                if (child.Contains(position))
                {
                    return(child.GetPositionElement(position, out element, out attribute));
                }
            }

            element = this;

            // If position is right at the start, it is actually before the end tag,
            // like when caret is between opening and closing tags: <table>|<table>
            if (EndTag != null)
            {
                if (position == EndTag.Start)
                {
                    return(HtmlPositionType.InContent);
                }

                if (EndTag.Contains(position))
                {
                    return(HtmlPositionType.InEndTag);
                }
            }

            if (this.IsScriptBlock())
            {
                return(HtmlPositionType.InScriptBlock);
            }

            if (this.IsStyleBlock())
            {
                return(HtmlPositionType.InStyleBlock);
            }

            return(HtmlPositionType.InContent);
        }