private static void UpdateHref(HtmlAgilityPack.HtmlNode link, string attribute, IDocumentBuildContext context, string relativePath) { var originalHref = link.GetAttributeValue(attribute, null); var anchor = link.GetAttributeValue("anchor", null); link.Attributes.Remove("anchor"); string href; var path = TypeForwardedToRelativePath.TryParse(originalHref); if (path?.IsFromWorkingFolder() == true) { var targetPath = (TypeForwardedToRelativePath)context.GetFilePath(path.UrlDecode()); if (targetPath != null) { href = (targetPath.RemoveWorkingFolder() - (TypeForwardedToRelativePath)relativePath).UrlEncode(); } else { Logger.LogWarning($"File {path} is not found in {relativePath}."); // TODO: what to do if file path not exists? // CURRENT: fallback to the original one href = (path.UrlDecode().RemoveWorkingFolder() - (TypeForwardedToRelativePath)relativePath).UrlEncode(); } link.SetAttributeValue(attribute, href + anchor); } }
private string NormalizeHref(string href, TypeForwardedToRelativePath relativeToFile) { if (!Utility.IsSupportedRelativeHref(href)) { return(href); } return((relativeToFile + (TypeForwardedToRelativePath)href).GetPathFromWorkingFolder()); }
private static List <HomepageInfo> GetHomepages(DocumentBuildContext context) { return(context.GetTocInfo() .Where(s => !string.IsNullOrEmpty(s.Homepage)) .Select(s => new HomepageInfo { Homepage = TypeForwardedToRelativePath.GetPathWithoutWorkingFolderChar(s.Homepage), TocPath = TypeForwardedToRelativePath.GetPathWithoutWorkingFolderChar(context.GetFilePath(s.TocFileKey)) }).ToList()); }
private static void UpdateToHrefFromWorkingFolder(HtmlNode html, string filePath) { foreach (var pair in GetHrefNodes(html)) { var link = pair.Attr; if (TypeForwardedToPathUtility.IsRelativePath(link.Value) && !TypeForwardedToRelativePath.IsPathFromWorkingFolder(link.Value) && !link.Value.StartsWith("#")) { link.Value = ((TypeForwardedToRelativePath)filePath + (TypeForwardedToRelativePath)link.Value).GetPathFromWorkingFolder(); } } }
private ImmutableDictionary <string, ImmutableList <LinkSourceInfo> > GetFileLinkSource(FileAndType ft, HtmlDocument doc) { 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 (TypeForwardedToRelativePath.IsRelativePath(linkFile)) { var path = (TypeForwardedToRelativePath)ft.File + (TypeForwardedToRelativePath)linkFile; string file = path.GetPathFromWorkingFolder().UrlDecode(); if (SourceFiles.ContainsKey(file)) { link.Value = file; if (!string.IsNullOrEmpty(anchor) && string.Equals(link.Name, "href", StringComparison.OrdinalIgnoreCase)) { pair.Node.SetAttributeValue("anchor", anchor); } } List <LinkSourceInfo> sources; if (!fileLinkSources.TryGetValue(file, out 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())); }
/// <summary> /// return the nearest toc relative to the current file /// "near" means less subdirectory count /// when subdirectory counts are same, "near" means less parent directory count /// e.g. "../../a/TOC.md" is nearer than "b/c/TOC.md" /// </summary> private static FileInfo GetNearestToc(IEnumerable <FileInfo> tocFiles, TypeForwardedToRelativePath file) { if (tocFiles == null) { return(null); } return((from toc in tocFiles where toc.File != null let relativePath = toc.File.RemoveWorkingFolder() - file orderby relativePath.SubdirectoryCount, relativePath.ParentDirectoryCount select toc) .FirstOrDefault()); }
public static string ReadAllText(this FileAbstractLayer fal, RelativePath file) { using var sr = OpenReadText(fal, file); return(sr.ReadToEnd()); }
public IEnumerable <string> GetExpectedPhysicalPath(RelativePath file) => from r in Readers from f in r.GetExpectedPhysicalPath(file) select f;
public FileInfo(string key, TypeForwardedToRelativePath file) { Key = key; File = file; }
public static StreamWriter CreateText(this FileAbstractLayer fal, RelativePath file) => new StreamWriter(fal.Create(file));
public static void WriteAllText(this FileAbstractLayer fal, RelativePath file, string content) { using var writer = CreateText(fal, file); writer.Write(content); }
/// <summary> /// return the nearest toc relative to the current file /// "near" means less subdirectory count /// when subdirectory counts are same, "near" means less parent directory count /// e.g. "../../a/TOC.md" is nearer than "b/c/TOC.md" /// </summary> private static FileInfo GetNearestToc(IEnumerable<FileInfo> tocFiles, TypeForwardedToRelativePath file) { if (tocFiles == null) { return null; } return (from toc in tocFiles where toc.File != null let relativePath = toc.File.RemoveWorkingFolder() - file orderby relativePath.SubdirectoryCount, relativePath.ParentDirectoryCount select toc) .FirstOrDefault(); }
public static bool HasProperty(this FileAbstractLayer fal, RelativePath file, string propertyName) { var dict = fal.GetProperties(file); return(dict.ContainsKey(propertyName)); }
public static StreamReader OpenReadText(this FileAbstractLayer fal, RelativePath file) => new StreamReader(fal.OpenRead(file));
public FileInfo(string key, TypeForwardedToRelativePath file) { Key = key; File = file; }
public IEnumerable <string> GetExpectedPhysicalPath(RelativePath file) => new[] { Path.Combine(InputFolder, file.RemoveWorkingFolder().ToString()) };
public static string GetOutputPhysicalPath(this FileAbstractLayer fal, RelativePath file) => FileAbstractLayerBuilder.Default .ReadFromOutput(fal) .Create() .GetPhysicalPath(file);
private string NormalizeHref(string href, TypeForwardedToRelativePath relativeToFile) { if (!Utility.IsSupportedRelativeHref(href)) { return href; } return (relativeToFile + (TypeForwardedToRelativePath)href).GetPathFromWorkingFolder(); }
public static FileLinkInfo Create(string fromFileInSource, string fromFileInDest, string href, IDocumentBuildContext context) { if (fromFileInSource == null) { throw new ArgumentNullException(nameof(fromFileInSource)); } if (fromFileInDest == null) { throw new ArgumentNullException(nameof(fromFileInDest)); } if (href == null) { throw new ArgumentNullException(nameof(href)); } if (UriUtility.HasFragment(href) || UriUtility.HasQueryString(href)) { throw new ArgumentException("fragment and query string is not supported", nameof(href)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var path = RelativePath.TryParse(href); if (path == null) { throw new ArgumentException("only relative path is supported", nameof(href)); } var fli = new FileLinkInfo { FromFileInSource = fromFileInSource, FromFileInDest = fromFileInDest }; if (path.IsFromWorkingFolder()) { var targetInSource = path.UrlDecode(); fli.ToFileInSource = targetInSource.RemoveWorkingFolder(); fli.ToFileInDest = RelativePath.GetPathWithoutWorkingFolderChar(context.GetFilePath(targetInSource)); fli.FileLinkInSource = targetInSource - (RelativePath)fromFileInSource; if (fli.ToFileInDest != null) { var resolved = (RelativePath)fli.ToFileInDest - (RelativePath)fromFileInDest; fli.FileLinkInDest = resolved; fli.Href = resolved.UrlEncode(); } else { fli.Href = (targetInSource.RemoveWorkingFolder() - ((RelativePath)fromFileInSource).RemoveWorkingFolder()).UrlEncode(); } } else { fli.FileLinkInSource = path.UrlDecode(); fli.ToFileInSource = ((RelativePath)fromFileInSource + path).RemoveWorkingFolder(); fli.FileLinkInDest = fli.FileLinkInSource; fli.Href = href; } return(fli); }