Files
Marcos Paulo 15d7f5e873 feat: editor blocks and lint, vault knowledge, calendar plugin, macOS menu
- notescraft-lint (rules, safe fixes, learned style) and notescraft-blocks (block model and edits); engine lint.* and block.* commands with CLI and MCP parity
- Lint tab, underlines, slash menu with preview in Source and Visual, block grip and menu, Settings > Editor and lint, Vim block keys
- Visual view: tables, note embeds, %% comments, wrapping property chips
- Vault knowledge (Related tab, assistant sources, Settings) and calendar plugin
- Sidebar top padding fixed, dot grid follows PaperCraft spacing, right-card tabs no longer cover the collapse button

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 12:36:00 -03:00

60 lines
2.2 KiB
Rust

//! Learned style votes and closest-title suggestions.
use notescraft_lint::style::{DEFAULT_MIN_NOTES, DEFAULT_THRESHOLD, StyleKind};
use notescraft_lint::suggest::closest;
use notescraft_lint::{HeadingStyle, Vote};
#[test]
fn style_needs_enough_notes_and_a_clear_majority() {
let mut vote = Vote::default();
for _ in 0..19 {
vote.add_note("- a\n- b\n\nDone 2026-10-17\n");
}
assert_eq!(vote.style(DEFAULT_MIN_NOTES, DEFAULT_THRESHOLD).list_marker, None);
vote.add_note("- a\n2026-01-02\n");
let style = vote.style(DEFAULT_MIN_NOTES, DEFAULT_THRESHOLD);
assert_eq!(style.list_marker, Some('-'));
assert_eq!(style.date_format.as_deref(), Some("YYYY-MM-DD"));
assert_eq!(style.heading_style, None);
for _ in 0..6 {
vote.add_note("* a\n");
}
assert_eq!(vote.style(DEFAULT_MIN_NOTES, DEFAULT_THRESHOLD).list_marker, None);
let report = vote.report();
let dash = report.iter().find(|s| s.kind == StyleKind::ListMarker && s.value == "-").expect("dash");
assert_eq!((dash.count, dash.total), (20, 26));
}
#[test]
fn removing_a_note_undoes_adding_it() {
let mut vote = Vote::default();
let note = "# T\n\n* a\n01/02/2026\n";
vote.add_note(note);
assert_eq!(vote.report().len(), 3);
vote.remove_note(note);
vote.remove_note(note);
assert_eq!(vote, Vote::default());
}
#[test]
fn headings_and_dates() {
let mut vote = Vote::default();
for _ in 0..25 {
vote.add_note("Title\n=====\n\nsee 31.12.2025\n");
}
let style = vote.style(DEFAULT_MIN_NOTES, DEFAULT_THRESHOLD);
assert_eq!(style.heading_style, Some(HeadingStyle::Setext));
assert_eq!(style.date_format.as_deref(), Some("DD.MM.YYYY"));
}
#[test]
fn closest_prefers_same_folder() {
let c = vec![("other/Release notes.md".to_string(), "Release notes".to_string()), ("mine/Release note.md".to_string(), "Release note".to_string())];
let (title, sim) = closest("Release nots", &c, "mine").expect("match");
assert_eq!(title, "Release note");
assert!(sim > 0.8 && sim <= 1.0);
assert_eq!(closest("Release nots", &c, "x").expect("match").0, "Release notes");
assert!(closest("Completely different", &c, "x").is_none());
assert!(closest("", &c, "x").is_none());
}