package services import ( "archive/zip" "fmt" "html/template" "os" "path/filepath" "strings" "time" "github.com/yuin/goldmark" ) type ExportService struct{} func NewExportService() *ExportService { return &ExportService{} } func (es *ExportService) ExportHTML(title, content, outputPath string) error { var htmlContent strings.Builder if err := goldmark.Convert([]byte(content), &htmlContent); err != nil { return err } htmlTemplate := ` {{.Title}}

{{.Title}}

{{.Content}}

导出于 {{.ExportTime}} | Kenaito Notebook

` tmpl, err := template.New("html").Parse(htmlTemplate) if err != nil { return err } file, err := os.Create(outputPath) if err != nil { return err } defer file.Close() return tmpl.Execute(file, map[string]string{ "Title": title, "Content": htmlContent.String(), "ExportTime": fmt.Sprintf("%s", time.Now().Format("2006-01-02 15:04:05")), }) } func (es *ExportService) ExportMarkdown(title, content, outputPath string) error { fullContent := fmt.Sprintf("# %s\n\n%s", title, content) return os.WriteFile(outputPath, []byte(fullContent), 0644) } func (es *ExportService) ExportFolderMarkdown(folderTitle string, notes []NoteInfo, outputPath string) error { var content strings.Builder content.WriteString(fmt.Sprintf("# %s\n\n", folderTitle)) for _, note := range notes { content.WriteString(fmt.Sprintf("## %s\n\n", note.Title)) content.WriteString(note.Content) content.WriteString("\n\n---\n\n") } return os.WriteFile(outputPath, []byte(content.String()), 0644) } func (es *ExportService) ExportAllMarkdown(notes []NoteInfo, outputPath string) error { var content strings.Builder content.WriteString("# 所有笔记\n\n") for _, note := range notes { content.WriteString(fmt.Sprintf("## %s\n\n", note.Title)) content.WriteString(note.Content) content.WriteString("\n\n---\n\n") } return os.WriteFile(outputPath, []byte(content.String()), 0644) } func (es *ExportService) ExportFolderZip(folderTitle string, notes []*NoteInfo, outputPath string) error { file, err := os.Create(outputPath) if err != nil { return err } defer file.Close() w := zip.NewWriter(file) defer w.Close() rootFolder := es.GetSafeFilename(folderTitle) + "/" _, err = w.Create(rootFolder) if err != nil { return err } es.addNotesToZip(w, notes, rootFolder) return nil } func (es *ExportService) ExportAllZip(notes []*NoteInfo, outputPath string) error { file, err := os.Create(outputPath) if err != nil { return err } defer file.Close() w := zip.NewWriter(file) defer w.Close() rootFolder := "所有笔记/" _, err = w.Create(rootFolder) if err != nil { return err } es.addNotesToZip(w, notes, rootFolder) return nil } func (es *ExportService) addNotesToZip(w *zip.Writer, notes []*NoteInfo, parentPath string) { for _, note := range notes { safeName := es.GetSafeFilename(note.Title) if note.IsFolder { folderPath := parentPath + safeName + "/" _, _ = w.Create(folderPath) if note.Children != nil { es.addNotesToZip(w, note.Children, folderPath) } } else { filePath := parentPath + safeName + ".md" fullContent := fmt.Sprintf("# %s\n\n%s", note.Title, note.Content) f, err := w.Create(filePath) if err != nil { continue } _, _ = f.Write([]byte(fullContent)) } } } type NoteInfo struct { Title string Content string IsFolder bool Children []*NoteInfo } func (es *ExportService) GetDefaultExportPath(title, ext string) string { homeDir, _ := os.UserHomeDir() exportDir := filepath.Join(homeDir, "Desktop") safeName := es.GetSafeFilename(title) return filepath.Join(exportDir, fmt.Sprintf("%s%s", safeName, ext)) } func (es *ExportService) GetSafeFilename(title string) string { safeName := strings.ReplaceAll(title, "/", "-") safeName = strings.ReplaceAll(safeName, "\\", "-") safeName = strings.ReplaceAll(safeName, ":", "-") safeName = strings.ReplaceAll(safeName, "*", "") safeName = strings.ReplaceAll(safeName, "?", "") safeName = strings.ReplaceAll(safeName, "\"", "") safeName = strings.ReplaceAll(safeName, "<", "") safeName = strings.ReplaceAll(safeName, ">", "") safeName = strings.ReplaceAll(safeName, "|", "") if strings.TrimSpace(safeName) == "" { safeName = "未命名笔记" } return safeName }