Добавлен линтер golangci-lint
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

This commit is contained in:
Алексей Бадяев 2024-10-17 23:29:54 +07:00
parent 950aecc036
commit b32f3ab88a
Signed by: alexey
GPG Key ID: 686FBC1363E4AFAE
16 changed files with 601 additions and 90 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.go text eol=lf

View File

@ -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

2
.gitignore vendored
View File

@ -35,6 +35,6 @@ go.work
# Built Visual Studio Code Extensions # Built Visual Studio Code Extensions
*.vsix *.vsix
# Vuild outputs # Build outputs
tmp/ tmp/
out/ out/

314
.golangci.yaml Normal file
View File

@ -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

View File

@ -7,15 +7,8 @@
## Разработка ## Разработка
Для удобного редактирования, сборки, отладки и тестирования проекта в локальном В проекте приняты (не строго обязательные) соглашения
окружении программиста необходимо выполнить следующие действия: [Uber Go Style Guide](https://github.com/uber-go/guide/blob/master/style.md).
1. Клонировать репозиторий проекта в папку `$GOPATH/src/git.mousesoft.ru/ms/`.
2. Установить все Go-пакеты, от которых зависит этот проект
(см. следующий раздел).
3. Если предполагается формирование отчёта о покрытии кода модульными тестами,
то нужно установить необходимые для этого пакеты
(см. раздел [Тестирование](#тестирование) далее).
### Структура проекта ### Структура проекта
@ -25,6 +18,7 @@
- `build` - Сборка и непрерывная интеграция (Continuous Integration, *CI*). - `build` - Сборка и непрерывная интеграция (Continuous Integration, *CI*).
- `cmd` - Основные приложения проекта. Имя директории для каждого приложения - `cmd` - Основные приложения проекта. Имя директории для каждого приложения
должно совпадать с именем исполняемого файла, который вы хотите собрать. должно совпадать с именем исполняемого файла, который вы хотите собрать.
- `internal` - Внутренний код приложения и библиотек.
- `pkg` - Код библиотек, пригодных для использования в сторонних приложениях. - `pkg` - Код библиотек, пригодных для использования в сторонних приложениях.
- `scripts` - Скрипты для сборки, установки, анализа и прочих операций над проектом. - `scripts` - Скрипты для сборки, установки, анализа и прочих операций над проектом.

View File

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" "git.mousesoft.ru/ms/drawio-export/pkg/drawio"
) )
var ( var (
@ -13,23 +13,44 @@ var (
version string // Версия приложения version string // Версия приложения
) )
type flags struct {
flagHelp bool // Вывести справку о приложении и выйти
flagVersion bool // Вывести информацию о версии приложения и выйти
flagIgnoreErrors bool // Игнорировать ошибки
}
func main() { func main() {
var (
opts drawio.Options // Аргументы командной строки приложения
flags flags // Флаги командной строки
)
initFlags(&opts, &flags)
flag.Parse() flag.Parse()
if flagHelp {
if flags.flagHelp {
flag.Usage() flag.Usage()
os.Exit(0) os.Exit(0)
} }
if flagVersion {
fmt.Println(appname, version) if flags.flagVersion {
_, _ = fmt.Println(appname, version)
os.Exit(0) os.Exit(0)
} }
if flag.NArg() < 1 { if flag.NArg() < 1 {
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
} }
exporter := drawio.NewWithOptions(&opts) 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) fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1) os.Exit(1)
} }
} }

View File

