mirror of
https://github.com/kovetskiy/mark.git
synced 2025-04-24 05:42:40 +08:00
add pseudo protocol attachment://
This commit is contained in:
parent
2abc2f122b
commit
51f28f8f06
23
main.go
23
main.go
@ -75,6 +75,7 @@ Options:
|
|||||||
-k Lock page editing to current user only to prevent accidental
|
-k Lock page editing to current user only to prevent accidental
|
||||||
manual edits over Confluence Web UI.
|
manual edits over Confluence Web UI.
|
||||||
--dry-run Show resulting HTML and don't update Confluence page content.
|
--dry-run Show resulting HTML and don't update Confluence page content.
|
||||||
|
--debug Enable debug logs.
|
||||||
--trace Enable trace logs.
|
--trace Enable trace logs.
|
||||||
-h --help Show this screen and call 911.
|
-h --help Show this screen and call 911.
|
||||||
-v --version Show version.
|
-v --version Show version.
|
||||||
@ -85,7 +86,7 @@ var (
|
|||||||
log *cog.Logger
|
log *cog.Logger
|
||||||
)
|
)
|
||||||
|
|
||||||
func initlog(trace bool) {
|
func initlog(debug, trace bool) {
|
||||||
stderr := lorg.NewLog()
|
stderr := lorg.NewLog()
|
||||||
stderr.SetIndentLines(true)
|
stderr.SetIndentLines(true)
|
||||||
stderr.SetFormat(
|
stderr.SetFormat(
|
||||||
@ -94,9 +95,16 @@ func initlog(trace bool) {
|
|||||||
|
|
||||||
log = cog.NewLogger(stderr)
|
log = cog.NewLogger(stderr)
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
log.SetLevel(lorg.LevelDebug)
|
||||||
|
}
|
||||||
|
|
||||||
if trace {
|
if trace {
|
||||||
log.SetLevel(lorg.LevelTrace)
|
log.SetLevel(lorg.LevelTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mark.SetLogger(log)
|
||||||
|
confluence.SetLogger(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -109,10 +117,9 @@ func main() {
|
|||||||
targetFile, _ = args["-f"].(string)
|
targetFile, _ = args["-f"].(string)
|
||||||
dryRun = args["--dry-run"].(bool)
|
dryRun = args["--dry-run"].(bool)
|
||||||
editLock = args["-k"].(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"))
|
config, err := getConfig(filepath.Join(os.Getenv("HOME"), ".config/mark"))
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
@ -129,10 +136,8 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlData := mark.CompileMarkdown(markdownData)
|
|
||||||
|
|
||||||
if dryRun {
|
if dryRun {
|
||||||
fmt.Println(string(htmlData))
|
fmt.Println(string(mark.CompileMarkdown(markdownData)))
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,11 +192,15 @@ func main() {
|
|||||||
target = page
|
target = page
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mark.ResolveAttachments(api, target, ".", meta.Attachments)
|
attaches, err := mark.ResolveAttachments(api, target, ".", meta.Attachments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf(err, "unable to create/update attachments")
|
log.Fatalf(err, "unable to create/update attachments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markdownData = mark.CompileAttachmentLinks(markdownData, attaches)
|
||||||
|
|
||||||
|
htmlData := mark.CompileMarkdown(markdownData)
|
||||||
|
|
||||||
err = api.UpdatePage(
|
err = api.UpdatePage(
|
||||||
target,
|
target,
|
||||||
MacroLayout{meta.Layout, [][]byte{htmlData}}.Render(),
|
MacroLayout{meta.Layout, [][]byte{htmlData}}.Render(),
|
||||||
|
@ -239,9 +239,9 @@ func (api *API) UpdateAttachment(
|
|||||||
return info, err
|
return info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//if request.Raw.StatusCode != 200 {
|
if request.Raw.StatusCode != 200 {
|
||||||
return info, newErrorStatusNotOK(request)
|
return info, newErrorStatusNotOK(request)
|
||||||
//}
|
}
|
||||||
|
|
||||||
if len(result.Results) == 0 {
|
if len(result.Results) == 0 {
|
||||||
return info, errors.New(
|
return info, errors.New(
|
||||||
|
@ -32,7 +32,7 @@ func EnsureAncestry(
|
|||||||
break
|
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:]
|
rest = ancestry[i:]
|
||||||
parent = page
|
parent = page
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package mark
|
package mark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kovetskiy/mark/pkg/confluence"
|
"github.com/kovetskiy/mark/pkg/confluence"
|
||||||
@ -32,8 +33,8 @@ func ResolveAttachments(
|
|||||||
page *confluence.PageInfo,
|
page *confluence.PageInfo,
|
||||||
base string,
|
base string,
|
||||||
names []string,
|
names []string,
|
||||||
) error {
|
) ([]Attachment, error) {
|
||||||
attachs := []Attachment{}
|
attaches := []Attachment{}
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
attach := Attachment{
|
attach := Attachment{
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -43,7 +44,7 @@ func ResolveAttachments(
|
|||||||
|
|
||||||
checksum, err := getChecksum(attach.Path)
|
checksum, err := getChecksum(attach.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return karma.Format(
|
return nil, karma.Format(
|
||||||
err,
|
err,
|
||||||
"unable to get checksum for attachment: %q", attach.Name,
|
"unable to get checksum for attachment: %q", attach.Name,
|
||||||
)
|
)
|
||||||
@ -51,7 +52,7 @@ func ResolveAttachments(
|
|||||||
|
|
||||||
attach.Checksum = checksum
|
attach.Checksum = checksum
|
||||||
|
|
||||||
attachs = append(attachs, attach)
|
attaches = append(attaches, attach)
|
||||||
}
|
}
|
||||||
|
|
||||||
remotes, err := api.GetAttachments(page.ID)
|
remotes, err := api.GetAttachments(page.ID)
|
||||||
@ -62,7 +63,7 @@ func ResolveAttachments(
|
|||||||
existing := []Attachment{}
|
existing := []Attachment{}
|
||||||
creating := []Attachment{}
|
creating := []Attachment{}
|
||||||
updating := []Attachment{}
|
updating := []Attachment{}
|
||||||
for _, attach := range attachs {
|
for _, attach := range attaches {
|
||||||
var found bool
|
var found bool
|
||||||
var same bool
|
var same bool
|
||||||
for _, remote := range remotes {
|
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 {
|
for i, attach := range creating {
|
||||||
log.Infof(nil, "creating attachment: %q", attach.Name)
|
log.Infof(nil, "creating attachment: %q", attach.Name)
|
||||||
|
|
||||||
@ -117,7 +103,7 @@ func ResolveAttachments(
|
|||||||
attach.Path,
|
attach.Path,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return karma.Format(
|
return nil, karma.Format(
|
||||||
err,
|
err,
|
||||||
"unable to create attachment %q",
|
"unable to create attachment %q",
|
||||||
attach.Name,
|
attach.Name,
|
||||||
@ -141,7 +127,7 @@ func ResolveAttachments(
|
|||||||
attach.Path,
|
attach.Path,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return karma.Format(
|
return nil, karma.Format(
|
||||||
err,
|
err,
|
||||||
"unable to update attachment %q",
|
"unable to update attachment %q",
|
||||||
attach.Name,
|
attach.Name,
|
||||||
@ -153,7 +139,53 @@ func ResolveAttachments(
|
|||||||
updating[i] = attach
|
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) {
|
func getChecksum(filename string) (string, error) {
|
||||||
|
@ -39,7 +39,11 @@ func (code MacroCode) Render() string {
|
|||||||
// compileMarkdown will replace tags like <ac:rich-tech-body> with escaped
|
// compileMarkdown will replace tags like <ac:rich-tech-body> with escaped
|
||||||
// equivalent, because blackfriday markdown parser replaces that tags with
|
// equivalent, because blackfriday markdown parser replaces that tags with
|
||||||
// <a href="ac:rich-text-body">ac:rich-text-body</a> for whatever reason.
|
// <a href="ac:rich-text-body">ac:rich-text-body</a> 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---`)
|
colon := regexp.MustCompile(`---BLACKFRIDAY-COLON---`)
|
||||||
|
|
||||||
tags := regexp.MustCompile(`<(/?\S+):(\S+)>`)
|
tags := regexp.MustCompile(`<(/?\S+):(\S+)>`)
|
||||||
@ -68,15 +72,21 @@ func CompileMarkdown(markdown []byte) []byte {
|
|||||||
blackfriday.EXTENSION_TABLES |
|
blackfriday.EXTENSION_TABLES |
|
||||||
blackfriday.EXTENSION_FENCED_CODE |
|
blackfriday.EXTENSION_FENCED_CODE |
|
||||||
blackfriday.EXTENSION_AUTOLINK |
|
blackfriday.EXTENSION_AUTOLINK |
|
||||||
|
blackfriday.EXTENSION_LAX_HTML_BLOCKS |
|
||||||
blackfriday.EXTENSION_STRIKETHROUGH |
|
blackfriday.EXTENSION_STRIKETHROUGH |
|
||||||
blackfriday.EXTENSION_SPACE_HEADERS |
|
blackfriday.EXTENSION_SPACE_HEADERS |
|
||||||
blackfriday.EXTENSION_HEADER_IDS |
|
blackfriday.EXTENSION_HEADER_IDS |
|
||||||
|
blackfriday.EXTENSION_AUTO_HEADER_IDS |
|
||||||
|
blackfriday.EXTENSION_TITLEBLOCK |
|
||||||
blackfriday.EXTENSION_BACKSLASH_LINE_BREAK |
|
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(`:`))
|
html = colon.ReplaceAll(html, []byte(`:`))
|
||||||
|
|
||||||
|
log.Tracef(nil, "rendered markdown to html:\n%s", string(html))
|
||||||
|
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user