Ejemplo n.º 1
0
        /// <summary>
        /// Balances out the stream of nodes to form a valid tree.
        /// This process will always try to resolve conflicts by introducing extra inline elements over block elements.
        /// </summary>
        public void Balance(NodeCollection nodes)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException();
            }
            // Fill in missing elements
            List <string> nameStack = new List <string>();

            nodes.Reset();
            Node node = null;

            while ((node = nodes.Next()) != null)
            {
                switch (node.Type)
                {
                case NodeType.Open:
                    OpenNode openNode = (OpenNode)node;
                    if (openNode.Closed)
                    {
                        continue;
                    }
                    nameStack.Insert(0, openNode.Name);
                    break;

                case NodeType.Close:
                    CloseNode closeNode = (CloseNode)node;
                    if (!nameStack.Contains(closeNode.Name))
                    {
                        // Found CloseNode without OpenNode
                        // Fix by insert an OpenNode before it
                        nodes.InsertBefore(
                            closeNode,
                            new OpenNode(closeNode.Name, "", false));
                    }
                    nameStack.Remove(closeNode.Name);
                    break;
                }
            }
            while (nameStack.Count > 0)
            {
                // Found OpenNode without CloseNode
                // Fix by adding a CloseNode at the end of the stream
                string name = nameStack[0];
                nameStack.RemoveAt(0);
                nodes.Add(new CloseNode(name, ""));
            }
            // Resolve tree structure
            List <OpenNode> nodeStack = new List <OpenNode>();

            nodes.Reset();
            while ((node = nodes.Next()) != null)
            {
                switch (node.Type)
                {
                case NodeType.Open:
                    OpenNode on = (OpenNode)node;
                    if (on.Closed)
                    {
                        continue;
                    }
                    nodeStack.Insert(0, on);
                    break;

                case NodeType.Close:
                    // A bit of setup
                    CloseNode closeNode = (CloseNode)node;
                    bool      block     = blockElements.Contains(closeNode.Name);
                    // Find matching OpenNode
                    OpenNode openNode = null;
                    foreach (OpenNode o in nodeStack)
                    {
                        if (o.Name == closeNode.Name)
                        {
                            openNode = o;
                            break;
                        }
                    }
                    if (openNode == null)
                    {
                        throw new InvalidOperationException("Unable to find matching OpenNode to CloseNode");
                    }
                    // Handle incorrect balance
                    int offset = 0;
                    while (nodeStack[offset].Name != closeNode.Name)
                    {
                        OpenNode n = nodeStack[offset];
                        if (block)
                        {
                            nodes.InsertBefore(node, new CloseNode(n.Name, ""));
                            nodes.InsertAfter(node, n.Clone());
                            nodeStack.RemoveAt(offset);
                            offset--;
                        }
                        else
                        {
                            nodes.InsertBefore(n, closeNode.Clone());
                            nodes.InsertAfter(n, openNode.Clone());
                        }
                        offset++;
                    }
                    // All fixed
                    nodeStack.RemoveAt(offset);
                    break;
                }
            }
            // And we're done!
            nodes.Reset();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sanitizes the stream of nodes into exclusively valid AOML.
        /// This process involves changing and removing nodes.
        /// </summary>
        public void Sanitize(NodeCollection nodes)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException();
            }
            // Loop through all nodes
            nodes.Reset();
            Node node = null;

            while ((node = nodes.Next()) != null)
            {
                // Skip content nodes
                if (node.Type == NodeType.Content)
                {
                    continue;
                }
                // Gather info
                OpenNode  openNode  = null;
                CloseNode closeNode = null;
                string    name      = null;
                if (node.Type == NodeType.Open)
                {
                    openNode = (OpenNode)node;
                    name     = openNode.Name;
                    // Check attributes
                    for (int i = 0; i < openNode.Count; i++)
                    {
                        string attr = openNode.GetAttributeName(i);
                        if (!validAttributes.Contains(attr))
                        {
                            openNode.RemoveAttribute(attr);
                            i--;
                        }
                    }
                }
                else if (node.Type == NodeType.Close)
                {
                    closeNode = (CloseNode)node;
                    name      = closeNode.Name;
                }
                // Singular elements
                if (singularElements.Contains(name))
                {
                    // Singular elements don't have closing nodes
                    if (closeNode != null)
                    {
                        nodes.Remove(closeNode);
                    }
                    // Singular elements are always self-closing
                    if (openNode != null)
                    {
                        openNode.Closed = true;
                    }
                    continue;
                }
                else if (inlineElements.Contains(name) || blockElements.Contains(name))
                {
                    if (openNode == null)
                    {
                        continue;
                    }
                    // Let's not use self-closing elements here
                    if (openNode.Closed)
                    {
                        openNode.Closed = false;
                        nodes.InsertAfter(openNode, new CloseNode(name, ""));
                    }
                    continue;
                }
                // Replace node as content node
                if (this.InvalidElementsToContent)
                {
                    // Replace node as content
                    this.ReplaceContent(nodes, node, node.Raw, node.Raw);
                }
                else
                {
                    // Remove node
                    this.ReplaceContent(nodes, node, "", "");
                }
            }
            // And we're done!
            nodes.Reset();
        }