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

57 lines
2.6 KiB
Rust

//! The calendar through the CLI: `run <id> <json>` gives the engine's answer.
mod common;
use common::{empty_vault, exists, note, read_file, run};
use notescraft_engine::{Registry, Session, register_core};
use serde_json::{Value, json};
fn vault(name: &str) -> std::path::PathBuf {
let root = empty_vault(name);
note(&root, "Calendar/lunch.md", "---\ntitle: Lunch\nstart: 2026-10-20T12:00\nend: 2026-10-20T13:00\n---\n");
note(&root, "Calendar/clash.md", "---\ntitle: Dentist\nstart: 2026-10-20T12:30\nend: 2026-10-20T13:30\n---\n");
note(&root, "Calendar/standup.md", "---\ntitle: Standup\nstart: 2026-10-19T09:30\nrepeat: weekly\n---\n");
root
}
fn engine(root: &std::path::Path, id: &str, params: &Value) -> Value {
let mut registry = Registry::new();
register_core(&mut registry).expect("register");
let mut session = Session::open_read_only(root).expect("open");
registry.run(id, &mut session, params).expect("engine run")
}
#[test]
fn reads_match_the_engine_with_json() {
let root = vault("cal-cli-read");
for (id, params) in [
("calendar.agenda", json!({ "from": "2026-10-19", "to": "2026-11-02", "group": "day" })),
("calendar.free", json!({ "day": "2026-10-20", "min_minutes": 15 })),
("calendar.conflicts", json!({ "from": "2026-10-19", "to": "2026-10-25" })),
("calendar.year", json!({ "year": 2026 })),
] {
let out = run(&root, &["--json", "run", id, &params.to_string()]);
assert_eq!(out.code, 0, "{id}: {}", out.stderr);
assert_eq!(out.result(), engine(&root, id, &params), "{id}");
}
}
#[test]
fn writes_work_and_a_repeating_event_needs_a_scope() {
let root = vault("cal-cli-write");
let added = run(&root, &["--json", "run", "calendar.add", &json!({ "text": "Gym 2026-11-03 at 7:00 for 1h" }).to_string()]);
assert_eq!(added.code, 0, "{}", added.stderr);
assert!(exists(&root, "Calendar/2026-11-03-gym.md"));
let missing = run(&root, &["--json", "run", "calendar.edit", &json!({ "id": "Calendar/standup.md", "fields": { "title": "x" } }).to_string()]);
assert_eq!(missing.code, 1);
assert_eq!(missing.error_code(), "command_failed");
assert!(missing.stdout.contains("this, following or all"), "{}", missing.stdout);
assert!(read_file(&root, "Calendar/standup.md").contains("title: Standup"), "nothing changed");
let scoped =
run(&root, &["--json", "run", "calendar.edit", &json!({ "id": "Calendar/standup.md", "scope": "all", "fields": { "title": "Sync" } }).to_string()]);
assert_eq!(scoped.code, 0, "{}", scoped.stderr);
assert!(read_file(&root, "Calendar/standup.md").contains("title: Sync"));
}