Skip to content

Commit

Permalink
Merge pull request #36 from mschmieder/extensions
Browse files Browse the repository at this point in the history
added support for exclude-filters, nested parents and document titles
  • Loading branch information
justmiles authored Jan 18, 2021
2 parents a348358 + 724a48c commit 2af6fa8
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 37 deletions.
71 changes: 52 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ and add the binary in your local `PATH`

```shell
curl -LO https://github.com/justmiles/go-markdown2confluence/releases/download/v3.1.2/go-markdown2confluence_3.1.2_linux_x86_64.tar.gz

sudo tar -xzvf go-markdown2confluence_3.1.2_linux_x86_64.tar.gz -C /usr/local/bin/ markdown2confluence
```

- OSX

```shell
curl -LO https://github.com/justmiles/go-markdown2confluence/releases/download/v3.1.2/go-markdown2confluence_3.1.2_darwin_x86_64.tar.gz

sudo tar -xzvf go-markdown2confluence_3.1.2_darwin_x86_64.tar.gz -C /usr/local/bin/ markdown2confluence
```

- Windows

Download [the latest release](https://github.com/justmiles/go-markdown2confluence/releases/download/v3.1.2/go-markdown2confluence_3.1.2_windows_x86_64.tar.gz) and add to your system `PATH`

## Use with Docker
Expand Down Expand Up @@ -54,46 +54,79 @@ For best practice we recommend you [authenticate using an API token](https://id.
Push markdown files to Confluence Cloud
Usage:
markdown2confluence [flags] (files or directories)
markdown2confluence [flags]
Flags:
-d, --debug Enable debug logging
-e, --endpoint string Confluence endpoint. (Alternatively set CONFLUENCE_ENDPOINT environment variable) (default "https://mydomain.atlassian.net/wiki")
-h, --help help for markdown2confluence
-m, --modified-since int Only upload files that have modifed in the past n minutes
--parent string Optional parent page to nest content under
-p, --password string Confluence password. (Alternatively set CONFLUENCE_PASSWORD environment variable)
-s, --space string Space in which page should be created
-t, --title string Set the page title on upload (defaults to filename without extension)
-u, --username string Confluence username. (Alternatively set CONFLUENCE_USERNAME environment variable)
-w, --hardwraps Render newlines as <br />
--version version for markdown2confluence
-d, --debug Enable debug logging
-e, --endpoint string Confluence endpoint. (Alternatively set CONFLUENCE_ENDPOINT environment variable) (default "https://mydomain.atlassian.net/wiki")
-x, --exclude strings list of exclude file patterns (regex) that will be applied on markdown file paths
-w, --hardwraps Render newlines as <br />
-h, --help help for markdown2confluence
-m, --modified-since int Only upload files that have modifed in the past n minutes
--parent string Optional parent page to next content under
-p, --password string Confluence password. (Alternatively set CONFLUENCE_PASSWORD environment variable)
-s, --space string Space in which page should be created
-t, --title string Set the page title on upload (defaults to filename without extension)
--use-document-title Will use the Markdown document title (# Title) if available
-u, --username string Confluence username. (Alternatively set CONFLUENCE_USERNAME environment variable)
--version version for markdown2confluence
```

## Examples

Upload a local directory of markdown files called `markdown-files` to Confluence.

```shell
markdown2confluence --space 'MyTeamSpace' markdown-files
markdown2confluence \
--space 'MyTeamSpace' \
markdown-files
```

Upload the same directory, but only those modified in the last 30 minutes. This is particurlarly useful for cron jobs/recurring one-way syncs.

```shell
markdown2confluence --space 'MyTeamSpace' --modified-since 30 markdown-files
markdown2confluence \
--space 'MyTeamSpace' \
--modified-since 30 \
markdown-files
```

Upload a single file

```shell
markdown2confluence --space 'MyTeamSpace' markdown-files/test.md
markdown2confluence \
--space 'MyTeamSpace' \
markdown-files/test.md
```

Upload a directory of markdown files in space `MyTeamSpace` under the parent page `API Docs`

```shell
markdown2confluence --space 'MyTeamSpace' --parent 'API Docs' markdown-files
markdown2confluence \
--space 'MyTeamSpace' \
--parent 'API Docs' \
markdown-files
```

Upload a directory of markdown files in space `MyTeamSpace` under a _nested_ parent page `Docs/API` and _exclude_ mardown files/directories that match `.*generated.*` or `.*temp.md`

```shell
markdown2confluence \
--space 'MyTeamSpace' \
--parent 'API/Docs' \
--exclude '.*generated.*' \
--exclude '.*temp.md' \
markdown-files
```

Upload a directory of markdown files in space `MyTeamSpace` under the parent page `API Docs` and use the markdown _document-title_ instead of the filname as document title (if available) in Confluence.

```shell
markdown2confluence \
--space 'MyTeamSpace' \
--parent 'API Docs' \
--use-document-title \
markdown-files
```

## Enhancements
Expand Down
3 changes: 2 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&m.Endpoint, "endpoint", "e", lib.DefaultEndpoint, "Confluence endpoint. (Alternatively set CONFLUENCE_ENDPOINT environment variable)")
rootCmd.PersistentFlags().StringVar(&m.Parent, "parent", "", "Optional parent page to next content under")
rootCmd.PersistentFlags().BoolVarP(&m.Debug, "debug", "d", false, "Enable debug logging")
rootCmd.PersistentFlags().BoolVarP(&m.UseDocumentTitle, "use-document-title", "", false, "Will use the Markdown document title (# Title) if available")
rootCmd.PersistentFlags().BoolVarP(&m.WithHardWraps, "hardwraps", "w", false, "Render newlines as <br />")
rootCmd.PersistentFlags().IntVarP(&m.Since, "modified-since", "m", 0, "Only upload files that have modifed in the past n minutes")
rootCmd.PersistentFlags().StringVarP(&m.Title, "title", "t", "", "Set the page title on upload (defaults to filename without extension)")

rootCmd.PersistentFlags().StringSliceVarP(&m.ExcludeFilePatterns, "exclude", "x", []string{}, "list of exclude file patterns (regex) for that will be applied on markdown file paths")
m.SourceEnvironmentVariables()

}
Expand Down
86 changes: 69 additions & 17 deletions lib/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package lib
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"sync"
"time"
Expand All @@ -28,19 +31,21 @@ const (

// Markdown2Confluence stores the settings for each run
type Markdown2Confluence struct {
Space string
Title string
File string
Ancestor string
Debug bool
WithHardWraps bool
Since int
Username string
Password string
Endpoint string
Parent string
SourceMarkdown []string
client *confluence.Client
Space string
Title string
File string
Ancestor string
Debug bool
UseDocumentTitle bool
WithHardWraps bool
Since int
Username string
Password string
Endpoint string
Parent string
SourceMarkdown []string
ExcludeFilePatterns []string
client *confluence.Client
}

// CreateClient returns a new markdown clietn
Expand Down Expand Up @@ -100,6 +105,18 @@ func (m Markdown2Confluence) Validate() error {
return nil
}

func (m *Markdown2Confluence) IsExcluded(p string) bool {
for _, pattern := range m.ExcludeFilePatterns {
r := regexp.MustCompile(pattern)
if r.MatchString(p) {
fmt.Printf("excluding markdown file '%s': exclude pattern '%s'\n", p, pattern)
return true
}
}

return false
}

// Run the sync
func (m *Markdown2Confluence) Run() []error {
var markdownFiles []MarkdownFile
Expand Down Expand Up @@ -133,7 +150,7 @@ func (m *Markdown2Confluence) Run() []error {
return err
}

if strings.HasSuffix(path, ".md") {
if strings.HasSuffix(path, ".md") && !m.IsExcluded(path) {

// Only include this file if it was modified m.Since minutes ago
if m.Since != 0 {
Expand All @@ -156,14 +173,22 @@ func (m *Markdown2Confluence) Run() []error {
tempParents = deleteFromSlice(strings.Split(filepath.Dir(strings.TrimPrefix(filepath.ToSlash(path), filepath.ToSlash(f))), "/"), ".")
}

if m.UseDocumentTitle == true {
doc_title := getDocumentTitle(path)
if doc_title != "" {
tempTitle = doc_title
}
}

md = MarkdownFile{
Path: path,
Parents: tempParents,
Title: tempTitle,
}

if m.Parent != "" {
md.Parents = append([]string{m.Parent}, md.Parents...)
parents := strings.Split(m.Parent, "/")
md.Parents = append(parents, md.Parents...)
md.Parents = deleteEmpty(md.Parents)
}

Expand All @@ -183,11 +208,17 @@ func (m *Markdown2Confluence) Run() []error {
}

if md.Title == "" {
md.Title = strings.TrimSuffix(filepath.Base(f), ".md")
if m.UseDocumentTitle == true {
md.Title = getDocumentTitle(f)
}
if md.Title == "" {
md.Title = strings.TrimSuffix(filepath.Base(f), ".md")
}
}

if m.Parent != "" {
md.Parents = append([]string{m.Parent}, md.Parents...)
parents := strings.Split(m.Parent, "/")
md.Parents = append(parents, md.Parents...)
md.Parents = deleteEmpty(md.Parents)
}

Expand Down Expand Up @@ -299,3 +330,24 @@ func deleteFromSlice(s []string, del string) []string {
}
return s
}

func getDocumentTitle(p string) string {
// Read file to check for the content
file_content, err := ioutil.ReadFile(p)
if err != nil {
log.Fatal(err)
}
// Convert []byte to string and print to screen
text := string(file_content)

// check if there is a
e := `^#\s+(.+)`
r := regexp.MustCompile(e)
result := r.FindStringSubmatch(text)
if len(result) > 1 {
// assign the Title to the matching group
return result[1]
}

return ""
}

0 comments on commit 2af6fa8

Please sign in to comment.