Beispiel #1
0
        private void ConvertHtmlTextNode(HtmlStringNode htmlStringNode)
        {
            var origString = htmlStringNode.String;
            var text       = origString.TrimEnd();

            _lastBlockIsMarkdown = true;

            bool isFirstCharWhitespace = origString.Length > 1 && char.IsWhiteSpace(origString[0]);

            if (_options.LinesMaxLength != 0)
            {
                string[] words = text.Split(SpacesAndNewLines, StringSplitOptions.RemoveEmptyEntries);
                for (var i = 0; i < words.Length; i++)
                {
                    AppendWithBreak(words[i], i == 0 && !isFirstCharWhitespace);
                }
            }
            else
            {
                AppendWithBreak(text, true);
            }

            if (origString.Length > 1 && char.IsWhiteSpace(origString[^ 1]) && !_result.IsLastCharWhitespaceOrLeadingPunctuation())
Beispiel #2
0
        private HtmlElementNode ParseElementNode(HtmlParser.ElementContext elementContext)
        {
            var content = new List <Node>(elementContext.content().Length);

            foreach (var contentContext in elementContext.content())
            {
                content.Add(ParseContent(contentContext));
            }

            bool voidElement = elementContext.voidElementTag() != null;

            var tagName = new HtmlStringNode(voidElement
                ? (ITerminalNode)elementContext.voidElementTag().GetChild(0)
                : elementContext.TAG_NAME());
            var attributes = new Dictionary <string, HtmlAttributeNode>();

            foreach (HtmlParser.AttributeContext attributeContext in elementContext.attribute())
            {
                var nameNode = new HtmlStringNode(attributeContext.TAG_NAME());

                var    valueTerminal = attributeContext.ATTR_VALUE();
                var    valueSymbol   = valueTerminal.Symbol;
                string value         = valueSymbol.Text.Trim('\'', '"');
                var    valueNode     = new HtmlStringNode(valueTerminal, value,
                                                          valueSymbol.StartIndex, valueSymbol.StopIndex - valueSymbol.StartIndex + 1);

                attributes.Add(nameNode.String.ToLowerInvariant(), new HtmlAttributeNode(attributeContext, nameNode, valueNode));
            }

            HtmlStringNode?address         = null;
            bool           isImage         = false;
            string         tagNameString   = tagName.String.ToLowerInvariant();
            string?        addressAttrName = null;

            if (tagNameString == "a")
            {
                addressAttrName = "href";
            }
            else if (tagNameString == "img")
            {
                addressAttrName = "src";
                isImage         = true;
            }
            else if (tagNameString == LinkmapTagName)
            {
                Link?srcLink = null, dstLink = null;

                if (!attributes.TryGetValue("src", out HtmlAttributeNode? srcNode))
                {
                    _logger.Error($"{LinkmapTagName} element should contain src attribute at {tagName.LineColumnSpan}");
                }
                else
                {
                    srcLink = Link.Create(srcNode.Value, srcNode.Value.String);
                    Link?existingLink;
                    if ((existingLink = _linksMap.Keys.FirstOrDefault(key => key.Address.Equals(srcLink.Address))) != null)
                    {
                        _logger.Warn($"{LinkmapTagName} \"{srcLink.Node.Substring}\" at {srcLink.Node.LineColumnSpan} replaces linkmap at {existingLink.Node.LineColumnSpan}");
                    }
                }

                if (!attributes.TryGetValue("dst", out HtmlAttributeNode? dstNode))
                {
                    _logger.Error($"{LinkmapTagName} element should contain dst attribute at {tagName.LineColumnSpan}");
                }
                else
                {
                    dstLink = Link.Create(dstNode.Value, dstNode.Value.String);
                }

                if (srcLink != null && dstLink != null)
                {
                    if (srcLink.Address == HeaderImageLink)
                    {
                        _headerImageLink = dstLink;
                    }
                    else
                    {
                        _linksMap[srcLink] = dstLink;
                    }
                }
            }
            else if (tagNameString == IncludeTagName)
            {
                if (!attributes.TryGetValue("src", out HtmlAttributeNode? srcNode))
                {
                    _logger.Error($"{IncludeTagName} element should contain src attribute at {tagName.LineColumnSpan}");
                }
                else
                {
                    var srcLink = Link.Create(srcNode.Value, srcNode.Value.String);
                    if (srcLink is LocalLink localLink)
                    {
                        var rootDirectory   = Path.GetDirectoryName(_file.Name) ?? "";
                        var includeFilePath = Path.Combine(rootDirectory, localLink.Address);
                        if (!File.Exists(includeFilePath))
                        {
                            _logger.Error($"File {includeFilePath} does not exist at {localLink.Node.LineColumnSpan}");
                        }
                        else
                        {
                            var includeFile        = new TextFile(File.ReadAllText(includeFilePath), includeFilePath);
                            var parser             = new Parser(_options, _logger, includeFile);
                            var includeParseResult = parser.Parse();

                            foreach (KeyValuePair <Node, Link> pair in includeParseResult.Links)
                            {
                                _links.Add(pair.Key, pair.Value);
                            }

                            foreach ((Link includeKey, Link includeValue) in includeParseResult.LinksMap)
                            {
                                Link?existingLinkMap;
                                if ((existingLinkMap = _linksMap.Keys.FirstOrDefault(key => key.Address.Equals(includeKey.Address))) != null)
                                {
                                    _logger.Warn($"{LinkmapTagName} \"{existingLinkMap.Node.Substring}\" at {existingLinkMap.Node.LineColumnSpan} replaces " +
                                                 $"linkmap at {includeKey.Node.LineColumnSpan} at {includeKey.Node.File.Name}");
                                }
                                else
                                {
                                    _linksMap.Add(includeKey, includeValue);
                                }
                            }

                            foreach ((string anchorKey, Anchor anchorValue) in includeParseResult.Anchors)
                            {
                                if (_anchors.TryGetValue(anchorKey, out Anchor? existingAnchor))
                                {
                                    _logger.Warn($"Anchor {existingAnchor.Address} at {existingAnchor.Node.LineColumnSpan} replaces "
                                                 + $"anchor at {anchorValue.Node.LineColumnSpan} at {anchorValue.Node.File.Name}");
                                }
                                else
                                {
                                    _anchors.Add(anchorKey, anchorValue);
                                }
                            }

                            content.Add(includeParseResult.Node);
                        }
                    }
                    else
                    {
                        _logger.Error($"Only local files can be included via <include/> element at {srcLink.Node.LineColumnSpan}");
                    }
                }
            }

            if (addressAttrName != null)
            {
                if (attributes.TryGetValue(addressAttrName, out HtmlAttributeNode? htmlAttributeNode))
                {
                    address = htmlAttributeNode.Value;
                }
                else
                {
                    _logger.Error($"Element <{tagNameString}> does not contain required '{addressAttrName}' attribute at {tagName.LineColumnSpan}");
                }
            }

            var closingTag = elementContext.GetChild(elementContext.ChildCount - 1);
            var result     = new HtmlElementNode(elementContext, tagName, attributes, content,
                                                 closingTag is ParserRuleContext parserRuleContext
                    ? new HtmlStringNode(parserRuleContext)
                    : new HtmlStringNode((ITerminalNode)closingTag));

            if (address != null)
            {
                _links.Add(result, Link.Create(result, address.String, isImage, address.Start, address.Length));
            }

            return(result);
        }