- Build Go backend with Cobra CLI and REST API - CRUD operations for markdown files (GET, POST, PUT, DELETE) - File storage with flat .md file structure - Comprehensive logrus logging with JSON format - Static asset serving for frontend - Build React/TypeScript frontend with Tailwind CSS - Markdown editor with live GFM preview - File management UI (list, create, open, delete) - Theme system (Dark/Light/System) with persistence - Responsive design (320px mobile, 1920px desktop) - Add comprehensive test coverage - Backend: API, storage, and logger tests (13 tests passing) - Frontend: Editor and App component tests - Setup Nix development environment with Go, Node.js, and TypeScript
75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
package storage
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/markdown-editor/pkg/logger"
|
|
)
|
|
|
|
type Storage struct {
|
|
dataDir string
|
|
}
|
|
|
|
func NewStorage(dataDir string) *Storage {
|
|
// Ensure data directory exists
|
|
if err := os.MkdirAll(dataDir, 0755); err != nil {
|
|
logger.Fatalf("Failed to create data directory: %v", err)
|
|
}
|
|
return &Storage{dataDir: dataDir}
|
|
}
|
|
|
|
func (s *Storage) ListFiles() ([]string, error) {
|
|
files, err := os.ReadDir(s.dataDir)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read directory: %w", err)
|
|
}
|
|
|
|
var mdFiles []string
|
|
for _, file := range files {
|
|
if !file.IsDir() && strings.HasSuffix(file.Name(), ".md") {
|
|
mdFiles = append(mdFiles, file.Name())
|
|
}
|
|
}
|
|
return mdFiles, nil
|
|
}
|
|
|
|
func (s *Storage) GetFile(filename string) (string, error) {
|
|
path := filepath.Join(s.dataDir, filename)
|
|
content, err := os.ReadFile(path)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return "", fmt.Errorf("file not found: %s", filename)
|
|
}
|
|
return "", fmt.Errorf("failed to read file: %w", err)
|
|
}
|
|
return string(content), nil
|
|
}
|
|
|
|
func (s *Storage) SaveFile(filename, content string) error {
|
|
path := filepath.Join(s.dataDir, filename)
|
|
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
|
return fmt.Errorf("failed to write file: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Storage) DeleteFile(filename string) error {
|
|
path := filepath.Join(s.dataDir, filename)
|
|
if err := os.Remove(path); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return fmt.Errorf("file not found: %s", filename)
|
|
}
|
|
return fmt.Errorf("failed to delete file: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Storage) Exists(filename string) bool {
|
|
path := filepath.Join(s.dataDir, filename)
|
|
_, err := os.Stat(path)
|
|
return err == nil
|
|
}
|