예제 #1
0
        void TrimNodeOnStart(HtmlText textNode)
        {
            // If we need to decode entities
            if (settings.DecodeEntityCharacters)
            {
                if (textNode.Slice.IndexOf('&') >= 0)
                {
                    var text = textNode.Slice.ToString();
                    textNode.Slice = new StringSlice(EntityHelper.Unescape(text));
                }
            }

            // If we don't do anything for TextNode, we can early exit
            if (!settings.CollapseWhitespaces)
            {
                return;
            }

            // Find the first non-transparent parent
            var parent = textNode.Parent;

            while (parent != null && (parent.Descriptor == null || parent.Descriptor.Category == ContentKind.Transparent))
            {
                parent = parent.Parent;
            }

            if (!textNode.Slice.IsEmptyOrWhiteSpace() || (parent?.Descriptor != null && xmlNamespaceCount == 0))
            {
                pendingTexts.Add(textNode);
            }
            else
            {
                textNode.Remove();
            }
        }
예제 #2
0
        private void TrimPendingTextNodes()
        {
            HtmlText previousTextNode = null;

            for (int i = 0; i < pendingTexts.Count; i++)
            {
                var textNode = pendingTexts[i];

                var previousElement = textNode.PreviousSibling as HtmlElement;
                var nextElement     = textNode.NextSibling as HtmlElement;

                // We can trim the heading whitespaces if:
                // - we don't have a previous element (either inline or parent container)
                // - OR the previous element (sibling or parent) is not a tag that require preserving spaces around
                // - OR the previous text node has already some trailing spaces
                if ((previousTextNode == null || previousTextNode.Slice.HasTrailingSpaces()) && (previousElement == null || textNode.Slice.IsEmptyOrWhiteSpace()))
                {
                    textNode.Slice.TrimStart();
                }

                // We can trim the traling whitespaces if:
                // - we don't have a next element (either inline or parent container)
                // - OR the next element (sibling or parent) is not a tag that require preserving spaces around
                if (nextElement == null && previousTextNode != null && textNode.NextSibling == null && (i + 1 >= pendingTexts.Count || pendingTexts[i + 1].Slice.StartsBySpace()))
                {
                    textNode.Slice.TrimEnd();
                }

                // If we are not in the context of a tag that doesn't accept to collapse whitespaces,
                // we can collapse them for this text node
                if (pendingTagNonCollapsibleWithSpaces == 0)
                {
                    textNode.Slice.CollapseSpaces();
                }

                // If the text node is empty, remove it from the tree
                if (textNode.Slice.IsEmpty())
                {
                    textNode.Remove();
                }
                else
                {
                    // Replace the previous textnode
                    previousTextNode = textNode;
                }
            }

            // Trim any trailing spaces of the last known text node if we are moving to a block level
            if (previousTextNode != null)
            {
                previousTextNode.Slice.TrimEnd();
                if (previousTextNode.Slice.IsEmpty())
                {
                    previousTextNode.Remove();
                }
            }

            pendingTexts.Clear();
        }
예제 #3
0
        HtmlText GetTextNode(SourceLocation from)
        {
            var textNode = CurrentParent.LastChild as HtmlText;

            if (textNode == null)
            {
                textNode = new HtmlText()
                {
                    Location = from
                };
                CurrentParent.AppendChild(textNode);
            }
            return(textNode);
        }
예제 #4
0
        protected override void Write(HtmlText node)
        {
            var descriptorName = node.Parent.Descriptor?.Name;

            var isOnlyChild = node.Parent.FirstChild == node.Parent.LastChild && node.IsFirstChild();

            var newlineForText            = !isOnlyChild || settings.OutputTextNodesOnNewLine;
            var previousNodeIsNonBreaking = node.PreviousSibling is HtmlElement e && settings.InlineTagsPreservingSpacesAround.ContainsKey(e.Descriptor?.Name ?? "null");

            if (ShouldPretty(node.Parent) && newlineForText && (descriptorName == null || !settings.TagsWithNonCollapsibleWhitespaces.ContainsKey(descriptorName)) && !previousNodeIsNonBreaking)
            {
                writer.WriteLine();
                this.WriteIndent();
                node.Slice.TrimStart();
            }

            base.Write(node);
        }
