mirror of
https://github.com/kovetskiy/mark.git
synced 2025-01-23 09:13:49 +08:00
Simplify config handling
* Switch to urfave/cli/v2 * Add more environment variables
This commit is contained in:
parent
d1f69bc704
commit
262853f6c0
58
README.md
58
README.md
@ -597,35 +597,33 @@ $ cp mark /usr/local/bin
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
mark [options] [-u <username>] [-p <password>] [-k] [-l <url>] -f <file>
|
||||
mark [options] [-u <username>] [-p <password>] [-k] [-b <url>] -f <file>
|
||||
mark [options] [-u <username>] [-p <password>] [--drop-h1] -f <file>
|
||||
mark -v | --version
|
||||
mark -h | --help
|
||||
```
|
||||
|
||||
- `-u <username>` — Use specified username for updating Confluence page.
|
||||
- `-p <password>` — Use specified password for updating Confluence page.
|
||||
Specify `-` as password to read password from stdin.
|
||||
- `-l <url>` — Edit specified Confluence page.
|
||||
If -l is not specified, file should contain metadata (see above).
|
||||
- `-b <url>` or `--base-url <url>` – Base URL for Confluence.
|
||||
Alternative option for `base_url` config field.
|
||||
- `-f <file>` — Use specified markdown file(s) for converting to html. Supports file globbing patterns (needs to be quoted).
|
||||
- `-c <path>` or `--config <path>` — Specify a path to the configuration file.
|
||||
- `-k` — Lock page editing to current user only to prevent accidental
|
||||
manual edits over Confluence Web UI.
|
||||
- `--space <space>` - Use specified space key. If the space key is not specified, it must be set in the page metadata.
|
||||
- `--drop-h1` – Don't include H1 headings in Confluence output.
|
||||
This option corresponds to the `h1_drop` setting in the configuration file.
|
||||
- `--title-from-h1` - 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.
|
||||
This option corresponds to the `h1_title` setting in the configuration file.
|
||||
- `--dry-run` — Show resulting HTML and don't update Confluence page content.
|
||||
- `--minor-edit` — Don't send notifications while updating Confluence page.
|
||||
- `--trace` — Enable trace logs.
|
||||
- `-v | --version` — Show version.
|
||||
- `-h | --help` — Show help screen and call 911.
|
||||
USAGE:
|
||||
mark [global options] [arguments...]
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--files value, -f value use specified markdown file(s) for converting to html. Supports file globbing patterns (needs to be quoted). [$MARK_FILES]
|
||||
--compile-only show resulting HTML and don't update Confluence page content. (default: false) [$MARK_COMPILE_ONLY]
|
||||
--dry-run resolve page and ancestry, show resulting HTML and exit. (default: false) [$MARK_DRY_RUN]
|
||||
--edit-lock, -k lock page editing to current user only to prevent accidental manual edits over Confluence Web UI. (default: false) [$MARK_EDIT_LOCK]
|
||||
--drop-h1 don't include H1 headings in Confluence output. (default: false) [$MARK_H1_DROP]
|
||||
--title-from-h1 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. (default: false) [$MARK_H1_TITLE]
|
||||
--minor-edit don't send notifications while updating Confluence page. (default: false) [$MARK_MINOR_EDIT]
|
||||
--color value display logs in color. Possible values: auto, never. (default: "auto") [$MARK_COLOR]
|
||||
--debug enable debug logs. (default: false) [$MARK_DEBUG]
|
||||
--trace enable trace logs. (default: false) [$MARK_TRACE]
|
||||
--username value, -u value use specified username for updating Confluence page. [$MARK_USERNAME]
|
||||
--password value, -p value 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. [$MARK_PASSWORD]
|
||||
--target-url value, -l value edit specified Confluence page. If -l is not specified, file should contain metadata (see above). [$MARK_TARGET_URL]
|
||||
--base-url value, -b value base URL for Confluence. Alternative option for base_url config field. [$MARK_BASE_URL]
|
||||
--config value, -c value use the specified configuration file. (default: "/home/mruger/.config/mark") [$MARK_CONFIG]
|
||||
--ci run on CI mode. It won't fail if files are not found. (default: false) [$MARK_CI]
|
||||
--space value use specified space key. If the space key is not specified, it must be set in the page metadata. [$MARK_SPACE]
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
|
||||
```
|
||||
|
||||
You can store user credentials in the configuration file, which should be
|
||||
located in ~/.config/mark (or specified via `-c --config <path>`) with the following format (TOML):
|
||||
@ -634,9 +632,9 @@ located in ~/.config/mark (or specified via `-c --config <path>`) with the follo
|
||||
username = "your-email"
|
||||
password = "password-or-api-key-for-confluence-cloud"
|
||||
# If you are using Confluence Cloud add the /wiki suffix to base_url
|
||||
base_url = "http://confluence.local"
|
||||
h1_title = true
|
||||
h1_drop = true
|
||||
base-url = "http://confluence.local"
|
||||
h1-title = true
|
||||
h1-drop = true
|
||||
```
|
||||
|
||||
**NOTE**: Labels aren't supported when using `minor-edit`!
|
||||
|
46
auth.go
46
auth.go
@ -18,32 +18,23 @@ type Credentials struct {
|
||||
}
|
||||
|
||||
func GetCredentials(
|
||||
flags Flags,
|
||||
config *Config,
|
||||
username string,
|
||||
password string,
|
||||
targetURL string,
|
||||
baseURL string,
|
||||
compileOnly bool,
|
||||
|
||||
) (*Credentials, error) {
|
||||
var err error
|
||||
|
||||
var (
|
||||
username = flags.Username
|
||||
password = flags.Password
|
||||
targetURL = flags.TargetURL
|
||||
)
|
||||
|
||||
if username == "" {
|
||||
username = config.Username
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
password = config.Password
|
||||
if password == "" {
|
||||
if !flags.CompileOnly {
|
||||
return nil, errors.New(
|
||||
"Confluence password should be specified using -p " +
|
||||
"flag or be stored in configuration file",
|
||||
)
|
||||
}
|
||||
password = "none"
|
||||
if !compileOnly {
|
||||
return nil, errors.New(
|
||||
"confluence password should be specified using -p " +
|
||||
"flag or be stored in configuration file",
|
||||
)
|
||||
}
|
||||
password = "none"
|
||||
}
|
||||
|
||||
if password == "-" {
|
||||
@ -58,7 +49,7 @@ func GetCredentials(
|
||||
password = string(stdin)
|
||||
}
|
||||
|
||||
if flags.CompileOnly && targetURL == "" {
|
||||
if compileOnly && targetURL == "" {
|
||||
targetURL = "http://localhost"
|
||||
}
|
||||
|
||||
@ -70,20 +61,15 @@ func GetCredentials(
|
||||
)
|
||||
}
|
||||
|
||||
baseURL := url.Scheme + "://" + url.Host
|
||||
|
||||
if url.Host == "" {
|
||||
baseURL = flags.BaseURL
|
||||
if baseURL == "" {
|
||||
baseURL = config.BaseURL
|
||||
}
|
||||
|
||||
if baseURL == "" {
|
||||
return nil, errors.New(
|
||||
"Confluence base URL should be specified using -l " +
|
||||
"confluence base URL should be specified using -l " +
|
||||
"flag or be stored in configuration file",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
baseURL = url.Scheme + "://" + url.Host
|
||||
}
|
||||
|
||||
baseURL = strings.TrimRight(baseURL, `/`)
|
||||
|
29
config.go
29
config.go
@ -1,29 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/kovetskiy/ko"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Username string `env:"MARK_USERNAME" toml:"username"`
|
||||
Password string `env:"MARK_PASSWORD" toml:"password"`
|
||||
BaseURL string `env:"MARK_BASE_URL" toml:"base_url"`
|
||||
H1Title bool `env:"MARK_H1_TITLE" toml:"h1_title"`
|
||||
H1Drop bool `env:"MARK_H1_DROP" toml:"h1_drop"`
|
||||
}
|
||||
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
config := &Config{}
|
||||
err := ko.Load(path, config)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
7
go.mod
7
go.mod
@ -3,14 +3,13 @@ module github.com/kovetskiy/mark
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
|
||||
github.com/kovetskiy/gopencils v0.0.0-20230119081704-a73db75b2f69
|
||||
github.com/kovetskiy/ko v1.6.1
|
||||
github.com/kovetskiy/lorg v1.2.0
|
||||
github.com/reconquest/karma-go v0.0.0-20220904173930-21741aa386a6
|
||||
github.com/reconquest/pkg v1.3.0
|
||||
github.com/reconquest/regexputil-go v0.0.0-20160905154124-38573e70c1f4
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/urfave/cli/v2 v2.25.1
|
||||
github.com/yuin/goldmark v1.5.4
|
||||
golang.org/x/tools v0.7.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
@ -18,11 +17,13 @@ require (
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/iancoleman/strcase v0.2.0 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/reconquest/cog v0.0.0-20210820140837-c5c4e8f49c65 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/zazab/zhash v0.0.0-20210630080733-6e809466f8d3 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
)
|
||||
|
14
go.sum
14
go.sum
@ -1,17 +1,13 @@
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/kovetskiy/gopencils v0.0.0-20230119081704-a73db75b2f69 h1:vn82v0gKhTTm67znr7nxYBNW4mJ8zfY7dywZivUy3tY=
|
||||
github.com/kovetskiy/gopencils v0.0.0-20230119081704-a73db75b2f69/go.mod h1:t7LFI5v8Q5+nl9sqId9PS0C9H9F4c5d4XlhkLve1MCM=
|
||||
github.com/kovetskiy/ko v1.6.1 h1:EO5v6CrW6x6vzxo7CKbN0r+foIRjz06U6wVSgxUVqMc=
|
||||
github.com/kovetskiy/ko v1.6.1/go.mod h1:WH6doo9XYpbDWe9HsELro1vXAfXCM4ByG5arIp9JjDE=
|
||||
github.com/kovetskiy/lorg v0.0.0-20200107130803-9a7136a95634/go.mod h1:B8HeKAukXULNzWWsW5k/SQyDkiQZPn7lTBJDB46MZ9I=
|
||||
github.com/kovetskiy/lorg v1.2.0 h1:wNIUT/VOhcjKOmizDClZLvchbKFGW+dzf9fQXbSVS5E=
|
||||
github.com/kovetskiy/lorg v1.2.0/go.mod h1:rdiamaIRUCkX9HtFZd0D9dQqUbad21hipHk+sat7Z6s=
|
||||
@ -31,6 +27,8 @@ github.com/reconquest/pkg v1.3.0 h1:Yuoxiw92rP/srKXMo5qSML2InhJ+xAqHJIx3/y/2zh8=
|
||||
github.com/reconquest/pkg v1.3.0/go.mod h1:hUQ0SzzBlFRSbo6lFYG2tSpLMjqOuUqm2LtpjR/+1sg=
|
||||
github.com/reconquest/regexputil-go v0.0.0-20160905154124-38573e70c1f4 h1:bcDXaTFC09IIg13Z8gfQHk4gSu001ET7ssW/wKRvPzg=
|
||||
github.com/reconquest/regexputil-go v0.0.0-20160905154124-38573e70c1f4/go.mod h1:OI1di2iiFSwX3D70iZjzdmCPPfssjOl+HX40tI3VaXA=
|
||||
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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@ -39,6 +37,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
|
||||
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
|
||||
github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zazab/zhash v0.0.0-20210630080733-6e809466f8d3 h1:BhVaeQJc3xalHGONn215FylzuxdQBIT3d/aRjDg4nXQ=
|
||||
|
269
main.go
269
main.go
@ -7,7 +7,6 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/docopt/docopt-go"
|
||||
"github.com/kovetskiy/lorg"
|
||||
"github.com/kovetskiy/mark/pkg/confluence"
|
||||
"github.com/kovetskiy/mark/pkg/mark"
|
||||
@ -16,96 +15,170 @@ import (
|
||||
"github.com/kovetskiy/mark/pkg/mark/stdlib"
|
||||
"github.com/reconquest/karma-go"
|
||||
"github.com/reconquest/pkg/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2/altsrc"
|
||||
)
|
||||
|
||||
type Flags struct {
|
||||
FileGlobPatten string `docopt:"-f"`
|
||||
CompileOnly bool `docopt:"--compile-only"`
|
||||
DryRun bool `docopt:"--dry-run"`
|
||||
EditLock bool `docopt:"-k"`
|
||||
DropH1 bool `docopt:"--drop-h1"`
|
||||
TitleFromH1 bool `docopt:"--title-from-h1"`
|
||||
MinorEdit bool `docopt:"--minor-edit"`
|
||||
Color string `docopt:"--color"`
|
||||
Debug bool `docopt:"--debug"`
|
||||
Trace bool `docopt:"--trace"`
|
||||
Username string `docopt:"-u"`
|
||||
Password string `docopt:"-p"`
|
||||
TargetURL string `docopt:"-l"`
|
||||
BaseURL string `docopt:"--base-url"`
|
||||
Config string `docopt:"--config"`
|
||||
Ci bool `docopt:"--ci"`
|
||||
Space string `docopt:"--space"`
|
||||
}
|
||||
|
||||
const (
|
||||
version = "9.1.4"
|
||||
usage = `mark - a tool for updating Atlassian Confluence pages from markdown.
|
||||
|
||||
Docs: https://github.com/kovetskiy/mark
|
||||
|
||||
Usage:
|
||||
mark [options] [-u <username>] [-p <token>] [-k] [-l <url>] -f <file>
|
||||
mark [options] [-u <username>] [-p <password>] [-k] [-b <url>] -f <file>
|
||||
mark -v | --version
|
||||
mark -h | --help
|
||||
|
||||
Options:
|
||||
-u <username> Use specified username for updating Confluence page.
|
||||
-p <token> 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.
|
||||
-l <url> Edit specified Confluence page.
|
||||
If -l is not specified, file should contain metadata (see
|
||||
above).
|
||||
-b --base-url <url> Base URL for Confluence.
|
||||
Alternative option for base_url config field.
|
||||
-f <file> Use specified markdown file(s) for converting to html.
|
||||
Supports file globbing patterns (needs to be quoted).
|
||||
-k Lock page editing to current user only to prevent accidental
|
||||
manual edits over Confluence Web UI.
|
||||
--space <space> Use specified space key. If the space key is not specified, it must
|
||||
be set in the page metadata.
|
||||
--drop-h1 Don't include H1 headings in Confluence output.
|
||||
--title-from-h1 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.
|
||||
--dry-run Resolve page and ancestry, show resulting HTML and exit.
|
||||
--compile-only Show resulting HTML and don't update Confluence page content.
|
||||
--minor-edit Don't send notifications while updating Confluence page.
|
||||
--debug Enable debug logs.
|
||||
--trace Enable trace logs.
|
||||
--color <when> Display logs in color. Possible values: auto, never.
|
||||
[default: auto]
|
||||
-c --config <path> Use the specified configuration file.
|
||||
[default: $HOME/.config/mark]
|
||||
--ci Runs on CI mode. It won't fail if files are not found.
|
||||
-h --help Show this message.
|
||||
-v --version Show version.
|
||||
version = "9.1.4"
|
||||
usage = "A tool for updating Atlassian Confluence pages from markdown."
|
||||
description = `Mark is a tool to update Atlassian Confluence pages from markdown. Documentation is available here: https://github.com/kovetskiy/mark
|
||||
`
|
||||
)
|
||||
|
||||
var flags = []cli.Flag{
|
||||
altsrc.NewStringFlag(&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).",
|
||||
EnvVars: []string{"MARK_FILES"},
|
||||
}),
|
||||
altsrc.NewBoolFlag(&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{
|
||||
Name: "dry-run",
|
||||
Value: false,
|
||||
Usage: "resolve page and ancestry, show resulting HTML and exit.",
|
||||
EnvVars: []string{"MARK_DRY_RUN"},
|
||||
}),
|
||||
altsrc.NewBoolFlag(&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{
|
||||
Name: "drop-h1",
|
||||
Value: false,
|
||||
Usage: "don't include H1 headings in Confluence output.",
|
||||
EnvVars: []string{"MARK_H1_DROP"},
|
||||
}),
|
||||
altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "title-from-h1",
|
||||
Value: false,
|
||||
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{
|
||||
Name: "minor-edit",
|
||||
Value: false,
|
||||
Usage: "don't send notifications while updating Confluence page.",
|
||||
EnvVars: []string{"MARK_MINOR_EDIT"},
|
||||
}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "color",
|
||||
Value: "auto",
|
||||
Usage: "display logs in color. Possible values: auto, never.",
|
||||
EnvVars: []string{"MARK_COLOR"},
|
||||
}),
|
||||
altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Value: false,
|
||||
Usage: "enable debug logs.",
|
||||
EnvVars: []string{"MARK_DEBUG"},
|
||||
}),
|
||||
altsrc.NewBoolFlag(&cli.BoolFlag{
|
||||
Name: "trace",
|
||||
Value: false,
|
||||
Usage: "enable trace logs.",
|
||||
EnvVars: []string{"MARK_TRACE"},
|
||||
}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "username",
|
||||
Aliases: []string{"u"},
|
||||
Value: "",
|
||||
Usage: "use specified username for updating Confluence page.",
|
||||
EnvVars: []string{"MARK_USERNAME"},
|
||||
}),
|
||||
altsrc.NewStringFlag(&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{
|
||||
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{
|
||||
Name: "base-url",
|
||||
Aliases: []string{"b"},
|
||||
Value: "",
|
||||
Usage: "base URL for Confluence. Alternative option for base_url config field.",
|
||||
EnvVars: []string{"MARK_BASE_URL"},
|
||||
}),
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Value: filepath.Join(os.Getenv("HOME"), ".config/mark"),
|
||||
Usage: "use the specified configuration file.",
|
||||
TakesFile: true,
|
||||
EnvVars: []string{"MARK_CONFIG"},
|
||||
},
|
||||
altsrc.NewBoolFlag(&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{
|
||||
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"},
|
||||
}),
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd, err := docopt.ParseArgs(os.ExpandEnv(usage), nil, version)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
app := &cli.App{
|
||||
Name: "mark",
|
||||
Usage: usage,
|
||||
Description: description,
|
||||
Version: version,
|
||||
Flags: flags,
|
||||
Before: altsrc.InitInputSourceWithContext(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
|
||||
return altsrc.NewTomlSourceFromFile(filepath.Join(os.Getenv("HOME"), ".config/mark"))
|
||||
}
|
||||
}),
|
||||
EnableBashCompletion: true,
|
||||
HideHelpCommand: true,
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
return RunMark(cCtx)
|
||||
},
|
||||
}
|
||||
|
||||
var flags Flags
|
||||
err = cmd.Bind(&flags)
|
||||
if err != nil {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if flags.Debug {
|
||||
func RunMark(cCtx *cli.Context) error {
|
||||
|
||||
if cCtx.Bool("debug") {
|
||||
log.SetLevel(lorg.LevelDebug)
|
||||
}
|
||||
|
||||
if flags.Trace {
|
||||
if cCtx.Bool("trace") {
|
||||
log.SetLevel(lorg.LevelTrace)
|
||||
}
|
||||
|
||||
if flags.Color == "never" {
|
||||
if cCtx.String("color") == "never" {
|
||||
log.GetLogger().SetFormat(
|
||||
lorg.NewFormat(
|
||||
`${time:2006-01-02 15:04:05.000} ${level:%s:left:true} ${prefix}%s`,
|
||||
@ -114,33 +187,20 @@ func main() {
|
||||
log.GetLogger().SetOutput(os.Stderr)
|
||||
}
|
||||
|
||||
config, err := LoadConfig(flags.Config)
|
||||
creds, err := GetCredentials(cCtx.String("username"), cCtx.String("password"), cCtx.String("target-url"), cCtx.String("base-url"), cCtx.Bool("compile-only"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if !flags.TitleFromH1 && config.H1Title {
|
||||
flags.TitleFromH1 = true
|
||||
}
|
||||
|
||||
if !flags.DropH1 && config.H1Drop {
|
||||
flags.DropH1 = true
|
||||
}
|
||||
|
||||
creds, err := GetCredentials(flags, config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
|
||||
api := confluence.NewAPI(creds.BaseURL, creds.Username, creds.Password)
|
||||
|
||||
files, err := filepath.Glob(flags.FileGlobPatten)
|
||||
files, err := filepath.Glob(cCtx.String("files"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if len(files) == 0 {
|
||||
msg := "No files matched"
|
||||
if flags.Ci {
|
||||
if cCtx.Bool("ci") {
|
||||
log.Warning(msg)
|
||||
} else {
|
||||
log.Fatal(msg)
|
||||
@ -155,7 +215,7 @@ func main() {
|
||||
file,
|
||||
)
|
||||
|
||||
target := processFile(file, api, flags, creds.PageID, creds.Username)
|
||||
target := processFile(file, api, cCtx, creds.PageID, creds.Username)
|
||||
|
||||
log.Infof(
|
||||
nil,
|
||||
@ -165,12 +225,13 @@ func main() {
|
||||
|
||||
fmt.Println(creds.BaseURL + target.Links.Full)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processFile(
|
||||
file string,
|
||||
api *confluence.API,
|
||||
flags Flags,
|
||||
cCtx *cli.Context,
|
||||
pageID string,
|
||||
username string,
|
||||
) *confluence.PageInfo {
|
||||
@ -181,7 +242,7 @@ func processFile(
|
||||
|
||||
markdown = bytes.ReplaceAll(markdown, []byte("\r\n"), []byte("\n"))
|
||||
|
||||
meta, markdown, err := mark.ExtractMeta(markdown, flags.Space, flags.TitleFromH1)
|
||||
meta, markdown, err := mark.ExtractMeta(markdown, cCtx.String("space"), cCtx.Bool("title-from-h1"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -258,24 +319,22 @@ func processFile(
|
||||
}
|
||||
}
|
||||
|
||||
links, err := mark.ResolveRelativeLinks(api, meta, markdown, filepath.Dir(file), flags.Space, flags.TitleFromH1)
|
||||
links, err := mark.ResolveRelativeLinks(api, meta, markdown, filepath.Dir(file), cCtx.String("space"), cCtx.Bool("title-from-h1"))
|
||||
if err != nil {
|
||||
log.Fatalf(err, "unable to resolve relative links")
|
||||
}
|
||||
|
||||
markdown = mark.SubstituteLinks(markdown, links)
|
||||
|
||||
if flags.DryRun {
|
||||
flags.CompileOnly = true
|
||||
|
||||
_, _, err := mark.ResolvePage(flags.DryRun, api, meta)
|
||||
if cCtx.Bool("dry-run") {
|
||||
_, _, err := mark.ResolvePage(cCtx.Bool("dry-run"), api, meta)
|
||||
if err != nil {
|
||||
log.Fatalf(err, "unable to resolve page location")
|
||||
}
|
||||
}
|
||||
|
||||
if flags.CompileOnly {
|
||||
if flags.DropH1 {
|
||||
if cCtx.Bool("compile-only") || cCtx.Bool("dry-run") {
|
||||
if cCtx.Bool("drop-h1") {
|
||||
log.Info(
|
||||
"the leading H1 heading will be excluded from the Confluence output",
|
||||
)
|
||||
@ -289,7 +348,7 @@ func processFile(
|
||||
var target *confluence.PageInfo
|
||||
|
||||
if meta != nil {
|
||||
parent, page, err := mark.ResolvePage(flags.DryRun, api, meta)
|
||||
parent, page, err := mark.ResolvePage(cCtx.Bool("dry-run"), api, meta)
|
||||
if err != nil {
|
||||
log.Fatalf(
|
||||
karma.Describe("title", meta.Title).Reason(err),
|
||||
@ -346,7 +405,7 @@ func processFile(
|
||||
|
||||
markdown = mark.CompileAttachmentLinks(markdown, attaches)
|
||||
|
||||
if flags.DropH1 {
|
||||
if cCtx.Bool("drop-h1") {
|
||||
log.Info(
|
||||
"the leading H1 heading will be excluded from the Confluence output",
|
||||
)
|
||||
@ -378,12 +437,12 @@ func processFile(
|
||||
html = buffer.String()
|
||||
}
|
||||
|
||||
err = api.UpdatePage(target, html, flags.MinorEdit, meta.Labels, meta.ContentAppearance)
|
||||
err = api.UpdatePage(target, html, cCtx.Bool("minor-edit"), meta.Labels, meta.ContentAppearance)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if flags.EditLock {
|
||||
if cCtx.Bool("edit-lock") {
|
||||
log.Infof(
|
||||
nil,
|
||||
`edit locked on page %q by user %q to prevent manual edits`,
|
||||
|
@ -181,7 +181,7 @@ func parseLinks(markdown string) []markdownLink {
|
||||
return links
|
||||
}
|
||||
|
||||
// getConfluenceLink build (to be) link for Conflunce, and tries to verify from
|
||||
// getConfluenceLink build (to be) link for Confluence, and tries to verify from
|
||||
// API if there's real link available
|
||||
func getConfluenceLink(
|
||||
api *confluence.API,
|
||||
|
Loading…
Reference in New Issue
Block a user