Skip to content

添加目录级搜索功能#19

Merged
kookyleo merged 14 commits intomainfrom
feature/directory-search
Nov 16, 2025
Merged

添加目录级搜索功能#19
kookyleo merged 14 commits intomainfrom
feature/directory-search

Conversation

@google-labs-jules
Copy link
Contributor

@google-labs-jules google-labs-jules bot commented Nov 13, 2025

Summary

Implements full-text search functionality for directory-level Markdown browsing with advanced features including Chinese word segmentation, auto-scroll to matched text, and modern UI design.

Fixes #17

Features

Search Engine

  • Tantivy 0.25 full-text search engine (replaced SQLite FTS5)
  • Chinese word segmentation using tantivy-jieba
  • In-memory indexing for fast search performance
  • Multi-field search across file names, titles, and content
  • Snippet generation with highlighted search terms

File Watching

  • Automatic index updates when files change
  • File watcher using notify crate
  • Real-time synchronization of file changes

User Experience

  • Keyboard navigation - Up/Down arrows, Enter to select
  • Auto-scroll to match - Jumps to exact position in document
  • Keyword highlighting - Temporary pulse animation on matched text
  • Full-screen clean UI - Content constrained to article width
  • Theme-aware styling - Light/dark/auto mode support
  • Search shortcut (/) - Quick access to search

UI Improvements

  • ✅ Modern full-screen search modal
  • ✅ Disabled browser autocomplete for clean search experience
  • ✅ Result highlighting with left border accent
  • ✅ Responsive design (desktop/mobile)
  • ✅ Keyboard shortcuts help panel integration
  • ✅ Print-friendly (highlights removed in print mode)

Testing

  • 24 tests passing (11 unit + 13 integration)
  • ✅ Test coverage for:
    • Index creation and basic search
    • Chinese word segmentation
    • Multi-field search
    • File updates and deletions
    • Snippet generation
    • Large file indexing
    • Concurrent searches
    • Mixed language search

Technical Details

Dependencies

  • tantivy = "0.25" - Search engine
  • tantivy-jieba = "0.17" - Chinese tokenizer
  • notify = "6.1.1" - File watcher
  • walkdir = "2.5.0" - Directory traversal
  • tempfile = "3.17" (dev) - Test fixtures

Key Files

  • src/search.rs - Search index implementation (299 lines)
  • src/lib.rs - Module exports for testing
  • assets/js/managers/search-manager.js - Frontend search UI
  • assets/js/managers/highlight-manager.js - Text highlighting
  • tests/search_integration_test.rs - Integration tests

Architecture

  • Relative path storage for portable URLs
  • Separate index for search, SQLite retained for annotations
  • ServerConfig struct for cleaner parameter passing
  • HighlightManager works independently of search feature

Usage

Enable search functionality:

cargo run -- --enable-search

Or for specific file:

cargo run -- path/to/file.md --enable-search

Keyboard Shortcuts

  • / - Open search
  • ↑/↓ - Navigate results
  • Enter - Select result
  • ESC - Close search
  • ? - View all shortcuts

Breaking Changes

None. Search is opt-in via --enable-search flag.

Recent Updates

Latest Commits

  • fix: Make keyboard shortcuts link always visible
  • fix: Constrain search content to article width and disable autocomplete
  • fix: Optimize search UI spacing and z-index
  • refactor: Redesign search UI to use clean full-screen layout
  • feat: Add search result highlighting and auto-scroll to matched text
  • fix: Use relative paths for search results navigation
  • enhance: Improve search UI with keyboard navigation and modern styling
  • refactor: Move search shortcut to separate category in help panel
  • test: Add comprehensive unit and integration tests for search functionality
  • Replace SQLite FTS5 with Tantivy 0.25 search engine

This commit introduces a directory-level search functionality to Markon.

Users can enable this feature by using the `--enable-search` flag when running the application. When enabled, Markon will index all Markdown files in the current directory and its subdirectories.

