diff --git a/README.md b/README.md index b8ca79a..5c8dc7f 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ File in extended format should follow specification + + ``` @@ -61,6 +63,33 @@ follows include tag: --> ``` +Mark also supports attachments. The standard way involves declaring an +`Attachment` along with the other items in the header, then have any links +start with an `attachment://` pseudo-URL: + +```markdown + + + + +An attached link is [here](attachment://) +``` + +The standard attachment mechanism may not work in some circumstances (e.g. +keeping content as close to identical as possible between GitHub and +Confluence), so `ExactAttachment` has been introduced: + +```markdown + + + + +An attached link is [here]() +``` + +**NOTE**: Be careful with `ExactAttachment`! If your path string is a subset of +another longer string or referenced in text, you may get undesired behavior. + Mark also supports macro definitions, which are defined as regexps which will be replaced with specified template: diff --git a/pkg/mark/attachment.go b/pkg/mark/attachment.go index 6ae83d3..abd2ff3 100644 --- a/pkg/mark/attachment.go +++ b/pkg/mark/attachment.go @@ -28,20 +28,22 @@ type Attachment struct { Path string Checksum string Link string + Replace string } func ResolveAttachments( api *confluence.API, page *confluence.PageInfo, base string, - names []string, + replacements map[string]string, ) ([]Attachment, error) { attaches := []Attachment{} - for _, name := range names { + for replace, name := range replacements { attach := Attachment{ Name: name, Filename: strings.ReplaceAll(name, "/", "_"), Path: filepath.Join(base, name), + Replace: replace, } checksum, err := getChecksum(attach.Path) @@ -160,18 +162,18 @@ func ResolveAttachments( func CompileAttachmentLinks(markdown []byte, attaches []Attachment) []byte { links := map[string]string{} - names := []string{} + replaces := []string{} for _, attach := range attaches { uri, err := url.ParseRequestURI(attach.Link) if err != nil { - links[attach.Name] = strings.ReplaceAll("&", "&", attach.Link) + links[attach.Replace] = strings.ReplaceAll("&", "&", attach.Link) } else { - links[attach.Name] = uri.Path + + links[attach.Replace] = uri.Path + "?" + url.QueryEscape(uri.Query().Encode()) } - names = append(names, attach.Name) + replaces = append(replaces, attach.Replace) } // sort by length so first items will have bigger length @@ -179,13 +181,13 @@ func CompileAttachmentLinks(markdown []byte, attaches []Attachment) []byte { // 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]) + sort.SliceStable(replaces, func(i, j int) bool { + return len(replaces[i]) > len(replaces[j]) }) - for _, name := range names { - from := `attachment://` + name - to := links[name] + for _, replace := range replaces { + from := replace + to := links[replace] log.Debugf(nil, "replacing: %q -> %q", from, to) diff --git a/pkg/mark/meta.go b/pkg/mark/meta.go index f70300f..252007d 100644 --- a/pkg/mark/meta.go +++ b/pkg/mark/meta.go @@ -11,11 +11,12 @@ import ( ) const ( - HeaderParent = `Parent` - HeaderSpace = `Space` - HeaderTitle = `Title` - HeaderLayout = `Layout` - HeaderAttachment = `Attachment` + HeaderParent = `Parent` + HeaderSpace = `Space` + HeaderTitle = `Title` + HeaderLayout = `Layout` + HeaderAttachment = `Attachment` + HeaderExactAttachment = `ExactAttachment` ) type Meta struct { @@ -23,7 +24,7 @@ type Meta struct { Space string Title string Layout string - Attachments []string + Attachments map[string]string } var ( @@ -64,6 +65,7 @@ func ExtractMeta(data []byte) (*Meta, []byte, error) { if meta == nil { meta = &Meta{} + meta.Attachments = make(map[string]string) } header := strings.Title(matches[1]) @@ -87,7 +89,10 @@ func ExtractMeta(data []byte) (*Meta, []byte, error) { meta.Layout = strings.TrimSpace(value) case HeaderAttachment: - meta.Attachments = append(meta.Attachments, value) + meta.Attachments["attachment://"+value] = value + + case HeaderExactAttachment: + meta.Attachments[value] = value default: log.Errorf(