diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d207b18 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.go text eol=lf diff --git a/.gitea/workflows/golangci-lint.yaml b/.gitea/workflows/golangci-lint.yaml new file mode 100644 index 0000000..cb90cd8 --- /dev/null +++ b/.gitea/workflows/golangci-lint.yaml @@ -0,0 +1,22 @@ +name: golangci-lint +on: push + +jobs: + lint: + strategy: + matrix: + go: [stable] + os: [ubuntu-latest, windows-latest] + name: lint + runs-on: ${{ matrix.os }} + steps: + - name: check-out + uses: https://gitea.com/actions/checkout@v4 + - name: set-up go + uses: https://gitea.com/actions/setup-go@v5 + with: + go-version: ${{ matrix.go }} + - name: lint + uses: https://github.com/golangci/golangci-lint-action@v6 + with: + version: v1.60 diff --git a/.gitignore b/.gitignore index f4a1cb9..74dc80e 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,6 @@ go.work # Built Visual Studio Code Extensions *.vsix -# Vuild outputs +# Build outputs tmp/ out/ diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..1d86466 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,314 @@ +# This file contains all available configuration options +# with their default values (in comments). +# +# This file is not a configuration example, +# it contains the exhaustive configuration with explanations of the options. + +linters: + # Disable all linters. + # Default: false + disable-all: true + # Enable specific linter + # https://golangci-lint.run/usage/linters/#enabled-by-default + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - canonicalheader + - containedctx + - contextcheck + - copyloopvar + - cyclop + - decorder + - dogsled + - dupl + - dupword + - durationcheck + - err113 + - errcheck + - errchkjson + - errname + - errorlint + - exhaustive + - fatcontext + - forcetypeassert + - funlen + - gci + - ginkgolinter + - gocheckcompilerdirectives + # - gochecknoglobals + - gochecknoinits + - gochecksumtype + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - godox + - gofmt + - gofumpt + - goheader + - goimports + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - inamedparam + - ineffassign + - interfacebloat + - intrange + - ireturn + - lll + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - mnd + - musttag + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - nosprintfhostport + - paralleltest + - perfsprint + - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - revive + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck + - staticcheck + - stylecheck + - tagalign + - tagliatelle + - tenv + - testableexamples + - testifylint + - testpackage + - thelper + - tparallel + - unconvert + - unparam + - unused + - usestdlibvars + - varnamelen + - wastedassign + - whitespace + - wrapcheck + - wsl + - zerologlint + + # Enable all available linters. + # Default: false + enable-all: false + + # Enable only fast linters from enabled linters set (first run won't be fast) + # Default: false + fast: true + +# All available settings of specific linters. +linters-settings: + cyclop: + # The maximal code complexity to report. + # Default: 10 + max-complexity: 20 + # Should ignore tests. + # Default: false + skip-tests: true + + funlen: + # Checks the number of lines in a function. + # If lower than 0, disable the check. + # Default: 60 + lines: 80 + # Checks the number of statements in a function. + # If lower than 0, disable the check. + # Default: 40 + statements: 50 + # Ignore comments when counting lines. + # Default false + ignore-comments: true + + gocognit: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 20 + + gocyclo: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 20 + + godot: + # Comments to be checked: `declarations`, `toplevel`, or `all`. + # Default: declarations + scope: all + # List of regexps for excluding particular comment lines from check. + # Default: [] + exclude: + # Exclude todo and fixme comments. + - "^fixme:" + - "^todo:" + # Check that each sentence ends with a period. + # Default: true + period: false + # Check that each sentence starts with a capital letter. + # Default: false + capital: true + + goimports: + local-prefixes: git.mousesoft.ru/ms/drawio-export + + gosec: + excludes: + - G115 + + revive: + rules: + - name: unexported-return + disabled: true + +# output configuration options +output: + # The formats used to render issues. + # Formats: + # - `colored-line-number` + # - `line-number` + # - `json` + # - `colored-tab` + # - `tab` + # - `html` + # - `checkstyle` + # - `code-climate` + # - `junit-xml` + # - `junit-xml-extended` + # - `github-actions` + # - `teamcity` + # - `sarif` + # Output path can be either `stdout`, `stderr` or path to the file to write to. + # + # For the CLI flag (`--out-format`), multiple formats can be specified by separating them by comma. + # The output can be specified for each of them by separating format name and path by colon symbol. + # Example: "--out-format=checkstyle:report.xml,json:stdout,colored-line-number" + # The CLI flag (`--out-format`) override the configuration file. + # + # Default: + # formats: + # - format: colored-line-number + # path: stdout + formats: + # - format: json + # path: stderr + # - format: checkstyle + # path: report.xml + - format: colored-line-number + + # Print lines of code with issue. + # Default: true + print-issued-lines: false + + # Print linter name in the end of issue text. + # Default: true + print-linter-name: true + + # Make issues output unique by line. + # Default: true + uniq-by-line: false + + # Add a prefix to the output file references. + # Default: "" + path-prefix: "" + + # Sort results by the order defined in `sort-order`. + # Default: false + sort-results: true + + # Order to use when sorting results. + # Require `sort-results` to `true`. + # Possible values: `file`, `linter`, and `severity`. + # + # If the severity values are inside the following list, they are ordered in this order: + # 1. error + # 2. warning + # 3. high + # 4. medium + # 5. low + # Either they are sorted alphabetically. + # + # Default: ["file"] + sort-order: + - linter + - severity + - file # filepath, line, and column. + + # Show statistics per linter. + # Default: false + show-stats: true + +# Options for analysis running. +run: + # Timeout for analysis, e.g. 30s, 5m. + # Default: 1m + timeout: 5m + + # Exit code when at least one issue was found. + # Default: 1 + issues-exit-code: 2 + + # Include test files or not. + # Default: true + tests: false + + # List of build tags, all linters use it. + # Default: [] + build-tags: + - mytag + + # If set, we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + # + # Allowed values: readonly|vendor|mod + # Default: "" + modules-download-mode: readonly + + # Allow multiple parallel golangci-lint instances running. + # If false, golangci-lint acquires file lock on start. + # Default: false + allow-parallel-runners: true + + # Allow multiple golangci-lint instances running, but serialize them around a lock. + # If false, golangci-lint exits with an error if it fails to acquire file lock on start. + # Default: false + allow-serial-runners: true + + # Define the Go version limit. + # Mainly related to generics support since go1.18. + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 + go: "1.22" + + # Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously. + # If it is explicitly set to 0 (i.e. not the default) then golangci-lint will automatically set the value to match Linux container CPU quota. + # Default: the number of logical CPUs in the machine + concurrency: 4 diff --git a/README.md b/README.md index e8923fd..0f55fd9 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,8 @@ ## Разработка -Для удобного редактирования, сборки, отладки и тестирования проекта в локальном -окружении программиста необходимо выполнить следующие действия: - -1. Клонировать репозиторий проекта в папку `$GOPATH/src/git.mousesoft.ru/ms/`. -2. Установить все Go-пакеты, от которых зависит этот проект - (см. следующий раздел). -3. Если предполагается формирование отчёта о покрытии кода модульными тестами, - то нужно установить необходимые для этого пакеты - (см. раздел [Тестирование](#тестирование) далее). +В проекте приняты (не строго обязательные) соглашения +[Uber Go Style Guide](https://github.com/uber-go/guide/blob/master/style.md). ### Структура проекта @@ -25,6 +18,7 @@ - `build` - Сборка и непрерывная интеграция (Continuous Integration, *CI*). - `cmd` - Основные приложения проекта. Имя директории для каждого приложения должно совпадать с именем исполняемого файла, который вы хотите собрать. +- `internal` - Внутренний код приложения и библиотек. - `pkg` - Код библиотек, пригодных для использования в сторонних приложениях. - `scripts` - Скрипты для сборки, установки, анализа и прочих операций над проектом. diff --git a/cmd/drawio-export/main.go b/cmd/drawio-export/main.go index adb9967..d939e3b 100644 --- a/cmd/drawio-export/main.go +++ b/cmd/drawio-export/main.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" + "git.mousesoft.ru/ms/drawio-export/pkg/drawio" ) var ( @@ -13,23 +13,44 @@ var ( version string // Версия приложения ) +type flags struct { + flagHelp bool // Вывести справку о приложении и выйти + flagVersion bool // Вывести информацию о версии приложения и выйти + flagIgnoreErrors bool // Игнорировать ошибки +} + func main() { + var ( + opts drawio.Options // Аргументы командной строки приложения + flags flags // Флаги командной строки + ) + + initFlags(&opts, &flags) + flag.Parse() - if flagHelp { + + if flags.flagHelp { flag.Usage() + os.Exit(0) } - if flagVersion { - fmt.Println(appname, version) + + if flags.flagVersion { + _, _ = fmt.Println(appname, 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 && !flagIgnoreErrors { + if err := exporter.Export(flag.Args()...); err != nil && !flags.flagIgnoreErrors { fmt.Fprintln(os.Stderr, "Error:", err) + os.Exit(1) } } diff --git a/cmd/drawio-export/options.go b/cmd/drawio-export/options.go index 1d52740..7da685f 100644 --- a/cmd/drawio-export/options.go +++ b/cmd/drawio-export/options.go @@ -3,23 +3,16 @@ package main import ( "flag" - "git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" + "git.mousesoft.ru/ms/drawio-export/pkg/drawio" ) -var ( - flagHelp bool // Вывести справку о приложении и выйти - flagVersion bool // Вывести информацию о версии приложения и выйти - flagIgnoreErrors bool // Игнорировать ошибки - opts = drawio.Options{} // Аргументы командной строки приложения -) - -func init() { - // version - flag.BoolVar(&flagVersion, "V", false, "Prints version information") - flag.BoolVar(&flagVersion, "version", false, "Prints version information") +func initFlags(opts *drawio.Options, flags *flags) { + // Version + flag.BoolVar(&flags.flagVersion, "V", false, "Prints version information") + flag.BoolVar(&flags.flagVersion, "version", false, "Prints version information") // Ignore Errors - flag.BoolVar(&flagIgnoreErrors, "I", false, "Ignore Draw.IO errors") - flag.BoolVar(&flagIgnoreErrors, "ignore-errors", false, "Ignore Draw.IO errors") + flag.BoolVar(&flags.flagIgnoreErrors, "I", false, "Ignore Draw.IO errors") + flag.BoolVar(&flags.flagIgnoreErrors, "ignore-errors", false, "Ignore Draw.IO errors") // Application flag.StringVar(&opts.Application, "A", "", "Draw.io Desktop Application") flag.StringVar(&opts.Application, "application", "", "Draw.io Desktop Application") @@ -76,7 +69,7 @@ func init() { 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") + // Help + flag.BoolVar(&flags.flagHelp, "h", false, "Prints help information") + flag.BoolVar(&flags.flagHelp, "help", false, "Prints help information") } diff --git a/drawio-export b/drawio-export deleted file mode 100755 index ad7c142..0000000 Binary files a/drawio-export and /dev/null differ diff --git a/go.mod b/go.mod index 6453683..3bc037e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ -module git.mousesoft.ru/ms/drawio-exporter +module git.mousesoft.ru/ms/drawio-export -go 1.20 +go 1.22 require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/makefile b/makefile index b49b501..23d93a5 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,8 @@ # drawio-exporter makefile # ======================== +SHELL := /usr/bin/env bash + PROJECT_ID := drawio-export PROJECT_NAME ?= MouseSoft Draw.IO Export BIN_SUFFIX := @@ -27,14 +29,13 @@ COVERAGE_FORMAT ?= html GOCMD := go GOTEST := $(GOCMD) test GOVET := $(GOCMD) vet -ECHO_CMD := echo +ECHO_CMD := echo -e ifeq ($(OS),Windows_NT) DIST_SUFFIX := windows-$(GOARCH) MSI_FILE ?= $(PROJECT_ID)_$(VERSION)_$(GOARCH).msi DIST_EXT := .zip DIST_OPTS := -a -cf -ECHO_CMD := echo -e MSI_VERSION := $(shell echo $(VERSION_NUMBER) | sed -e 's/-.*//') BIN_SUFFIX := .exe else @@ -193,14 +194,18 @@ endif ## Lint -lint: lint-go ## Run all available linters. +lint: ## Run all available linters. + go vet ./... + errcheck ./... + staticcheck ./... + usestdlibvars ./... @$(ECHO_CMD) "Lint\t\t${GREEN}[OK]${RESET}" .PHONY:lint -lint-go: - go fmt ./... - go vet ./... -.PHONY:lint-go +golangci-lint: ## Run golangci-lint linter + @golangci-lint run + @$(ECHO_CMD) "GolangCI Lint\t${GREEN}[OK]${RESET}" +.PHONY:golangci-lint ## Documentation diff --git a/pkg/drawio/execution.go b/pkg/drawio/execution.go index 54ce958..e1263fa 100644 --- a/pkg/drawio/execution.go +++ b/pkg/drawio/execution.go @@ -7,14 +7,13 @@ import ( // Последовательный запуск команд в ОС func RunSequence(command ...*exec.Cmd) error { - var ( - errs = []error{} - err error - ) + var errs []error + for _, cmd := range command { - if err = cmd.Run(); err != nil { + if err := cmd.Run(); err != nil { errs = append(errs, err) } } + return errors.Join(errs...) } diff --git a/pkg/drawio/export.go b/pkg/drawio/export.go index 83d1cc1..530a3ba 100644 --- a/pkg/drawio/export.go +++ b/pkg/drawio/export.go @@ -24,12 +24,14 @@ func New(opt ...Option) Exporter { for _, opt := range opt { opt.apply(options) } + return NewWithOptions(options) } // Создать нового экспортёра с параметрами func NewWithOptions(opts *Options) Exporter { exp := Exporter{opts: opts} + if opts.openFile == nil { exp.openFile = func(name string) (io.ReadCloser, error) { return os.Open(name) @@ -37,13 +39,13 @@ func NewWithOptions(opts *Options) Exporter { } else { exp.openFile = opts.openFile } + if opts.readDir == nil { - exp.readDir = func(name string) ([]os.DirEntry, error) { - return os.ReadDir(name) - } + exp.readDir = os.ReadDir } else { exp.readDir = opts.readDir } + return exp } @@ -58,30 +60,37 @@ type Exporter struct { func (exp Exporter) Export(fileOrDir ...string) error { var ( commands = []*exec.Cmd{} - err error errs = []error{} args = exp.opts.Args() info fs.FileInfo ) + for _, item := range fileOrDir { + var err error if info, err = os.Stat(item); err != nil { errs = append(errs, err) + continue } + var addCommands []*exec.Cmd if info.IsDir() { addCommands, err = exp.ExportDir(item, args) } else { addCommands, err = exp.ExportFile(item, args) } + commands = append(commands, addCommands...) + if err != nil { errs = append(errs, err) } } - if err = RunSequence(commands...); err != nil { + + if err := RunSequence(commands...); err != nil { errs = append(errs, err) } + return errors.Join(errs...) } @@ -95,12 +104,16 @@ func (exp Exporter) ExportDir( entries []fs.DirEntry errs []error ) + if entries, err = exp.readDir(dirPath); err != nil { return commands, err } + for _, entry := range entries { name := entry.Name() + var addCommands []*exec.Cmd + if entry.IsDir() { if exp.opts.Recursive { deep := len(subDir) @@ -114,11 +127,14 @@ func (exp Exporter) ExportDir( } else { addCommands, err = exp.ExportFile(path.Join(dirPath, name), args, subDir...) } + commands = append(commands, addCommands...) + if err != nil { errs = append(errs, err) } } + return commands, errors.Join(errs...) } @@ -126,43 +142,57 @@ func (exp Exporter) ExportDir( func (exp Exporter) ExportFile( filePath string, args []string, subDir ...string, ) ([]*exec.Cmd, error) { + const AdditionalArgsNumber = 10 + var ( commands = []*exec.Cmd{} err error file io.ReadCloser diagrams []string ) + if file, err = exp.openFile(filePath); err != nil { return commands, err } - defer file.Close() + + defer func() { _ = file.Close() }() + if diagrams, err = Diagrams(file); err != nil { return commands, err } + outDirs := make([]string, 1, len(subDir)+1) outDirs[0] = exp.opts.OutDir() outDirs = append(outDirs, subDir...) output := path.Join(outDirs...) - for i, name := range diagrams { + + for index, 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)+10) + drawioArgs := make([]string, len(args), len(args)+AdditionalArgsNumber) + copy(drawioArgs, args) + drawioArgs = append(drawioArgs, - "--page-index", strconv.Itoa(i), + "--page-index", strconv.Itoa(index), "--output", path.Join(output, outName), "--export", filePath, ) + if exp.opts.EnableXvfb { drawioArgs = append(drawioArgs, "--disable-gpu", "--headless", "--no-sandbox") } - cmd := exec.Command(exp.opts.App(), drawioArgs...) + + cmd := exec.Command(exp.opts.App(), drawioArgs...) //nolint:gosec commands = append(commands, cmd) } + return commands, err } @@ -175,15 +205,18 @@ func Diagrams(reader io.Reader) ([]string, error) { br, "mxfile", "diagram", ).ParseAttributesOnly("diagram") ) + for xml := range parser.Stream() { if xml.Err != nil { return result, xml.Err } + if items, ok := xml.Childs["diagram"]; ok { for _, item := range items { result = append(result, item.Attrs["name"]) } } } + return result, nil } diff --git a/pkg/drawio/export_test.go b/pkg/drawio/export_test.go index f029260..f60d418 100644 --- a/pkg/drawio/export_test.go +++ b/pkg/drawio/export_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" + "git.mousesoft.ru/ms/drawio-export/pkg/drawio" "github.com/stretchr/testify/assert" ) @@ -344,7 +344,7 @@ func TestExportFile(t *testing.T) { for _, test := range testData { t.Run(test.name, func(t *testing.T) { for filePath, source := range test.files { - var openOpt = drawio.WithNop() + var openOpt drawio.Option = drawio.WithNop() if len(source.output) > 0 { openOpt = drawio.WithOutput(source.output) } diff --git a/pkg/drawio/options.go b/pkg/drawio/options.go index 6f4b4ca..387fcb6 100644 --- a/pkg/drawio/options.go +++ b/pkg/drawio/options.go @@ -14,25 +14,25 @@ type Option interface { } // Ошибка "неподдерживаемый формат" -type ErrUnsupportedFormat struct { +type UnsupportedFormatError struct { Format string } // Описание ошибки -func (e ErrUnsupportedFormat) Error() string { +func (e UnsupportedFormatError) Error() string { return fmt.Sprintf("unsupported format: '%s'", e.Format) } // Проверка эквивалентности ошибок -func (e ErrUnsupportedFormat) Is(target error) bool { - switch t := target.(type) { - case ErrUnsupportedFormat: +func (e UnsupportedFormatError) Is(target error) bool { + if t, ok := target.(UnsupportedFormatError); ok { return t.Format == e.Format } + return false } -var _ error = (*ErrUnsupportedFormat)(nil) // Проверка реализации интерфейса +var _ error = (*UnsupportedFormatError)(nil) // Проверка реализации интерфейса type Format string // Формат экспортированного файла @@ -55,10 +55,12 @@ func (f *Format) Set(str string) error { for _, fmt := range SupportedFormats() { if str == string(fmt) { *f = Format(str) + return nil } } - return &ErrUnsupportedFormat{str} + + return &UnsupportedFormatError{str} } // Список всех поддерживаемых форматов экспорта @@ -108,9 +110,11 @@ func (opts Options) App() string { if opts.EnableXvfb { return "xvfb-run" } + if len(opts.Application) == 0 { return "drawio" } + return opts.Application } @@ -120,6 +124,7 @@ func (opts Options) OutDir() string { if len(out) == 0 { out = "export" } + return out } @@ -129,12 +134,14 @@ func (opts Options) OutExt() string { 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 { @@ -142,49 +149,63 @@ func (opts Options) Args() []string { } 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) Option { +func WithAppPath(path string) optionApplication { return optionApplication(path) } @@ -197,7 +218,7 @@ func (opt optionApplication) apply(opts *Options) { } // Запускать drawio внутри xvfb-run -func WithXvfb() Option { +func WithXvfb() optionXvfb { return optionXvfb{} } @@ -210,7 +231,7 @@ func (opt optionXvfb) apply(opts *Options) { } // Путь к папке с экспортированными файлами -func WithOutput(path string) Option { +func WithOutput(path string) optionOutput { return optionOutput(path) } @@ -223,18 +244,18 @@ func (opt optionOutput) apply(opts *Options) { } // Формат экспортированных файлов -func WithFormat(format Format) Option { +func WithFormat(format Format) Format { return format } var _ Option = (*Format)(nil) // Проверка реализации интерфейса -func (opt Format) apply(opts *Options) { - opts.Format = opt +func (f Format) apply(opts *Options) { + opts.Format = f } // Рекурсивно сканировать вложенные папки с файлами -func WithRecursive() Option { +func WithRecursive() optionRecursive { return optionRecursive{} } @@ -247,7 +268,7 @@ func (opt optionRecursive) apply(opts *Options) { } // Удалять суффикс страницы, если это возможно -func WithRemovePageSuffix() Option { +func WithRemovePageSuffix() optionRemovePageSuffix { return optionRemovePageSuffix{} } @@ -260,7 +281,7 @@ func (opt optionRemovePageSuffix) apply(opts *Options) { } // Качество экспортированного изображения (только для JPEG) -func WithQuality(q uint) Option { +func WithQuality(q uint) optionQuality { return optionQuality(q) } @@ -273,7 +294,7 @@ func (opt optionQuality) apply(opts *Options) { } // Прозрачный фона для PNG -func WithTransparent() Option { +func WithTransparent() optionTransparent { return optionTransparent{} } @@ -286,7 +307,7 @@ func (opt optionTransparent) apply(opts *Options) { } // Включать копию диаграммы в экспортированный файл для PDF, PNG и SVG -func WithEmbedDiagram() Option { +func WithEmbedDiagram() optionEmbedDiagram { return optionEmbedDiagram{} } @@ -299,7 +320,7 @@ func (opt optionEmbedDiagram) apply(opts *Options) { } // Встраивать изображения в файл формата SVG -func WithEmbedSvgImages() Option { +func WithEmbedSvgImages() optionEmbedSvgImages { return optionEmbedSvgImages{} } @@ -312,7 +333,7 @@ func (opt optionEmbedSvgImages) apply(opts *Options) { } // Ширина рамки вокруг диаграмм -func WithBorder(border uint) Option { +func WithBorder(border uint) optionBorder { return optionBorder(border) } @@ -325,7 +346,7 @@ func (opt optionBorder) apply(opts *Options) { } // Масштаб в процентах размера экспортированных диаграмм -func WithScale(scale uint) Option { +func WithScale(scale uint) optionScale { return optionScale(scale) } @@ -338,7 +359,7 @@ func (opt optionScale) apply(opts *Options) { } // Ширина экспортированной диаграммы с сохранением масштаба -func WithWidth(width uint) Option { +func WithWidth(width uint) optionWidth { return optionWidth(width) } @@ -351,7 +372,7 @@ func (opt optionWidth) apply(opts *Options) { } // Высота экспортированной диаграммы с сохранением масштаба -func WithHeight(height uint) Option { +func WithHeight(height uint) optionHeight { return optionHeight(height) } @@ -364,7 +385,7 @@ func (opt optionHeight) apply(opts *Options) { } // Обрезать результирующий PDF до размера диаграммы -func WithCrop() Option { +func WithCrop() optionCrop { return optionCrop{} } @@ -377,7 +398,7 @@ func (opt optionCrop) apply(opts *Options) { } // Выводить несжатый XML -func WithUncompressed() Option { +func WithUncompressed() optionUncompressed { return optionUncompressed{} } @@ -390,7 +411,7 @@ func (opt optionUncompressed) apply(opts *Options) { } // Включить подключаемые модули -func WithEnablePlugins() Option { +func WithEnablePlugins() optionEnablePlugins { return optionEnablePlugins{} } @@ -403,7 +424,7 @@ func (opt optionEnablePlugins) apply(opts *Options) { } // Открыть файл -func WithOpenFile(openFile OpenFileFunc) Option { +func WithOpenFile(openFile OpenFileFunc) optionOpenFile { return optionOpenFile{openFile} } @@ -418,7 +439,7 @@ func (opt optionOpenFile) apply(opts *Options) { } // Прочитать папку на диске -func WithReadDir(readDir ReadDirFunc) Option { +func WithReadDir(readDir ReadDirFunc) optionReadDir { return optionReadDir{readDir} } @@ -433,7 +454,7 @@ func (opt optionReadDir) apply(opts *Options) { } // Пустой параметр -func WithNop() Option { +func WithNop() optionNop { return optionNop{} } @@ -441,6 +462,6 @@ type optionNop struct{} var _ Option = optionNop{} -func (opt optionNop) apply(opts *Options) { +func (opt optionNop) apply(_ *Options) { // Не требуется действий, так как это пустой параметр } diff --git a/pkg/drawio/options_test.go b/pkg/drawio/options_test.go index 161309d..860918e 100644 --- a/pkg/drawio/options_test.go +++ b/pkg/drawio/options_test.go @@ -3,7 +3,7 @@ package drawio_test import ( "testing" - "git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" + "git.mousesoft.ru/ms/drawio-export/pkg/drawio" "github.com/stretchr/testify/assert" ) @@ -52,7 +52,7 @@ func TestFormat(t *testing.T) { }, { name: "svvg", - err: drawio.ErrUnsupportedFormat{"svvg"}, + err: drawio.UnsupportedFormatError{"svvg"}, format: drawio.Format(""), ext: "", }, diff --git a/report.xml b/report.xml new file mode 100644 index 0000000..d2d8131 --- /dev/null +++ b/report.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +