mirror of
				https://github.com/kovetskiy/mark.git
				synced 2025-11-04 22:47: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
 | 
			
		||||
                        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(),
 | 
			
		||||
 | 
			
		||||
@ -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(
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,11 @@ func (code MacroCode) Render() string {
 | 
			
		||||
// compileMarkdown will replace tags like <ac:rich-tech-body> with escaped
 | 
			
		||||
// equivalent, because blackfriday markdown parser replaces that tags with
 | 
			
		||||
// <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---`)
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user