From 40b12d17f9a2582046c8b14d3d3ffdf45aad2d08 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Tue, 18 Jul 2023 21:46:56 -0700 Subject: [PATCH] Relative Path to relative to content --- .kanbn/board.json | 234 ++++++++++++ .kanbn/board.md | Bin 4198 -> 5686 bytes .kanbn/index.md | 4 + .kanbn/tasks/markdown-links-to-json.md | 10 + .kanbn/tasks/markdown-to-json.md | 10 + .../relative-path-to-relative-to-content.md | 11 + .vscode/launch.json | 11 +- .vscode/settings.json | 16 +- .vscode/tasks.json | 50 ++- File-Folder-Helper.csproj | 4 +- Helpers/HelperCreateNoteFiles.cs | 176 ++++++--- Helpers/HelperMarkdown.cs | 338 ++++++++++++++---- Helpers/PackageJson.cs | 2 +- Models/AppSettings.cs | 2 +- Models/Binder/AppSettings.cs | 2 +- Worker.cs | 7 +- package.json | 11 +- 17 files changed, 716 insertions(+), 172 deletions(-) create mode 100644 .kanbn/board.json create mode 100644 .kanbn/tasks/markdown-links-to-json.md create mode 100644 .kanbn/tasks/markdown-to-json.md create mode 100644 .kanbn/tasks/relative-path-to-relative-to-content.md diff --git a/.kanbn/board.json b/.kanbn/board.json new file mode 100644 index 0000000..efbf89b --- /dev/null +++ b/.kanbn/board.json @@ -0,0 +1,234 @@ +{ + "headings": [ + { + "name": "Backlog", + "heading": "^:^+Backlog^:" + }, + { + "name": "Todo", + "heading": "^:^+Todo^:" + }, + { + "name": "In Progress", + "heading": "^:^c»^: ^+In Progress^:" + }, + { + "name": "Done", + "heading": "^:^g✓^: ^+Done^:" + } + ], + "lanes": [ + { + "name": "All tasks", + "columns": [ + [ + { + "id": "relative-path-to-relative-to-content", + "name": "Relative Path to relative to content", + "description": "- [ ] Update method ConvertLinksForHugo to actual wanted results", + "metadata": { + "created": "2023-07-18T14:50:28.239Z", + "updated": "2023-07-18T14:54:09.060Z", + "assigned": "", + "progress": 0, + "tags": [] + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Backlog", + "workload": 2, + "progress": 0, + "remainingWorkload": 2 + }, + { + "id": "markdown-links-to-json", + "name": "Markdown links to json", + "description": "", + "metadata": { + "created": "2023-07-18T14:53:27.412Z", + "updated": "2023-07-18T14:53:33.147Z", + "assigned": "", + "progress": 0, + "tags": [] + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Backlog", + "workload": 2, + "progress": 0, + "remainingWorkload": 2 + }, + { + "id": "markdown-to-json", + "name": "Markdown to json", + "description": "", + "metadata": { + "created": "2023-07-18T14:48:18.667Z", + "updated": "2023-07-18T14:48:18.660Z", + "assigned": "", + "progress": 0, + "tags": [] + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Backlog", + "workload": 2, + "progress": 0, + "remainingWorkload": 2 + } + ], + [ + { + "id": "find-orphan-links", + "name": "Find orphan links", + "description": "", + "metadata": { + "created": "2023-07-08T00:30:27.277Z", + "updated": "2023-07-08T04:49:18.108Z", + "assigned": "", + "progress": 0, + "tags": [], + "started": "2023-07-08T04:41:56.433Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Todo", + "workload": 2, + "progress": 0, + "remainingWorkload": 2 + } + ], + [], + [ + { + "id": "break-circular-references", + "name": "Break Circular References", + "description": "", + "metadata": { + "created": "2023-07-08T00:31:18.301Z", + "updated": "2023-07-08T03:13:47.959Z", + "assigned": "", + "progress": 0, + "tags": [], + "started": "2023-07-08T00:31:22.970Z", + "completed": "2023-07-08T03:13:47.959Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Done", + "workload": 2, + "progress": 1, + "remainingWorkload": 0 + }, + { + "id": "populate-a-collection-of-file-info-front-matter-and-first-indent-of-1", + "name": "Populate a collection of FileInfo, Front Matter and First # indent of 1", + "description": "", + "metadata": { + "created": "2023-07-08T00:30:00.353Z", + "updated": "2023-07-08T04:08:04.155Z", + "assigned": "", + "progress": 0, + "tags": [], + "started": "2023-07-08T02:17:23.556Z", + "completed": "2023-07-08T04:08:04.156Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Done", + "workload": 2, + "progress": 1, + "remainingWorkload": 0 + }, + { + "id": "use-humanizer-on-title-of-links", + "name": "Use humanizer on title of links", + "description": "", + "metadata": { + "created": "2023-07-08T03:22:14.065Z", + "updated": "2023-07-08T04:08:05.706Z", + "assigned": "", + "progress": 0, + "tags": [], + "completed": "2023-07-08T04:08:05.706Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Done", + "workload": 2, + "progress": 1, + "remainingWorkload": 0 + }, + { + "id": "convert-files-to-slug-name", + "name": "Convert files to slug name", + "description": "", + "metadata": { + "created": "2023-07-08T00:31:48.068Z", + "updated": "2023-07-08T03:13:39.928Z", + "assigned": "", + "progress": 0, + "tags": [], + "completed": "2023-07-08T03:13:39.928Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Done", + "workload": 2, + "progress": 1, + "remainingWorkload": 0 + }, + { + "id": "convert-wiki-links-to-markdown-links", + "name": "Convert Wiki Links to Markdown Links", + "description": "", + "metadata": { + "created": "2023-07-08T00:28:50.180Z", + "updated": "2023-07-08T03:14:14.308Z", + "assigned": "", + "progress": 0, + "tags": [], + "started": "2023-07-08T02:17:20.346Z", + "completed": "2023-07-08T03:14:14.308Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Done", + "workload": 2, + "progress": 1, + "remainingWorkload": 0 + }, + { + "id": "add-update-date-in-front-matter", + "name": "Add / Update date in Front Matter", + "description": "- [ ] Maybe done", + "metadata": { + "created": "2023-07-08T00:27:35.865Z", + "updated": "2023-07-08T03:13:43.907Z", + "assigned": "", + "progress": 0, + "tags": [], + "completed": "2023-07-08T03:13:43.907Z" + }, + "subTasks": [], + "relations": [], + "comments": [], + "column": "Done", + "workload": 2, + "progress": 1, + "remainingWorkload": 0 + } + ] + ] + } + ] +} \ No newline at end of file diff --git a/.kanbn/board.md b/.kanbn/board.md index 6b41138721ca7089750e671a4e2c0146326d4f4a..6bace8d5c2d8b620a3a3a8d5893c6f20270aa548 100644 GIT binary patch delta 275 zcmaE+uuW&es>v;kyCyrZvus@Vg>iBN^RCHW%rZc_XR{Zx3!{4wLn=cKLn1>7LncER zkgdQF0On-?StShlK(Yu!1w=d2)Ne#$qjsGHm9)5G0J0VhuDd(r5dayj#H0u@&uqS aLHZ-O5uC{p+ya}Ec;&#dn;ZC^F#-VFE=*hi delta 85 zcmdm{^GspFs?8~kKNu(PW09Ghz}&NWABzj)WH~;8$rIRFHeX! diff --git a/.kanbn/index.md b/.kanbn/index.md index 91336aa..e45f770 100644 --- a/.kanbn/index.md +++ b/.kanbn/index.md @@ -13,6 +13,9 @@ updated: 2023-07-07T03:46:47.454Z ## Backlog +- [markdown-links-to-json](tasks/markdown-links-to-json.md) +- [markdown-to-json](tasks/markdown-to-json.md) + ## Todo - [find-orphan-links](tasks/find-orphan-links.md) @@ -27,3 +30,4 @@ updated: 2023-07-07T03:46:47.454Z - [convert-files-to-slug-name](tasks/convert-files-to-slug-name.md) - [convert-wiki-links-to-markdown-links](tasks/convert-wiki-links-to-markdown-links.md) - [add-update-date-in-front-matter](tasks/add-update-date-in-front-matter.md) +- [relative-path-to-relative-to-content](tasks/relative-path-to-relative-to-content.md) diff --git a/.kanbn/tasks/markdown-links-to-json.md b/.kanbn/tasks/markdown-links-to-json.md new file mode 100644 index 0000000..4d478f3 --- /dev/null +++ b/.kanbn/tasks/markdown-links-to-json.md @@ -0,0 +1,10 @@ +--- +type: "kanbn" +created: 2023-07-18T14:53:27.412Z +updated: 2023-07-18T14:53:33.147Z +assigned: "" +progress: 0 +tags: [] +--- + +# Markdown links to json diff --git a/.kanbn/tasks/markdown-to-json.md b/.kanbn/tasks/markdown-to-json.md new file mode 100644 index 0000000..92fca40 --- /dev/null +++ b/.kanbn/tasks/markdown-to-json.md @@ -0,0 +1,10 @@ +--- +type: "kanbn" +created: 2023-07-18T14:48:18.667Z +updated: 2023-07-18T14:48:18.660Z +assigned: "" +progress: 0 +tags: [] +--- + +# Markdown to json diff --git a/.kanbn/tasks/relative-path-to-relative-to-content.md b/.kanbn/tasks/relative-path-to-relative-to-content.md new file mode 100644 index 0000000..70e76da --- /dev/null +++ b/.kanbn/tasks/relative-path-to-relative-to-content.md @@ -0,0 +1,11 @@ +--- +type: kanbn +created: 2023-07-18T14:50:28.239Z +updated: 2023-07-19T04:46:32.554Z +assigned: "" +progress: 0 +tags: [] +completed: 2023-07-19T04:40:41.523Z +--- + +# Relative Path to relative to content diff --git a/.vscode/launch.json b/.vscode/launch.json index 2926d90..db9b413 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,14 +37,5 @@ // dotnet run "s" "C:/Users/phares/.nuget/packages" // dotnet run "s" "D:/ProgramData/EC_EAFRepository/nupkg" // dotnet run "s" "D:/Baget/packages" -// dotnet run "s" "L:/Baget/packages" -// dotnet run "s" "L:/Verdaccio/storage" // dotnet run "s" "\\messdv002.na.infineon.com\Candela\BaGet\packages" -// dotnet run "s" "\\messa01ec.ec.local\apps\Metrology\Run Data Repository" -// dotnet run "s" "D:/Documents/Obsidian/Infineon/.kanbn" -// dotnet run "s" "L:/Git/View-by-Distance-MKLink-Console/.kanbn" -// dotnet run "s" "T:/MESAFIBACKLOG/06_SourceCode/MESAFIBACKLOG/Adaptation/.kanbn" -// dotnet run "s" "D:/Documents/Projects/EC-Documentation - Foam/.kanbn" -// dotnet run "s" "D:/Documents/Notes/Infineon" -// dotnet run "s" "D:/5-Other-Small/Notes/Infineon/.kanbn" -// dotnet run "s" "D:/Documents/Projects/EC-Documentation" \ No newline at end of file +// dotnet run "s" "T:/MESAFIBACKLOG/06_SourceCode/MESAFIBACKLOG/Adaptation/.kanbn" \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 9f3821c..7d21eb0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,12 +10,14 @@ "**/node_modules": true }, "cSpell.words": [ - "ASPNETCORE", - "endianness", - "Infineon", - "Kanban", - "Phares", - "Serilog", - "SYSLIB" + "ASPNETCORE", + "endianness", + "Infineon", + "Kanban", + "kanbn", + "onenote", + "Phares", + "Serilog", + "SYSLIB" ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 052fb40..01b9f0c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,7 @@ "version": "2.0.0", "tasks": [ { - "label": "userSecretsInit", + "label": "User Secrets Init", "command": "dotnet", "type": "process", "args": [ @@ -14,7 +14,7 @@ "problemMatcher": "$msCompile" }, { - "label": "userSecretsSet", + "label": "User Secrets Set", "command": "dotnet", "type": "process", "args": [ @@ -28,7 +28,7 @@ "problemMatcher": "$msCompile" }, { - "label": "format", + "label": "Format", "command": "dotnet", "type": "process", "args": [ @@ -79,7 +79,7 @@ "problemMatcher": "$msCompile" }, { - "label": "publishAot", + "label": "Publish AOT", "command": "dotnet", "type": "process", "args": [ @@ -96,6 +96,48 @@ "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" + }, + { + "label": "File-Folder-Helper AOT s H Run Data Repository", + "type": "shell", + "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.ec.local\\apps\\Metrology\\Run Data Repository'", + "problemMatcher": [] + }, + { + "label": "File-Folder-Helper AOT s J Verdaccio", + "type": "shell", + "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s J 'L:/Verdaccio/storage'", + "problemMatcher": [] + }, + { + "label": "File-Folder-Helper AOT s M Self .Kanbn Tasks", + "type": "shell", + "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s M '.kanbn/tasks'", + "problemMatcher": [] + }, + { + "label": "File-Folder-Helper AOT s S BaGet", + "type": "shell", + "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s S 'L:/BaGet/packages'", + "problemMatcher": [] + }, + { + "label": "Kanbn Console", + "type": "npm", + "script": "kanbn.board", + "problemMatcher": [] + }, + { + "label": "Kanbn Write Boad", + "type": "shell", + "command": "& kanbn board -j | L:/Git/kanbn2md/kanbn2md.exe >.kanbn/board.md", + "problemMatcher": [] + }, + { + "label": "Kanbn Write json", + "type": "npm", + "script": "kanbn.board.json", + "problemMatcher": [] } ] } \ No newline at end of file diff --git a/File-Folder-Helper.csproj b/File-Folder-Helper.csproj index 73f5b92..e14b967 100644 --- a/File-Folder-Helper.csproj +++ b/File-Folder-Helper.csproj @@ -1,4 +1,4 @@ - + enable 11.0 @@ -10,7 +10,7 @@ - + diff --git a/Helpers/HelperCreateNoteFiles.cs b/Helpers/HelperCreateNoteFiles.cs index 21acec2..9801260 100644 --- a/Helpers/HelperCreateNoteFiles.cs +++ b/Helpers/HelperCreateNoteFiles.cs @@ -1,12 +1,15 @@ -using Humanizer; using System.Globalization; using System.Text; +using System.Text.RegularExpressions; namespace File_Folder_Helper.Helpers; -internal static class HelperCreateNoteFiles +internal static partial class HelperCreateNoteFiles { + [GeneratedRegex("[^a-z0-9-]")] + private static partial Regex AlphaNumOnly(); + private static void CleanExistingFiles(string directory, long ticks) { string check; @@ -97,31 +100,102 @@ internal static class HelperCreateNoteFiles } } + private static string? GetTags(string tagsText) + { + string? result; + StringBuilder stringBuilder = new(); + if (string.IsNullOrEmpty(tagsText)) + result = null; + else + { + string[] segments; + _ = stringBuilder.AppendLine("tags:"); + string[] tags = tagsText.Split(';', StringSplitOptions.RemoveEmptyEntries); + foreach (string tag in tags) + { + segments = tag.Split(':'); + _ = stringBuilder.AppendLine($"- '{segments.First()}'"); + } + result = stringBuilder.ToString().Trim(); + } + return result; + } + + private static string? GetLinks(string type, string linksText) + { + string? result; + StringBuilder stringBuilder = new(); + if (!string.IsNullOrEmpty(linksText)) + result = null; + else + { + string linkLower; + string[] segments; + string[] links = linksText.Split(';', StringSplitOptions.RemoveEmptyEntries); + foreach (string link in links) + { + segments = link.Split(':'); + linkLower = AlphaNumOnly().Replace(segments.First().Trim().ToLower(), "-").Replace("--", "-"); + if (segments.Length == 1) + _ = stringBuilder.AppendLine($"- [[{type}/{linkLower}]]"); + else if (segments.Length == 2) + _ = stringBuilder.AppendLine($"- [{type}/{linkLower}]({segments.Last()})"); + else + continue; + } + result = stringBuilder.ToString().Trim(); + } + return result; + } + + private static string? GetAttributes(string[] columns, string[]? headerColumns, int expectedCount) + { + string? result; + if (headerColumns is null || columns.Length <= expectedCount) + result = null; + else + { + StringBuilder stringBuilder = new(); + for (int j = expectedCount; j < columns.Length; j++) + { + if (headerColumns.Length <= j) + continue; + _ = stringBuilder.AppendLine($"{headerColumns[j].Trim()}: '{columns[j].Trim()}'"); + } + result = stringBuilder.ToString().Trim(); + } + return result; + } + private static void CreateImportFiles(long ticks, List importFiles) { bool csv; bool tsv; string file; + string text; string type; string title; + string? tags; + string? links; string[] lines; - string[] links; - int bodyKey = 4; + int bodyKey = 5; + int tagsKey = 3; int typeKey = 0; - string linkText; - int linksKey = 3; + string fileName; + string tagsText; + int linksKey = 4; int titleKey = 1; + string linksText; string[] columns; string? directory; - string[] segments; + string? attributes; int descriptionKey = 2; string[]? headerColumns; string destinationDirectory; + List allLines = new(); DateTime dateTime = new(ticks); - StringBuilder attributes = new(); - StringBuilder keyValuePairLinks = new(); - string csvHeader = "type,title,description,links,body"; - string tsvHeader = "type\ttitle\tdescription\tlinks\tbody"; + string csvHeader = "type,title,description,tags,links,body"; + string tsvHeader = "type\ttitle\tdescription\ttags\tlinks\tbody"; int expectedCount = csvHeader.Length - csvHeader.Replace(",", string.Empty).Length + 1; foreach (string importFile in importFiles) { @@ -158,58 +232,42 @@ internal static class HelperCreateNoteFiles continue; if (columns.Length < expectedCount) continue; - _ = attributes.Clear(); - _ = keyValuePairLinks.Clear(); title = columns[titleKey].Trim(); - linkText = columns[linksKey].Trim(); - type = columns[typeKey].Trim().ToLower().Replace(' ', '-'); - if (string.IsNullOrEmpty(linkText)) - links = Array.Empty(); - else - links = linkText.Split(';', StringSplitOptions.RemoveEmptyEntries); - if (headerColumns is not null && columns.Length > expectedCount) - { - for (int j = expectedCount; j < columns.Length; j++) - { - if (headerColumns.Length <= j) - continue; - _ = attributes.AppendLine($"{headerColumns[j].Trim().Camelize()}: '{columns[j].Trim()}'"); - } - } - foreach (string link in links) - { - segments = link.Split(':'); - if (segments.Length == 1) - _ = keyValuePairLinks.AppendLine($"- [[{segments.First()}]]"); - else if (segments.Length == 2) - _ = keyValuePairLinks.AppendLine($"- [{segments.First()}]({segments.Last()})"); - else - continue; - } + tagsText = columns[tagsKey].Trim(); + linksText = columns[linksKey].Trim(); + fileName = AlphaNumOnly().Replace(title.ToLower(), "-").Replace("--", "-"); + type = AlphaNumOnly().Replace(columns[typeKey].Trim().ToLower(), "-").Replace("--", "-"); + tags = GetTags(tagsText); + links = GetLinks(type, linksText); + attributes = GetAttributes(columns, headerColumns, expectedCount); destinationDirectory = Path.Combine(directory, type); if (!Directory.Exists(destinationDirectory)) _ = Directory.CreateDirectory(destinationDirectory); - file = Path.Combine(destinationDirectory, $"{title.ToLower().Replace(' ', '-')}.md"); - File.WriteAllLines(file, new string[] - { - "---", - $"type: '{type}'", - $"title: '{title}'", - $"description: '{columns[descriptionKey].Trim()}'", - $"created: {dateTime:yyyy-MM-ddTHH:mm:ss.fffZ}", - $"updated: {dateTime:yyyy-MM-ddTHH:mm:ss.fffZ}", - attributes.ToString(), - "---", - string.Empty, - $"# {title}", - string.Empty, - keyValuePairLinks.ToString(), - string.Empty, - $"## Comment {dateTime:yyyy-MM-dd}", - string.Empty, - columns[bodyKey].Trim(), - string.Empty, - }); + file = Path.Combine(destinationDirectory, $"{fileName}.md"); + allLines.Clear(); + allLines.Add("---"); + allLines.Add($"type: '{type}'"); + allLines.Add($"title: '{title}'"); + allLines.Add($"description: '{columns[descriptionKey].Trim()}'"); + allLines.Add($"created: {dateTime:yyyy-MM-ddTHH:mm:ss.fffZ}"); + allLines.Add($"updated: {dateTime:yyyy-MM-ddTHH:mm:ss.fffZ}"); + if (!string.IsNullOrEmpty(tags)) + allLines.Add(tags); + if (!string.IsNullOrEmpty(attributes)) + allLines.Add(attributes); + allLines.Add("---"); + allLines.Add(string.Empty); + allLines.Add($"# {title}"); + allLines.Add(string.Empty); + if (!string.IsNullOrEmpty(links)) + allLines.Add(links); + allLines.Add(string.Empty); + allLines.Add($"## Comment {dateTime:yyyy-MM-dd}"); + allLines.Add(string.Empty); + allLines.Add(columns[bodyKey].Trim()); + allLines.Add(string.Empty); + text = string.Join(Environment.NewLine, allLines); + File.WriteAllText(file, text); } } } diff --git a/Helpers/HelperMarkdown.cs b/Helpers/HelperMarkdown.cs index 56abe9a..10bd952 100644 --- a/Helpers/HelperMarkdown.cs +++ b/Helpers/HelperMarkdown.cs @@ -1,4 +1,5 @@ -using Humanizer; +using File_Folder_Helper.Models; +using Microsoft.Extensions.Logging; using System.Text; using System.Text.Json; @@ -7,8 +8,12 @@ namespace File_Folder_Helper.Helpers; internal static partial class HelperMarkdown { + private record Record(string Source, + string? StartAt, + string? Destination); + /// - /// Determines a text file's encoding by analyzing its byte order mark (BOM). + /// Determines files text file's encoding by analyzing its byte order mark (BOM). /// Defaults to ASCII when detection of the text file's endianness fails. /// /// The text file to analyze. @@ -38,14 +43,20 @@ internal static partial class HelperMarkdown return result; } - internal static string[] GetFiles(Models.AppSettings appSettings, string directory) + internal static string[] GetFiles(AppSettings appSettings, string directory) { - string[] files = Directory.GetFiles(directory, "*.md", SearchOption.AllDirectories). + string[] results = Directory.GetFiles(directory, "*.md", SearchOption.AllDirectories). Where(l => !appSettings.Exclude.Any(m => l.Contains(m))).ToArray(); - return files; + return results; } - private static (string type, string h1) GetTypeAndH1(Models.AppSettings appSettings, string h1, List lines, LineNumber lineNumber) + private static string[] GetFiles(AppSettings appSettings, Record record) + { + string[] results = record.StartAt is null ? GetFiles(appSettings, record.Source) : GetFiles(appSettings, record.StartAt); + return results; + } + + private static (string type, string h1) GetTypeAndH1(AppSettings appSettings, string h1, List lines, LineNumber lineNumber) { string type = lineNumber.Type is null ? appSettings.DefaultNoteType : lines[lineNumber.Type.Value].Replace("type: ", string.Empty); string h1FromFile = lineNumber.H1 is null ? h1 : lines[lineNumber.H1.Value][2..]; @@ -108,7 +119,7 @@ internal static partial class HelperMarkdown return (lines.ToList(), lineNumber); } - internal static List<(MarkdownFile, string[])> GetCollection(Models.AppSettings appSettings, string[] files) + internal static List<(MarkdownFile, string[])> GetCollection(AppSettings appSettings, string[] files) { List<(MarkdownFile, string[])> results = new(); string h1; @@ -125,7 +136,7 @@ internal static partial class HelperMarkdown continue; (lines, lineNumber) = GetStatusAndMetaEndLineNumbers(fileInfo); fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); - h1 = fileNameWithoutExtension.ToLower().Hyphenate(); + h1 = fileNameWithoutExtension.ToLower().Replace("%20", "-").Replace(' ', '-'); if (lines.Any()) (type, h1) = GetTypeAndH1(appSettings, h1, lines, lineNumber); else @@ -140,9 +151,9 @@ internal static partial class HelperMarkdown return results; } - internal static bool SetFrontMatterAndH1(Models.AppSettings appSettings, List<(MarkdownFile, string[])> collection) + private static int SetFrontMatterAndH1(AppSettings appSettings, List<(MarkdownFile, string[])> collection) { - bool result = false; + int result = 0; string h1Line; string typeLine; string createdLine; @@ -203,17 +214,16 @@ internal static partial class HelperMarkdown else if (results[markdownFile.LineNumber.Created.Value][..createdLineCompare.Length] != createdLineCompare) results[markdownFile.LineNumber.Created.Value] = createdLine; } - if (!result) - result = true; File.WriteAllLines(markdownFile.File, results); File.SetLastWriteTime(markdownFile.File, markdownFile.LastWriteDateTime); + result += 1; } return result; } - internal static bool CircularReference(List<(MarkdownFile, string[])> collection) + private static int CircularReference(ILogger logger, List<(MarkdownFile, string[])> collection) { - bool result = false; + int result = 0; string line; string check; bool circularReference; @@ -255,22 +265,22 @@ internal static partial class HelperMarkdown if (lines[i] == line) continue; lines[i] = line; + logger.LogInformation("circular reference for <{file}>", markdownFile.FileName); if (!circularReference) circularReference = true; } if (circularReference) { - if (!result) - result = true; File.WriteAllLines(markdownFile.File, lines); + result += 1; } } return result; } - internal static bool FindReplace(List<(MarkdownFile, string[])> collection) + private static int FindReplace(List<(MarkdownFile, string[])> collection) { - bool result = false; + int result = 0; bool found; string line; string check; @@ -305,9 +315,8 @@ internal static partial class HelperMarkdown } if (found) { - if (!result) - result = true; File.WriteAllLines(markdownFile.File, lines); + result += 1; } } return result; @@ -330,31 +339,65 @@ internal static partial class HelperMarkdown return results; } + private static Dictionary> GetKeyValuePairs(AppSettings appSettings, Record record) + { + Dictionary> results; + string[] files = GetFiles(appSettings, record.Source); + List<(MarkdownFile MarkdownFile, string[] Lines)> collection = GetCollection(appSettings, files); + results = GetKeyValuePairs(collection); + return results; + } + + private static (string?, string?) GetMatchAndTitle(string? directory, List markdownFiles) + { + int check = 0; + string? match = null; + string? title = null; + string? directoryName = Path.GetFileName(directory); + foreach (MarkdownFile markdownFile in markdownFiles) + { + if (directory is null || directoryName is null) + continue; + if (markdownFiles.Count == 1) + { + check++; + match = markdownFile.File; + title = markdownFile.H1; + } + else + { + if (Path.GetFileName(markdownFile.Directory) == directoryName) + { + check++; + match = markdownFile.File; + title = markdownFile.H1; + } + } + } + if (check != 1) + { + match = null; + title = null; + } + return (match, title); + } + private static (string?, string?) GetRelativePath(Dictionary> keyValuePairs, MarkdownFile markdownFile, string file) { string? result; string? match; string? title; List? markdownFiles; + string? directory = Path.GetDirectoryName(file); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); if (keyValuePairs.TryGetValue(fileNameWithoutExtension, out markdownFiles)) - { - if (markdownFiles.Count != 1) - (match, title) = (null, null); - else - (match, title) = (markdownFiles.First().File, markdownFiles.First().H1); - } + (match, title) = GetMatchAndTitle(directory, markdownFiles); else { - if (!keyValuePairs.TryGetValue(fileNameWithoutExtension.ToLower(), out markdownFiles)) - (match, title) = (null, null); + if (keyValuePairs.TryGetValue(fileNameWithoutExtension.ToLower(), out markdownFiles)) + (match, title) = GetMatchAndTitle(directory, markdownFiles); else - { - if (markdownFiles.Count != 1) - (match, title) = (null, null); - else - (match, title) = (markdownFiles.First().File, markdownFiles.First().H1); - } + (match, title) = (null, null); } if (match is null) { @@ -411,19 +454,17 @@ internal static partial class HelperMarkdown return (result, title); } - internal static bool ConvertToRelativePath(List<(MarkdownFile MarkdownFile, string[] Lines)> collection) + private static int ConvertToRelativePath(AppSettings appSettings, ILogger logger, Record record, List<(MarkdownFile MarkdownFile, string[] Lines)> collection) { - bool result = false; + int result = 0; bool write; string line; - string after; - string before; string? title; string[] segmentsA; string[] segmentsB; string[] segmentsC; string? relativePath; - Dictionary> keyValuePairs = GetKeyValuePairs(collection); + Dictionary> keyValuePairs = record.StartAt is null ? GetKeyValuePairs(collection) : GetKeyValuePairs(appSettings, record); foreach ((MarkdownFile markdownFile, string[] lines) in collection) { if (lines.Length < 1) @@ -437,19 +478,20 @@ internal static partial class HelperMarkdown segmentsB = segmentsA.First().Split("[["); if (segmentsB.Length is not 2 or 3) continue; - after = segmentsA.Last(); - before = segmentsB.First(); segmentsC = segmentsB.Last().Split('|'); (relativePath, title) = GetRelativePath(keyValuePairs, markdownFile, segmentsC.First()); if (relativePath is null) + { + logger.LogInformation("Didn't find {line} in <{file}>", lines[i], markdownFile.FileNameWithoutExtension); continue; + } if (title is null) { - title = segmentsC.Last().Humanize(LetterCasing.Title); + title = segmentsC.Last(); if (title.Length != segmentsC.Last().Length) title = segmentsC.Last(); } - line = $"{before}[{title}]({relativePath.Replace('\\', '/')}){after}"; + line = $"{segmentsB.First()}[{title}]({relativePath.Replace('\\', '/')}){segmentsA.Last()}"; if (lines[i] == line) continue; lines[i] = line; @@ -458,19 +500,18 @@ internal static partial class HelperMarkdown } if (write) { - if (!result) - result = true; File.WriteAllLines(markdownFile.File, lines); + result += 1; } } return result; } - internal static bool ConvertFileToSlugName(List<(MarkdownFile MarkdownFile, string[] Lines)> collection) + private static int ConvertFileToSlugName(AppSettings appSettings, ILogger logger, Record record, List<(MarkdownFile MarkdownFile, string[] Lines)> collection) { - bool result = false; - bool write; + int result = 0; string h1; + bool write; string file; string line; string? title; @@ -483,10 +524,9 @@ internal static partial class HelperMarkdown string[] segmentsC; string checkFileName; string segmentsALast; + string? relativePath; string segmentsBFirst; - string relativeDirectory; - string formattedRelativeDirectory; - Dictionary> keyValuePairs = GetKeyValuePairs(collection); + Dictionary> keyValuePairs = record.StartAt is null ? GetKeyValuePairs(collection) : GetKeyValuePairs(appSettings, record); foreach ((MarkdownFile markdownFile, string[] lines) in collection) { if (markdownFile.FileNameWithoutExtension == "index") @@ -511,25 +551,31 @@ internal static partial class HelperMarkdown directory = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(directory)) continue; - relativeDirectory = segmentsBFirst[..^fileName.Length]; - formattedRelativeDirectory = relativeDirectory.Replace(" ", "%20"); checkFileName = fileName.ToLower().Replace("%20", "-").Replace(' ', '-'); checkName = Path.Combine(directory, checkFileName); segmentsC = segmentsA.First().Split('['); - (_, title) = GetRelativePath(keyValuePairs, markdownFile, file); + (relativePath, title) = GetRelativePath(keyValuePairs, markdownFile, file); + if (relativePath is null) + { + logger.LogInformation("Didn't find {line} in <{file}>", lines[i], markdownFile.FileNameWithoutExtension); + continue; + } if (title is null) { - title = segmentsC.Last().Humanize(LetterCasing.Title); + title = segmentsC.Last(); if (title.Length != segmentsC.Last().Length) title = segmentsC.Last(); } - line = $"{segmentsC.First()}[{title}]({Path.Combine(formattedRelativeDirectory, checkFileName)}){segmentsB.Last()}"; + line = $"{segmentsC.First()}[{title}]({relativePath.Replace('\\', '/')}){segmentsB.Last()}"; if (lines[i] == line) continue; if (fileName.Contains(' ') || fileName.Contains("%20")) { if (!File.Exists(file)) + { + logger.LogInformation("Didn't find <{file}>", file); continue; + } if (File.Exists(checkName)) continue; File.Move(file, checkName); @@ -539,7 +585,10 @@ internal static partial class HelperMarkdown if (file != checkName) { if (!File.Exists(file)) + { + logger.LogInformation("Didn't find <{file}>", file); continue; + } File.Move(file, checkName); } } @@ -549,12 +598,11 @@ internal static partial class HelperMarkdown } if (write) { - if (!result) - result = true; File.WriteAllLines(markdownFile.File, lines); + result += 1; } } - if (!result) + if (result == 0) { foreach ((MarkdownFile markdownFile, string[] lines) in collection) { @@ -563,13 +611,12 @@ internal static partial class HelperMarkdown h1 = lines[markdownFile.LineNumber.H1.Value]; if (h1.Length > 2) { - h1Check = $"# {h1[2..].Humanize(LetterCasing.Title)}"; + h1Check = $"# {h1[2..]}"; if (h1Check.Length == h1.Length && h1Check != h1) { lines[markdownFile.LineNumber.H1.Value] = h1Check; - if (!result) - result = true; File.WriteAllLines(markdownFile.File, lines); + result += 1; } } } @@ -581,29 +628,79 @@ internal static partial class HelperMarkdown checkName = Path.Combine(markdownFile.Directory, checkFileName); if (checkName == markdownFile.File) continue; - if (!result) - result = true; File.Move(markdownFile.File, checkName); + result += 1; } } return result; } - internal static void MarkdownWikiLinkVerification(Models.AppSettings appSettings, string argsZero) + private static Record GetRecord(List args) { - string fullPath = Path.GetFullPath(argsZero); + Record result; + string? startAt = null; + string? destination = null; + for (int i = 1; i < args.Count; i++) + { + if (args[i].Length == 2 && i + 1 < args.Count) + { + if (args[i][1] == 's') + startAt = Path.GetFullPath(args[i + 1]); + else if (args[i][1] == 'd') + destination = Path.GetFullPath(args[i + 1]); + i++; + } + } + if (startAt is not null && !Directory.Exists(startAt)) + throw new Exception($"Start at directory <{startAt}> doesn't exist!"); + if (destination is not null) + { + string? root = Path.GetPathRoot(destination); + if (root is null || !Directory.Exists(root)) + throw new NotSupportedException($"This method requires a valid -d path <{root}>!"); + if (!Directory.Exists(destination)) + _ = Directory.CreateDirectory(destination); + } + result = new(Path.GetFullPath(args.First()), startAt, destination); + return result; + } + + internal static void MarkdownWikiLinkVerification(AppSettings appSettings, ILogger logger, List args) + { + int updated; + Record record = GetRecord(args); List<(MarkdownFile MarkdownFile, string[] Lines)> collection; - collection = GetCollection(appSettings, GetFiles(appSettings, fullPath)); - if (SetFrontMatterAndH1(appSettings, collection)) - collection = GetCollection(appSettings, GetFiles(appSettings, fullPath)); - if (CircularReference(collection)) - collection = GetCollection(appSettings, GetFiles(appSettings, fullPath)); - if (FindReplace(collection)) - collection = GetCollection(appSettings, GetFiles(appSettings, fullPath)); - if (ConvertToRelativePath(collection)) - collection = GetCollection(appSettings, GetFiles(appSettings, fullPath)); - if (ConvertFileToSlugName(collection)) - collection = GetCollection(appSettings, GetFiles(appSettings, fullPath)); + collection = GetCollection(appSettings, GetFiles(appSettings, record)); + updated = SetFrontMatterAndH1(appSettings, collection); + if (updated != 0) + { + collection = GetCollection(appSettings, GetFiles(appSettings, record)); + logger.LogInformation("{updated} Markdown file(s) were updated", updated); + } + updated = CircularReference(logger, collection); + if (updated != 0) + { + collection = GetCollection(appSettings, GetFiles(appSettings, record)); + logger.LogInformation("{updated} Markdown file(s) were updated", updated); + } + updated = FindReplace(collection); + if (updated != 0) + { + collection = GetCollection(appSettings, GetFiles(appSettings, record)); + logger.LogInformation("{updated} Markdown file(s) were updated", updated); + } + updated = ConvertToRelativePath(appSettings, logger, record, collection); + if (updated != 0) + { + collection = GetCollection(appSettings, GetFiles(appSettings, record)); + logger.LogInformation("{updated} Markdown file(s) were updated", updated); + } + updated = ConvertFileToSlugName(appSettings, logger, record, collection); + if (updated != 0) + { + collection = GetCollection(appSettings, GetFiles(appSettings, record)); + logger.LogInformation("{updated} Markdown file(s) were updated", updated); + } string directory = Path.Combine(Environment.CurrentDirectory, ".vscode"); if (!Directory.Exists(directory)) { @@ -618,4 +715,91 @@ internal static partial class HelperMarkdown } } + private static List<(string, string, string[])> GetWithLinksForHugo(AppSettings appSettings, Record record) + { + List<(string, string, string[])> results = new(); + string file; + string line; + string fileName; + string? directory; + string[] segmentsA; + string[] segmentsB; + string[] segmentsC; + string relativeFile; + string segmentsALast; + string segmentsBFirst; + int sourceDirectoryLength = record.Source.Length; + List<(MarkdownFile MarkdownFile, string[] Lines)> collection = GetCollection(appSettings, GetFiles(appSettings, record)); + foreach ((MarkdownFile markdownFile, string[] lines) in collection) + { + if (record.Destination is null) + continue; + if (markdownFile.File.Length < sourceDirectoryLength) + continue; + if (!File.Exists(markdownFile.File)) + continue; + fileName = $"{record.Destination}{markdownFile.File[sourceDirectoryLength..]}"; + directory = Path.GetDirectoryName(fileName); + if (string.IsNullOrEmpty(directory)) + continue; + for (int i = 0; i < lines.Length; i++) + { + segmentsA = lines[i].Split("]("); + if (segmentsA.Length != 2) + continue; + segmentsALast = segmentsA.Last(); + if (segmentsALast.StartsWith("http:") || segmentsALast.StartsWith("https:") || segmentsALast.StartsWith("rdp:") || segmentsALast.StartsWith("onenote:")) + continue; + segmentsB = segmentsALast.Split(")"); + if (segmentsB.Length != 2) + continue; + segmentsBFirst = segmentsB.First(); + segmentsC = segmentsA.First().Split('['); + file = Path.GetFullPath(Path.Combine(markdownFile.Directory, segmentsBFirst)); + relativeFile = Path.GetRelativePath(record.Source, file).Replace('\\', '/'); + line = $"{segmentsC.First()}[[{relativeFile}]]{segmentsB.Last()}"; + if (lines[i] == line) + throw new NotSupportedException($"Line {i} shouldn't match with {line}"); + lines[i] = line; + } + results.Add((directory, fileName, lines)); + } + return results; + } + + private static List GetDistinct(List<(string, string, string[])> collection) + { + List results = new(); + foreach ((string directory, _, _) in collection) + { + if (results.Contains(directory)) + continue; + results.Add(directory); + } + return results; + } + + private static void CreateMissingDirectories(List directories) + { + foreach (string directory in directories) + { + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + } + } + + internal static void MarkdownConvertLinksForHugo(AppSettings appSettings, ILogger logger, List args) + { + Record record = GetRecord(args); + if (string.IsNullOrEmpty(record.Destination)) + throw new NotSupportedException("This method requires a -d path!"); + List<(string, string, string[])> collection = GetWithLinksForHugo(appSettings, record); + if (!collection.Any()) + logger.LogInformation("No files?"); + List distinct = GetDistinct(collection); + CreateMissingDirectories(distinct); + foreach ((_, string file, string[] lines) in collection) + File.WriteAllLines(file, lines); + } + } \ No newline at end of file diff --git a/Helpers/PackageJson.cs b/Helpers/PackageJson.cs index eead9fe..44719e8 100644 --- a/Helpers/PackageJson.cs +++ b/Helpers/PackageJson.cs @@ -17,4 +17,4 @@ internal partial class PackageJsonSourceGenerationContext : JsonSerializerContex [JsonSerializable(typeof(PackageJson[]))] internal partial class PackageJsonCollectionSourceGenerationContext : JsonSerializerContext { -} +} \ No newline at end of file diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs index 864933d..731bc3b 100644 --- a/Models/AppSettings.cs +++ b/Models/AppSettings.cs @@ -21,4 +21,4 @@ public record AppSettings(string Company, [JsonSerializable(typeof(AppSettings))] internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext { -} +} \ No newline at end of file diff --git a/Models/Binder/AppSettings.cs b/Models/Binder/AppSettings.cs index 60eabc7..133c4fc 100644 --- a/Models/Binder/AppSettings.cs +++ b/Models/Binder/AppSettings.cs @@ -54,4 +54,4 @@ public class AppSettings [JsonSerializable(typeof(AppSettings))] internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext { -} +} \ No newline at end of file diff --git a/Worker.cs b/Worker.cs index 096d621..842684a 100644 --- a/Worker.cs +++ b/Worker.cs @@ -41,6 +41,7 @@ public class Worker : BackgroundService ConsoleKey.R, ConsoleKey.S, ConsoleKey.T, + ConsoleKey.U, ConsoleKey.Z, ConsoleKey.Delete }; @@ -101,6 +102,7 @@ public class Worker : BackgroundService _Logger.LogInformation("R) Rename to old, copy, delete old"); _Logger.LogInformation("S) Set Date from Zip Entry"); _Logger.LogInformation("T) Too long rename"); + _Logger.LogInformation("U) Links for Hugo"); _Logger.LogInformation("Z) Zip file(s) by date,"); _Logger.LogInformation("Delete) Delete empty directories,"); consoleKey = Console.ReadKey().Key; @@ -131,7 +133,7 @@ public class Worker : BackgroundService Helpers.HelperCreateNoteFiles.CreateNoteFiles(_Args[0]); break; case ConsoleKey.M: - Helpers.HelperMarkdown.MarkdownWikiLinkVerification(_AppSettings, _Args[0]); + Helpers.HelperMarkdown.MarkdownWikiLinkVerification(_AppSettings, _Logger, _Args); break; case ConsoleKey.R: Helpers.HelperRenameToOldMoveDeleteOldMerge.RenameToOldMoveDeleteOld(_Logger, _Args[0]); @@ -143,6 +145,9 @@ public class Worker : BackgroundService Helpers.HelperTooLong.TooLong(_Args[0], delete: false); Helpers.HelperTooLong.TooLong(_Args[0], delete: true); break; + case ConsoleKey.U: + Helpers.HelperMarkdown.MarkdownConvertLinksForHugo(_AppSettings, _Logger, _Args); + break; case ConsoleKey.Z: Helpers.HelperZipFilesByDate.ZipFilesByDate(_Logger, _Args[0]); break; diff --git a/package.json b/package.json index c49ea53..51512c5 100644 --- a/package.json +++ b/package.json @@ -2,15 +2,8 @@ "scripts": { "prettier.check": "prettier . --check", "prettier.write": "prettier . --write", - "Alpha": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "nuget-clear": "dotnet nuget locals all --clear", - "build": "dotnet build --runtime win-x64 --self-contained", - "build-Package-Management": "dotnet build --runtime win-x64 --self-contained --source https://packagemanagement.eu.infineon.com:4430/api/v2/", - "build-nuget-And-Package-Management": "dotnet build --runtime win-x64 --self-contained --source https://api.nuget.org/v3/index.json --source https://packagemanagement.eu.infineon.com:4430/api/v2/", - "build-All-Sources": "dotnet build --runtime win-x64 --self-contained --source https://api.nuget.org/v3/index.json --source https://packagemanagement.eu.infineon.com:4430/api/v2/ --source https://tfs.intra.infineon.com/tfs/ManufacturingIT/_packaging/eaf/nuget/v3/index.json --source http://192.168.0.73:5002/v3/index.json", - "dotnet-format": "dotnet format --report .vscode --verbosity detailed --severity warn", - "MSBuild": "\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe\" /target:Build /restore:True /p:RestoreSources=https://api.nuget.org/v3/index.json%3Bhttps://packagemanagement.eu.infineon.com:4430/api/v2/%3Bhttps://tfs.intra.infineon.com/tfs/ManufacturingIT/_packaging/eaf/nuget/v3/index.json /DetailedSummary /ConsoleLoggerParameters:PerformanceSummary;ErrorsOnly; /property:Configuration=Debug;TargetFrameworkVersion=v4.8 File-Folder-Helper.csproj", - "pull": "git pull", + "kanbn.board": "kanbn board", + "kanbn.board.json": "kanbn board -j > .kanbn/board.json", "garbage-collect": "git gc" }, "devDependencies": {