Files
md_reader/AGENTS.md
2026-03-18 20:12:14 +08:00

223 lines
4.1 KiB
Markdown

# AGENTS.md - MD Reader
Markdown reader application.
## Build & Run Commands
### Rust (Recommended)
```bash
# 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)
```bash
# Install dependencies
npm install
# Development
npm run dev
# Production build
npm run build
# Run
npm start
```
## Testing
### Rust
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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)**
```rust
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 `thiserror` for library code
- Use `.context()` for error context
```rust
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**
```rust
#[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**
```typescript
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**
```typescript
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-cmark` or `markdown`
- **CLI**: `clap` (derive)
- **Logging**: `tracing`
## Key Dependencies (Node.js)
- **Markdown parsing**: `markdown-it`, `marked`, `remark`
- **UI**: `React` or `Vue`
- **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