feat(office): add Workspace TUI with shared bootstrap and test suite

Introduce the office Bubble Tea browser (module tree, multi-select lists,
markdown preview) alongside oo, with cmd/internal/bootstrap for shared auth,
unit tests across preview/model/ui/fetch, CI build for both binaries, and
GoReleaser archives for office.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-24 16:29:04 +01:00
co-authored by Cursor
parent 4acec6bbc9
commit f8a73edef3
32 changed files with 2267 additions and 94 deletions
+65
View File
@@ -0,0 +1,65 @@
package preview
import (
"bytes"
"encoding/csv"
"encoding/json"
"fmt"
"strings"
xls "github.com/eslider/go-xls/v2"
)
// CSVToMarkdownTable parses CSV bytes into a GitHub pipe table markdown string.
func CSVToMarkdownTable(data []byte) (string, error) {
tab, err := parseCSV(data)
if err != nil {
return "", err
}
var buf bytes.Buffer
if err := xls.WriteMarkdownTable(&buf, tab); err != nil {
return "", err
}
return strings.TrimSpace(buf.String()) + "\n", nil
}
func parseCSV(data []byte) (xls.Table, error) {
r := csv.NewReader(bytes.NewReader(data))
r.TrimLeadingSpace = true
records, err := r.ReadAll()
if err != nil {
return xls.Table{}, err
}
if len(records) == 0 {
return xls.Table{}, fmt.Errorf("preview: empty csv")
}
return xls.Table{Columns: records[0], Rows: records[1:]}, nil
}
// JSONToMarkdown wraps JSON in a fenced code block for preview.
func JSONToMarkdown(data []byte) (string, error) {
var v any
if err := json.Unmarshal(data, &v); err != nil {
return "", err
}
pretty, err := json.MarshalIndent(v, "", " ")
if err != nil {
return "", err
}
return fmt.Sprintf("```json\n%s\n```\n", string(pretty)), nil
}
// FileBytesToMarkdown picks a preview format based on file extension.
func FileBytesToMarkdown(name string, data []byte) (string, error) {
ext := strings.ToLower(name)
switch {
case strings.HasSuffix(ext, ".csv"):
return CSVToMarkdownTable(data)
case strings.HasSuffix(ext, ".json"):
return JSONToMarkdown(data)
case strings.HasSuffix(ext, ".md"), strings.HasSuffix(ext, ".txt"):
return string(data), nil
default:
return fmt.Sprintf("```\n(binary or unsupported preview for %s, %d bytes)\n```\n", name, len(data)), nil
}
}