private static ImmutableDictionary <string, ImmutableList <LinkSourceInfo> > GetFileLinkSource(string currentFile, HtmlDocument doc, ImmutableDictionary <string, FileAndType> sourceFiles) { var fileLinkSources = new Dictionary <string, List <LinkSourceInfo> >(); foreach (var pair in (from n in doc.DocumentNode.Descendants() where !string.Equals(n.Name, "xref", StringComparison.OrdinalIgnoreCase) from attr in n.Attributes where string.Equals(attr.Name, "src", StringComparison.OrdinalIgnoreCase) || string.Equals(attr.Name, "href", StringComparison.OrdinalIgnoreCase) where !string.IsNullOrWhiteSpace(attr.Value) select new { Node = n, Attr = attr }).ToList()) { string anchor = null; var link = pair.Attr; string linkFile = link.Value; var index = linkFile.IndexOfAny(UriFragmentOrQueryString); if (index != -1) { anchor = linkFile.Substring(index); linkFile = linkFile.Remove(index); } if (RelativePath.IsRelativePath(linkFile)) { var path = (RelativePath)currentFile + RelativePath.FromUrl(linkFile); var file = path.GetPathFromWorkingFolder(); if (sourceFiles.ContainsKey(file)) { string anchorInHref; if (!string.IsNullOrEmpty(anchor) && string.Equals(link.Name, "href", StringComparison.OrdinalIgnoreCase)) { anchorInHref = anchor; } else { anchorInHref = null; } link.Value = file.UrlEncode().ToString() + anchorInHref; } if (!fileLinkSources.TryGetValue(file, out List <LinkSourceInfo> sources)) { sources = new List <LinkSourceInfo>(); fileLinkSources[file] = sources; } sources.Add(new LinkSourceInfo { Target = file, Anchor = anchor, SourceFile = pair.Node.GetAttributeValue("sourceFile", null), LineNumber = pair.Node.GetAttributeValue("sourceStartLineNumber", 0), }); } } return(fileLinkSources.ToImmutableDictionary(x => x.Key, x => x.Value.ToImmutableList())); }