diff --git a/main.go b/main.go index f6f098c..4fd6f21 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ Options: -k Lock page editing to current user only to prevent accidental manual edits over Confluence Web UI. --dry-run Show resulting HTML and don't update Confluence page content. + --debug Enable debug logs. --trace Enable trace logs. -h --help Show this screen and call 911. -v --version Show version. @@ -85,7 +86,7 @@ var ( log *cog.Logger ) -func initlog(trace bool) { +func initlog(debug, trace bool) { stderr := lorg.NewLog() stderr.SetIndentLines(true) stderr.SetFormat( @@ -94,9 +95,16 @@ func initlog(trace bool) { log = cog.NewLogger(stderr) + if debug { + log.SetLevel(lorg.LevelDebug) + } + if trace { log.SetLevel(lorg.LevelTrace) } + + mark.SetLogger(log) + confluence.SetLogger(log) } func main() { @@ -109,10 +117,9 @@ func main() { targetFile, _ = args["-f"].(string) dryRun = args["--dry-run"].(bool) editLock = args["-k"].(bool) - trace = args["--trace"].(bool) ) - initlog(trace) + initlog(args["--debug"].(bool), args["--trace"].(bool)) config, err := getConfig(filepath.Join(os.Getenv("HOME"), ".config/mark")) if err != nil && !os.IsNotExist(err) { @@ -129,10 +136,8 @@ func main() { log.Fatal(err) } - htmlData := mark.CompileMarkdown(markdownData) - if dryRun { - fmt.Println(string(htmlData)) + fmt.Println(string(mark.CompileMarkdown(markdownData))) os.Exit(0) } @@ -187,11 +192,15 @@ func main() { target = page } - err = mark.ResolveAttachments(api, target, ".", meta.Attachments) + attaches, err := mark.ResolveAttachments(api, target, ".", meta.Attachments) if err != nil { log.Fatalf(err, "unable to create/update attachments") } + markdownData = mark.CompileAttachmentLinks(markdownData, attaches) + + htmlData := mark.CompileMarkdown(markdownData) + err = api.UpdatePage( target, MacroLayout{meta.Layout, [][]byte{htmlData}}.Render(), diff --git a/pkg/confluence/api.go b/pkg/confluence/api.go index 3338611..d75ae45 100644 --- a/pkg/confluence/api.go +++ b/pkg/confluence/api.go @@ -239,9 +239,9 @@ func (api *API) UpdateAttachment( return info, err } - //if request.Raw.StatusCode != 200 { - return info, newErrorStatusNotOK(request) - //} + if request.Raw.StatusCode != 200 { + return info, newErrorStatusNotOK(request) + } if len(result.Results) == 0 { return info, errors.New( diff --git a/pkg/mark/ancestry.go b/pkg/mark/ancestry.go index 710e551..e27e665 100644 --- a/pkg/mark/ancestry.go +++ b/pkg/mark/ancestry.go @@ -32,7 +32,7 @@ func EnsureAncestry( break } - log.Tracef(nil, "parent page %q exists: %s", title, page.Links.Full) + log.Debugf(nil, "parent page %q exists: %s", title, page.Links.Full) rest = ancestry[i:] parent = page diff --git a/pkg/mark/attachment.go b/pkg/mark/attachment.go index f57682d..922b1ff 100644 --- a/pkg/mark/attachment.go +++ b/pkg/mark/attachment.go @@ -1,13 +1,14 @@ package mark import ( + "bytes" "crypto/sha256" "encoding/hex" - "encoding/json" - "fmt" "io" + "net/url" "os" "path/filepath" + "sort" "strings" "github.com/kovetskiy/mark/pkg/confluence" @@ -32,8 +33,8 @@ func ResolveAttachments( page *confluence.PageInfo, base string, names []string, -) error { - attachs := []Attachment{} +) ([]Attachment, error) { + attaches := []Attachment{} for _, name := range names { attach := Attachment{ Name: name, @@ -43,7 +44,7 @@ func ResolveAttachments( checksum, err := getChecksum(attach.Path) if err != nil { - return karma.Format( + return nil, karma.Format( err, "unable to get checksum for attachment: %q", attach.Name, ) @@ -51,7 +52,7 @@ func ResolveAttachments( attach.Checksum = checksum - attachs = append(attachs, attach) + attaches = append(attaches, attach) } remotes, err := api.GetAttachments(page.ID) @@ -62,7 +63,7 @@ func ResolveAttachments( existing := []Attachment{} creating := []Attachment{} updating := []Attachment{} - for _, attach := range attachs { + for _, attach := range attaches { var found bool var same bool for _, remote := range remotes { @@ -92,21 +93,6 @@ func ResolveAttachments( } } - { - marshaledXXX, _ := json.MarshalIndent(existing, "", " ") - fmt.Printf("existing: %s\n", string(marshaledXXX)) - } - - { - marshaledXXX, _ := json.MarshalIndent(creating, "", " ") - fmt.Printf("creating: %s\n", string(marshaledXXX)) - } - - { - marshaledXXX, _ := json.MarshalIndent(updating, "", " ") - fmt.Printf("updating: %s\n", string(marshaledXXX)) - } - for i, attach := range creating { log.Infof(nil, "creating attachment: %q", attach.Name) @@ -117,7 +103,7 @@ func ResolveAttachments( attach.Path, ) if err != nil { - return karma.Format( + return nil, karma.Format( err, "unable to create attachment %q", attach.Name, @@ -141,7 +127,7 @@ func ResolveAttachments( attach.Path, ) if err != nil { - return karma.Format( + return nil, karma.Format( err, "unable to update attachment %q", attach.Name, @@ -153,7 +139,53 @@ func ResolveAttachments( updating[i] = attach } - return nil + attaches = []Attachment{} + attaches = append(attaches, existing...) + attaches = append(attaches, creating...) + attaches = append(attaches, updating...) + + return attaches, nil +} + +func CompileAttachmentLinks(markdown []byte, attaches []Attachment) []byte { + links := map[string]string{} + names := []string{} + + for _, attach := range attaches { + uri, err := url.ParseRequestURI(attach.Link) + if err != nil { + links[attach.Name] = strings.ReplaceAll("&", "&", attach.Link) + } else { + links[attach.Name] = uri.Path + + "?" + url.QueryEscape(uri.Query().Encode()) + } + + names = append(names, attach.Name) + } + + // sort by length so first items will have bigger length + // it's helpful for replacing in case of following names + // attachments/a.jpg + // attachments/a.jpg.jpg + // so we replace longer and then shorter + sort.SliceStable(names, func(i, j int) bool { + return len(names[i]) > len(names[j]) + }) + + for _, name := range names { + from := `attachment://` + name + to := links[name] + + log.Debugf(nil, "replacing: %q -> %q", from, to) + + markdown = bytes.ReplaceAll( + markdown, + []byte(from), + []byte(to), + ) + } + + return markdown } func getChecksum(filename string) (string, error) { diff --git a/pkg/mark/markdown.go b/pkg/mark/markdown.go index bd10d29..0e79350 100644 --- a/pkg/mark/markdown.go +++ b/pkg/mark/markdown.go @@ -39,7 +39,11 @@ func (code MacroCode) Render() string { // compileMarkdown will replace tags like with escaped // equivalent, because blackfriday markdown parser replaces that tags with // ac:rich-text-body for whatever reason. -func CompileMarkdown(markdown []byte) []byte { +func CompileMarkdown( + markdown []byte, +) []byte { + log.Tracef(nil, "rendering markdown:\n%s", string(markdown)) + colon := regexp.MustCompile(`---BLACKFRIDAY-COLON---`) tags := regexp.MustCompile(`<(/?\S+):(\S+)>`) @@ -68,15 +72,21 @@ func CompileMarkdown(markdown []byte) []byte { blackfriday.EXTENSION_TABLES | blackfriday.EXTENSION_FENCED_CODE | blackfriday.EXTENSION_AUTOLINK | + blackfriday.EXTENSION_LAX_HTML_BLOCKS | blackfriday.EXTENSION_STRIKETHROUGH | blackfriday.EXTENSION_SPACE_HEADERS | blackfriday.EXTENSION_HEADER_IDS | + blackfriday.EXTENSION_AUTO_HEADER_IDS | + blackfriday.EXTENSION_TITLEBLOCK | blackfriday.EXTENSION_BACKSLASH_LINE_BREAK | - blackfriday.EXTENSION_DEFINITION_LISTS, + blackfriday.EXTENSION_DEFINITION_LISTS | + blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK, }, ) html = colon.ReplaceAll(html, []byte(`:`)) + log.Tracef(nil, "rendered markdown to html:\n%s", string(html)) + return html }