The frontend has been updated with a search modal that can be triggered by pressing the `/` key or by clicking the "Search" link in the footer. The search results are displayed in real-time as the user types.

The backend has been updated with a new `/search` endpoint that queries the search index and returns the results in JSON format. The search index is created in-memory using SQLite and the FTS5 extension.
@google-labs-jules
Copy link
Contributor Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!


For security, I will only act on instructions from the user who triggered this task.

New to Jules? Learn more at jules.google/docs.

This commit enhances the directory-level search functionality by adding a file watcher that automatically updates the search index when files are created, modified, or deleted.

The search logic has been refactored into a separate `src/search.rs` module for better code organization and maintainability.

A new `watch_files_for_changes` function has been implemented using the `notify` crate to monitor file system events. This function runs in a background task and updates the search index in real-time.

A debounce mechanism has been added to prevent excessive updates when multiple file events are triggered in a short period.
@kookyleo kookyleo marked this pull request as ready for review November 14, 2025 05:51
… suggestions

- Introduce ServerConfig struct to reduce start() function arguments from 8 to 1
- Replace map_or with is_some_and for cleaner extension checks
- Remove unnecessary borrows in rusqlite execute calls
- Run cargo fmt to fix formatting issues
@kookyleo kookyleo force-pushed the feature/directory-search branch from 5bc5808 to 685297c Compare November 15, 2025 14:36
- Upgrade to tantivy 0.25 and tantivy-jieba 0.17
- Implement full-text search with Chinese word segmentation (jieba)
- Create in-memory search index for markdown files
- Add file watcher for automatic index updates
- Support multi-field search (filename, title, content)
- Generate highlighted snippets in search results
- Keep rusqlite only for shared annotations feature
…nality

- Add 11 unit tests in src/search.rs covering:
  * Index creation and basic search
  * Chinese word segmentation with jieba
  * Multi-field search (file_name, title, content)
  * File update and deletion
  * Snippet generation
  * Title extraction
  * Search limit functionality
  * Empty queries and non-markdown files

- Add 13 integration tests in tests/search_integration_test.rs:
  * Directory structure traversal
  * Chinese content search
  * Mixed language search
  * File update/deletion workflows
  * Concurrent searches
  * Large file indexing
  * Special characters handling
  * Empty directory handling

- Fix critical bugs:
  * Change path field from STORED to STRING | STORED for deletions
  * Add reader.reload() after commits for visibility
  * Fix update_file to delete and add in same transaction
  * Make SearchResult fields public for testing

- Add tempfile dev dependency for test fixtures
- Create src/lib.rs to expose modules for integration tests
- Create dedicated 'Search (when enabled)' category
- Add visibility check for search shortcuts similar to Viewed
- Remove search shortcut from Core category for better organization
UI Improvements:
- Modern modal design with backdrop blur and rounded corners
- Better spacing and typography for search results
- Display result title, file path, and snippet separately
- Monospace font for file paths
- Smooth transitions and animations
- Theme-aware styling (light/dark/auto)

Keyboard Navigation:
- Up/Down arrow keys to navigate results
- Enter key to select current result
- Mouse hover updates selection
- Auto-scroll selected item into view
- Click overlay to close modal

Visual Enhancements:
- Selected item has left border accent and subtle transform
- Highlighted search terms in snippets
- Improved contrast and readability
- Max height for results with scroll
- Better empty state message
Problem:
- Search results used absolute file paths (e.g., /tmp/xxx/file.md)
- Clicking search results navigated to incorrect URLs

Solution:
- Store start_dir in SearchIndex struct
- Calculate relative paths using strip_prefix() when indexing
- Apply same logic in index_file(), update_file(), and delete_file()
- Search results now use paths relative to start_dir

Testing:
- All 11 unit tests pass
- Paths are now relative (e.g., docs/guide.md instead of /full/path/docs/guide.md)
Features:
- Click search result navigates to exact match location
- Matched keywords are highlighted in the document
- Auto-scroll to first match with smooth animation
- Temporary pulse animation on highlighted text (3 seconds)

