/// <summary> /// Copies a folder to another folder, maintaining its internal structure. /// Allows for file processing as well. /// </summary> /// <param name="src">The source folder.</param> /// <param name="dst">The destination folder.</param> /// <param name="processFunction">The function which will process each file before it is copied.</param> private static void CopyFolderToFolder(string src, string dst, Action <ProcessFileInfo> processFunction = null) { string[] sourceFiles = Directory.GetFiles(src, "*", SearchOption.AllDirectories); string[] directories = Directory.GetDirectories(src, "*", SearchOption.AllDirectories); foreach (string dir in directories) { Directory.CreateDirectory(dir.Replace(src, dst)); } foreach (string file in sourceFiles) { // Check if file is being skipped. string fileName = Path.GetFileName(file); if (SkippedFiles.FirstOrDefault(x => x == fileName) != null) { continue; } string destName = file.Replace(src, dst); if (processFunction != null) { string[] contents = File.ReadAllLines(file); var info = new ProcessFileInfo(destName, contents); processFunction(info); File.WriteAllLines(info.FileName, info.Contents); } else { File.Copy(file, destName, true); } } }
/// <summary> /// Transforms the markdown file into an html file. /// </summary> /// <param name="fileInfo"></param> /// <returns></returns> private static ProcessFileInfo ProcessFile(ProcessFileInfo fileInfo) { Console.WriteLine($" Processing file {fileInfo.FileName}..."); fileInfo.FileName = Path.Join(Path.GetDirectoryName(fileInfo.FileName), Path.GetFileNameWithoutExtension(fileInfo.FileName)) + ".html"; // Check if the markdown template is loaded. if (_cachedMarkdownTemplate == null) { string templateFile = Path.Join(Settings.TemplateDirectory, "markdownTemplate.html"); if (File.Exists(templateFile)) { _cachedMarkdownTemplate = File.ReadAllLines(templateFile).ToList(); // Find the index where the content is to be inserted. for (int i = 0; i < _cachedMarkdownTemplate.Count; i++) { if (!_cachedMarkdownTemplate[i].Contains("[Content]")) { continue; } _cachedMarkdownTemplate.RemoveAt(i); _markdownTemplateInsertionIndex = i; break; } if (_markdownTemplateInsertionIndex == -1) { Console.WriteLine(" [!] Couldn't find markdown template [Content] tag!"); } Console.WriteLine(" Loaded markdown template file!"); } else { Console.WriteLine(" [!] Couldn't find markdown template html!"); return(fileInfo); } } // Copy the template into a new content holder. var newFileContent = new List <string>(); newFileContent.AddRange(_cachedMarkdownTemplate); // Insert the rendered html. string htmlMarkdown = Markdown.ToHtml(string.Join("\n", fileInfo.Contents), MarkDigPipeline); newFileContent.Insert(_markdownTemplateInsertionIndex, htmlMarkdown); // Perform additional processing on html to insert relative paths to the template. for (int i = 0; i < newFileContent.Count; i++) { newFileContent[i] = newFileContent[i].Replace("[RelativePath]", Path.GetRelativePath(Path.GetDirectoryName(fileInfo.FileName), Settings.OutputDirectory).Replace("\\", "/")); } fileInfo.Contents = newFileContent.ToArray(); return(fileInfo); }
/// <summary> /// Preprocess HTML tags. /// - [Title] turns into Settings.WikiTitle /// </summary> /// <param name="fileInfo">The file info.</param> /// <returns>The processed file info.</returns> public static ProcessFileInfo ProcessHTMLTags(ProcessFileInfo fileInfo) { var processingTags = new Dictionary <string, string> { { "[Title]", Settings.WikiTitle } }; FindReplaceTags(fileInfo.Contents, processingTags); return(fileInfo); }
/// <summary> /// Applies markdown preprocessing such as: /// - Adding wiki style links. /// </summary> /// <param name="fileInfo">The file info.</param> /// <param name="topNode">The top node in the tree.</param> /// <returns>The processed file info.</returns> private static ProcessFileInfo PreprocessFile(ProcessFileInfo fileInfo, Node topNode) { Console.WriteLine($" Preprocessing file {fileInfo.FileName}..."); string[] contents = fileInfo.Contents; // Create a lookup for node links. var nodeLookup = new Dictionary <string, Node>(StringComparer.OrdinalIgnoreCase); var nodeStack = new Stack <Node>(); nodeStack.Push(topNode); while (nodeStack.Count != 0) { Node curNode = nodeStack.Pop(); // Add children to the stack to be processed. foreach (Node child in curNode.Children) { nodeStack.Push(child); } // Check if the node name is taken. string keyName = curNode.Name; if (!nodeLookup.ContainsKey(keyName)) { nodeLookup.Add(keyName, curNode); } // Add the node as relative path as well. string pathFromSource = Path.Join(Path.GetDirectoryName(curNode.File).Replace(Settings.SourcePath, ""), Path.GetFileNameWithoutExtension(curNode.File)); if (!string.IsNullOrEmpty(pathFromSource) && pathFromSource != "about:blank" && !nodeLookup.ContainsKey(pathFromSource)) { nodeLookup.Add(pathFromSource, curNode); } } for (int i = 0; i < contents.Length; i++) { // Replace with custom tags. foreach (Tag tag in Settings.CustomTags) { contents[i] = contents[i].Replace(tag.Key, tag.Value); } // Look for links. Match match = _linkFinder.Match(contents[i]); if (match.Success) { while (match.Success) { string linkText = match.Groups[1].Value; //string linkOverwrite = match.Groups[3].Value; string link; // Look for a link overwrite. Format is "[regex matched](link overwrite)" string linkOverwrite = null; int matchEnd = match.Index + match.Length; if (matchEnd < contents[i].Length - 1) { // Link overwrite opening tag. if (contents[i][matchEnd] == '(') { // Find the closing bracket. linkOverwrite = ""; int openingBracketsCount = 1; int pointer = matchEnd; while (pointer <= contents[i].Length - 1) { pointer++; char nextChar = contents[i][pointer]; if (nextChar == ')') { openingBracketsCount--; } if (openingBracketsCount == 0) { break; } if (nextChar == '(') { openingBracketsCount++; } linkOverwrite += nextChar; } matchEnd = pointer + 1; } } bool foundLink = nodeLookup.TryGetValue(string.IsNullOrEmpty(linkOverwrite) ? linkText : linkOverwrite, out Node referencedNode); if (foundLink) { string path = TransformPathToWeb(referencedNode.File); link = $"<a class=\"link\" link='{path}'>{linkText}</a>"; } else { link = $"<span class=\"missingLink\">{linkText}</span>"; } contents[i] = contents[i].Substring(0, match.Index) + link + contents[i].Substring(matchEnd); match = _linkFinder.Match(contents[i]); } } // Look for tabs. match = _tabFinder.Match(contents[i]); if (!match.Success) { continue; } while (match.Success) { contents[i] = contents[i].Substring(0, match.Index) + " " + contents[i].Substring(match.Index + match.Length); match = _linkFinder.Match(contents[i]); } } return(fileInfo); }