@ -3,23 +3,16 @@ package main
import ( import (
"flag" "flag"
"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" "git.mousesoft.ru/ms/drawio-export/pkg/drawio"
) )
var ( func initFlags(opts *drawio.Options, flags *flags) {
flagHelp bool // Вывести справку о приложении и выйти // Version
flagVersion bool // Вывести информацию о версии приложения и выйти flag.BoolVar(&flags.flagVersion, "V", false, "Prints version information")
flagIgnoreErrors bool // Игнорировать ошибки flag.BoolVar(&flags.flagVersion, "version", false, "Prints version information")
opts = drawio.Options{} // Аргументы командной строки приложения
)
func init() {
// version
flag.BoolVar(&flagVersion, "V", false, "Prints version information")
flag.BoolVar(&flagVersion, "version", false, "Prints version information")
// Ignore Errors // Ignore Errors
flag.BoolVar(&flagIgnoreErrors, "I", false, "Ignore Draw.IO errors") flag.BoolVar(&flags.flagIgnoreErrors, "I", false, "Ignore Draw.IO errors")
flag.BoolVar(&flagIgnoreErrors, "ignore-errors", false, "Ignore Draw.IO errors") flag.BoolVar(&flags.flagIgnoreErrors, "ignore-errors", false, "Ignore Draw.IO errors")
// Application // Application
flag.StringVar(&opts.Application, "A", "", "Draw.io Desktop Application") flag.StringVar(&opts.Application, "A", "", "Draw.io Desktop Application")
flag.StringVar(&opts.Application, "application", "", "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") flag.BoolVar(&opts.Uncompressed, "uncompressed", false, "Uncompressed XML output")
// EnablePlugins // EnablePlugins
flag.BoolVar(&opts.EnablePlugins, "enable-plugins", false, "Enable Plugins") flag.BoolVar(&opts.EnablePlugins, "enable-plugins", false, "Enable Plugins")
// help // Help
flag.BoolVar(&flagHelp, "h", false, "Prints help information") flag.BoolVar(&flags.flagHelp, "h", false, "Prints help information")
flag.BoolVar(&flagHelp, "help", false, "Prints help information") flag.BoolVar(&flags.flagHelp, "help", false, "Prints help information")
} }

Binary file not shown.

4
go.mod
View File

@ -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 ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect

View File

@ -1,6 +1,8 @@
# drawio-exporter makefile # drawio-exporter makefile
# ======================== # ========================
SHELL := /usr/bin/env bash
PROJECT_ID := drawio-export PROJECT_ID := drawio-export
PROJECT_NAME ?= MouseSoft Draw.IO Export PROJECT_NAME ?= MouseSoft Draw.IO Export
BIN_SUFFIX := BIN_SUFFIX :=
@ -27,14 +29,13 @@ COVERAGE_FORMAT ?= html
GOCMD := go GOCMD := go
GOTEST := $(GOCMD) test GOTEST := $(GOCMD) test
GOVET := $(GOCMD) vet GOVET := $(GOCMD) vet
ECHO_CMD := echo ECHO_CMD := echo -e
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
DIST_SUFFIX := windows-$(GOARCH) DIST_SUFFIX := windows-$(GOARCH)
MSI_FILE ?= $(PROJECT_ID)_$(VERSION)_$(GOARCH).msi MSI_FILE ?= $(PROJECT_ID)_$(VERSION)_$(GOARCH).msi
DIST_EXT := .zip DIST_EXT := .zip
DIST_OPTS := -a -cf DIST_OPTS := -a -cf
ECHO_CMD := echo -e
MSI_VERSION := $(shell echo $(VERSION_NUMBER) | sed -e 's/-.*//') MSI_VERSION := $(shell echo $(VERSION_NUMBER) | sed -e 's/-.*//')
BIN_SUFFIX := .exe BIN_SUFFIX := .exe
else else
@ -193,14 +194,18 @@ endif
## Lint ## 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}" @$(ECHO_CMD) "Lint\t\t${GREEN}[OK]${RESET}"
.PHONY:lint .PHONY:lint
lint-go: golangci-lint: ## Run golangci-lint linter
go fmt ./... @golangci-lint run
go vet ./... @$(ECHO_CMD) "GolangCI Lint\t${GREEN}[OK]${RESET}"
.PHONY:lint-go .PHONY:golangci-lint
## Documentation ## Documentation

View File

@ -7,14 +7,13 @@ import (
// Последовательный запуск команд в ОС // Последовательный запуск команд в ОС
func RunSequence(command ...*exec.Cmd) error { func RunSequence(command ...*exec.Cmd) error {
var ( var errs []error
errs = []error{}
err error
)
for _, cmd := range command { for _, cmd := range command {
if err = cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
errs = append(errs, err) errs = append(errs, err)
} }
} }
return errors.Join(errs...) return errors.Join(errs...)
} }

View File

