Initial commit: Phase 1+2 prototype
- Go backend with SQLite, JWT auth, file CRUD - Vue 3 frontend with split/raw/WYSIWYG editor modes - Markdown preview (marked, GFM) - Formatting toolbar + keyboard shortcuts - File tree with search, create, delete - Light/dark theme toggle - Admin panel (user management) - Preferences (timezone, theme, default mode) - Shared documents section (placeholder) - Export: PDF, HTML, MD - Build daemon (Python, stdlib only) - Build job queue API - Docker deployment
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package files
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SearchResult struct {
|
||||
Path string `json:"path"`
|
||||
Snippet string `json:"snippet"`
|
||||
}
|
||||
|
||||
// Search finds files containing the query string (case-insensitive).
|
||||
func Search(dataDir, userID, query string) ([]SearchResult, error) {
|
||||
root := UserDir(dataDir, userID)
|
||||
query = strings.ToLower(query)
|
||||
var results []SearchResult
|
||||
|
||||
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil || info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
rel, _ := filepath.Rel(root, path)
|
||||
|
||||
// Match filename
|
||||
if strings.Contains(strings.ToLower(info.Name()), query) {
|
||||
results = append(results, SearchResult{Path: rel, Snippet: "(filename match)"})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Match content (only for .md and .txt)
|
||||
ext := strings.ToLower(filepath.Ext(path))
|
||||
if ext == ".md" || ext == ".txt" {
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
lower := strings.ToLower(string(content))
|
||||
idx := strings.Index(lower, query)
|
||||
if idx >= 0 {
|
||||
// Extract snippet
|
||||
start := idx - 40
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
end := idx + len(query) + 40
|
||||
if end > len(content) {
|
||||
end = len(content)
|
||||
}
|
||||
snippet := string(content[start:end])
|
||||
results = append(results, SearchResult{Path: rel, Snippet: snippet})
|
||||
}
|
||||
}
|
||||
|
||||
if len(results) >= 50 {
|
||||
return filepath.SkipAll
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if results == nil {
|
||||
results = []SearchResult{}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
Reference in New Issue
Block a user