|
|
|
@ -2,6 +2,7 @@ using File_Folder_Helper.Models;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
using System.Text.Json.Serialization;
|
|
|
|
|
|
|
|
|
|
namespace File_Folder_Helper.Helpers;
|
|
|
|
|
|
|
|
|
@ -12,6 +13,12 @@ internal static partial class HelperMarkdown
|
|
|
|
|
string? StartAt,
|
|
|
|
|
string? Destination);
|
|
|
|
|
|
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
|
|
|
|
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
|
|
|
|
|
internal partial class DictionaryStringAndJsonElementSourceGenerationContext : JsonSerializerContext
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 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.
|
|
|
|
@ -63,7 +70,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
return (type, h1FromFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static (List<string>, LineNumber) GetStatusAndMetaEndLineNumbers(FileInfo fileInfo)
|
|
|
|
|
internal static (List<string>, LineNumber) GetStatusAndFrontMatterYamlEndLineNumbers(FileInfo fileInfo)
|
|
|
|
|
{
|
|
|
|
|
string line;
|
|
|
|
|
int? h1LineNumber = null;
|
|
|
|
@ -71,7 +78,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
int? statusLineNumber = null;
|
|
|
|
|
int? createdLineNumber = null;
|
|
|
|
|
int? updatedLineNumber = null;
|
|
|
|
|
int? metaEndLineNumber = null;
|
|
|
|
|
int? frontMatterYamlEndLineNumber = null;
|
|
|
|
|
Encoding? encoding = GetEncoding(fileInfo.FullName) ?? Encoding.Default;
|
|
|
|
|
string[] lines = File.ReadAllLines(fileInfo.FullName, encoding);
|
|
|
|
|
for (int i = 1; i < lines.Length; i++)
|
|
|
|
@ -81,7 +88,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
continue;
|
|
|
|
|
if (line[..3] == "---")
|
|
|
|
|
{
|
|
|
|
|
metaEndLineNumber = i;
|
|
|
|
|
frontMatterYamlEndLineNumber = i;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (line.Length > 6 && line[..6] == "type: ")
|
|
|
|
@ -112,7 +119,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
}
|
|
|
|
|
LineNumber lineNumber = new(createdLineNumber,
|
|
|
|
|
h1LineNumber,
|
|
|
|
|
metaEndLineNumber,
|
|
|
|
|
frontMatterYamlEndLineNumber,
|
|
|
|
|
statusLineNumber,
|
|
|
|
|
typeLineNumber,
|
|
|
|
|
updatedLineNumber);
|
|
|
|
@ -134,15 +141,15 @@ internal static partial class HelperMarkdown
|
|
|
|
|
fileInfo = new(file);
|
|
|
|
|
if (fileInfo.DirectoryName is null)
|
|
|
|
|
continue;
|
|
|
|
|
(lines, lineNumber) = GetStatusAndMetaEndLineNumbers(fileInfo);
|
|
|
|
|
(lines, lineNumber) = GetStatusAndFrontMatterYamlEndLineNumbers(fileInfo);
|
|
|
|
|
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
|
|
|
|
|
h1 = fileNameWithoutExtension.ToLower().Replace("%20", "-").Replace(' ', '-');
|
|
|
|
|
if (lines.Any())
|
|
|
|
|
(type, h1) = GetTypeAndH1(appSettings, h1, lines, lineNumber);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
type = "note";
|
|
|
|
|
File.WriteAllLines(file, new string[] { "---", $"type: {type}", "---", string.Empty, $"# {h1}" });
|
|
|
|
|
type = appSettings.DefaultNoteType;
|
|
|
|
|
File.WriteAllLines(file, new string[] { "---", $"type: \"{type}\"", "---", string.Empty, $"# {h1}" });
|
|
|
|
|
lines = File.ReadAllLines(file).ToList();
|
|
|
|
|
}
|
|
|
|
|
markdownFile = new(file, fileInfo.DirectoryName, fileInfo.Name, fileNameWithoutExtension, fileInfo.Extension, fileInfo.CreationTime, fileInfo.LastWriteTime, lineNumber, type, h1);
|
|
|
|
@ -177,13 +184,13 @@ internal static partial class HelperMarkdown
|
|
|
|
|
results.Clear();
|
|
|
|
|
results.AddRange(lines);
|
|
|
|
|
creationDateTime = markdownFile.CreationDateTime > markdownFile.LastWriteDateTime ? markdownFile.LastWriteDateTime : markdownFile.CreationDateTime;
|
|
|
|
|
typeLine = $"type: {appSettings.DefaultNoteType}";
|
|
|
|
|
typeLine = $"type: \"{appSettings.DefaultNoteType}\"";
|
|
|
|
|
h1Line = $"# {markdownFile.FileNameWithoutExtension}";
|
|
|
|
|
createdLineCompare = $"created: {creationDateTime.ToUniversalTime():yyyy-MM-dd}";
|
|
|
|
|
createdLine = $"created: {creationDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}";
|
|
|
|
|
updatedLineCompare = $"updated: {markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-dd}";
|
|
|
|
|
updatedLine = $"updated: {markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}";
|
|
|
|
|
if (markdownFile.LineNumber.MetaEnd is null)
|
|
|
|
|
createdLineCompare = $"created: \"{creationDateTime.ToUniversalTime():yyyy-MM-dd}T";
|
|
|
|
|
createdLine = $"created: \"{creationDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}\"";
|
|
|
|
|
updatedLineCompare = $"updated: \"{markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-dd}T";
|
|
|
|
|
updatedLine = $"updated: \"{markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}\"";
|
|
|
|
|
if (markdownFile.LineNumber.FrontMatterYamlEnd is null)
|
|
|
|
|
{
|
|
|
|
|
if (markdownFile.LineNumber.H1 is null)
|
|
|
|
|
{
|
|
|
|
@ -201,14 +208,14 @@ internal static partial class HelperMarkdown
|
|
|
|
|
{
|
|
|
|
|
if (markdownFile.LineNumber.H1 is null)
|
|
|
|
|
{
|
|
|
|
|
results.Insert(markdownFile.LineNumber.MetaEnd.Value + 1, string.Empty);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.MetaEnd.Value + 1, h1Line);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.MetaEnd.Value + 1, string.Empty);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value + 1, string.Empty);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value + 1, h1Line);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value + 1, string.Empty);
|
|
|
|
|
}
|
|
|
|
|
if (markdownFile.LineNumber.Type is null)
|
|
|
|
|
results.Insert(markdownFile.LineNumber.MetaEnd.Value, typeLine);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, typeLine);
|
|
|
|
|
if (markdownFile.LineNumber.Updated is null)
|
|
|
|
|
results.Insert(markdownFile.LineNumber.MetaEnd.Value, updatedLine);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, updatedLine);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (results[markdownFile.LineNumber.Updated.Value].Contains('$'))
|
|
|
|
@ -218,7 +225,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
results[markdownFile.LineNumber.Updated.Value] = updatedLine;
|
|
|
|
|
}
|
|
|
|
|
if (markdownFile.LineNumber.Created is null)
|
|
|
|
|
results.Insert(markdownFile.LineNumber.MetaEnd.Value, createdLine);
|
|
|
|
|
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, createdLine);
|
|
|
|
|
else if (results[markdownFile.LineNumber.Created.Value][..createdLineCompare.Length] != createdLineCompare)
|
|
|
|
|
results[markdownFile.LineNumber.Created.Value] = createdLine;
|
|
|
|
|
}
|
|
|
|
@ -229,6 +236,149 @@ internal static partial class HelperMarkdown
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static (string?, Dictionary<string, JsonElement>?, string[]) Get(int frontMatterYamlEnd, string[] lines)
|
|
|
|
|
{
|
|
|
|
|
string? result;
|
|
|
|
|
List<string> results = new();
|
|
|
|
|
Dictionary<string, JsonElement>? keyValuePairs;
|
|
|
|
|
string[] segments;
|
|
|
|
|
string[] segmentsB;
|
|
|
|
|
string segmentsLast;
|
|
|
|
|
string segmentsFirst;
|
|
|
|
|
List<string> jsonLines = new();
|
|
|
|
|
for (int i = 0; i < frontMatterYamlEnd; i++)
|
|
|
|
|
{
|
|
|
|
|
if (lines[i] == "---")
|
|
|
|
|
continue;
|
|
|
|
|
segments = lines[i].Split(": ");
|
|
|
|
|
if (segments.Length != 2)
|
|
|
|
|
{
|
|
|
|
|
jsonLines.Clear();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
segmentsLast = segments.Last().Trim();
|
|
|
|
|
segmentsFirst = segments.First().Trim();
|
|
|
|
|
if (string.IsNullOrEmpty(segmentsLast))
|
|
|
|
|
continue;
|
|
|
|
|
if (segmentsFirst.First() == '"' && segmentsFirst.Last() == '"')
|
|
|
|
|
jsonLines.Add($"{segmentsFirst}: ");
|
|
|
|
|
else if (segmentsFirst.First() == '\'' && segmentsFirst.Last() == '\'')
|
|
|
|
|
jsonLines.Add($"\"{segmentsFirst[1..^1]}\": ");
|
|
|
|
|
else
|
|
|
|
|
jsonLines.Add($"\"{segmentsFirst}\": ");
|
|
|
|
|
if (segmentsLast == "[]")
|
|
|
|
|
jsonLines.RemoveAt(jsonLines.Count - 1);
|
|
|
|
|
else if (segmentsLast.First() == '"' && segmentsLast.Last() == '"')
|
|
|
|
|
jsonLines.Add($"{segmentsLast},");
|
|
|
|
|
else if (segmentsLast.First() == '"' && segmentsLast.Last() == '"')
|
|
|
|
|
jsonLines.Add($"\"{segmentsLast[1..^1]}\"");
|
|
|
|
|
else if (!segmentsLast.Contains('"') && !segmentsLast.Contains('\''))
|
|
|
|
|
{
|
|
|
|
|
if (segmentsLast is "true" or "false")
|
|
|
|
|
jsonLines.Add($"{segmentsLast},");
|
|
|
|
|
else if (DateTime.TryParse(segmentsLast, out DateTime dateTime))
|
|
|
|
|
jsonLines.Add($"\"{segmentsLast}\",");
|
|
|
|
|
else if (segmentsLast.All(l => char.IsNumber(l)))
|
|
|
|
|
jsonLines.Add($"{segmentsLast},");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
segmentsB = segmentsLast.Split('.');
|
|
|
|
|
if (segmentsB.Length == 2 && segmentsB.First().Length < 7 && segmentsB.Last().Length < 7 && segmentsB.First().All(l => char.IsNumber(l)) && segmentsB.Last().All(l => char.IsNumber(l)))
|
|
|
|
|
jsonLines.Add($"{segmentsLast},");
|
|
|
|
|
else if (!segmentsLast.Contains('[') && !segmentsLast.Contains('{'))
|
|
|
|
|
jsonLines.Add($"\"{segmentsLast}\",");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
jsonLines.Clear();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
jsonLines.Clear();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!jsonLines.Any())
|
|
|
|
|
(result, keyValuePairs) = (null, null);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string afterTrim;
|
|
|
|
|
string jsonLinesLast = jsonLines.Last();
|
|
|
|
|
jsonLines.RemoveAt(jsonLines.Count - 1);
|
|
|
|
|
jsonLines.Add(jsonLinesLast[..^1]);
|
|
|
|
|
jsonLines.Insert(0, "{");
|
|
|
|
|
jsonLines.Add("}");
|
|
|
|
|
result = string.Join(Environment.NewLine, jsonLines);
|
|
|
|
|
keyValuePairs = JsonSerializer.Deserialize(result, DictionaryStringAndJsonElementSourceGenerationContext.Default.DictionaryStringJsonElement);
|
|
|
|
|
if (keyValuePairs is null)
|
|
|
|
|
throw new NullReferenceException(nameof(keyValuePairs));
|
|
|
|
|
result = JsonSerializer.Serialize(keyValuePairs, DictionaryStringAndJsonElementSourceGenerationContext.Default.DictionaryStringJsonElement);
|
|
|
|
|
jsonLines = result.Split(Environment.NewLine).ToList();
|
|
|
|
|
foreach (string jsonLine in jsonLines)
|
|
|
|
|
{
|
|
|
|
|
afterTrim = jsonLine.Trim();
|
|
|
|
|
if (string.IsNullOrEmpty(afterTrim) || afterTrim.First() is '{' or '}')
|
|
|
|
|
continue;
|
|
|
|
|
segments = afterTrim.Split(": ");
|
|
|
|
|
if (segments.Length != 2)
|
|
|
|
|
{
|
|
|
|
|
result = null;
|
|
|
|
|
results.Clear();
|
|
|
|
|
keyValuePairs = null;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (afterTrim[^1] != ',')
|
|
|
|
|
results.Add(afterTrim[1..].Replace("\": ", ": "));
|
|
|
|
|
else
|
|
|
|
|
results.Add(afterTrim[1..^1].Replace("\": ", ": "));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (result, keyValuePairs, results.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int ConvertFrontMatterToJsonFriendly(List<(MarkdownFile, string[])> collection)
|
|
|
|
|
{
|
|
|
|
|
int result = 0;
|
|
|
|
|
bool write;
|
|
|
|
|
List<string> results = new();
|
|
|
|
|
string[] frontMatterYamlLines;
|
|
|
|
|
foreach ((MarkdownFile markdownFile, string[] lines) in collection)
|
|
|
|
|
{
|
|
|
|
|
if (!lines.Any())
|
|
|
|
|
continue;
|
|
|
|
|
results.Clear();
|
|
|
|
|
if (markdownFile.LineNumber.FrontMatterYamlEnd is null)
|
|
|
|
|
continue;
|
|
|
|
|
(_, _, frontMatterYamlLines) = Get(markdownFile.LineNumber.FrontMatterYamlEnd.Value, lines);
|
|
|
|
|
if (!frontMatterYamlLines.Any())
|
|
|
|
|
continue;
|
|
|
|
|
results.Add("---");
|
|
|
|
|
results.AddRange(frontMatterYamlLines);
|
|
|
|
|
results.Add("---");
|
|
|
|
|
for (int i = markdownFile.LineNumber.FrontMatterYamlEnd.Value + 1; i < lines.Length; i++)
|
|
|
|
|
results.Add(lines[i]);
|
|
|
|
|
if (results.Count == lines.Length)
|
|
|
|
|
{
|
|
|
|
|
write = false;
|
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (results[i] == lines[i])
|
|
|
|
|
continue;
|
|
|
|
|
write = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!write)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
File.WriteAllLines(markdownFile.File, results);
|
|
|
|
|
File.SetLastWriteTime(markdownFile.File, markdownFile.LastWriteDateTime);
|
|
|
|
|
result += 1;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int CircularReference(ILogger<Worker> logger, List<(MarkdownFile, string[])> collection)
|
|
|
|
|
{
|
|
|
|
|
int result = 0;
|
|
|
|
@ -237,7 +387,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
bool circularReference;
|
|
|
|
|
foreach ((MarkdownFile markdownFile, string[] lines) in collection)
|
|
|
|
|
{
|
|
|
|
|
if (lines.Length < 1)
|
|
|
|
|
if (!lines.Any())
|
|
|
|
|
continue;
|
|
|
|
|
circularReference = false;
|
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
|
|
@ -294,7 +444,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
string check;
|
|
|
|
|
foreach ((MarkdownFile markdownFile, string[] lines) in collection)
|
|
|
|
|
{
|
|
|
|
|
if (lines.Length < 1)
|
|
|
|
|
if (!lines.Any())
|
|
|
|
|
continue;
|
|
|
|
|
found = false;
|
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
|
|
@ -501,7 +651,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
Dictionary<string, List<MarkdownFile>> keyValuePairs = record.StartAt is null ? GetKeyValuePairs(collection) : GetKeyValuePairs(appSettings, record);
|
|
|
|
|
foreach ((MarkdownFile markdownFile, string[] lines) in collection)
|
|
|
|
|
{
|
|
|
|
|
if (lines.Length < 1)
|
|
|
|
|
if (!lines.Any())
|
|
|
|
|
continue;
|
|
|
|
|
write = false;
|
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
|
|
@ -748,7 +898,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
{
|
|
|
|
|
string? root = Path.GetPathRoot(destination);
|
|
|
|
|
if (root is null || !Directory.Exists(root))
|
|
|
|
|
throw new NotSupportedException($"This method requires a valid -d path <{root}>!");
|
|
|
|
|
throw new NotSupportedException($"This method requires frontMatterYamlLines valid -d path <{root}>!");
|
|
|
|
|
if (!Directory.Exists(destination))
|
|
|
|
|
_ = Directory.CreateDirectory(destination);
|
|
|
|
|
}
|
|
|
|
@ -768,6 +918,12 @@ internal static partial class HelperMarkdown
|
|
|
|
|
collection = GetCollection(appSettings, GetFiles(appSettings, record));
|
|
|
|
|
logger.LogInformation("{updated} Markdown file(s) were updated", updated);
|
|
|
|
|
}
|
|
|
|
|
updated = ConvertFrontMatterToJsonFriendly(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)
|
|
|
|
|
{
|
|
|
|
@ -884,7 +1040,7 @@ internal static partial class HelperMarkdown
|
|
|
|
|
{
|
|
|
|
|
Record record = GetRecord(args);
|
|
|
|
|
if (string.IsNullOrEmpty(record.Destination))
|
|
|
|
|
throw new NotSupportedException("This method requires a -d path!");
|
|
|
|
|
throw new NotSupportedException("This method requires frontMatterYamlLines -d path!");
|
|
|
|
|
List<(string, string, string[])> collection = GetWithLinksForHugo(appSettings, record);
|
|
|
|
|
if (!collection.Any())
|
|
|
|
|
logger.LogInformation("No files?");
|
|
|
|
|