Все требования реализованы без полного покрытия модульными тестами. (#3)
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				drawio-export/pipeline/head This commit looks good
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	drawio-export/pipeline/head This commit looks good
				
			PR closes #1 Reviewed-on: #3
This commit is contained in:
		
							parent
							
								
									0d6f42f425
								
							
						
					
					
						commit
						78624641e4
					
				| @ -1,7 +1,31 @@ | |||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import "fmt" | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 
 | ||||||
|  | 	"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var version string // Версия приложения | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 	fmt.Println("Draw.io Exporter") | 	flag.Parse() | ||||||
|  | 	if flagHelp { | ||||||
|  | 		flag.Usage() | ||||||
|  | 		os.Exit(0) | ||||||
|  | 	} | ||||||
|  | 	if flagVersion { | ||||||
|  | 		fmt.Println("Draw.io Export cli util", version) | ||||||
|  | 		os.Exit(0) | ||||||
|  | 	} | ||||||
|  | 	if flag.NArg() < 1 { | ||||||
|  | 		flag.Usage() | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 	exporter := drawio.NewWithOptions(&opts) | ||||||
|  | 	if err := exporter.Export(flag.Args()...); err != nil { | ||||||
|  | 		fmt.Fprintln(os.Stderr, "Error:", err) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										75
									
								
								cmd/drawio-export/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								cmd/drawio-export/options.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 
 | ||||||
|  | 	"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	flagHelp    bool               // Вывести справку о приложении и выйти | ||||||
|  | 	flagVersion bool               // Вывести информацию о версии приложения и выйти | ||||||
|  | 	opts        = drawio.Options{} // Аргументы командной строки приложения | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	// version | ||||||
|  | 	flag.BoolVar(&flagVersion, "V", false, "Prints version information") | ||||||
|  | 	flag.BoolVar(&flagVersion, "version", false, "Prints version information") | ||||||
|  | 	// Application | ||||||
|  | 	flag.StringVar(&opts.Application, "A", "", "Draw.io Desktop Application") | ||||||
|  | 	flag.StringVar(&opts.Application, "application", "", "Draw.io Desktop Application") | ||||||
|  | 	// Output | ||||||
|  | 	flag.StringVar(&opts.Output, "o", "", "Exported folder name [default: export]") | ||||||
|  | 	flag.StringVar(&opts.Output, "output", "", "Exported folder name [default: export]") | ||||||
|  | 	// Format | ||||||
|  | 	flag.Var(&opts.Format, "f", | ||||||
|  | 		"Exported format [default: pdf]  [possible values: pdf, png, jpg, svg, vsdx, xml]") | ||||||
|  | 	flag.Var(&opts.Format, "format", | ||||||
|  | 		"Exported format [default: pdf]  [possible values: pdf, png, jpg, svg, vsdx, xml]") | ||||||
|  | 	// Recursive | ||||||
|  | 	flag.BoolVar(&opts.Recursive, "r", false, | ||||||
|  | 		"For a folder input, recursively convert all files in sub-folders also") | ||||||
|  | 	flag.BoolVar(&opts.Recursive, "recursive", false, | ||||||
|  | 		"For a folder input, recursively convert all files in sub-folders also") | ||||||
|  | 	// RemovePageSuffix | ||||||
|  | 	flag.BoolVar(&opts.RemovePageSuffix, "remove-page-suffix", false, | ||||||
|  | 		"Remove page suffix when possible (in case of single page file") | ||||||
|  | 	// Quality | ||||||
|  | 	flag.UintVar(&opts.Quality, "q", 0, "Output image quality for JPEG [default: 90]") | ||||||
|  | 	flag.UintVar(&opts.Quality, "quality", 0, "Output image quality for JPEG [default: 90]") | ||||||
|  | 	// Transparent | ||||||
|  | 	flag.BoolVar(&opts.Transparent, "t", false, "Set transparent background for PNG") | ||||||
|  | 	flag.BoolVar(&opts.Transparent, "transparent", false, "Set transparent background for PNG") | ||||||
|  | 	// EmbedDiagram | ||||||
|  | 	flag.BoolVar(&opts.EmbedDiagram, "e", false, | ||||||
|  | 		"Includes a copy of the diagram for PDF, PNG, or SVG") | ||||||
|  | 	flag.BoolVar(&opts.EmbedDiagram, "embed-diagram", false, | ||||||
|  | 		"Includes a copy of the diagram for PDF, PNG, or SVG") | ||||||
|  | 	// EmbedSvgImages | ||||||
|  | 	flag.BoolVar(&opts.EmbedSvgImages, "embed-svg-images", false, "Embed Images in SVG file") | ||||||
|  | 	// Border | ||||||
|  | 	flag.UintVar(&opts.Border, "b", 0, | ||||||
|  | 		"Sets the border width around the diagram [default: 0]") | ||||||
|  | 	flag.UintVar(&opts.Border, "border", 0, | ||||||
|  | 		"Sets the border width around the diagram [default: 0]") | ||||||
|  | 	// Scale | ||||||
|  | 	flag.UintVar(&opts.Scale, "s", 0, "Scales the diagram size") | ||||||
|  | 	flag.UintVar(&opts.Scale, "scale", 0, "Scales the diagram size") | ||||||
|  | 	// Width | ||||||
|  | 	flag.UintVar(&opts.Width, "width", 0, | ||||||
|  | 		"Fits the generated image/pdf into the specified width, preserves aspect ratio") | ||||||
|  | 	// Height | ||||||
|  | 	flag.UintVar(&opts.Height, "height", 0, | ||||||
|  | 		"Fits the generated image/pdf into the specified height, preserves aspect ratio") | ||||||
|  | 	// Crop | ||||||
|  | 	flag.BoolVar(&opts.Crop, "crop", false, "Crops PDF to diagram size") | ||||||
|  | 	// Uncompressed | ||||||
|  | 	flag.BoolVar(&opts.Uncompressed, "u", false, "Uncompressed XML output") | ||||||
|  | 	flag.BoolVar(&opts.Uncompressed, "uncompressed", false, "Uncompressed XML output") | ||||||
|  | 	// EnablePlugins | ||||||
|  | 	flag.BoolVar(&opts.EnablePlugins, "enable-plugins", false, "Enable Plugins") | ||||||
|  | 	// help | ||||||
|  | 	flag.BoolVar(&flagHelp, "h", false, "Prints help information") | ||||||
|  | 	flag.BoolVar(&flagHelp, "help", false, "Prints help information") | ||||||
|  | } | ||||||
| @ -2,12 +2,67 @@ package drawio | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bufio" | 	"bufio" | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"io/fs" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	xmlparser "github.com/tamerh/xml-stream-parser" | 	xmlparser "github.com/tamerh/xml-stream-parser" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // Создать нового экспортёра диаграмм | ||||||
|  | func New(opt ...Option) Exporter { | ||||||
|  | 	options := &Options{ | ||||||
|  | 		Application: "drawio", | ||||||
|  | 		Output:      "export", | ||||||
|  | 		Format:      Format("pdf"), | ||||||
|  | 	} | ||||||
|  | 	for _, opt := range opt { | ||||||
|  | 		opt.apply(options) | ||||||
|  | 	} | ||||||
|  | 	return NewWithOptions(options) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Создать нового экспортёра с параметрами | ||||||
|  | func NewWithOptions(opts *Options) Exporter { | ||||||
|  | 	return Exporter{opts: opts} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Экспортёр диаграмм | ||||||
|  | type Exporter struct { | ||||||
|  | 	opts *Options | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Экспорт диаграмм из указанный файлов или папок | ||||||
|  | func (exp Exporter) Export(fileOrDir ...string) error { | ||||||
|  | 	var ( | ||||||
|  | 		err  error | ||||||
|  | 		errs = []error{} | ||||||
|  | 		args = exp.opts.Args() | ||||||
|  | 		info fs.FileInfo | ||||||
|  | 	) | ||||||
|  | 	for _, item := range fileOrDir { | ||||||
|  | 		if info, err = os.Stat(item); err != nil { | ||||||
|  | 			errs = append(errs, err) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		if info.IsDir() { | ||||||
|  | 			err = exp.exportDir(item, args) | ||||||
|  | 		} else { | ||||||
|  | 			err = exp.exportFile(item, args) | ||||||
|  | 		} | ||||||
|  | 		if err != nil { | ||||||
|  | 			errs = append(errs, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return errors.Join(errs...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Разбирает данные и возвращает срез имён диаграмм в них | // Разбирает данные и возвращает срез имён диаграмм в них | ||||||
| func Diagrams(reader io.Reader) ([]string, error) { | func Diagrams(reader io.Reader) ([]string, error) { | ||||||
| 	var ( | 	var ( | ||||||
| @ -21,7 +76,6 @@ func Diagrams(reader io.Reader) ([]string, error) { | |||||||
| 		if xml.Err != nil { | 		if xml.Err != nil { | ||||||
| 			return result, xml.Err | 			return result, xml.Err | ||||||
| 		} | 		} | ||||||
| 		fmt.Println(xml.Name) |  | ||||||
| 		if items, ok := xml.Childs["diagram"]; ok { | 		if items, ok := xml.Childs["diagram"]; ok { | ||||||
| 			for _, item := range items { | 			for _, item := range items { | ||||||
| 				result = append(result, item.Attrs["name"]) | 				result = append(result, item.Attrs["name"]) | ||||||
| @ -30,3 +84,72 @@ func Diagrams(reader io.Reader) ([]string, error) { | |||||||
| 	} | 	} | ||||||
| 	return result, nil | 	return result, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Экспорт диаграмм из всех файлов в папке | ||||||
|  | func (exp Exporter) exportDir(dirPath string, args []string, subDir ...string) error { | ||||||
|  | 	var ( | ||||||
|  | 		entries []fs.DirEntry | ||||||
|  | 		err     error | ||||||
|  | 		errs    []error | ||||||
|  | 	) | ||||||
|  | 	if entries, err = os.ReadDir(dirPath); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	for _, entry := range entries { | ||||||
|  | 		name := entry.Name() | ||||||
|  | 		outDir := make([]string, len(subDir), len(subDir)+1) | ||||||
|  | 		outDir = append(outDir, name) | ||||||
|  | 		if entry.IsDir() && exp.opts.Recursive { | ||||||
|  | 			err = exp.exportDir(path.Join(dirPath, name), args, outDir...) | ||||||
|  | 		} else { | ||||||
|  | 			err = exp.exportFile(path.Join(dirPath, name), args, outDir...) | ||||||
|  | 		} | ||||||
|  | 		if err != nil { | ||||||
|  | 			errs = append(errs, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return errors.Join(errs...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Экспорт файла с диаграммами | ||||||
|  | func (exp Exporter) exportFile(filePath string, args []string, subDir ...string) error { | ||||||
|  | 	var ( | ||||||
|  | 		file     *os.File | ||||||
|  | 		diagrams []string | ||||||
|  | 		err      error | ||||||
|  | 	) | ||||||
|  | 	if file, err = os.Open(filePath); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer file.Close() | ||||||
|  | 	if diagrams, err = Diagrams(file); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	outDirs := make([]string, 1, len(subDir)+1) | ||||||
|  | 	outDirs[0] = exp.opts.Output | ||||||
|  | 	outDirs = append(outDirs, subDir...) | ||||||
|  | 	output := path.Join(outDirs...) | ||||||
|  | 	errs := []error{} | ||||||
|  | 	for i, name := range diagrams { | ||||||
|  | 		outName := strings.TrimSuffix(path.Base(filePath), path.Ext(filePath)) | ||||||
|  | 		if !exp.opts.RemovePageSuffix || len(diagrams) > 1 { | ||||||
|  | 			outName += "-" + name | ||||||
|  | 		} | ||||||
|  | 		outName += exp.opts.OutExt() | ||||||
|  | 		drawioArgs := make([]string, len(args), len(args)+4) | ||||||
|  | 		copy(drawioArgs, args) | ||||||
|  | 		drawioArgs = append(drawioArgs, | ||||||
|  | 			"--page-index", strconv.Itoa(i), | ||||||
|  | 			"--output", path.Join(output, outName), | ||||||
|  | 			"--export", filePath, | ||||||
|  | 		) | ||||||
|  | 		cmd := exec.Command(exp.opts.App(), drawioArgs...) | ||||||
|  | 		cmd.Stdout = os.Stdout | ||||||
|  | 		cmd.Stderr = os.Stderr | ||||||
|  | 		fmt.Println("Run command:", cmd.Path, cmd.Args) | ||||||
|  | 		if err = cmd.Run(); err != nil { | ||||||
|  | 			errs = append(errs, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return errors.Join(errs...) | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										350
									
								
								pkg/drawio/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								pkg/drawio/options.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,350 @@ | |||||||
|  | package drawio | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Интерфейс параметра экспортёра диаграмм | ||||||
|  | type Option interface { | ||||||
|  | 	apply(opts *Options) // Применить параметр к хранилищу параметров | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Ошибка "неподдерживаемый формат" | ||||||
|  | type ErrUnsupportedFormat struct { | ||||||
|  | 	Format string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Описание ошибки | ||||||
|  | func (e ErrUnsupportedFormat) Error() string { | ||||||
|  | 	return fmt.Sprintf("unsupported format: '%s'", e.Format) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ error = (*ErrUnsupportedFormat)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | type Format string // Формат экспортированного файла | ||||||
|  | 
 | ||||||
|  | // Строковое представление формата | ||||||
|  | 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 &ErrUnsupportedFormat{str} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ flag.Value = (*Format)(nil) // Поверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | // Расширение файла заданного формата | ||||||
|  | func (f Format) ext() string { | ||||||
|  | 	return "." + string(f) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Параметры экспортёра диаграмм | ||||||
|  | type Options struct { | ||||||
|  | 	Application      string // Путь к приложению drawio | ||||||
|  | 	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 // Включить подключаемые модули | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Путь к приложению drawio | ||||||
|  | func (opts Options) App() string { | ||||||
|  | 	app := opts.Application | ||||||
|  | 	if len(app) == 0 { | ||||||
|  | 		app = "drawio" | ||||||
|  | 	} | ||||||
|  | 	return app | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Путь к папке с экспортированными файлами | ||||||
|  | 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() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Формирование аргументов командной строки | ||||||
|  | func (opts Options) Args() []string { | ||||||
|  | 	args := []string{} | ||||||
|  | 	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) Option { | ||||||
|  | 	return optionApplication(path) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionApplication string | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionApplication)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionApplication) apply(opts *Options) { | ||||||
|  | 	opts.Application = string(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Путь к папке с экспортированными файлами | ||||||
|  | func WithOutput(path string) Option { | ||||||
|  | 	return optionOutput(path) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionOutput string | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionOutput)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionOutput) apply(opts *Options) { | ||||||
|  | 	opts.Output = string(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Формат экспортированных файлов | ||||||
|  | func WithFormat(format Format) Option { | ||||||
|  | 	return format | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ Option = (*Format)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt Format) apply(opts *Options) { | ||||||
|  | 	opts.Format = opt | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Рекурсивно сканировать вложенные папки с файлами | ||||||
|  | func WithRecursive() Option { | ||||||
|  | 	return optionRecursive{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionRecursive struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionRecursive{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionRecursive) apply(opts *Options) { | ||||||
|  | 	opts.Recursive = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Удалять суффикс страницы, если это возможно | ||||||
|  | func WithRemovePageSuffix() Option { | ||||||
|  | 	return optionRemovePageSuffix{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionRemovePageSuffix struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionRemovePageSuffix{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionRemovePageSuffix) apply(opts *Options) { | ||||||
|  | 	opts.RemovePageSuffix = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Качество экспортированного изображения (только для JPEG) | ||||||
|  | func WithQuality(q int) Option { | ||||||
|  | 	return optionQuality(q) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionQuality uint | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionQuality)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionQuality) apply(opts *Options) { | ||||||
|  | 	opts.Quality = uint(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Прозрачный фона для PNG | ||||||
|  | func WithTransparent() Option { | ||||||
|  | 	return optionTransparent{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionTransparent struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionTransparent{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionTransparent) apply(opts *Options) { | ||||||
|  | 	opts.Transparent = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Включать копию диаграммы в экспортированный файл для PDF, PNG и SVG | ||||||
|  | func WithEmbedDiagram() Option { | ||||||
|  | 	return optionEmbedDiagram{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionEmbedDiagram struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionEmbedDiagram{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionEmbedDiagram) apply(opts *Options) { | ||||||
|  | 	opts.EmbedDiagram = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Встраивать изображения в файл формата SVG | ||||||
|  | func WithEmbedSvgImages() Option { | ||||||
|  | 	return optionEmbedSvgImages{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionEmbedSvgImages struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionEmbedSvgImages{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionEmbedSvgImages) apply(opts *Options) { | ||||||
|  | 	opts.EmbedSvgImages = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Ширина рамки вокруг диаграмм | ||||||
|  | func WithBorder(border int) Option { | ||||||
|  | 	return optionBorder(border) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionBorder uint | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionBorder)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionBorder) apply(opts *Options) { | ||||||
|  | 	opts.Border = uint(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Масштаб в процентах размера экспортированных диаграмм | ||||||
|  | func WithScale(scale int) Option { | ||||||
|  | 	return optionScale(scale) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionScale uint | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionScale)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionScale) apply(opts *Options) { | ||||||
|  | 	opts.Scale = uint(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Ширина экспортированной диаграммы с сохранением масштаба | ||||||
|  | func WithWidth(width int) Option { | ||||||
|  | 	return optionWidth(width) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionWidth uint | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionWidth)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionWidth) apply(opts *Options) { | ||||||
|  | 	opts.Width = uint(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Высота экспортированной диаграммы с сохранением масштаба | ||||||
|  | func WithHeight(height int) Option { | ||||||
|  | 	return optionHeight(height) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionHeight uint | ||||||
|  | 
 | ||||||
|  | var _ Option = (*optionHeight)(nil) // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionHeight) apply(opts *Options) { | ||||||
|  | 	opts.Height = uint(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Обрезать результирующий PDF до размера диаграммы | ||||||
|  | func WithCrop() Option { | ||||||
|  | 	return optionCrop{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionCrop struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionCrop{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionCrop) apply(opts *Options) { | ||||||
|  | 	opts.Crop = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Выводить несжатый XML | ||||||
|  | func WithUncompressed() Option { | ||||||
|  | 	return optionUncompressed{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionUncompressed struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionUncompressed{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionUncompressed) apply(opts *Options) { | ||||||
|  | 	opts.Uncompressed = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Включить подключаемые модули | ||||||
|  | func WithEnablePlugins() Option { | ||||||
|  | 	return optionEnablePlugins{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type optionEnablePlugins struct{} | ||||||
|  | 
 | ||||||
|  | var _ Option = optionEnablePlugins{} // Проверка реализации интерфейса | ||||||
|  | 
 | ||||||
|  | func (opt optionEnablePlugins) apply(opts *Options) { | ||||||
|  | 	opts.EnablePlugins = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Список всех поддерживаемых форматов экспорта | ||||||
|  | func SupportedFormats() []Format { | ||||||
|  | 	return []Format{"pdf", "png", "jpg", "svg", "vsdx", "xml"} | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user