/// <summary> /// This copies additional content files from the specified source /// folder to the specified destination folder and builds table of /// content entries for them. If any subfolders are found below the /// source folder and the wildcard is "*.*", the subfolders are also /// copied recursively. /// </summary> /// <param name="previewing">Pass true to generate the table of content /// collection for previewing without actually copying anything.</param> /// <param name="sourcePath">The source path from which to copy.</param> /// <param name="destPath">The destination path to which to copy.</param> /// <returns>The table of content entry for the folder and all /// of its children or null if there is nothing to show in the table /// of content for this item.</returns> protected TocEntry RecursiveContentCopy(bool previewing, string sourcePath, string destPath) { TocEntry tocFolder, tocEntry; string[] files; string filename, nameLower, rootPath = workingFolder + @"Output\"; bool hasContent = false; if (sourcePath == null) { throw new ArgumentNullException("sourcePath"); } if (destPath == null) { throw new ArgumentNullException("destPath"); } if (toc == null) { throw new ArgumentNullException("toc"); } int idx = sourcePath.LastIndexOf('\\'); string dirName = sourcePath.Substring(0, idx), fileSpec = sourcePath.Substring(idx + 1); tocFolder = new TocEntry(); tocFolder.SourceFile = dirName + @"\"; tocFolder.Title = dirName.Substring(dirName.LastIndexOf("\\") + 1); // Copy all the files in the folder files = Directory.GetFiles(dirName, fileSpec); foreach (string name in files) { if (exclusionList.ContainsKey(name)) { continue; } filename = destPath + Path.GetFileName(name); nameLower = name.ToLower(CultureInfo.InvariantCulture); if (nameLower.EndsWith(".htm") || nameLower.EndsWith(".html")) { tocEntry = BuildProcess.GetTocInfo(name); } else { tocEntry = null; } // If the filename matches the folder name and it's an HTML // file, extract the TOC info from it for the root node. // If there is no info or its excluded, the folder entry won't // have an associated page. Even if excluded, it will still use // the title, default topic, and sort order properties though. if (tocEntry != null) { if (Path.GetFileNameWithoutExtension(name) == tocFolder.Title) { tocFolder.Title = tocEntry.Title; tocFolder.IsDefaultTopic = tocEntry.IsDefaultTopic; tocFolder.SortOrder = tocEntry.SortOrder; tocFolder.SourceFile = name; hasContent = true; // In case it's this page only if (tocEntry.IncludePage) { tocFolder.DestinationFile = filename.Remove(0, rootPath.Length); if (tocFolder.IsDefaultTopic) { defaultTopic = tocFolder.DestinationFile; } } else { tocFolder.DestinationFile = null; } } else { if (tocEntry.IncludePage) { tocEntry.SourceFile = name; tocEntry.DestinationFile = filename.Remove(0, rootPath.Length); tocFolder.Children.Add(tocEntry); } if (tocEntry.IsDefaultTopic) { defaultTopic = tocEntry.DestinationFile; } } } if (!previewing && !Directory.Exists(destPath)) { Directory.CreateDirectory(destPath); } // If the file contains links that need to be resolved, // it is handled separately. if (!previewing && tocEntry != null && (tocEntry.HasLinks || tocEntry.HasCodeBlocks || tocEntry.NeedsColorizing || tocEntry.HasProjectTags)) { // Figure out the path to the root if needed string[] parts = destPath.Remove(0, rootPath.Length).Split('\\'); pathToRoot = String.Empty; for (int part = 0; part < parts.Length - 1; part++) { pathToRoot += "../"; } this.ResolveLinksAndCopy(name, filename, tocEntry); } else { this.ReportProgress("{0} -> {1}", name, filename); // All attributes are turned off so that we can delete // it later. if (!previewing) { File.Copy(name, filename, true); File.SetAttributes(filename, FileAttributes.Normal); } } } // For "*.*", copy subfolders too if (fileSpec == "*.*") { string[] subFolders = Directory.GetDirectories(dirName); foreach (string folder in subFolders) { tocEntry = this.RecursiveContentCopy(previewing, folder + @"\*.*", destPath + folder.Substring(dirName.Length + 1) + @"\"); if (tocEntry != null) { tocFolder.Children.Add(tocEntry); } } } return((hasContent || tocFolder.Children.Count != 0) ? tocFolder : null); }
/// <summary> /// This is called to copy the additional content files and build a /// list of them for the help file project. /// </summary> /// <param name="previewing">Pass true to generate the table of content /// collection for previewing without actually copying anything.</param> /// <remarks>Note that for wilcard content items, the folders are /// copied recursively.</remarks> protected void CopyAdditionalContent(bool previewing) { TocEntry tocEntry; string source, filename, dirName, srcLower, rootPath = workingFolder + @"Output\"; string[] fileList; int idx; toc = new TocEntryCollection(); exclusionList = new Dictionary <string, string>(); // Get a list of the exclusions first foreach (ContentItem ci in project.AdditionalContent) { if (!ci.ExcludeItems) { continue; } source = ci.SourcePath; if (source.IndexOfAny(new char[] { '*', '?' }) == -1) { exclusionList.Add(source, null); } else { idx = source.LastIndexOf('\\'); dirName = source.Substring(0, idx); filename = source.Substring(idx + 1); fileList = Directory.GetFiles(dirName, filename, SearchOption.AllDirectories); foreach (string matchFile in fileList) { exclusionList.Add(matchFile, null); } } } // Now copy the additional content less the excluded files foreach (ContentItem ci in project.AdditionalContent) { if (ci.ExcludeItems) { continue; } source = ci.SourcePath; dirName = workingFolder + @"Output\" + ci.DestinationPath; filename = dirName + Path.GetFileName(source); if (source.IndexOfAny(new char[] { '*', '?' }) == -1) { if (exclusionList.ContainsKey(source)) { continue; } srcLower = source.ToLower(CultureInfo.InvariantCulture); if (srcLower.EndsWith(".htm") || srcLower.EndsWith(".html")) { tocEntry = BuildProcess.GetTocInfo(source); // If not to be included in the TOC, don't add it if (tocEntry.IncludePage) { tocEntry.SourceFile = source; tocEntry.DestinationFile = filename.Remove(0, rootPath.Length); toc.Add(tocEntry); } if (tocEntry.IsDefaultTopic) { defaultTopic = tocEntry.DestinationFile; } } else { tocEntry = null; } if (!previewing && !Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } // If the file contains links that need to be resolved, // it is handled separately. if (!previewing && tocEntry != null && (tocEntry.HasLinks || tocEntry.HasCodeBlocks || tocEntry.NeedsColorizing || tocEntry.HasProjectTags)) { // Figure out the path to the root if needed string[] parts = ci.DestinationPath.Split('\\'); pathToRoot = String.Empty; for (int part = 0; part < parts.Length - 1; part++) { pathToRoot += "../"; } this.ResolveLinksAndCopy(source, filename, tocEntry); } else { this.ReportProgress("{0} -> {1}", source, filename); // All attributes are turned off so that we can delete // it later. if (!previewing) { File.Copy(source, filename, true); File.SetAttributes(filename, FileAttributes.Normal); } } } else { tocEntry = this.RecursiveContentCopy(previewing, source, dirName); if (tocEntry != null) { if (ci.DestinationPath.Length != 0) { toc.Add(tocEntry); } else { // If the content is copied to the root, just // add the children to the TOC. foreach (TocEntry te in tocEntry.Children) { toc.Add(te); } } } } } // Sort the additional content entries into the proper order toc.Sort(); codeColorizer = null; sharedContent = null; exclusionList = null; }