private static void AddNodes(HtmlElement parent, string html, bool removeInstructions)
        {
            int len = html.Length;
            int i = -1;
            string text = "";

            while (i < len - 1)
            {
                i++;

                if (i >= html.Length)
                    break;

                string s = html.Substring(i, 1);

                if (s == "<")
                {
                    int start = i + 1;
                    int stop = html.IndexOf(">", i, StringComparison.Ordinal);
                    if (stop < i)
                        continue;
                    if (text.Trim() != "")
                        parent.Add(new HtmlText(text));
                    text = "";

                    string fragment = html.Substring(start, stop - start);

                    //html comment
                    if (fragment.StartsWith("!--") && fragment.EndsWith("--"))
                    {
                        parent.Add(new HtmlComment(fragment.Substring(3).Substring(0, fragment.Length - 5)));
                        i = stop;
                    }
                    //html instruction
                    else if (fragment.StartsWith("!"))
                    {
                        if (!removeInstructions)
                            parent.Add(new HtmlInstruction(fragment.Substring(1).Substring(0, fragment.Length - 1)));
                        i = stop;
                    }
                    else if (fragment.StartsWith("/"))
                    {
                        //remove invalid closing tags
                        i = stop;
                    }
                    else
                    {
                        HtmlElement node = CreateNode(html, start, ref stop);
                        parent.Add(node);
                        i = stop + (node.IsClosed ? 0 : (node.Name.Length + 2));
                    }
                    continue;
                }

                text += s;
            }

            if (text.Trim() != string.Empty)
                parent.Add(new HtmlText(text));
        }
        private static HtmlElement CreateNode(string htmlPart)
        {
            string html = htmlPart.Trim();
            bool isClosed = html.EndsWith("/");

            int spaceIndex = html.IndexOf(" ", StringComparison.Ordinal);
            if (spaceIndex < 0)
            {
                if(isClosed)
                    html = html.Substring(0, html.Length - 1);

                return new HtmlElement(html, !CanHaveContent(html));
            }

            string tagName = html.Substring(0, spaceIndex);
            html = html.Substring(spaceIndex + 1);

            if (isClosed)
                html = html.Substring(0, html.Length - 1);

            if (!isClosed && !CanHaveContent(tagName.ToLower()))
                isClosed = true;

            HtmlElement element = new HtmlElement(tagName, isClosed);

            int len = html.Length;
            string attrName = string.Empty;
            string attrVal = string.Empty;
            bool isName = true;
            bool isValue = false;
            bool hasQuotes = false;

            for (var i = 0; i < len; i++)
            {
                string s = html.Substring(i, 1);

                if (s == "=" && !isValue)
                {
                    isName = false;
                    isValue = true;

                    string nextChar = html.Substring(i + 1, 1);
                    hasQuotes = (nextChar == "\"" || nextChar == "'");
                }
                else if (s == " " && isName)
                {
                    //add attribute that requires no value
                    element.Add(attrName, attrName);

                    //reset attribute name
                    attrName = string.Empty;
                    attrVal = string.Empty;
                }
                else if (s == " " && attrVal.Length > 0)
                {
                    if (!hasQuotes || (attrVal[0] == attrVal[attrVal.Length - 1]))
                    {
                        isValue = false;
                        isName = true;

                        string value = FixAttributeValue(attrVal);
                        element.Add(attrName, value);

                        attrName = string.Empty;
                        attrVal = string.Empty;
                    }
                    else if (isValue)
                        attrVal += s;
                }

                else if (isName)
                {
                    attrName += s;
                }
                else if (isValue)
                    attrVal += s;
            }

            if (isName && attrName != string.Empty && attrVal == string.Empty)
                attrVal = attrName;

            if (attrName != string.Empty && attrVal != string.Empty)
            {
                string value = FixAttributeValue(attrVal);
                element.Add(attrName, value);
            }

            return element;
        }
        public static void ReplaceMedia(HtmlElement element)
        {
            for (int i = 0; i < element.ChildNodes.Count; i++)
            {
                if (element.ChildNodes[i] is HtmlElement)
                {
                    HtmlElement innerElement = element.ChildNodes[i] as HtmlElement;

                    if (innerElement.Name == "img")
                    {
                        HtmlAttribute srcAttribute = innerElement.Attributes.FirstOrDefault(p => p.Name == "src");
                        Uri address;

                        if (srcAttribute != null &&
                            !string.IsNullOrEmpty(srcAttribute.Value) &&
                            Uri.TryCreate(srcAttribute.Value, UriKind.RelativeOrAbsolute, out address))
                        {
                            if (!address.PathAndQuery.StartsWith("/scripts/ckeditor/plugins/smiley/images/"))
                            {
                                innerElement.Add("data-original", srcAttribute.Value);
                                innerElement.Add("src", "/images/gimp_5834.png");
                                innerElement.Add("style", "");
                                innerElement.Add("width", "");
                                innerElement.Add("height", "");
                                innerElement.Add("class", "art-img-thumb");
                            }
                        }
                    }
                    else if (innerElement.Name == "iframe" || innerElement.Name == "frame")
                    {
                        element.RemoveChildAt(i);

                        HtmlElement newImage = new HtmlElement("img", true);
                        newImage.Add("src", "/images/youtube-icon.png");
                        newImage.Add("class", "art-img-thumb-yt");
                        element.Insert(i, newImage);
                    }
                    else
                    {
                        ReplaceMedia(innerElement);
                    }
                }
            }
        }