Files
lc ce439db449 增加API分页和轻量级查询支持,完善备份恢复功能
主要改动:
- API: 为 /api/pages 添加 lightweight 模式和分页支持
- 备份恢复: 增强 restore API 的错误处理和验证逻辑
- 工具函数: 新增 page-utils 辅助函数
- 会话管理: 优化 session 和 auth 相关逻辑
- 文档: 添加 CLAUDE.md 项目指南,包含编辑器配置注意事项

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 16:30:31 +08:00

5.8 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

NoteAI is a local knowledge note-taking application built with Next.js, Prisma (SQLite), and TipTap editor. The app provides a hierarchical page structure with rich text editing, markdown import/export, and password-protected access.

Development Commands

# Development server (runs on port 3001)
npm run dev

# Build for production
npm run build

# Initialize environment variables
npm run env:init

# Build with environment initialization
npm run build:init

# Start production server (port 3001)
npm start

# Linting
npm run lint

# Type checking and linting together
npm run check

# Run editor block operations tests
npm test

Architecture

Database Layer (Prisma + SQLite)

  • Schema: prisma/schema.prisma
  • Client: Singleton instance in src/lib/prisma.ts
  • Models:
    • Page: Hierarchical pages with self-referential parent-child relationships. Supports both "file" and "folder" types with ordering, locking, tags, and icons.
    • GlobalSettings: Stores scrypt-hashed password for app-wide authentication.

State Management

  • Zustand stores with persistence:
    • src/lib/store.ts: Main editor state (pages, activePageId, CRUD operations)
    • src/lib/search-store.ts: Search functionality state
    • src/lib/settings-store.ts: Application settings state
    • src/lib/page-history.ts: Undo/redo history management with snapshots

Authentication & Session

  • Session management: src/lib/session.ts - Custom HMAC-based session tokens stored in cookies (24h TTL)
  • Auth utilities: src/lib/auth.ts - Scrypt password hashing/verification
  • API auth: src/lib/api-auth.ts - Middleware for protecting API routes
  • Rate limiting: src/lib/rate-limit.ts - Token bucket rate limiter for auth endpoints

Editor System (TipTap)

  • Extensions: Custom TipTap extensions in src/components/editor/extensions/
    • callout.ts & callout-component.tsx: Custom callout blocks
    • ai-mark.ts: AI-generated content marking
    • task-item.tsx: Custom task list items
  • Block operations: src/lib/editor-block-ops.ts - Core logic for moving/reordering contiguous spans of blocks (drag-and-drop support)
  • Tests: src/lib/editor-block-ops.test.ts run via scripts/run-editor-block-ops-tests.mjs

CRITICAL: Editor Initialization Configuration

When modifying src/components/editor.tsx, preserve these critical settings for proper markdown import functionality:

// In useEditor() configuration:
{
  extensions: [
    // ... other extensions
    Markdown.configure({
      html: true,
      transformPastedText: true,
      transformCopiedText: true,  // MUST be true for markdown conversion
    }),
  ],
  content,  // MUST pass content prop directly, NOT empty string
  onUpdate: ({ editor }) => {
    // ... update logic
  }
}

// In useEffect for content updates:
useEffect(() => {
  if (editor && content !== editor.getHTML()) {
    const normalizedContent = cleanupAccidentalStandaloneInlineCode(content);
    suppressNextUpdateRef.current = true;
    allowOnUpdateRef.current = false;
    queueMicrotask(() => {
      editor.commands.setContent(normalizedContent);  // Simple call, no extra options
    });
    if (normalizedContent !== content) {
      onChange(normalizedContent);
    }
  }
  if (editor && onEditorReady) {
    onEditorReady(editor);
  }
}, [content, editor, onEditorReady]);  // Dependencies: do NOT include onChange

Common mistakes to avoid:

  • Setting content: '' instead of content breaks markdown import display
  • Setting transformCopiedText: false disables markdown conversion
  • Adding unnecessary options to setContent() can cause whitespace issues
  • Including onChange in useEffect dependencies causes infinite re-renders

Import/Export

  • Markdown import: src/lib/markdown-import.ts - Converts markdown to HTML with special handling for fenced code blocks
  • Export: src/lib/export.ts - Handles exporting pages to various formats
  • File I/O: src/lib/file-io.ts - File system operations for import/export
  • HTML sanitization: src/lib/sanitize-html.ts - Sanitizes HTML content

API Routes

All routes in src/app/api/:

  • /api/auth/login & /api/auth/logout: Authentication
  • /api/settings/init: First-time password setup (requires INIT_SETUP_TOKEN in production)
  • /api/settings/password: Change password
  • /api/settings/status: Check initialization status
  • /api/settings/restore: Restore from backup
  • /api/pages: CRUD operations for pages
  • /api/pages/[id]: Individual page operations
  • /api/pages/reorder: Batch reorder pages
  • /api/ai/chat: AI chat integration

Special Features

  • Wiki links: src/lib/wiki-links.ts - Internal page linking system
  • Page utilities: src/lib/page-utils.ts - Helper functions for page operations
  • Search: src/lib/search-query.ts - Search query parsing and execution

Environment Variables

Required in .env:

DATABASE_URL="file:./dev.db"
SESSION_SECRET="<32+ character random string>"
INIT_DEFAULT_PASSWORD="<initial password>"
INIT_SETUP_TOKEN="<optional token for production init>"

Path Aliases

  • @/* maps to src/* (configured in tsconfig.json)

Testing

Tests use Node's native test runner with --experimental-strip-types flag. Test files use .test.ts extension and are run via custom scripts in scripts/ directory.

Database Migrations

# Generate Prisma client after schema changes
npx prisma generate

# Create and apply migrations
npx prisma migrate dev

# Apply migrations in production
npx prisma migrate deploy

Build Targets

Prisma is configured for both native and linux-musl-openssl-3.0.x targets to support Docker deployments.