Premier commit déjà bien avancé
This commit is contained in:
421
CLAUDE.md
Normal file
421
CLAUDE.md
Normal file
@ -0,0 +1,421 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
A lightweight web-based Markdown note-taking application with a Go backend and modern JavaScript frontend. Notes are stored as plain Markdown files with YAML front matter containing metadata (title, date, last_modified, tags). The system provides a sophisticated CodeMirror 6 editor with live preview, rich search capabilities, hierarchical organization, and automatic front matter management.
|
||||
|
||||
**Recent Modernization**: The project has been migrated from a simple textarea editor to CodeMirror 6, with a Vite build system for frontend modules. The backend remains unchanged, maintaining the same Go architecture with htmx for dynamic interactions.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Backend (Go)
|
||||
|
||||
Three main packages under `internal/`:
|
||||
- **indexer**: Maintains an in-memory index mapping tags to note files. Parses YAML front matter from `.md` files to build the index. Thread-safe with RWMutex.
|
||||
- **watcher**: Uses `fsnotify` to monitor filesystem changes and trigger re-indexing with 200ms debounce. Recursively watches all subdirectories.
|
||||
- **api**: HTTP handlers that serve templates and handle CRUD operations on notes. Updates front matter automatically on save.
|
||||
|
||||
The server (`cmd/server/main.go`) coordinates these components:
|
||||
1. Loads initial index from notes directory
|
||||
2. Starts filesystem watcher for automatic re-indexing
|
||||
3. Pre-parses HTML templates from `templates/`
|
||||
4. Serves routes: `/` (main page), `/api/search`, `/api/notes/*`, `/api/tree`, `/api/folders/create`, `/api/files/move`
|
||||
5. Handles static files from `static/` directory
|
||||
|
||||
### Frontend
|
||||
|
||||
The frontend uses a modern build system with Vite and CodeMirror 6:
|
||||
|
||||
#### Architecture
|
||||
- **Build System**: Vite compiles frontend modules from `frontend/src/` to `static/dist/`
|
||||
- **Editor**: CodeMirror 6 with Markdown language support, One Dark theme, and syntax highlighting
|
||||
- **Templates**: `index.html`, `editor.html`, `file-tree.html`, `search-results.html`, `new-note-prompt.html`
|
||||
- **HTMX Integration**: Server returns HTML fragments that htmx swaps into the DOM
|
||||
- **Out-of-band swaps**: Update the file tree after saves/deletes without full page reload
|
||||
|
||||
#### Frontend Source Structure
|
||||
```
|
||||
frontend/src/
|
||||
├── main.js # Entry point - imports all modules
|
||||
├── editor.js # CodeMirror 6 editor implementation with slash commands
|
||||
├── file-tree.js # Drag-and-drop file organization
|
||||
└── ui.js # Sidebar toggle functionality
|
||||
```
|
||||
|
||||
#### CodeMirror 6 Editor Features
|
||||
- **Syntax Highlighting**: Full Markdown language support (`@codemirror/lang-markdown`)
|
||||
- **Theme**: One Dark theme (`@codemirror/theme-one-dark`) - VS Code-inspired dark theme
|
||||
- **Live Preview**: Debounced updates (150ms) synchronized with editor scroll position
|
||||
- **Auto-Save**: Triggers after 2 seconds of inactivity
|
||||
- **Keyboard Shortcuts**:
|
||||
- `Ctrl/Cmd+S` for manual save
|
||||
- `Tab` for proper indentation
|
||||
- Full keyboard navigation
|
||||
- **View Modes**: Toggle between split view, editor-only, and preview-only
|
||||
- **Slash Commands**: Type `/` to open command palette for quick Markdown insertion
|
||||
- **Front Matter Handling**: Automatically strips YAML front matter in preview
|
||||
|
||||
#### File Tree Features
|
||||
- **Folder Management**: Expand/collapse folders with visual indicators (📁/📂)
|
||||
- **Drag & Drop**: Move files between folders with visual feedback
|
||||
- **Folder Creation**: Modal-based creation supporting nested paths
|
||||
- **Safe Validation**: Prevents dangerous path operations
|
||||
|
||||
#### Rendering Pipeline
|
||||
- **marked.js**: Markdown to HTML conversion
|
||||
- **DOMPurify**: HTML sanitization to prevent XSS attacks
|
||||
- **Highlight.js**: Syntax highlighting for code blocks in preview
|
||||
- **Custom Theme**: Material Darker theme in `static/theme.css` with CSS custom properties
|
||||
|
||||
### Note Format
|
||||
|
||||
Notes have YAML front matter with these fields:
|
||||
```yaml
|
||||
---
|
||||
title: "Note Title"
|
||||
date: "08-11-2025"
|
||||
last_modified: "08-11-2025:13:02"
|
||||
tags: [tag1, tag2]
|
||||
---
|
||||
```
|
||||
|
||||
The `indexer` package handles both single-value and array-format tags via custom `UnmarshalYAML`.
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Building the Frontend
|
||||
|
||||
**IMPORTANT**: The frontend must be built before running the application. The compiled JavaScript is required.
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install # Install dependencies (first time only)
|
||||
npm run build # Compile frontend modules to static/dist/
|
||||
```
|
||||
|
||||
Output files (loaded by templates):
|
||||
- `static/dist/project-notes-frontend.es.js` (ES module)
|
||||
- `static/dist/project-notes-frontend.umd.js` (UMD format)
|
||||
|
||||
Frontend dependencies (from `frontend/package.json`):
|
||||
- `@codemirror/basic-setup` - Base editor functionality
|
||||
- `@codemirror/lang-markdown` - Markdown language support
|
||||
- `@codemirror/state` - Editor state management
|
||||
- `@codemirror/view` - Editor view layer
|
||||
- `@codemirror/theme-one-dark` - Dark theme
|
||||
- `vite` - Build tool
|
||||
|
||||
### Running the Server
|
||||
|
||||
```bash
|
||||
go run ./cmd/server
|
||||
```
|
||||
|
||||
Server starts on `http://localhost:8080`. Use flags to customize:
|
||||
- `-addr :PORT` - Change server address (default: `:8080`)
|
||||
- `-notes-dir PATH` - Change notes directory (default: `./notes`)
|
||||
|
||||
### Testing
|
||||
|
||||
Run all tests:
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Run specific package tests:
|
||||
```bash
|
||||
go test ./internal/indexer
|
||||
go test ./internal/api
|
||||
```
|
||||
|
||||
Run tests with verbose output:
|
||||
```bash
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
### Building the Server Binary
|
||||
|
||||
```bash
|
||||
go build ./cmd/server
|
||||
```
|
||||
|
||||
### Backend Dependencies
|
||||
|
||||
Update Go dependencies:
|
||||
```bash
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
Key backend dependencies:
|
||||
- `github.com/fsnotify/fsnotify` - Filesystem watcher
|
||||
- `gopkg.in/yaml.v3` - YAML parsing for front matter
|
||||
|
||||
### Vite Build System
|
||||
|
||||
The frontend uses Vite (`frontend/vite.config.js`) for bundling JavaScript modules:
|
||||
|
||||
**Configuration**:
|
||||
- **Entry Point**: `frontend/src/main.js` (imports editor.js, file-tree.js, ui.js)
|
||||
- **Output Directory**: `static/dist/` (served by Go server)
|
||||
- **Library Mode**: Builds as a library with both ES and UMD formats
|
||||
- **Single Bundle**: No code splitting - all dependencies bundled together
|
||||
- **Aliases**: Path aliases for `@codemirror/state` and `@codemirror/view` to ensure consistent versions
|
||||
|
||||
**Build Process**:
|
||||
1. Vite reads all source files from `frontend/src/`
|
||||
2. Resolves npm dependencies (@codemirror packages)
|
||||
3. Bundles everything into two formats:
|
||||
- ES module (`project-notes-frontend.es.js`) - 1.0 MB
|
||||
- UMD (`project-notes-frontend.umd.js`) - 679 KB
|
||||
4. Outputs to `static/dist/` where Go server can serve them
|
||||
5. Templates load the ES module version via `<script type="module">`
|
||||
|
||||
**Development Workflow**:
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build # Build for production
|
||||
npm run build -- --watch # Watch mode for development
|
||||
```
|
||||
|
||||
The Go server does not need to be restarted after frontend builds - simply refresh the browser.
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### Front Matter Management
|
||||
|
||||
The system automatically manages front matter when saving notes:
|
||||
- `title`: Auto-generated from filename if missing (converts hyphens to spaces, title-cases)
|
||||
- `date`: Set to creation date for new files, preserved for existing files
|
||||
- `last_modified`: Always updated to current timestamp on save (format: `DD-MM-YYYY:HH:MM`)
|
||||
- `tags`: Preserved from user input; defaults to `["default"]` for new notes
|
||||
|
||||
Front matter extraction happens in two places:
|
||||
- `indexer.ExtractFrontMatterAndBody()` - For file paths
|
||||
- `indexer.ExtractFrontMatterAndBodyFromReader()` - For `io.Reader` (used when parsing form content)
|
||||
|
||||
### Indexing and Search
|
||||
|
||||
The indexer maintains two data structures:
|
||||
- `tags map[string][]string` - Maps tags to file paths for tag-based lookup
|
||||
- `docs map[string]*Document` - Stores full document metadata for rich search
|
||||
|
||||
Re-indexing happens:
|
||||
- On server startup
|
||||
- When files are created/modified/deleted (via watcher with 200ms debounce)
|
||||
- After POST/DELETE/MOVE operations (background goroutine)
|
||||
|
||||
Rich search supports multiple query formats:
|
||||
- General terms: Search across title, tags, path, and body (AND logic)
|
||||
- `tag:value` - Filter by specific tag (case-insensitive)
|
||||
- `title:value` - Filter by title content
|
||||
- `path:value` - Filter by file path
|
||||
- Quoted phrases: `"exact phrase"` preserves spaces
|
||||
- Results are scored and ranked by relevance (title matches score highest)
|
||||
|
||||
### Security Considerations
|
||||
|
||||
File path validation in `handler.go`:
|
||||
- `filepath.Clean()` to normalize paths
|
||||
- Reject paths starting with `..` or absolute paths (directory traversal prevention)
|
||||
- Enforce `.md` extension for notes
|
||||
- Use `filepath.Join()` to construct safe paths within notes directory
|
||||
- DOMPurify sanitizes Markdown-rendered HTML to prevent XSS attacks
|
||||
|
||||
### Template System
|
||||
|
||||
Templates are pre-parsed at startup. The API handler returns HTML fragments that htmx inserts into the page. Out-of-band swaps update the file tree sidebar without full page reload.
|
||||
|
||||
### Concurrency
|
||||
|
||||
- Indexer uses `sync.RWMutex` for thread-safe access (read locks for searches, write locks for re-indexing)
|
||||
- Re-indexing after saves/deletes/moves happens in background goroutines to avoid blocking HTTP responses
|
||||
- Watcher runs in separate goroutine with proper context cancellation
|
||||
- Server shutdown uses 5-second graceful shutdown timeout with context
|
||||
|
||||
### File Organization
|
||||
|
||||
The application supports hierarchical note organization:
|
||||
- Notes can be organized in subdirectories within the `notes/` directory
|
||||
- The file tree displays folders and files in a hierarchical view
|
||||
- Folders are displayed before files, both sorted alphabetically (case-insensitive)
|
||||
- API endpoints for folder creation (`/api/folders/create`) and file moving (`/api/files/move`)
|
||||
- Watcher recursively monitors all subdirectories for changes
|
||||
|
||||
### CodeMirror 6 Editor Implementation
|
||||
|
||||
The editor is implemented in `frontend/src/editor.js` with two main classes:
|
||||
|
||||
#### MarkdownEditor Class
|
||||
Manages the CodeMirror 6 instance and its interactions:
|
||||
|
||||
**Initialization**:
|
||||
```javascript
|
||||
EditorState.create({
|
||||
doc: content,
|
||||
extensions: [
|
||||
basicSetup, // Line numbers, search, fold gutter
|
||||
markdown(), // Markdown syntax support
|
||||
oneDark, // One Dark theme
|
||||
keymap.of([indentWithTab]),
|
||||
EditorView.updateListener.of(...), // Preview & auto-save
|
||||
keymap.of([{ key: "Mod-s", run: saveFunction }])
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
**Key Features**:
|
||||
- **Live Preview**: Updates preview pane with 150ms debounce on editor changes
|
||||
- **Auto-Save**: Triggers form submission after 2 seconds of inactivity
|
||||
- **Scroll Sync**: Bidirectional scroll synchronization between editor and preview (50ms debounce)
|
||||
- **Front Matter Stripping**: Removes YAML front matter from preview rendering
|
||||
- **View Modes**: Three modes (split/editor-only/preview-only) saved to localStorage
|
||||
- **Height Management**: Dynamic height calculation (`window.innerHeight - 180px`) with resize handling
|
||||
- **Cleanup**: Proper destruction of editor instances to prevent memory leaks
|
||||
|
||||
**Integration**:
|
||||
- Replaces the hidden textarea element
|
||||
- HTMX events trigger editor initialization (`htmx:afterSwap`)
|
||||
- Form submission uses `requestSubmit()` to trigger HTMX POST
|
||||
|
||||
#### SlashCommands Class
|
||||
Provides command palette for quick Markdown insertion:
|
||||
|
||||
**Trigger**: Type `/` at the beginning of a line to open the palette
|
||||
|
||||
**Implementation**:
|
||||
- Monitors editor state changes for `/` character
|
||||
- Filters commands in real-time as user types
|
||||
- Positions palette dynamically using CodeMirror's `coordsAtPos()`
|
||||
- Keyboard navigation with arrow keys, Enter/Tab to select
|
||||
- Inserts Markdown text using CodeMirror transactions
|
||||
- 13 built-in commands with text templates
|
||||
|
||||
**UI/UX**:
|
||||
- Styled palette with gradient selection indicator
|
||||
- Smooth animations and transitions
|
||||
- Accessible keyboard navigation
|
||||
- Auto-closes on selection or Escape key
|
||||
|
||||
### Slash Commands
|
||||
|
||||
The editor includes a slash command system integrated with CodeMirror 6:
|
||||
- Type `/` at the start of a line to trigger the command palette
|
||||
- Available commands (13 total):
|
||||
- **Headings**: h1, h2, h3 - Insert Markdown headers
|
||||
- **Formatting**: bold, italic, code - Text formatting
|
||||
- **Blocks**: codeblock, quote, hr, table - Block-level elements
|
||||
- **Lists**: list - Unordered list
|
||||
- **Dynamic**: date - Insert current date in French format (DD/MM/YYYY)
|
||||
- **Links**: link - Insert link template `[text](url)`
|
||||
- Navigate with Arrow Up/Down, select with Enter/Tab, cancel with Escape
|
||||
- Commands are filtered in real-time as you type after the `/`
|
||||
- The palette is positioned dynamically near the cursor using CodeMirror coordinates
|
||||
- Implementation in `frontend/src/editor.js` with the `SlashCommands` class
|
||||
- Styled command palette with gradient selection indicator
|
||||
|
||||
## Frontend Libraries
|
||||
|
||||
The application uses a mix of npm packages (for the editor) and CDN-loaded libraries (for utilities):
|
||||
|
||||
### NPM Packages (Built with Vite)
|
||||
Managed in `frontend/package.json`:
|
||||
- **@codemirror/basic-setup (^0.20.0)**: Base editor functionality (line numbers, search, etc.)
|
||||
- **@codemirror/lang-markdown (^6.5.0)**: Markdown language support and syntax highlighting
|
||||
- **@codemirror/state (^6.5.2)**: Editor state management
|
||||
- **@codemirror/view (^6.38.6)**: Editor view layer and rendering
|
||||
- **@codemirror/theme-one-dark (^6.1.3)**: Dark theme for CodeMirror
|
||||
- **vite (^5.0.0)**: Build tool for bundling frontend modules
|
||||
|
||||
### CDN Libraries
|
||||
Loaded in `templates/index.html`:
|
||||
- **htmx (1.9.10)**: AJAX interactions and dynamic content loading
|
||||
- **marked.js**: Markdown to HTML conversion for preview
|
||||
- **DOMPurify**: HTML sanitization to prevent XSS attacks
|
||||
- **Highlight.js (11.9.0)**: Syntax highlighting for code blocks in preview with Atom One Dark theme
|
||||
|
||||
### Styling
|
||||
- **Material Darker Theme**: Custom dark theme in `static/theme.css`
|
||||
- **Color System**: CSS custom properties for consistent theming
|
||||
- Background colors: `--bg-primary`, `--bg-secondary`, `--bg-tertiary`, `--bg-elevated`
|
||||
- Text colors: `--text-primary`, `--text-secondary`, `--text-muted`
|
||||
- Accent colors: `--accent-blue`, `--accent-violet`
|
||||
- **No CSS Framework**: All styles hand-crafted with CSS Grid and Flexbox
|
||||
- **Responsive Design**: Adaptive layout for different screen sizes
|
||||
- **Custom Scrollbars**: Styled scrollbars matching the dark theme
|
||||
|
||||
### Build Output
|
||||
The Vite build process produces:
|
||||
- `static/dist/project-notes-frontend.es.js` - ES module format (1.0 MB, includes all CodeMirror 6 dependencies)
|
||||
- `static/dist/project-notes-frontend.umd.js` - UMD format (679 KB, legacy compatibility)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
project-notes/
|
||||
├── cmd/
|
||||
│ └── server/
|
||||
│ └── main.go # Server entry point
|
||||
├── internal/
|
||||
│ ├── api/
|
||||
│ │ └── handler.go # HTTP handlers for CRUD operations
|
||||
│ ├── indexer/
|
||||
│ │ └── indexer.go # Note indexing and search
|
||||
│ └── watcher/
|
||||
│ └── watcher.go # Filesystem watcher with fsnotify
|
||||
├── frontend/ # Frontend build system (NEW)
|
||||
│ ├── src/
|
||||
│ │ ├── main.js # Entry point
|
||||
│ │ ├── editor.js # CodeMirror 6 implementation (26 KB)
|
||||
│ │ ├── file-tree.js # Drag-and-drop file management (11 KB)
|
||||
│ │ └── ui.js # Sidebar toggle (720 B)
|
||||
│ ├── package.json # NPM dependencies
|
||||
│ ├── package-lock.json
|
||||
│ └── vite.config.js # Vite build configuration
|
||||
├── static/
|
||||
│ ├── dist/ # Compiled frontend (generated)
|
||||
│ │ ├── project-notes-frontend.es.js
|
||||
│ │ └── project-notes-frontend.umd.js
|
||||
│ └── theme.css # Material Darker theme
|
||||
├── templates/
|
||||
│ ├── index.html # Main page layout
|
||||
│ ├── editor.html # Editor component
|
||||
│ ├── file-tree.html # File tree sidebar
|
||||
│ ├── search-results.html # Search results
|
||||
│ └── new-note-prompt.html # New note modal
|
||||
├── notes/ # Note storage directory
|
||||
│ └── *.md # Markdown files with YAML front matter
|
||||
├── go.mod # Go dependencies
|
||||
├── go.sum
|
||||
└── CLAUDE.md # This file
|
||||
```
|
||||
|
||||
### Key Files to Edit
|
||||
|
||||
**Backend Development**:
|
||||
- `cmd/server/main.go` - Server initialization and routing
|
||||
- `internal/api/handler.go` - API endpoints and request handling
|
||||
- `internal/indexer/indexer.go` - Search and indexing logic
|
||||
- `internal/watcher/watcher.go` - Filesystem monitoring
|
||||
|
||||
**Frontend Development**:
|
||||
- `frontend/src/editor.js` - CodeMirror editor, preview, slash commands
|
||||
- `frontend/src/file-tree.js` - File tree interactions and drag-and-drop
|
||||
- `frontend/src/ui.js` - UI utilities (sidebar toggle)
|
||||
- `static/theme.css` - Styling and theming
|
||||
- `templates/*.html` - HTML templates (Go template syntax)
|
||||
|
||||
**Configuration**:
|
||||
- `frontend/vite.config.js` - Frontend build configuration
|
||||
- `frontend/package.json` - NPM dependencies and scripts
|
||||
- `go.mod` - Go dependencies
|
||||
|
||||
### Important Notes
|
||||
|
||||
1. **Frontend builds are required**: The application will not work without compiled JavaScript in `static/dist/`
|
||||
2. **No hot reload for frontend**: Changes to `frontend/src/` require running `npm run build` and refreshing the browser
|
||||
3. **Backend changes**: Require restarting the Go server (`go run ./cmd/server`)
|
||||
4. **Template changes**: Require restarting the Go server (templates are pre-parsed at startup)
|
||||
5. **CSS changes**: Only require browser refresh (loaded via `<link>` tag)
|
||||
6. **Note changes**: Automatically detected by filesystem watcher, trigger re-indexing
|
||||
Reference in New Issue
Block a user