mirror of
				https://github.com/kovetskiy/mark.git
				synced 2025-11-04 14:27:36 +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