@ -24,12 +24,14 @@ func New(opt ...Option) Exporter {
for _, opt := range opt { for _, opt := range opt {
opt.apply(options) opt.apply(options)
} }
return NewWithOptions(options) return NewWithOptions(options)
} }
// Создать нового экспортёра с параметрами // Создать нового экспортёра с параметрами
func NewWithOptions(opts *Options) Exporter { func NewWithOptions(opts *Options) Exporter {
exp := Exporter{opts: opts} exp := Exporter{opts: opts}
if opts.openFile == nil { if opts.openFile == nil {
exp.openFile = func(name string) (io.ReadCloser, error) { exp.openFile = func(name string) (io.ReadCloser, error) {
return os.Open(name) return os.Open(name)
@ -37,13 +39,13 @@ func NewWithOptions(opts *Options) Exporter {
} else { } else {
exp.openFile = opts.openFile exp.openFile = opts.openFile
} }
if opts.readDir == nil { if opts.readDir == nil {
exp.readDir = func(name string) ([]os.DirEntry, error) { exp.readDir = os.ReadDir
return os.ReadDir(name)
}
} else { } else {
exp.readDir = opts.readDir exp.readDir = opts.readDir
} }
return exp return exp
} }
@ -58,30 +60,37 @@ type Exporter struct {
func (exp Exporter) Export(fileOrDir ...string) error { func (exp Exporter) Export(fileOrDir ...string) error {
var ( var (
commands = []*exec.Cmd{} commands = []*exec.Cmd{}
err error
errs = []error{} errs = []error{}
args = exp.opts.Args() args = exp.opts.Args()
info fs.FileInfo info fs.FileInfo
) )
for _, item := range fileOrDir { for _, item := range fileOrDir {
var err error
if info, err = os.Stat(item); err != nil { if info, err = os.Stat(item); err != nil {
errs = append(errs, err) errs = append(errs, err)
continue continue
} }
var addCommands []*exec.Cmd var addCommands []*exec.Cmd
if info.IsDir() { if info.IsDir() {
addCommands, err = exp.ExportDir(item, args) addCommands, err = exp.ExportDir(item, args)
} else { } else {
addCommands, err = exp.ExportFile(item, args) addCommands, err = exp.ExportFile(item, args)
} }
commands = append(commands, addCommands...) commands = append(commands, addCommands...)
if err != nil { if err != nil {
errs = append(errs, err) errs = append(errs, err)
} }
} }
if err = RunSequence(commands...); err != nil {
if err := RunSequence(commands...); err != nil {
errs = append(errs, err) errs = append(errs, err)
} }
return errors.Join(errs...) return errors.Join(errs...)
} }
@ -95,12 +104,16 @@ func (exp Exporter) ExportDir(
entries []fs.DirEntry entries []fs.DirEntry
errs []error errs []error
) )
if entries, err = exp.readDir(dirPath); err != nil { if entries, err = exp.readDir(dirPath); err != nil {
return commands, err return commands, err
} }
for _, entry := range entries { for _, entry := range entries {
name := entry.Name() name := entry.Name()
var addCommands []*exec.Cmd var addCommands []*exec.Cmd
if entry.IsDir() { if entry.IsDir() {
if exp.opts.Recursive { if exp.opts.Recursive {
deep := len(subDir) deep := len(subDir)
@ -114,11 +127,14 @@ func (exp Exporter) ExportDir(
} else { } else {
addCommands, err = exp.ExportFile(path.Join(dirPath, name), args, subDir...) addCommands, err = exp.ExportFile(path.Join(dirPath, name), args, subDir...)
} }
commands = append(commands, addCommands...) commands = append(commands, addCommands...)
if err != nil { if err != nil {
errs = append(errs, err) errs = append(errs, err)
} }
} }
return commands, errors.Join(errs...) return commands, errors.Join(errs...)
} }
@ -126,43 +142,57 @@ func (exp Exporter) ExportDir(
func (exp Exporter) ExportFile( func (exp Exporter) ExportFile(
filePath string, args []string, subDir ...string, filePath string, args []string, subDir ...string,
) ([]*exec.Cmd, error) { ) ([]*exec.Cmd, error) {
const AdditionalArgsNumber = 10
var ( var (
commands = []*exec.Cmd{} commands = []*exec.Cmd{}
err error err error
file io.ReadCloser file io.ReadCloser
diagrams []string diagrams []string
) )
if file, err = exp.openFile(filePath); err != nil { if file, err = exp.openFile(filePath); err != nil {
return commands, err return commands, err
} }
defer file.Close()
defer func() { _ = file.Close() }()
if diagrams, err = Diagrams(file); err != nil { if diagrams, err = Diagrams(file); err != nil {
return commands, err return commands, err
} }
outDirs := make([]string, 1, len(subDir)+1) outDirs := make([]string, 1, len(subDir)+1)
outDirs[0] = exp.opts.OutDir() outDirs[0] = exp.opts.OutDir()
outDirs = append(outDirs, subDir...) outDirs = append(outDirs, subDir...)
output := path.Join(outDirs...) output := path.Join(outDirs...)
for i, name := range diagrams {
for index, name := range diagrams {
outName := strings.TrimSuffix(path.Base(filePath), path.Ext(filePath)) outName := strings.TrimSuffix(path.Base(filePath), path.Ext(filePath))
if !exp.opts.RemovePageSuffix || len(diagrams) > 1 { if !exp.opts.RemovePageSuffix || len(diagrams) > 1 {
outName += "-" + name outName += "-" + name
} }
outName += exp.opts.OutExt() outName += exp.opts.OutExt()
drawioArgs := make([]string, len(args), len(args)+10) drawioArgs := make([]string, len(args), len(args)+AdditionalArgsNumber)
copy(drawioArgs, args) copy(drawioArgs, args)
drawioArgs = append(drawioArgs, drawioArgs = append(drawioArgs,
"--page-index", strconv.Itoa(i), "--page-index", strconv.Itoa(index),
"--output", path.Join(output, outName), "--output", path.Join(output, outName),
"--export", filePath, "--export", filePath,
) )
if exp.opts.EnableXvfb { if exp.opts.EnableXvfb {
drawioArgs = append(drawioArgs, drawioArgs = append(drawioArgs,
"--disable-gpu", "--headless", "--no-sandbox") "--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) commands = append(commands, cmd)
} }
return commands, err return commands, err
} }
@ -175,15 +205,18 @@ func Diagrams(reader io.Reader) ([]string, error) {
br, "mxfile", "diagram", br, "mxfile", "diagram",
).ParseAttributesOnly("diagram") ).ParseAttributesOnly("diagram")
) )
for xml := range parser.Stream() { for xml := range parser.Stream() {
if xml.Err != nil { if xml.Err != nil {
return result, xml.Err return result, xml.Err
} }
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"])
} }
} }
} }
return result, nil return result, nil
} }