예제 #5
0
 protected virtual void Write(HtmlText node)
 {
     Write(node.Slice.ToString());
 }
예제 #6
0
        private void TrimPendingTextNodes()
        {
            if (pendingTagNonCollapsibleWithSpaces == 0)
            {
                HtmlText previousTextNode = null;
                HtmlText firstTextNode    = null;
                for (int i = 0; i < pendingTexts.Count; i++)
                {
                    var textNode = pendingTexts[i];
                    if (firstTextNode == null)
                    {
                        firstTextNode = textNode;
                    }

                    var previousElement = textNode.PreviousSibling as HtmlElement;
                    var nextElement     = textNode.NextSibling as HtmlElement;

                    var isPreviousElementPreservingSpace = previousElement != null &&
                                                           settings.InlineTagsPreservingSpacesAround.ContainsKey(
                        previousElement.Name);
                    var isNextElementPreservingSpace = nextElement != null &&
                                                       settings.InlineTagsPreservingSpacesAround.ContainsKey(nextElement
                                                                                                             .Name);

                    // If we expect to keep one space after collapsing
                    var isFirstText = textNode == firstTextNode;
                    var isLastText  = i + 1 == pendingTexts.Count;
                    if (!settings.KeepOneSpaceWhenCollapsing || isFirstText || isLastText)
                    {
                        var isPreviousTrailing  = previousTextNode != null && previousTextNode.Slice.HasTrailingSpaces();
                        var isNextStartsBySpace = i + 1 >= pendingTexts.Count ||
                                                  pendingTexts[i + 1].Slice.StartsBySpace();

                        // We can trim the heading whitespaces if:
                        // - we don't have a previous element (either inline or parent container)
                        // - OR the previous element (sibling or parent) is not a tag that require preserving spaces around
                        // - OR the previous text node has already some trailing spaces
                        if (!isPreviousElementPreservingSpace && (previousTextNode == null || isPreviousTrailing) &&
                            (previousElement == null || isFirstText))
                        {
                            textNode.Slice.TrimStart();
                        }

                        // We can trim the traling whitespaces if:
                        // - we don't have a next element (either inline or parent container)
                        // - OR the next element (sibling or parent) is not a tag that require preserving spaces around
                        if (!isNextElementPreservingSpace && isNextStartsBySpace)
                        {
                            textNode.Slice.TrimEnd();
                        }
                    }

                    // If we are not in the context of a tag that doesn't accept to collapse whitespaces,
                    // we can collapse them for this text node
                    textNode.Slice.CollapseSpaces();

                    // If the text node is empty, remove it from the tree
                    if (textNode.Slice.IsEmpty() || (textNode.Slice.IsEmptyOrWhiteSpace() &&
                                                     !isPreviousElementPreservingSpace &&
                                                     !isNextElementPreservingSpace))
                    {
                        textNode.Remove();
                        if (firstTextNode == textNode)
                        {
                            firstTextNode = null;
                        }
                    }
                    else
                    {
                        // Replace the previous textnode
                        previousTextNode = textNode;
                    }
                }

                // Trim any trailing spaces of the last known text node if we are moving to a block level
                if (previousTextNode != null && previousTextNode.NextSibling == null)
                {
                    previousTextNode.Slice.TrimEnd();
                    if (previousTextNode.Slice.IsEmpty())
                    {
                        previousTextNode.Remove();
                    }
                }
            }

            pendingTexts.Clear();
        }
예제 #7
0
 protected override void Write(HtmlText node)
 {
     Start("#txt");
     base.Write(node);
     FlushDOM();
 }