package main import ( "encoding/json" "flag" "fmt" "os" "strings" ) func main() { field := flag.String("field", "", "имя поля для JSON, например body или biography (необязательно)") flag.Parse() args := flag.Args() if len(args) == 0 { fmt.Println("Использование:") fmt.Println(" txt2json файл.txt") fmt.Println(" txt2json -field=biography файл.txt") fmt.Println() fmt.Println("Разложи текст в обычном .txt файле по абзацам (пустая строка") fmt.Println("между абзацами), и утилита сама превратит его в готовую строку") fmt.Println("для JSON, сохранив разбивку на абзацы.") os.Exit(1) } hadErrors := false for _, path := range args { if err := convert(path, *field); err != nil { fmt.Fprintf(os.Stderr, "Ошибка с файлом %q: %v\n", path, err) hadErrors = true } } if hadErrors { os.Exit(1) } } func convert(path, field string) error { data, err := os.ReadFile(path) if err != nil { return err } text := strings.ReplaceAll(string(data), "\r\n", "\n") // Абзацы разделены пустой строкой. Внутри абзаца одиночные переносы // (например, из-за переноса по ширине окна в текстовом редакторе) // склеиваются в один текст без разрывов. rawParagraphs := strings.Split(text, "\n\n") var paragraphs []string for _, p := range rawParagraphs { collapsed := strings.Join(strings.Fields(p), " ") collapsed = strings.TrimSpace(collapsed) if collapsed != "" { paragraphs = append(paragraphs, collapsed) } } joined := strings.Join(paragraphs, "\n\n") jsonValue, err := json.Marshal(joined) if err != nil { return err } var output string if field != "" { output = fmt.Sprintf("\"%s\": %s", field, string(jsonValue)) } else { output = string(jsonValue) } outPath := path + ".snippet.json" if err := os.WriteFile(outPath, []byte(output+"\n"), 0o644); err != nil { return err } fmt.Printf("Готово: %s → %s\n\n%s\n\n", path, outPath, output) return nil }