4.1 KiB
4.1 KiB
AGENTS.md - MD Reader
Markdown reader application.
Build & Run Commands
Rust (Recommended)
# Build project
cargo build
cargo build --release
# Run application
cargo run
cargo run -- --help
# Single binary output
cargo build --release
./target/release/md_reader
Node.js / Electron (Alternative)
# Install dependencies
npm install
# Development
npm run dev
# Production build
npm run build
# Run
npm start
Testing
Rust
# Run all tests
cargo test
# Run single test by name
cargo test test_name
# Run with output
cargo test -- --nocapture
# Doc tests
cargo test --doc
Node.js
# Run all tests
npm test
# Run single test file
npm test -- tests/single.test.ts
# Run tests in watch mode
npm run test:watch
# Coverage
npm run test:coverage
Linting & Formatting
Rust
# Format code (max_width=100, tab_spaces=4)
cargo fmt
cargo fmt -- --check
# Lint
cargo clippy
cargo clippy --all-features
# Check for errors
cargo check
Node.js
# Lint
npm run lint
# Format
npm run format
# Type check
npm run typecheck
Code Style
General
- Keep lines under 100 characters
- Use meaningful variable/function names
- Document public APIs with doc comments
Rust Style
Imports (order: std → external → local)
use std::path::Path;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use crate::core::parser::MarkdownParser;
Error Handling
- Use
anyhow::Result<T>for application code - Use
thiserrorfor library code - Use
.context()for error context
fn example() -> Result<SomeType> {
let content = std::fs::read_to_string(path)
.context("Failed to read markdown file")?;
Ok(result)
}
Naming Conventions
- Types/Enums: PascalCase (
MarkdownDoc,NodeType) - Functions/Variables: snake_case (
parse_markdown,render_html) - Files: snake_case (
markdown_parser.rs) - Traits: PascalCase (
Renderer,Parser)
Types
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarkdownDoc {
pub content: String,
pub title: Option<String>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum NodeType {
Heading,
Paragraph,
CodeBlock,
}
Node.js Style
Imports
import { readFile } from 'fs/promises';
import { parse, Document } from 'markdown-it';
import type { Plugin } from './types';
Naming Conventions
- Types/Interfaces: PascalCase (
MarkdownDoc,RenderOptions) - Functions/Variables: camelCase (
parseMarkdown,renderHtml) - Files: kebab-case (
markdown-parser.ts,render-options.ts)
Error Handling
async function readMarkdown(path: string): Promise<string> {
try {
return await readFile(path, 'utf-8');
} catch (error) {
throw new Error(`Failed to read markdown: ${path}`, { cause: error });
}
}
Project Structure
src/
├── main.rs # Entry point (Rust)
├── lib.rs # Library exports (Rust)
├── parser/ # Markdown parsing logic
├── renderer/ # Output rendering (HTML, PDF, etc.)
├── ui/ # User interface components
└── utils/ # Utility functions
# Node.js alternative
src/
├── index.ts # Entry point
├── parser/ # Markdown parsing
├── renderer/ # Rendering logic
├── ui/ # UI components
└── utils/ # Utilities
Key Dependencies (Rust)
- Error handling:
anyhow,thiserror - Serialization:
serde,serde_json - Markdown:
pulldown-cmarkormarkdown - CLI:
clap(derive) - Logging:
tracing
Key Dependencies (Node.js)
- Markdown parsing:
markdown-it,marked,remark - UI:
ReactorVue - Build:
vite,webpack - Testing:
vitest,jest
Cursor Rules (from momentry_core)
- No unit tests exist - add tests when implementing features
- Focus on clean, maintainable code
- Use appropriate abstractions
- Keep modules focused and single-purpose