drawio-export/pkg/drawio/options.go
Алексей Бадяев b32f3ab88a
Some checks failed
golangci-lint / lint (stable, ubuntu-latest) (push) Failing after 4s
golangci-lint / lint (stable, windows-latest) (push) Failing after 12s
build / build (push) Failing after 27s
build / build_windows (push) Successful in 52s
Добавлен линтер golangci-lint
2024-10-17 23:29:54 +07:00

468 lines
13 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package drawio
import (
"flag"
"fmt"
"io"
"os"
"strconv"
)
// Интерфейс параметра экспортёра диаграмм
type Option interface {
apply(opts *Options) // Применить параметр к хранилищу параметров
}
// Ошибка "неподдерживаемый формат"
type UnsupportedFormatError struct {
Format string
}
// Описание ошибки
func (e UnsupportedFormatError) Error() string {
return fmt.Sprintf("unsupported format: '%s'", e.Format)
}
// Проверка эквивалентности ошибок
func (e UnsupportedFormatError) Is(target error) bool {
if t, ok := target.(UnsupportedFormatError); ok {
return t.Format == e.Format
}
return false
}
var _ error = (*UnsupportedFormatError)(nil) // Проверка реализации интерфейса
type Format string // Формат экспортированного файла
const (
PDF Format = "pdf"
PNG Format = "png"
JPG Format = "jpg"
SVG Format = "svg"
VSDX Format = "vsdx"
XML Format = "xml"
)
// Строковое представление формата
func (f Format) String() string {
return string(f)
}
// Загрузка формата из строки
func (f *Format) Set(str string) error {
for _, fmt := range SupportedFormats() {
if str == string(fmt) {
*f = Format(str)
return nil
}
}
return &UnsupportedFormatError{str}
}
// Список всех поддерживаемых форматов экспорта
func SupportedFormats() []Format {
return []Format{"pdf", "png", "jpg", "svg", "vsdx", "xml"}
}
var _ flag.Value = (*Format)(nil) // Поверка реализации интерфейса
// Расширение файла заданного формата
func (f Format) ext() string {
return "." + string(f)
}
// Параметры экспортёра диаграмм
type Options struct {
Application string // Путь к приложению drawio
EnableXvfb bool // Запускать drawio внутри xvfb-run
Output string // Путь к папке с экспортированными файлами
Format Format // Формат экспортированных файлов
Recursive bool // Рекурсивно сканировать вложенные папки с файлами
RemovePageSuffix bool // Удалять суффикс страницы, если это возможно
Quality uint // Качество экспортированного изображения (только для JPEG)
Transparent bool // Прозрачный фона для PNG
// Включать копию диаграммы в экспортированный файл для PDF, PNG и SVG
EmbedDiagram bool
EmbedSvgImages bool // Встраивать изображения в файл формата SVG
Border uint // Ширина рамки вокруг диаграмм
Scale uint // Масштаб в процентах размера экспортированных диаграмм
Width uint // Ширина экспортированной диаграммы с сохранением масштаба
Height uint // Высота экспортированной диаграммы с сохранением масштаба
Crop bool // Обрезать результирующий PDF до размера диаграммы
Uncompressed bool // Выводить несжатый XML
EnablePlugins bool // Включить подключаемые модули
openFile OpenFileFunc // Открыть файл
readDir ReadDirFunc // Прочитать папку на диске
}
// Функция открытия файла
type OpenFileFunc func(string) (io.ReadCloser, error)
// Функция чтения папки на диске
type ReadDirFunc func(string) ([]os.DirEntry, error)
// Путь к приложению drawio
func (opts Options) App() string {
if opts.EnableXvfb {
return "xvfb-run"
}
if len(opts.Application) == 0 {
return "drawio"
}
return opts.Application
}
// Путь к папке с экспортированными файлами
func (opts Options) OutDir() string {
out := opts.Output
if len(out) == 0 {
out = "export"
}
return out
}
// Расширение экспортированных файлов
func (opts Options) OutExt() string {
fmt := opts.Format
if len(fmt) == 0 {
fmt = Format("pdf")
}
return fmt.ext()
}
// Аргументы командной строки drawio
func (opts Options) Args() []string {
args := []string{}
if opts.EnableXvfb {
var app string
if len(opts.Application) == 0 {
app = "drawio"
} else {
app = opts.Application
}
args = append(args, "-a", "-l", app)
}
if len(opts.Format) > 0 {
args = append(args, "--format", string(opts.Format))
}
if opts.Quality != 0 {
args = append(args, "--quality", strconv.Itoa(int(opts.Quality)))
}
if opts.Transparent {
args = append(args, "--transparent")
}
if opts.EmbedDiagram {
args = append(args, "--embed-diagram")
}
if opts.EmbedSvgImages {
args = append(args, "--embed-svg-images")
}
if opts.Border != 0 {
args = append(args, "--border", strconv.Itoa(int(opts.Border)))
}
if opts.Scale != 0 {
args = append(args, "--scale", strconv.Itoa(int(opts.Scale)))
}
if opts.Width != 0 {
args = append(args, "--width", strconv.Itoa(int(opts.Width)))
}
if opts.Height != 0 {
args = append(args, "--height", strconv.Itoa(int(opts.Height)))
}
if opts.Crop {
args = append(args, "--crop")
}
if opts.Uncompressed {
args = append(args, "--uncompressed")
}
if opts.EnablePlugins {
args = append(args, "--enable-plugins")
}
return args
}
// Путь к приложению drawio
func WithAppPath(path string) optionApplication {
return optionApplication(path)
}
type optionApplication string
var _ Option = (*optionApplication)(nil) // Проверка реализации интерфейса
func (opt optionApplication) apply(opts *Options) {
opts.Application = string(opt)
}
// Запускать drawio внутри xvfb-run
func WithXvfb() optionXvfb {
return optionXvfb{}
}
type optionXvfb struct{}
var _ Option = optionXvfb{}
func (opt optionXvfb) apply(opts *Options) {
opts.EnableXvfb = true
}
// Путь к папке с экспортированными файлами
func WithOutput(path string) optionOutput {
return optionOutput(path)
}
type optionOutput string
var _ Option = (*optionOutput)(nil) // Проверка реализации интерфейса
func (opt optionOutput) apply(opts *Options) {
opts.Output = string(opt)
}
// Формат экспортированных файлов
func WithFormat(format Format) Format {
return format
}
var _ Option = (*Format)(nil) // Проверка реализации интерфейса
func (f Format) apply(opts *Options) {
opts.Format = f
}
// Рекурсивно сканировать вложенные папки с файлами
func WithRecursive() optionRecursive {
return optionRecursive{}
}
type optionRecursive struct{}
var _ Option = optionRecursive{} // Проверка реализации интерфейса
func (opt optionRecursive) apply(opts *Options) {
opts.Recursive = true
}
// Удалять суффикс страницы, если это возможно
func WithRemovePageSuffix() optionRemovePageSuffix {
return optionRemovePageSuffix{}
}
type optionRemovePageSuffix struct{}
var _ Option = optionRemovePageSuffix{} // Проверка реализации интерфейса
func (opt optionRemovePageSuffix) apply(opts *Options) {
opts.RemovePageSuffix = true
}
// Качество экспортированного изображения (только для JPEG)
func WithQuality(q uint) optionQuality {
return optionQuality(q)
}
type optionQuality uint
var _ Option = (*optionQuality)(nil) // Проверка реализации интерфейса
func (opt optionQuality) apply(opts *Options) {
opts.Quality = uint(opt)
}
// Прозрачный фона для PNG
func WithTransparent() optionTransparent {
return optionTransparent{}
}
type optionTransparent struct{}
var _ Option = optionTransparent{} // Проверка реализации интерфейса
func (opt optionTransparent) apply(opts *Options) {
opts.Transparent = true
}
// Включать копию диаграммы в экспортированный файл для PDF, PNG и SVG
func WithEmbedDiagram() optionEmbedDiagram {
return optionEmbedDiagram{}
}
type optionEmbedDiagram struct{}
var _ Option = optionEmbedDiagram{} // Проверка реализации интерфейса
func (opt optionEmbedDiagram) apply(opts *Options) {
opts.EmbedDiagram = true
}
// Встраивать изображения в файл формата SVG
func WithEmbedSvgImages() optionEmbedSvgImages {
return optionEmbedSvgImages{}
}
type optionEmbedSvgImages struct{}
var _ Option = optionEmbedSvgImages{} // Проверка реализации интерфейса
func (opt optionEmbedSvgImages) apply(opts *Options) {
opts.EmbedSvgImages = true
}
// Ширина рамки вокруг диаграмм
func WithBorder(border uint) optionBorder {
return optionBorder(border)
}
type optionBorder uint
var _ Option = (*optionBorder)(nil) // Проверка реализации интерфейса
func (opt optionBorder) apply(opts *Options) {
opts.Border = uint(opt)
}
// Масштаб в процентах размера экспортированных диаграмм
func WithScale(scale uint) optionScale {
return optionScale(scale)
}
type optionScale uint
var _ Option = (*optionScale)(nil) // Проверка реализации интерфейса
func (opt optionScale) apply(opts *Options) {
opts.Scale = uint(opt)
}
// Ширина экспортированной диаграммы с сохранением масштаба
func WithWidth(width uint) optionWidth {
return optionWidth(width)
}
type optionWidth uint
var _ Option = (*optionWidth)(nil) // Проверка реализации интерфейса
func (opt optionWidth) apply(opts *Options) {
opts.Width = uint(opt)
}
// Высота экспортированной диаграммы с сохранением масштаба
func WithHeight(height uint) optionHeight {
return optionHeight(height)
}
type optionHeight uint
var _ Option = (*optionHeight)(nil) // Проверка реализации интерфейса
func (opt optionHeight) apply(opts *Options) {
opts.Height = uint(opt)
}
// Обрезать результирующий PDF до размера диаграммы
func WithCrop() optionCrop {
return optionCrop{}
}
type optionCrop struct{}
var _ Option = optionCrop{} // Проверка реализации интерфейса
func (opt optionCrop) apply(opts *Options) {
opts.Crop = true
}
// Выводить несжатый XML
func WithUncompressed() optionUncompressed {
return optionUncompressed{}
}
type optionUncompressed struct{}
var _ Option = optionUncompressed{} // Проверка реализации интерфейса
func (opt optionUncompressed) apply(opts *Options) {
opts.Uncompressed = true
}
// Включить подключаемые модули
func WithEnablePlugins() optionEnablePlugins {
return optionEnablePlugins{}
}
type optionEnablePlugins struct{}
var _ Option = optionEnablePlugins{} // Проверка реализации интерфейса
func (opt optionEnablePlugins) apply(opts *Options) {
opts.EnablePlugins = true
}
// Открыть файл
func WithOpenFile(openFile OpenFileFunc) optionOpenFile {
return optionOpenFile{openFile}
}
type optionOpenFile struct {
openFile OpenFileFunc
}
var _ Option = optionOpenFile{} // Проверка реализации интерфейса
func (opt optionOpenFile) apply(opts *Options) {
opts.openFile = opt.openFile
}
// Прочитать папку на диске
func WithReadDir(readDir ReadDirFunc) optionReadDir {
return optionReadDir{readDir}
}
type optionReadDir struct {
readDir ReadDirFunc
}
var _ Option = optionReadDir{} // Проверка реализации интерфейса
func (opt optionReadDir) apply(opts *Options) {
opts.readDir = opt.readDir
}
// Пустой параметр
func WithNop() optionNop {
return optionNop{}
}
type optionNop struct{}
var _ Option = optionNop{}
func (opt optionNop) apply(_ *Options) {
// Не требуется действий, так как это пустой параметр
}