View File

@ -10,7 +10,7 @@ import (
"testing" "testing"
"time" "time"
"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" "git.mousesoft.ru/ms/drawio-export/pkg/drawio"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -344,7 +344,7 @@ func TestExportFile(t *testing.T) {
for _, test := range testData { for _, test := range testData {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
for filePath, source := range test.files { for filePath, source := range test.files {
var openOpt = drawio.WithNop() var openOpt drawio.Option = drawio.WithNop()
if len(source.output) > 0 { if len(source.output) > 0 {
openOpt = drawio.WithOutput(source.output) openOpt = drawio.WithOutput(source.output)
} }

View File

@ -14,25 +14,25 @@ type Option interface {
} }
// Ошибка "неподдерживаемый формат" // Ошибка "неподдерживаемый формат"
type ErrUnsupportedFormat struct { type UnsupportedFormatError struct {
Format string Format string
} }
// Описание ошибки // Описание ошибки
func (e ErrUnsupportedFormat) Error() string { func (e UnsupportedFormatError) Error() string {
return fmt.Sprintf("unsupported format: '%s'", e.Format) return fmt.Sprintf("unsupported format: '%s'", e.Format)
} }
// Проверка эквивалентности ошибок // Проверка эквивалентности ошибок
func (e ErrUnsupportedFormat) Is(target error) bool { func (e UnsupportedFormatError) Is(target error) bool {
switch t := target.(type) { if t, ok := target.(UnsupportedFormatError); ok {
case ErrUnsupportedFormat:
return t.Format == e.Format return t.Format == e.Format
} }
return false return false
} }
var _ error = (*ErrUnsupportedFormat)(nil) // Проверка реализации интерфейса var _ error = (*UnsupportedFormatError)(nil) // Проверка реализации интерфейса
type Format string // Формат экспортированного файла type Format string // Формат экспортированного файла
@ -55,10 +55,12 @@ func (f *Format) Set(str string) error {
for _, fmt := range SupportedFormats() { for _, fmt := range SupportedFormats() {
if str == string(fmt) { if str == string(fmt) {
*f = Format(str) *f = Format(str)
return nil return nil
} }
} }
return &ErrUnsupportedFormat{str}
return &UnsupportedFormatError{str}
} }
// Список всех поддерживаемых форматов экспорта // Список всех поддерживаемых форматов экспорта
@ -108,9 +110,11 @@ func (opts Options) App() string {
if opts.EnableXvfb { if opts.EnableXvfb {
return "xvfb-run" return "xvfb-run"
} }
if len(opts.Application) == 0 { if len(opts.Application) == 0 {
return "drawio" return "drawio"
} }
return opts.Application return opts.Application
} }
@ -120,6 +124,7 @@ func (opts Options) OutDir() string {
if len(out) == 0 { if len(out) == 0 {
out = "export" out = "export"
} }
return out return out
} }
@ -129,12 +134,14 @@ func (opts Options) OutExt() string {
if len(fmt) == 0 { if len(fmt) == 0 {
fmt = Format("pdf") fmt = Format("pdf")
} }
return fmt.ext() return fmt.ext()
} }
// Аргументы командной строки drawio // Аргументы командной строки drawio
func (opts Options) Args() []string { func (opts Options) Args() []string {
args := []string{} args := []string{}
if opts.EnableXvfb { if opts.EnableXvfb {
var app string var app string
if len(opts.Application) == 0 { if len(opts.Application) == 0 {
@ -142,49 +149,63 @@ func (opts Options) Args() []string {
} else { } else {
app = opts.Application app = opts.Application
} }
args = append(args, "-a", "-l", app) args = append(args, "-a", "-l", app)
} }
if len(opts.Format) > 0 { if len(opts.Format) > 0 {
args = append(args, "--format", string(opts.Format)) args = append(args, "--format", string(opts.Format))
} }
if opts.Quality != 0 { if opts.Quality != 0 {
args = append(args, "--quality", strconv.Itoa(int(opts.Quality))) args = append(args, "--quality", strconv.Itoa(int(opts.Quality)))
} }
if opts.Transparent { if opts.Transparent {
args = append(args, "--transparent") args = append(args, "--transparent")
} }
if opts.EmbedDiagram { if opts.EmbedDiagram {
args = append(args, "--embed-diagram") args = append(args, "--embed-diagram")
} }
if opts.EmbedSvgImages { if opts.EmbedSvgImages {
args = append(args, "--embed-svg-images") args = append(args, "--embed-svg-images")
} }
if opts.Border != 0 { if opts.Border != 0 {
args = append(args, "--border", strconv.Itoa(int(opts.Border))) args = append(args, "--border", strconv.Itoa(int(opts.Border)))
} }
if opts.Scale != 0 { if opts.Scale != 0 {
args = append(args, "--scale", strconv.Itoa(int(opts.Scale))) args = append(args, "--scale", strconv.Itoa(int(opts.Scale)))
} }
if opts.Width != 0 { if opts.Width != 0 {
args = append(args, "--width", strconv.Itoa(int(opts.Width))) args = append(args, "--width", strconv.Itoa(int(opts.Width)))
} }
if opts.Height != 0 { if opts.Height != 0 {
args = append(args, "--height", strconv.Itoa(int(opts.Height))) args = append(args, "--height", strconv.Itoa(int(opts.Height)))
} }
if opts.Crop { if opts.Crop {
args = append(args, "--crop") args = append(args, "--crop")
} }
if opts.Uncompressed { if opts.Uncompressed {
args = append(args, "--uncompressed") args = append(args, "--uncompressed")
} }
if opts.EnablePlugins { if opts.EnablePlugins {
args = append(args, "--enable-plugins") args = append(args, "--enable-plugins")
} }
return args return args
} }
// Путь к приложению drawio // Путь к приложению drawio
func WithAppPath(path string) Option { func WithAppPath(path string) optionApplication {
return optionApplication(path) return optionApplication(path)
} }
@ -197,7 +218,7 @@ func (opt optionApplication) apply(opts *Options) {
} }
// Запускать drawio внутри xvfb-run // Запускать drawio внутри xvfb-run
func WithXvfb() Option { func WithXvfb() optionXvfb {
return 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) 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 return format
} }
var _ Option = (*Format)(nil) // Проверка реализации интерфейса var _ Option = (*Format)(nil) // Проверка реализации интерфейса
func (opt Format) apply(opts *Options) { func (f Format) apply(opts *Options) {
opts.Format = opt opts.Format = f
} }
// Рекурсивно сканировать вложенные папки с файлами // Рекурсивно сканировать вложенные папки с файлами
func WithRecursive() Option { func WithRecursive() optionRecursive {
return optionRecursive{} return optionRecursive{}
} }
@ -247,7 +268,7 @@ func (opt optionRecursive) apply(opts *Options) {
} }
// Удалять суффикс страницы, если это возможно // Удалять суффикс страницы, если это возможно
func WithRemovePageSuffix() Option { func WithRemovePageSuffix() optionRemovePageSuffix {
return optionRemovePageSuffix{} return optionRemovePageSuffix{}
} }
@ -260,7 +281,7 @@ func (opt optionRemovePageSuffix) apply(opts *Options) {
} }
// Качество экспортированного изображения (только для JPEG) // Качество экспортированного изображения (только для JPEG)
func WithQuality(q uint) Option { func WithQuality(q uint) optionQuality {
return optionQuality(q) return optionQuality(q)
} }
@ -273,7 +294,7 @@ func (opt optionQuality) apply(opts *Options) {
} }
// Прозрачный фона для PNG // Прозрачный фона для PNG
func WithTransparent() Option { func WithTransparent() optionTransparent {
return optionTransparent{} return optionTransparent{}
} }
@ -286,7 +307,7 @@ func (opt optionTransparent) apply(opts *Options) {
} }
// Включать копию диаграммы в экспортированный файл для PDF, PNG и SVG // Включать копию диаграммы в экспортированный файл для PDF, PNG и SVG
func WithEmbedDiagram() Option { func WithEmbedDiagram() optionEmbedDiagram {
return optionEmbedDiagram{} return optionEmbedDiagram{}
} }
@ -299,7 +320,7 @@ func (opt optionEmbedDiagram) apply(opts *Options) {
} }
// Встраивать изображения в файл формата SVG // Встраивать изображения в файл формата SVG
func WithEmbedSvgImages() Option { func WithEmbedSvgImages() optionEmbedSvgImages {
return 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) 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) 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) 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) return optionHeight(height)
} }
@ -364,7 +385,7 @@ func (opt optionHeight) apply(opts *Options) {
} }
// Обрезать результирующий PDF до размера диаграммы // Обрезать результирующий PDF до размера диаграммы
func WithCrop() Option { func WithCrop() optionCrop {
return optionCrop{} return optionCrop{}
} }
@ -377,7 +398,7 @@ func (opt optionCrop) apply(opts *Options) {
} }
// Выводить несжатый XML // Выводить несжатый XML
func WithUncompressed() Option { func WithUncompressed() optionUncompressed {
return optionUncompressed{} return optionUncompressed{}
} }
@ -390,7 +411,7 @@ func (opt optionUncompressed) apply(opts *Options) {
} }
// Включить подключаемые модули // Включить подключаемые модули
func WithEnablePlugins() Option { func WithEnablePlugins() optionEnablePlugins {
return 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} 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} return optionReadDir{readDir}
} }
@ -433,7 +454,7 @@ func (opt optionReadDir) apply(opts *Options) {
} }
// Пустой параметр // Пустой параметр
func WithNop() Option { func WithNop() optionNop {
return optionNop{} return optionNop{}
} }
@ -441,6 +462,6 @@ type optionNop struct{}
var _ Option = optionNop{} var _ Option = optionNop{}
func (opt optionNop) apply(opts *Options) { func (opt optionNop) apply(_ *Options) {
// Не требуется действий, так как это пустой параметр // Не требуется действий, так как это пустой параметр
} }

