diff --git a/go.mod b/go.mod index 4c6f851..7d17c3a 100644 --- a/go.mod +++ b/go.mod @@ -13,18 +13,18 @@ require ( github.com/reconquest/pkg v1.3.1-0.20240901105413-68c2adbf2b64 github.com/reconquest/regexputil-go v0.0.0-20160905154124-38573e70c1f4 github.com/stretchr/testify v1.10.0 - github.com/urfave/cli/v2 v2.27.6 + github.com/urfave/cli-altsrc/v3 v3.0.1 + github.com/urfave/cli/v3 v3.3.3 github.com/yuin/goldmark v1.7.12 golang.org/x/tools v0.33.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/BurntSushi/toml v1.4.0 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect github.com/chromedp/cdproto v0.0.0-20250319231242-a755498943c8 // indirect github.com/chromedp/chromedp v0.13.3 // indirect github.com/chromedp/sysutil v1.1.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535 // indirect github.com/gobwas/httphead v0.1.0 // indirect @@ -33,8 +33,6 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/reconquest/cog v0.0.0-20240830113510-c7ba12d0beeb // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/zazab/zhash v0.0.0-20221031090444-2b0d50417446 // indirect golang.org/x/sys v0.33.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect diff --git a/go.sum b/go.sum index 112f9a3..dcd922b 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Shopify/toxiproxy/v2 v2.12.0 h1:d1x++lYZg/zijXPPcv7PH0MvHMzEI5aX/YuUi/Sw+yg= github.com/Shopify/toxiproxy/v2 v2.12.0/go.mod h1:R9Z38Pw6k2cGZWXHe7tbxjGW9azmY1KbDQJ1kd+h7Tk= github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= @@ -10,8 +10,6 @@ github.com/chromedp/chromedp v0.13.3 h1:c6nTn97XQBykzcXiGYL5LLebw3h3CEyrCihm4Hqu github.com/chromedp/chromedp v0.13.3/go.mod h1:khsDP9OP20GrowpJfZ7N05iGCwcAYxk7qf9AZBzR3Qw= github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM= github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8= -github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -50,14 +48,12 @@ github.com/reconquest/regexputil-go v0.0.0-20160905154124-38573e70c1f4 h1:bcDXaT github.com/reconquest/regexputil-go v0.0.0-20160905154124-38573e70c1f4/go.mod h1:OI1di2iiFSwX3D70iZjzdmCPPfssjOl+HX40tI3VaXA= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= -github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= -github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/urfave/cli-altsrc/v3 v3.0.1 h1:v+gHk59syLk8ao9rYybZs43+D5ut/gzj0omqQ1XYl8k= +github.com/urfave/cli-altsrc/v3 v3.0.1/go.mod h1:8UtsKKcxFVzvaoySFPfvQOk413T+IXJhaCWyyoPW3yM= +github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I= +github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY= github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/zazab/zhash v0.0.0-20221031090444-2b0d50417446 h1:75pcOSsb40+ub185cJI7g5uykl9Uu76rD5ONzK/4s40= diff --git a/main.go b/main.go index ee71d40..faace92 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,12 @@ package main import ( + "context" "os" "github.com/kovetskiy/mark/util" "github.com/reconquest/pkg/log" - "github.com/urfave/cli/v2" - "github.com/urfave/cli/v2/altsrc" + "github.com/urfave/cli/v3" ) const ( @@ -16,32 +16,18 @@ const ( ) func main() { - app := &cli.App{ + cmd := &cli.Command{ Name: "mark", Usage: usage, Description: description, Version: version, Flags: util.Flags, - Before: altsrc.InitInputSourceWithContext(util.Flags, - func(context *cli.Context) (altsrc.InputSourceContext, error) { - if context.IsSet("config") { - filePath := context.String("config") - return altsrc.NewTomlSourceFromFile(filePath) - } else { - // Fall back to default if config is unset and path exists - _, err := os.Stat(util.ConfigFilePath()) - if os.IsNotExist(err) { - return &altsrc.MapInputSource{}, nil - } - return altsrc.NewTomlSourceFromFile(util.ConfigFilePath()) - } - }), - EnableBashCompletion: true, - HideHelpCommand: true, - Action: util.RunMark, + EnableShellCompletion: true, + HideHelpCommand: true, + Action: util.RunMark, } - if err := app.Run(os.Args); err != nil { + if err := cmd.Run(context.TODO(), os.Args); err != nil { log.Fatal(err) } } diff --git a/main_test.go b/main_test.go index 29f6f76..a011396 100644 --- a/main_test.go +++ b/main_test.go @@ -1,13 +1,12 @@ package main import ( - "flag" "testing" "github.com/kovetskiy/mark/util" "github.com/reconquest/pkg/log" "github.com/stretchr/testify/assert" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) func Test_setLogLevel(t *testing.T) { @@ -30,11 +29,17 @@ func Test_setLogLevel(t *testing.T) { } for name, tt := range tests { t.Run(name, func(t *testing.T) { - set := flag.NewFlagSet("test", flag.ContinueOnError) - set.String("log-level", tt.args.lvl, "") - cliCtx := cli.NewContext(nil, set, nil) - - err := util.SetLogLevel(cliCtx) + cmd := &cli.Command{ + Name: "test", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "log-level", + Value: tt.args.lvl, + Usage: "set the log level. Possible values: TRACE, DEBUG, INFO, WARNING, ERROR, FATAL.", + }, + }, + } + err := util.SetLogLevel(cmd) if tt.expectedErr != "" { assert.EqualError(t, err, tt.expectedErr) } else { diff --git a/markdown/markdown_test.go b/markdown/markdown_test.go index 8fa0fc2..85059f7 100644 --- a/markdown/markdown_test.go +++ b/markdown/markdown_test.go @@ -1,6 +1,7 @@ package mark_test import ( + "context" "os" "path" "path/filepath" @@ -12,8 +13,7 @@ import ( "github.com/kovetskiy/mark/stdlib" "github.com/kovetskiy/mark/util" "github.com/stretchr/testify/assert" - "github.com/urfave/cli/v2" - "github.com/urfave/cli/v2/altsrc" + "github.com/urfave/cli/v3" ) func loadData(t *testing.T, filename, variant string) ([]byte, string, []byte) { @@ -128,29 +128,15 @@ func TestCompileMarkdownStripNewlines(t *testing.T) { } func TestContinueOnError(t *testing.T) { - app := &cli.App{ - Name: "temp-mark", - Usage: "test usage", - Description: "mark unit tests", - Version: "TEST-VERSION", - Flags: util.Flags, - Before: altsrc.InitInputSourceWithContext(util.Flags, - func(context *cli.Context) (altsrc.InputSourceContext, error) { - if context.IsSet("config") { - filePath := context.String("config") - return altsrc.NewTomlSourceFromFile(filePath) - } else { - // Fall back to default if config is unset and path exists - _, err := os.Stat(util.ConfigFilePath()) - if os.IsNotExist(err) { - return &altsrc.MapInputSource{}, nil - } - return altsrc.NewTomlSourceFromFile(util.ConfigFilePath()) - } - }), - EnableBashCompletion: true, - HideHelpCommand: true, - Action: util.RunMark, + cmd := &cli.Command{ + Name: "temp-mark", + Usage: "test usage", + Description: "mark unit tests", + Version: "TEST-VERSION", + Flags: util.Flags, + EnableShellCompletion: true, + HideHelpCommand: true, + Action: util.RunMark, } filePath := filepath.Join("testdata", "batch-tests", "*.md") @@ -162,6 +148,6 @@ func TestContinueOnError(t *testing.T) { "--files", filePath, } - err := app.Run(argList) + err := cmd.Run(context.TODO(), argList) assert.NoError(t, err, "App should run without errors when continue-on-error is enabled") } diff --git a/util/cli.go b/util/cli.go index 84b3ed6..7487024 100644 --- a/util/cli.go +++ b/util/cli.go @@ -2,6 +2,7 @@ package util import ( "bytes" + "context" "crypto/sha1" "encoding/hex" "fmt" @@ -25,15 +26,15 @@ import ( "github.com/kovetskiy/mark/vfs" "github.com/reconquest/karma-go" "github.com/reconquest/pkg/log" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) -func RunMark(cCtx *cli.Context) error { - if err := SetLogLevel(cCtx); err != nil { +func RunMark(ctx context.Context, cmd *cli.Command) error { + if err := SetLogLevel(cmd); err != nil { return err } - if cCtx.String("color") == "never" { + if cmd.String("color") == "never" { log.GetLogger().SetFormat( lorg.NewFormat( `${time:2006-01-02 15:04:05.000} ${level:%s:left:true} ${prefix}%s`, @@ -42,20 +43,20 @@ func RunMark(cCtx *cli.Context) error { log.GetLogger().SetOutput(os.Stderr) } - creds, err := GetCredentials(cCtx.String("username"), cCtx.String("password"), cCtx.String("target-url"), cCtx.String("base-url"), cCtx.Bool("compile-only")) + creds, err := GetCredentials(cmd.String("username"), cmd.String("password"), cmd.String("target-url"), cmd.String("base-url"), cmd.Bool("compile-only")) if err != nil { return err } api := confluence.NewAPI(creds.BaseURL, creds.Username, creds.Password) - files, err := doublestar.FilepathGlob(cCtx.String("files")) + files, err := doublestar.FilepathGlob(cmd.String("files")) if err != nil { return err } if len(files) == 0 { msg := "No files matched" - if cCtx.Bool("ci") { + if cmd.Bool("ci") { log.Warning(msg) } else { log.Fatal(msg) @@ -63,16 +64,16 @@ func RunMark(cCtx *cli.Context) error { } log.Debug("config:") - for _, f := range cCtx.Command.Flags { + for _, f := range cmd.Flags { flag := f.Names() if flag[0] == "password" { log.Debugf(nil, "%20s: %v", flag[0], "******") } else { - log.Debugf(nil, "%20s: %v", flag[0], cCtx.Value(flag[0])) + log.Debugf(nil, "%20s: %v", flag[0], cmd.Value(flag[0])) } } - fatalErrorHandler := NewErrorHandler(cCtx.Bool("continue-on-error")) + fatalErrorHandler := NewErrorHandler(cmd.Bool("continue-on-error")) // Loop through files matched by glob pattern for _, file := range files { @@ -82,7 +83,7 @@ func RunMark(cCtx *cli.Context) error { file, ) - target := processFile(file, api, cCtx, creds.PageID, creds.Username, fatalErrorHandler) + target := processFile(file, api, cmd, creds.PageID, creds.Username, fatalErrorHandler) if target != nil { // on dry-run or compile-only, the target is nil log.Infof( @@ -99,7 +100,7 @@ func RunMark(cCtx *cli.Context) error { func processFile( file string, api *confluence.API, - cCtx *cli.Context, + cmd *cli.Command, pageID string, username string, fatalErrorHandler *FatalErrorHandler, @@ -112,9 +113,9 @@ func processFile( markdown = bytes.ReplaceAll(markdown, []byte("\r\n"), []byte("\n")) - parents := strings.Split(cCtx.String("parents"), cCtx.String("parents-delimiter")) + parents := strings.Split(cmd.String("parents"), cmd.String("parents-delimiter")) - meta, markdown, err := metadata.ExtractMeta(markdown, cCtx.String("space"), cCtx.Bool("title-from-h1"), parents, cCtx.Bool("title-append-generated-hash")) + meta, markdown, err := metadata.ExtractMeta(markdown, cmd.String("space"), cmd.Bool("title-from-h1"), parents, cmd.Bool("title-append-generated-hash")) if err != nil { fatalErrorHandler.Handle(err, "unable to extract metadata from file %q", file) return nil @@ -159,7 +160,7 @@ func processFile( for { templates, markdown, recurse, err = includes.ProcessIncludes( filepath.Dir(file), - cCtx.String("include-path"), + cmd.String("include-path"), markdown, templates, ) @@ -175,7 +176,7 @@ func processFile( macros, markdown, err := macro.ExtractMacros( filepath.Dir(file), - cCtx.String("include-path"), + cmd.String("include-path"), markdown, templates, ) @@ -194,7 +195,7 @@ func processFile( } } - links, err := page.ResolveRelativeLinks(api, meta, markdown, filepath.Dir(file), cCtx.String("space"), cCtx.Bool("title-from-h1"), parents, cCtx.Bool("title-append-generated-hash")) + links, err := page.ResolveRelativeLinks(api, meta, markdown, filepath.Dir(file), cmd.String("space"), cmd.Bool("title-from-h1"), parents, cmd.Bool("title-append-generated-hash")) if err != nil { fatalErrorHandler.Handle(err, "unable to resolve relative links") return nil @@ -202,21 +203,21 @@ func processFile( markdown = page.SubstituteLinks(markdown, links) - if cCtx.Bool("dry-run") { - _, _, err := page.ResolvePage(cCtx.Bool("dry-run"), api, meta) + if cmd.Bool("dry-run") { + _, _, err := page.ResolvePage(cmd.Bool("dry-run"), api, meta) if err != nil { fatalErrorHandler.Handle(err, "unable to resolve page location") return nil } } - if cCtx.Bool("compile-only") || cCtx.Bool("dry-run") { - if cCtx.Bool("drop-h1") { + if cmd.Bool("compile-only") || cmd.Bool("dry-run") { + if cmd.Bool("drop-h1") { log.Info( "the leading H1 heading will be excluded from the Confluence output", ) } - html, _ := mark.CompileMarkdown(markdown, stdlib, file, cCtx.String("mermaid-provider"), cCtx.Float64("mermaid-scale"), cCtx.Bool("drop-h1"), cCtx.Bool("strip-linebreaks")) + html, _ := mark.CompileMarkdown(markdown, stdlib, file, cmd.String("mermaid-provider"), cmd.Float("mermaid-scale"), cmd.Bool("drop-h1"), cmd.Bool("strip-linebreaks")) fmt.Println(html) return nil } @@ -224,7 +225,7 @@ func processFile( var target *confluence.PageInfo if meta != nil { - parent, page, err := page.ResolvePage(cCtx.Bool("dry-run"), api, meta) + parent, page, err := page.ResolvePage(cmd.Bool("dry-run"), api, meta) if err != nil { fatalErrorHandler.Handle(karma.Describe("title", meta.Title).Reason(err), "unable to resolve %s", meta.Type) return nil @@ -283,13 +284,13 @@ func processFile( markdown = attachment.CompileAttachmentLinks(markdown, attaches) - if cCtx.Bool("drop-h1") { + if cmd.Bool("drop-h1") { log.Info( "the leading H1 heading will be excluded from the Confluence output", ) } - html, inlineAttachments := mark.CompileMarkdown(markdown, stdlib, file, cCtx.String("mermaid-provider"), cCtx.Float64("mermaid-scale"), cCtx.Bool("drop-h1"), cCtx.Bool("strip-linebreaks")) + html, inlineAttachments := mark.CompileMarkdown(markdown, stdlib, file, cmd.String("mermaid-provider"), cmd.Float("mermaid-scale"), cmd.Bool("drop-h1"), cmd.Bool("strip-linebreaks")) // Resolve attachements detected from markdown _, err = attachment.ResolveAttachments( @@ -329,7 +330,7 @@ func processFile( var finalVersionMessage string var shouldUpdatePage = true - if cCtx.Bool("changes-only") { + if cmd.Bool("changes-only") { contentHash := getSHA1Hash(html) log.Debugf( @@ -360,13 +361,13 @@ func processFile( } } - finalVersionMessage = fmt.Sprintf("%s [v%s]", cCtx.String("version-message"), contentHash) + finalVersionMessage = fmt.Sprintf("%s [v%s]", cmd.String("version-message"), contentHash) } else { - finalVersionMessage = cCtx.String("version-message") + finalVersionMessage = cmd.String("version-message") } if shouldUpdatePage { - err = api.UpdatePage(target, html, cCtx.Bool("minor-edit"), finalVersionMessage, meta.Labels, meta.ContentAppearance, meta.Emoji) + err = api.UpdatePage(target, html, cmd.Bool("minor-edit"), finalVersionMessage, meta.Labels, meta.ContentAppearance, meta.Emoji) if err != nil { fatalErrorHandler.Handle(err, "unable to update page") return nil @@ -377,7 +378,7 @@ func processFile( return nil } - if cCtx.Bool("edit-lock") { + if cmd.Bool("edit-lock") { log.Infof( nil, `edit locked on page %q by user %q to prevent manual edits`, @@ -467,8 +468,8 @@ func ConfigFilePath() string { return filepath.Join(fp, "mark") } -func SetLogLevel(cCtx *cli.Context) error { - logLevel := cCtx.String("log-level") +func SetLogLevel(cmd *cli.Command) error { + logLevel := cmd.String("log-level") switch strings.ToUpper(logLevel) { case lorg.LevelTrace.String(): log.SetLevel(lorg.LevelTrace) diff --git a/util/flags.go b/util/flags.go index 81e673f..e7db36b 100644 --- a/util/flags.go +++ b/util/flags.go @@ -1,178 +1,187 @@ package util import ( - "github.com/urfave/cli/v2" - "github.com/urfave/cli/v2/altsrc" + altsrc "github.com/urfave/cli-altsrc/v3" + altsrctoml "github.com/urfave/cli-altsrc/v3/toml" + "github.com/urfave/cli/v3" ) +var filename = ConfigFilePath() + +var configFile = altsrc.NewStringPtrSourcer(&filename) + var Flags = []cli.Flag{ - altsrc.NewStringFlag(&cli.StringFlag{ + &cli.StringFlag{ Name: "files", Aliases: []string{"f"}, Value: "", Usage: "use specified markdown file(s) for converting to html. Supports file globbing patterns (needs to be quoted).", TakesFile: true, - EnvVars: []string{"MARK_FILES"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_FILES"), altsrctoml.TOML("files", configFile)), + }, + &cli.BoolFlag{ Name: "continue-on-error", Value: false, Usage: "don't exit if an error occurs while processing a file, continue processing remaining files.", - EnvVars: []string{"MARK_CONTINUE_ON_ERROR"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_CONTINUE_ON_ERROR"), altsrctoml.TOML("continue_on_error", configFile)), + }, + &cli.BoolFlag{ Name: "compile-only", Value: false, Usage: "show resulting HTML and don't update Confluence page content.", - EnvVars: []string{"MARK_COMPILE_ONLY"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_COMPILE_ONLY"), altsrctoml.TOML("compile_only", configFile)), + }, + &cli.BoolFlag{ Name: "dry-run", Value: false, Usage: "resolve page and ancestry, show resulting HTML and exit.", - EnvVars: []string{"MARK_DRY_RUN"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_DRY_RUN"), altsrctoml.TOML("dry_run", configFile)), + }, + &cli.BoolFlag{ Name: "edit-lock", Value: false, Aliases: []string{"k"}, Usage: "lock page editing to current user only to prevent accidental manual edits over Confluence Web UI.", - EnvVars: []string{"MARK_EDIT_LOCK"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_EDIT_LOCK"), altsrctoml.TOML("edit_lock", configFile)), + }, + &cli.BoolFlag{ Name: "drop-h1", Value: false, Aliases: []string{"h1_drop"}, Usage: "don't include the first H1 heading in Confluence output.", - EnvVars: []string{"MARK_H1_DROP"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_H1_DROP"), altsrctoml.TOML("drop_h1", configFile)), + }, + &cli.BoolFlag{ Name: "strip-linebreaks", Value: false, Aliases: []string{"L"}, Usage: "remove linebreaks inside of tags, to accomodate non-standard Confluence behavior", - EnvVars: []string{"MARK_STRIP_LINEBREAKS"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_STRIP_LINEBREAKS"), altsrctoml.TOML("strip_linebreaks", configFile)), + }, + &cli.BoolFlag{ Name: "title-from-h1", Value: false, Aliases: []string{"h1_title"}, Usage: "extract page title from a leading H1 heading. If no H1 heading on a page exists, then title must be set in the page metadata.", - EnvVars: []string{"MARK_H1_TITLE"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_H1_TITLE"), altsrctoml.TOML("title_from_h1", configFile)), + }, + &cli.BoolFlag{ Name: "title-append-generated-hash", Value: false, Usage: "appends a short hash generated from the path of the page (space, parents, and title) to the title", - EnvVars: []string{"MARK_TITLE_APPEND_GENERATED_HASH"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_TITLE_APPEND_GENERATED_HASH"), altsrctoml.TOML("title_append_generated_hash", configFile)), + }, + &cli.BoolFlag{ Name: "minor-edit", Value: false, Usage: "don't send notifications while updating Confluence page.", - EnvVars: []string{"MARK_MINOR_EDIT"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_MINOR_EDIT"), altsrctoml.TOML("minor_edit", configFile)), + }, + &cli.StringFlag{ Name: "version-message", Value: "", Usage: "add a message to the page version, to explain the edit (default: \"\")", - EnvVars: []string{"MARK_VERSION_MESSAGE"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ - Name: "color", - Value: "auto", - Usage: "display logs in color. Possible values: auto, never.", - EnvVars: []string{"MARK_COLOR"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_VERSION_MESSAGE"), altsrctoml.TOML("version_message", configFile)), + }, + &cli.StringFlag{ + Name: "color", + Value: "auto", + Usage: "display logs in color. Possible values: auto, never.", + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_COLOR"), + altsrctoml.TOML("color", configFile)), + }, + &cli.StringFlag{ Name: "log-level", Value: "info", Usage: "set the log level. Possible values: TRACE, DEBUG, INFO, WARNING, ERROR, FATAL.", - EnvVars: []string{"MARK_LOG_LEVEL"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_LOG_LEVEL"), altsrctoml.TOML("log_level", configFile)), + }, + &cli.StringFlag{ Name: "username", Aliases: []string{"u"}, Value: "", Usage: "use specified username for updating Confluence page.", - EnvVars: []string{"MARK_USERNAME"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_USERNAME"), + altsrctoml.TOML("username", configFile)), + }, + &cli.StringFlag{ Name: "password", Aliases: []string{"p"}, Value: "", Usage: "use specified token for updating Confluence page. Specify - as password to read password from stdin, or your Personal access token. Username is not mandatory if personal access token is provided. For more info please see: https://developer.atlassian.com/server/confluence/confluence-server-rest-api/#authentication.", - EnvVars: []string{"MARK_PASSWORD"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_PASSWORD"), altsrctoml.TOML("password", configFile)), + }, + &cli.StringFlag{ Name: "target-url", Aliases: []string{"l"}, Value: "", Usage: "edit specified Confluence page. If -l is not specified, file should contain metadata (see above).", - EnvVars: []string{"MARK_TARGET_URL"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_TARGET_URL"), altsrctoml.TOML("target_url", configFile)), + }, + &cli.StringFlag{ Name: "base-url", Aliases: []string{"b", "base_url"}, Value: "", Usage: "base URL for Confluence. Alternative option for base_url config field.", - EnvVars: []string{"MARK_BASE_URL"}, - }), + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_BASE_URL"), + altsrctoml.TOML("base_url", configFile)), + }, &cli.StringFlag{ Name: "config", Aliases: []string{"c"}, Value: ConfigFilePath(), Usage: "use the specified configuration file.", TakesFile: true, - EnvVars: []string{"MARK_CONFIG"}, + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_CONFIG")), + Destination: &filename, }, - altsrc.NewBoolFlag(&cli.BoolFlag{ + &cli.BoolFlag{ Name: "ci", Value: false, Usage: "run on CI mode. It won't fail if files are not found.", - EnvVars: []string{"MARK_CI"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_CI"), altsrctoml.TOML("ci", configFile)), + }, + &cli.StringFlag{ Name: "space", Value: "", Usage: "use specified space key. If the space key is not specified, it must be set in the page metadata.", - EnvVars: []string{"MARK_SPACE"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_SPACE"), altsrctoml.TOML("space", configFile)), + }, + &cli.StringFlag{ Name: "parents", Value: "", Usage: "A list containing the parents of the document separated by parents-delimiter (default: '/'). These will be prepended to the ones defined in the document itself.", - EnvVars: []string{"MARK_PARENTS"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_PARENTS"), altsrctoml.TOML("parents", configFile)), + }, + &cli.StringFlag{ Name: "parents-delimiter", Value: "/", Usage: "The delimiter used for the parents list", - EnvVars: []string{"MARK_PARENTS_DELIMITER"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_PARENTS_DELIMITER"), altsrctoml.TOML("parents_delimiter", configFile)), + }, + &cli.StringFlag{ Name: "mermaid-provider", Value: "cloudscript", Usage: "defines the mermaid provider to use. Supported options are: cloudscript, mermaid-go.", - EnvVars: []string{"MARK_MERMAID_PROVIDER"}, - }), - altsrc.NewFloat64Flag(&cli.Float64Flag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_MERMAID_PROVIDER"), altsrctoml.TOML("mermaid_provider", configFile)), + }, + &cli.FloatFlag{ Name: "mermaid-scale", Value: 1.0, Usage: "defines the scaling factor for mermaid renderings.", - EnvVars: []string{"MARK_MERMAID_SCALE"}, - }), - altsrc.NewStringFlag(&cli.StringFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_MERMAID_SCALE"), altsrctoml.TOML("mermaid_scale", configFile)), + }, + &cli.StringFlag{ Name: "include-path", Value: "", Usage: "Path for shared includes, used as a fallback if the include doesn't exist in the current directory.", TakesFile: true, - EnvVars: []string{"MARK_INCLUDE_PATH"}, - }), - altsrc.NewBoolFlag(&cli.BoolFlag{ + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_INCLUDE_PATH"), altsrctoml.TOML("include_path", configFile)), + }, + &cli.BoolFlag{ Name: "changes-only", Value: false, Usage: "Avoids re-uploading pages that haven't changed since the last run.", - EnvVars: []string{"MARK_CHANGES_ONLY"}, - }), + Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_CHANGES_ONLY"), altsrctoml.TOML("changes_only", configFile)), + }, }