- Исправлена двойная обработка ITableRow через reflection - Исправлен выход за границы изображения при отрисовке последнего разделителя - Добавлена защита от пустых данных (header, blocks) - Добавлена compile-time проверка интерфейса ITableRow - Переименован tablle_block_style.go → table_block_style.go - Добавлены комментарии на русском ко всем функциям и типам - Написана документация README.md с примерами использования - Добавлен CLAUDE.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
175 lines
5.0 KiB
Markdown
175 lines
5.0 KiB
Markdown
# image_table
|
||
|
||
Go-библиотека для рендеринга таблиц данных в PNG-изображения. Подходит для генерации отчётов, уведомлений в мессенджерах и визуализации табличных данных.
|
||
|
||
## Установка
|
||
|
||
```bash
|
||
go get git.gm6.ru/icewind/image_table
|
||
```
|
||
|
||
## Возможности
|
||
|
||
- Рендеринг одиночной таблицы с автоподбором ширины столбцов
|
||
- Рендеринг документа из нескольких именованных таблиц
|
||
- Поддержка различных типов данных в строках: срезы, структуры, интерфейс `ITableRow`
|
||
- Настройка цвета фона для отдельных строк через `TableBlockStyle`
|
||
- Встроенный шрифт JetBrains Mono — не требует внешних зависимостей для шрифтов
|
||
|
||
## Примеры
|
||
|
||
### Простая таблица
|
||
|
||
```go
|
||
package main
|
||
|
||
import (
|
||
"image/png"
|
||
"os"
|
||
|
||
"git.gm6.ru/icewind/image_table"
|
||
)
|
||
|
||
func main() {
|
||
header := []string{"Имя", "Возраст", "Город"}
|
||
|
||
rows := []any{
|
||
[]string{"Алиса", "23", "Москва"},
|
||
[]string{"Боб", "31", "Казань"},
|
||
[]string{"Олег", "44", "Сочи"},
|
||
}
|
||
|
||
img := image_table.DrawTableWarm(header, rows)
|
||
|
||
file, _ := os.Create("table.png")
|
||
defer file.Close()
|
||
png.Encode(file, img)
|
||
}
|
||
```
|
||
|
||
### Строки из структур
|
||
|
||
Поля структуры автоматически преобразуются в ячейки таблицы:
|
||
|
||
```go
|
||
type User struct {
|
||
Name string
|
||
Age int
|
||
City string
|
||
}
|
||
|
||
rows := []any{
|
||
User{"Елена", 27, "Минск"},
|
||
User{"Иван", 35, "Киев"},
|
||
}
|
||
|
||
img := image_table.DrawTableWarm(
|
||
[]string{"Имя", "Возраст", "Город"},
|
||
rows,
|
||
)
|
||
```
|
||
|
||
### Строки с пользовательским фоном
|
||
|
||
Используйте `TableBlockStyle` для задания цвета фона строки:
|
||
|
||
```go
|
||
rows := []any{
|
||
[]any{1, "Запрос обработан", "OK"},
|
||
&image_table.TableBlockStyle{
|
||
Cells: []any{2, "Ошибка соединения", "FAIL"},
|
||
BackgroundColor: color.RGBA{R: 255, G: 225, B: 225, A: 255}, // красный фон
|
||
},
|
||
}
|
||
|
||
img := image_table.DrawTableWarm(
|
||
[]string{"ID", "Описание", "Статус"},
|
||
rows,
|
||
)
|
||
```
|
||
|
||
> **Важно:** `TableBlockStyle` нужно передавать как указатель (`&TableBlockStyle{...}`), иначе интерфейс `ITableRow` не будет распознан.
|
||
|
||
### Документ из нескольких таблиц
|
||
|
||
`Document` позволяет объединить несколько таблиц с заголовками в одно изображение:
|
||
|
||
```go
|
||
doc := image_table.Document{
|
||
Blocks: []image_table.TableBlock{
|
||
{
|
||
Title: "Пользователи",
|
||
Header: []string{"ID", "Имя", "Возраст"},
|
||
Rows: []any{
|
||
[]any{1, "Иван", 30},
|
||
[]any{2, "Мария", 25},
|
||
},
|
||
},
|
||
{
|
||
Title: "Статистика",
|
||
Header: []string{"Метрика", "Значение"},
|
||
Rows: []any{
|
||
[]any{"Запросы", 12000},
|
||
&image_table.TableBlockStyle{
|
||
Cells: []any{"Ошибки", 37},
|
||
BackgroundColor: color.RGBA{R: 255, G: 225, B: 225, A: 255},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|
||
|
||
img := image_table.RenderDocument(doc)
|
||
|
||
file, _ := os.Create("document.png")
|
||
defer file.Close()
|
||
png.Encode(file, img)
|
||
```
|
||
|
||
### Собственная реализация ITableRow
|
||
|
||
Для полного контроля над строкой реализуйте интерфейс `ITableRow`:
|
||
|
||
```go
|
||
type AlertRow struct {
|
||
Level string
|
||
Message string
|
||
}
|
||
|
||
func (r *AlertRow) GetCells() []any {
|
||
return []any{r.Level, r.Message}
|
||
}
|
||
|
||
func (r *AlertRow) GetBackgroundColor() color.RGBA {
|
||
if r.Level == "CRITICAL" {
|
||
return color.RGBA{R: 255, G: 200, B: 200, A: 255}
|
||
}
|
||
return color.RGBA{R: 255, G: 255, B: 255, A: 255}
|
||
}
|
||
```
|
||
|
||
## API
|
||
|
||
### `DrawTableWarm(header []string, rows []any) image.Image`
|
||
|
||
Рендерит одну таблицу. Строки могут быть `[]string`, `[]any`, структурой или реализацией `ITableRow`.
|
||
|
||
### `RenderDocument(doc Document) image.Image`
|
||
|
||
Рендерит документ из нескольких таблиц (`Document.Blocks`), каждая с заголовком.
|
||
|
||
### `ITableRow`
|
||
|
||
```go
|
||
type ITableRow interface {
|
||
GetCells() []any
|
||
GetBackgroundColor() color.RGBA
|
||
}
|
||
```
|
||
|
||
Интерфейс для строк с пользовательским стилем. Готовая реализация — `TableBlockStyle`.
|
||
|
||
## Лицензия
|
||
|
||
MIT
|