Implementation:
- Add 'highlight' query parameter to search result URLs
- New HighlightManager to find and highlight text matches
- Smart text node traversal using TreeWalker
- Multi-word query support with individual highlighting
- Theme-aware highlighting colors (yellow/amber)

UI/UX:
- Smooth scroll to first match (center alignment)
- Pulse animation (3 iterations, 0.6s each)
- Yellow background for matches, amber for active match
- Fade out after 3 seconds
- Print-friendly (no highlights in print mode)

Technical:
- Split query into words for better matching
- Case-insensitive search
- Skip script/style tags and existing highlights
- Safe DOM manipulation with fragment replacement
- Works independently of search feature (can use URL directly)
Design Changes:
- Full-screen modal (100% width/height) with solid background
- Remove semi-transparent blur backdrop
- Remove rounded corners and centered card layout
- Use entire viewport space without scrollbars on container

Layout:
- Flexbox column layout (input at top, results fill remaining)
- Search input: larger padding (32px 48px), bigger font (1.4em)
- Results list: flex-grow to fill space, scrollable when needed
- Result items: increased padding (24px 48px) for better readability

Visual Improvements:
- Input has subtle background color different from results area
- Thicker bottom border (2px) on search input
- Cleaner separation between items with minimal borders
- Selected item uses left border accent (3px solid)
- Larger text sizes throughout (title 1.1em, snippet 0.95em)

Interaction:
- Remove click-overlay-to-close (ESC only)
- Full-screen immersive search experience
- Better focus on search results

Theme Support:
- Light: white background (#ffffff) with gray input (#f6f8fa)
- Dark: dark background (#0d1117) with darker input (#161b22)
- Auto: responds to system preference
Fixes:
- Increase z-index from 1000 to 10000 to overlay all elements
- Reduce excessive spacing for better content density

Spacing adjustments:
- Search input: 16px 24px (was 32px 48px)
- Search input font: 1.1em (was 1.4em)
- Result item padding: 12px 24px (was 24px 48px)
- Title font: 0.95em (was 1.1em)
- Path font: 0.8em (was 0.9em)
- Snippet font: 0.85em (was 0.95em)
- No results padding: 40px 24px (was 80px 48px)

Benefits:
- More search results visible without scrolling
- Better space utilization
- Maintains readability with appropriate font sizes
- Modal now properly overlays TOC and other UI elements
Layout improvements:
- Constrain search input and results to 980px max-width (same as article)
- Keep border and background full-width for visual consistency
- Center content using flexbox containers
- Match article padding (45px on desktop, 20px on mobile)

HTML structure changes:
- Add search-input-container wrapper for border management
- Add search-results-container for centered results
- Separate styling for container (full-width) vs content (constrained)

Autocomplete disabled:
- Add autocomplete="off" to prevent browser suggestions
- Add autocorrect="off" to disable auto-correction
- Add autocapitalize="off" to prevent auto-capitalization
- Add spellcheck="false" to disable spell checking

Visual result:
- Search UI now respects article content width
- Full-width separator line under search input
- Clean, uncluttered search experience
- No browser interference with search suggestions
Issue:
- 'Keyboard Shortcuts (?)' link was only shown when search is enabled
- This prevented users from accessing shortcuts help without --enable-search

Fix:
- Move keyboard shortcuts link outside of enable_search condition
- Keep search link inside the condition (only show when enabled)
- Apply same fix to both layout.html and directory.html

Result:
- Users can always access keyboard shortcuts help via footer link
- Equivalent to pressing '?' key
- Independent of search feature availability
- Replace len() >= 1 with !is_empty() for clarity
- Apply cargo fmt formatting to all test code
- Fix line length and formatting issues
@kookyleo kookyleo merged commit d0878df into main Nov 16, 2025
4 checks passed
@kookyleo kookyleo deleted the feature/directory-search branch November 16, 2025 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Add content search functionality at directory level

1 participant