View File

@ -3,7 +3,7 @@ package drawio_test
import ( import (
"testing" "testing"
"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" "git.mousesoft.ru/ms/drawio-export/pkg/drawio"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -52,7 +52,7 @@ func TestFormat(t *testing.T) {
}, },
{ {
name: "svvg", name: "svvg",
err: drawio.ErrUnsupportedFormat{"svvg"}, err: drawio.UnsupportedFormatError{"svvg"},
format: drawio.Format(""), format: drawio.Format(""),
ext: "", ext: "",
}, },

108
report.xml Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="5.0">
<file name="cmd/drawio-export/main.go">
<error column="2" line="8" message="import &#39;git.mousesoft.ru/ms/drawio-exporter/pkg/drawio&#39; is not allowed from list &#39;Main&#39;" severity="error" source="depguard"></error>
<error column="3" line="23" message="use of `fmt.Println` forbidden by pattern `^(fmt\.Print(|f|ln)|print|println)$`" severity="error" source="forbidigo"></error>
<error column="2" line="12" message="appname is a global variable" severity="error" source="gochecknoglobals"></error>
</file>
<file name="cmd/drawio-export/options.go">
<error column="2" line="6" message="import &#39;git.mousesoft.ru/ms/drawio-exporter/pkg/drawio&#39; is not allowed from list &#39;Main&#39;" severity="error" source="depguard"></error>
<error column="21" line="13" message="drawio.Options is missing fields Application, EnableXvfb, Output, Format, Recursive, RemovePageSuffix, Quality, Transparent, EmbedDiagram, EmbedSvgImages, Border, Scale, Width, Height, Crop, Uncompressed, EnablePlugins" severity="error" source="exhaustruct"></error>
<error column="0" line="16" message="Function &#39;init&#39; is too long (65 &gt; 60)" severity="error" source="funlen"></error>
<error column="2" line="10" message="flagHelp is a global variable" severity="error" source="gochecknoglobals"></error>
<error column="2" line="11" message="flagVersion is a global variable" severity="error" source="gochecknoglobals"></error>
<error column="2" line="12" message="flagIgnoreErrors is a global variable" severity="error" source="gochecknoglobals"></error>
<error column="2" line="13" message="opts is a global variable" severity="error" source="gochecknoglobals"></error>
<error column="1" line="16" message="don&#39;t use `init` function" severity="error" source="gochecknoinits"></error>
<error column="41" line="18" message="string `Prints version information` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="46" line="21" message="string `Ignore Draw.IO errors` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="45" line="24" message="string `Draw.io Desktop Application` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="45" line="27" message="string `Run drawio inside xvfb-run` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="40" line="30" message="string `Exported folder name [default: export]` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="3" line="34" message="string `Exported format [default: pdf] [possible values: pdf, png, jpg, svg, vsdx, xml]` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="3" line="39" message="string `For a folder input, recursively convert all files in sub-folders also` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="38" line="46" message="string `Output image quality for JPEG [default: 90]` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="46" line="49" message="string `Set transparent background for PNG` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="3" line="53" message="string `Includes a copy of the diagram for PDF, PNG, or SVG` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="3" line="60" message="string `Sets the border width around the diagram [default: 0]` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="36" line="64" message="string `Scales the diagram size` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="47" line="75" message="string `Uncompressed XML output` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="38" line="80" message="string `Prints help information` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
</file>
<file name="pkg/drawio/execution.go">
<error column="0" line="1" message="Missed header for check" severity="error" source="goheader"></error>
<error column="2" line="19" message="return with no blank line before" severity="error" source="nlreturn"></error>
<error column="2" line="14" message="ranges should only be cuddled with assignments used in the iteration" severity="error" source="wsl"></error>
<error column="2" line="19" message="return statements should not be cuddled if block has more than two lines" severity="error" source="wsl"></error>
</file>
<file name="pkg/drawio/export.go">
<error column="2" line="14" message="import &#39;github.com/tamerh/xml-stream-parser&#39; is not allowed from list &#39;Main&#39;" severity="error" source="depguard"></error>
<error column="14" line="19" message="drawio.Options is missing fields EnableXvfb, Recursive, RemovePageSuffix, Quality, Transparent, EmbedDiagram, EmbedSvgImages, Border, Scale, Width, Height, Crop, Uncompressed, EnablePlugins, openFile, readDir" severity="error" source="exhaustruct"></error>
<error column="9" line="32" message="drawio.Exporter is missing fields openFile, readDir" severity="error" source="exhaustruct"></error>
<error column="23" line="22" message="string `pdf` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="25" line="176" message="string `diagram` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="17" line="41" message="unlambda: replace `func(name string) ([]os.DirEntry, error) {&#xA;&#x9;return os.ReadDir(name)&#xA;}` with `os.ReadDir`" severity="error" source="gocritic"></error>
<error column="0" line="1" message="Missed header for check" severity="error" source="goheader"></error>
<error column="53" line="152" message="Magic number: 10, in &lt;argument&gt; detected" severity="error" source="mnd"></error>
<error column="2" line="27" message="return with no blank line before" severity="error" source="nlreturn"></error>
<error column="2" line="47" message="return with no blank line before" severity="error" source="nlreturn"></error>
<error column="4" line="69" message="continue with no blank line before" severity="error" source="nlreturn"></error>
<error column="6" line="146" message="variable name &#39;i&#39; is too short for the scope of its usage" severity="error" source="varnamelen"></error>
<error column="2" line="66" message="ranges should only be cuddled with assignments used in the iteration" severity="error" source="wsl"></error>
<error column="3" line="71" message="declarations should never be cuddled" severity="error" source="wsl"></error>
<error column="3" line="72" message="only one cuddle assignment allowed before if statement" severity="error" source="wsl"></error>
<error column="3" line="77" message="append only allowed to cuddle with appended value" severity="error" source="wsl"></error>
<error column="3" line="78" message="only one cuddle assignment allowed before if statement" severity="error" source="wsl"></error>
<error column="2" line="82" message="if statements should only be cuddled with assignments" severity="error" source="wsl"></error>
<error column="2" line="85" message="return statements should not be cuddled if block has more than two lines" severity="error" source="wsl"></error>
<error column="2" line="101" message="only one cuddle assignment allowed before range statement" severity="error" source="wsl"></error>
<error column="3" line="103" message="declarations should never be cuddled" severity="error" source="wsl"></error>
<error column="3" line="104" message="only one cuddle assignment allowed before if statement" severity="error" source="wsl"></error>
<error column="3" line="117" message="append only allowed to cuddle with appended value" severity="error" source="wsl"></error>
<error column="2" line="138" message="only one cuddle assignment allowed before defer statement" severity="error" source="wsl"></error>
<error column="2" line="139" message="if statements should only be cuddled with assignments" severity="error" source="wsl"></error>
<error column="2" line="142" message="assignments should only be cuddled with other assignments" severity="error" source="wsl"></error>
<error column="2" line="146" message="only one cuddle assignment allowed before range statement" severity="error" source="wsl"></error>
<error column="3" line="151" message="assignments should only be cuddled with other assignments" severity="error" source="wsl"></error>
<error column="3" line="163" message="assignments should only be cuddled with other assignments" severity="error" source="wsl"></error>
<error column="2" line="166" message="return statements should not be cuddled if block has more than two lines" severity="error" source="wsl"></error>
<error column="2" line="178" message="ranges should only be cuddled with assignments used in the iteration" severity="error" source="wsl"></error>
<error column="3" line="182" message="if statements should only be cuddled with assignments" severity="error" source="wsl"></error>
</file>
<file name="pkg/drawio/options.go">
<error column="1" line="136" message="calculated cyclomatic complexity for function Args is 15, max is 10" severity="error" source="cyclop"></error>
<error column="6" line="17" message="the type name `ErrUnsupportedFormat` should conform to the `XxxError` format" severity="error" source="errname"></error>
<error column="16" line="414" message="drawio.optionOpenFile is missing field openFile" severity="error" source="exhaustruct"></error>
<error column="16" line="429" message="drawio.optionReadDir is missing field readDir" severity="error" source="exhaustruct"></error>
<error column="10" line="112" message="string `drawio` has 2 occurrences, make it a constant" severity="error" source="goconst"></error>
<error column="2" line="28" message="singleCaseSwitch: should rewrite switch statement to if statement" severity="error" source="gocritic"></error>
<error column="0" line="1" message="Missed header for check" severity="error" source="goheader"></error>
<error column="14" line="77" message="fieldalignment: struct of size 136 could be 120" severity="error" source="govet"></error>
<error column="1" line="187" message="WithAppPath returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="200" message="WithXvfb returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="213" message="WithOutput returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="226" message="WithFormat returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="237" message="WithRecursive returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="250" message="WithRemovePageSuffix returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="263" message="WithQuality returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="276" message="WithTransparent returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="289" message="WithEmbedDiagram returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="302" message="WithEmbedSvgImages returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="315" message="WithBorder returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="328" message="WithScale returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="341" message="WithWidth returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="354" message="WithHeight returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="367" message="WithCrop returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="380" message="WithUncompressed returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="393" message="WithEnablePlugins returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="406" message="WithOpenFile returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="421" message="WithReadDir returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="436" message="WithNop returns interface (git.mousesoft.ru/ms/drawio-exporter/pkg/drawio.Option)" severity="error" source="ireturn"></error>
<error column="1" line="232" message="receiver-naming: receiver name opt should be consistent with previous receiver name f for Format" severity="warning" source="revive"></error>
<error column="28" line="444" message="unused-parameter: parameter &#39;opts&#39; seems to be unused, consider removing or renaming it as _" severity="warning" source="revive"></error>
<error column="18" line="54" message="ST1016: methods on the same type should have the same receiver name (seen 1x &#34;opt&#34;, 3x &#34;f&#34;)" severity="error" source="stylecheck"></error>
<error column="2" line="138" message="if statements should only be cuddled with assignments used in the if statement itself" severity="error" source="wsl"></error>
<error column="3" line="145" message="append only allowed to cuddle with appended value" severity="error" source="wsl"></error>
</file>
</checkstyle>