📄 src/Storage/NotePreviewBuilder.cs
namespace NotesApp.Storage;

// Shared by NoteViewActivity (recomputing its own preview after loading/saving) and
// NoteListActivity (recomputing a row's preview whenever NoteContentCache finishes fetching
// that note's full body) - both need the exact same rules, or the list and the editor would
// disagree on what a note's preview looks like.
public static class NotePreviewBuilder
{
    private const int MaxLength = 300;

    public static string Build(string content)
    {
        var withoutFrontmatter = StripFrontmatter(content);

        var trimmed =
            withoutFrontmatter.Length > MaxLength
                ? withoutFrontmatter[..MaxLength]
                : withoutFrontmatter;
        var lastNewline = trimmed.LastIndexOf('\n');
        return lastNewline > 0 ? trimmed[..lastNewline] : trimmed;
    }

    private static string StripFrontmatter(string content)
    {
        var lines = content.Split(
            ["\n", "\r\n"],
            StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries
        );
        if (lines is [])
            return content;

        var firstLine = lines[0];
        if (firstLine.Any(c => c != '-'))
            return content;

        for (var i = 1; i < lines.Length; i++)
        {
            var line = lines[i];
            if (line.Length == firstLine.Length && line.All(c => c == '-'))
                return string.Join('\n', lines[(i + 1)..]);
        }

        return content;
    }
}