📄 src/NewNote.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using Markdig;
using Markdig.Extensions.Yaml;
using Markdig.Syntax;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.Converters;

namespace NotesCli;

[Cmdlet(VerbsCommon.New, "Note", SupportsShouldProcess = true)]
[Alias("nn")]
public sealed class NewNote : PSCmdlet
{
    private static readonly MarkdownPipeline markdownPipeline = new MarkdownPipelineBuilder()
        .UseYamlFrontMatter()
        .Build();
    private static readonly IDeserializer yamlDeserializer = new DeserializerBuilder().Build();
    private static readonly ISerializer yamlSerializer = new SerializerBuilder()
        .WithTypeConverter(new DateOnlyConverter(formats: "yyyy-MM-dd"))
        .Build();

    [Parameter(HelpMessage = "Opens the newly created note for editing.")]
    public SwitchParameter Open { get; set; } = true;

    protected override void BeginProcessing()
    {
        var now = DateTimeOffset.Now;

        var frontmatter = GetPreviousFrontmatter() ?? [];
        frontmatter["date"] = DateOnly.FromDateTime(now.DateTime);

        var content = $"""
            ---
            {yamlSerializer.Serialize(frontmatter).TrimEnd()}
            ---



            """;
        var createdItems = InvokeProvider.Item.New(
            path: ".",
            name: $"{now:yyyy-MM-ddTHHmmss}.md",
            itemTypeName: "file",
            content: content
        );
        if (createdItems is not [{ BaseObject: FileInfo createdItem }])
        {
            return;
        }

        if (Open && ShouldProcess(createdItem.FullName, "Open"))
        {
            InvokeCommand.InvokeScript(
                $"{GetVariableValue("Env:EDITOR")} {createdItem.FullName}:{content.Count(c => c is '\n')}"
            );
        }

        WriteObject(createdItem);
    }

    private Dictionary<string, object>? GetPreviousFrontmatter()
    {
        var previousNote = InvokeProvider
            .ChildItem.Get("*.md", recurse: false)
            .Select(i => i.BaseObject)
            .OfType<FileInfo>()
            .MaxBy(f => f.Name);
        if (previousNote is null)
        {
            return null;
        }

        string previousText;
        using (var reader = new StreamReader(previousNote.OpenRead()))
        {
            previousText = reader.ReadToEnd();
        }

        var markdown = Markdown.Parse(previousText, markdownPipeline);

        var yamlBlock = markdown.Descendants<YamlFrontMatterBlock>().FirstOrDefault();
        if (yamlBlock?.Lines.ToString() is not string yaml)
        {
            return null;
        }

        return yamlDeserializer.Deserialize<Dictionary<string, object>>(yaml);
    }
}