diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a01d74c..2dba3fb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,13 +25,13 @@ jobs: uses: actions/checkout@v2 - name: dependencies - run: make deps + run: make --always-make deps - name: Fetch Theme - run: make theme + run: make --always-make theme - name: test - run: make test + run: make --always-make test # - name: coverage # uses: paambaati/codeclimate-action@v2.5.5 @@ -40,7 +40,7 @@ jobs: # debug: true - name: build - run: make build + run: make --always-make build - name: Run Monako and compose site - run: make compose \ No newline at end of file + run: make --always-make compose \ No newline at end of file diff --git a/Makefile b/Makefile index 1abac77..ba0326a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ #run: make run SHELL := /bin/bash -.PHONY: compose +.PHONY: compose test clean: rm -r tmp/theme || true @@ -21,7 +21,7 @@ build: clean theme: clean mkdir -p tmp/ - curl -o tmp/theme.zip --location https://github.com/snipem/monako-book/archive/v6s.1.zip + curl -o tmp/theme.zip --location https://github.com/snipem/monako-book/archive/master.zip ${GOPATH}/bin/go-bindata -pkg theme -o internal/theme/bindata.go tmp/... test: @@ -39,6 +39,11 @@ run_prd: build run: build compose serve +run_local: build + # Runs locally, clons this git repo to use test data + ./monako -config test/config.local.yaml -menu-config test/config.menu.local.md + $(MAKE) serve + compose: ./monako -config configs/config.monako.yaml \ -menu-config configs/config.menu.md diff --git a/README.md b/README.md index 2df6a3f..e495c37 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,6 @@ Init with `make init` ## TODOs -* Fail on wrong `docdir` ("TODO") * Fail on build fail to prevent false deployment to production * Reduce uncritical warnings by Asciidoctor diff --git a/cmd/monako/main.go b/cmd/monako/main.go index 98ea912..dba1707 100644 --- a/cmd/monako/main.go +++ b/cmd/monako/main.go @@ -16,7 +16,7 @@ import ( func compose(url string, branch string, subdir string, target string, username string, password string, whitelist []string) { - fs := helpers.CloneDir(url, branch, username, password) + _, fs := helpers.CloneDir(url, branch, username, password) helpers.CopyDir(fs, subdir, "compose/content/"+target+"/", whitelist) } @@ -57,7 +57,7 @@ func main() { addWorkarounds(config) helpers.HugoRun([]string{"--quiet", "new", "site", "compose"}) - theme.GetTheme(config, *menuconfigfilepath) + theme.CreateHugoPage(config, *menuconfigfilepath) for _, c := range config.Origins { compose(c.Source, c.Branch, c.DirWithDocs, c.TargetDir, os.Getenv(c.EnvUsername), os.Getenv(c.EnvPassword), config.FileWhitelist) diff --git a/go.mod b/go.mod index e14b96f..0186e49 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,7 @@ go 1.12 require ( github.com/artdarek/go-unzip v1.0.0 - github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect - github.com/codeskyblue/go-sh v0.0.0-20170112005953-b097669b1569 github.com/gobuffalo/envy v1.9.0 // indirect github.com/gohugoio/hugo v0.67.0 diff --git a/internal/theme/theme.go b/internal/theme/theme.go index 86608f9..70ceb5f 100644 --- a/internal/theme/theme.go +++ b/internal/theme/theme.go @@ -7,12 +7,17 @@ import ( "os" "github.com/artdarek/go-unzip" - "github.com/codeskyblue/go-sh" "github.com/snipem/monako/internal/config" ) -// GetTheme fetches the Monako theme and copies the hugoconfig and menuconfig to the needed files -func GetTheme(composeConfig config.ComposeConfig, menuconfig string) { +const monakoMenuDirectory = "monako_menu_directory" +const themeName = "monako-book-master" + +// CreateHugoPage extracts the Monako theme and copies the hugoconfig and menuconfig to the needed files +func CreateHugoPage(composeConfig config.ComposeConfig, menuconfig string) { + + dir := "compose/content/" + monakoMenuDirectory + dst := dir + "/index.md" extractTheme() err := createHugoConfig(composeConfig) @@ -20,16 +25,25 @@ func GetTheme(composeConfig config.ComposeConfig, menuconfig string) { log.Fatal(err) } - sh.Command("mkdir", "-p", "compose/content/menu/").Run() - sh.Command("cp", menuconfig, "compose/content/menu/index.md").Run() + os.Mkdir(dir, os.FileMode(0744)) + + data, err := ioutil.ReadFile(menuconfig) + if err != nil { + log.Fatal(err) + } + + err = ioutil.WriteFile(dst, data, 0644) + if err != nil { + log.Fatal(err) + } } func createHugoConfig(c config.ComposeConfig) error { - configContent := fmt.Sprintf(` + configContent := fmt.Sprintf(`# Autogenerated by Monako, do not edit baseURL = '%s' title = '%s' -theme = 'monako-book-6s.1' +theme = '%s' # Book configuration disablePathToLower = true @@ -44,48 +58,17 @@ unsafe = true startLevel = 1 [params] -# (Optional, default true) Controls table of contents visibility on right side of pages. -# Start and end levels can be controlled with markup.tableOfContents setting. -# You can also specify this parameter per page in front matter. +# See: https://github.com/snipem/monako-book#configuration for settings BookToC = true - -# (Optional, default none) Set the path to a logo for the book. If the logo is -# /static/logo.png then the path would be logo.png # BookLogo = 'logo.png' - -# (Optional, default none) Set leaf bundle to render as side menu -# When not specified file structure and weights will be used -BookMenuBundle = '/menu' - -# (Optional, default docs) Specify section of content to render as menu -# You can also set value to '*' to render all sections to menu +BookMenuBundle = '/%s' BookSection = 'docs' - -# Set source repository location. -# Used for 'Last Modified' and 'Edit this page' links. -BookRepo = 'https://github.com/alex-shpak/hugo-book' - -# Enable "Edit this page" links for 'doc' page type. -# Disabled by default. Uncomment to enable. Requires 'BookRepo' param. -# Path must point to 'content' directory of repo. -BookEditPath = 'edit/master/exampleSite/content' - -# Configure the date format used on the pages -# - In git information -# - In blog posts +#BookRepo = 'https://github.com/alex-shpak/hugo-book' +#BookEditPath = 'edit/master/exampleSite/content' BookDateFormat = 'Jan 2, 2006' - -# (Optional, default true) Enables search function with flexsearch, -# Index is built on fly, therefore it might slowdown your website. -# Configuration for indexing can be adjusted in i18n folder per language. BookSearch = true - -# (Optional, default true) Enables comments template on pages -# By default partals/docs/comments.html includes Disqus template -# See https://gohugo.io/content-management/comments/#configure-disqus -# Can be overwritten by same param in page frontmatter BookComments = true - `, c.BaseURL, c.Title) + `, c.BaseURL, c.Title, themeName, monakoMenuDirectory) return ioutil.WriteFile("compose/config.toml", []byte(configContent), os.FileMode(0700)) } @@ -98,7 +81,7 @@ func extractTheme() { // TODO Don't use local filesystem, keep it in memory tmpFile, err := ioutil.TempFile(os.TempDir(), "monako-theme-") if err != nil { - fmt.Println("Cannot create temporary file", err) + log.Fatalf("Cannot create temporary file %s", err) } tmpFile.Write(themezip) tempfilename := tmpFile.Name() @@ -111,7 +94,7 @@ func extractTheme() { uz := unzip.New(tempfilename, "compose/themes") err = uz.Extract() if err != nil { - fmt.Println(err) + log.Fatalf("Error extracting theme: %s ", err) } os.RemoveAll(tempfilename) } diff --git a/internal/workarounds/workarounds.go b/internal/workarounds/workarounds.go index 2eaf1b2..5bc278e 100644 --- a/internal/workarounds/workarounds.go +++ b/internal/workarounds/workarounds.go @@ -1,5 +1,7 @@ package workarounds +// run: make test + import ( "fmt" "io/ioutil" @@ -9,26 +11,34 @@ import ( "strings" ) +// AsciidocPostprocessing fixes common errors with Hugo processing vanilla Asciidoc +// 1. Add one level to relative picture img/ -> ../img/ since Hugo adds subfolders +// for pretty urls func AsciidocPostprocessing(dirty []byte) []byte { var d = string(dirty) - // FIXME really quick and dirty, just for testing - d = strings.ReplaceAll(d, "image:http", "imagexxxxxxhttp") + // FIXME really quick and dirty. There is a problem with Go regexp look ahead + d = strings.ReplaceAll(d, "image:http", "image_______http") d = strings.ReplaceAll(d, "image:", "image:../") - d = strings.ReplaceAll(d, "imagexxxxxxhttp", "image:http") + d = strings.ReplaceAll(d, "image_______http", "image:http") return []byte(d) } // MarkdownPostprocessing fixes common errors with Hugo processing vanilla Markdown // 1. Add one level to relative picture img/ -> ../img/ since Hugo adds subfolders +// for pretty urls func MarkdownPostprocessing(dirty []byte) []byte { var d = string(dirty) - // FIXME really quick and dirty, just for testing - d = strings.ReplaceAll(d, "](http", "]xxxxxxhttp") + // FIXME really quick and dirty. There is a problem with Go regexp look ahead + d = strings.ReplaceAll(d, "](http", ")_______http") + d = strings.ReplaceAll(d, "]](", "]]_______(") + d = strings.ReplaceAll(d, "](", "](../") - d = strings.ReplaceAll(d, "]xxxxxxhttp", "](http") + + d = strings.ReplaceAll(d, ")_______http", "](http") + d = strings.ReplaceAll(d, "]]_______(", "]](") return []byte(d) } @@ -40,6 +50,11 @@ func AddFakeAsciidoctorBinForDiagramsToPath(baseURL string) string { log.Fatal(err) } path := url.Path + + // Single slashes will add up to "//" which some webservers don't support + if path == "/" { + path = "" + } escapedPath := strings.ReplaceAll(path, "/", "\\/") // Asciidoctor attributes: https://asciidoctor.org/docs/user-manual/#builtin-attributes @@ -91,7 +106,6 @@ func AddFakeAsciidoctorBinForDiagramsToPath(baseURL string) string { if err != nil { log.Fatalf("Error creating asciidoctor fake binary: %s", err) } - // TODO Remove file afterwards os.Setenv("PATH", tempDir+":"+os.Getenv("PATH")) diff --git a/internal/workarounds/workarounds_test.go b/internal/workarounds/workarounds_test.go index 89a85fb..a6ccfd6 100644 --- a/internal/workarounds/workarounds_test.go +++ b/internal/workarounds/workarounds_test.go @@ -25,19 +25,34 @@ func TestAsciiDocImageFix(t *testing.T) { func TestMarkdownFix(t *testing.T) { - noNeedToClean := "!(caption example)[http://url/image.jpg]" + noNeedToClean := "![caption example](http://url/image.jpg)" clean := string(MarkdownPostprocessing([]byte(noNeedToClean))) if clean != noNeedToClean { t.Errorf("Clean was incorrect, got: %s, want: %s.", clean, noNeedToClean) } - dirty := "!(caption example)[lokalfolderurl/image.png]" - clean = string(MarkdownPostprocessing([]byte(dirty))) - want := "!(caption example)[lokalfolderurl/image.png]" +} +func TestMarkdownFixDontDo(t *testing.T) { + + dirty := "![caption example](lokalfolderurl/image.png)" + want := "![caption example](../lokalfolderurl/image.png)" + + clean := string(MarkdownPostprocessing([]byte(dirty))) if clean != want { t.Errorf("Clean was incorrect, got: %s, want: %s.", clean, want) } } +func TestMarkdownFixInnerLinks(t *testing.T) { + // Dont fix local links + + noNeedToClean := "[[1]](#1)" + + clean := string(MarkdownPostprocessing([]byte(noNeedToClean))) + + if clean != noNeedToClean { + t.Errorf("Clean was incorrect, got: %s, want: %s.", clean, noNeedToClean) + } +} diff --git a/pkg/helpers/file.go b/pkg/helpers/file.go index 65e71ca..7f39f8f 100644 --- a/pkg/helpers/file.go +++ b/pkg/helpers/file.go @@ -19,7 +19,7 @@ import ( var filemode = os.FileMode(0700) -func CloneDir(url string, branch string, username string, password string) billy.Filesystem { +func CloneDir(url string, branch string, username string, password string) (*git.Repository, billy.Filesystem) { log.Printf("Cloning in to %s with branch %s", url, branch) @@ -35,7 +35,7 @@ func CloneDir(url string, branch string, username string, password string) billy } } - _, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{ + repo, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{ URL: url, Depth: 1, ReferenceName: plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branch)), @@ -47,7 +47,7 @@ func CloneDir(url string, branch string, username string, password string) billy log.Fatal(err) } - return fs + return repo, fs } func shouldIgnoreFile(filename string, whitelist []string) bool { @@ -64,7 +64,12 @@ func CopyDir(fs billy.Filesystem, subdir string, target string, whitelist []stri log.Printf("Copying subdir '%s' to target dir %s", subdir, target) var files []os.FileInfo - fs, err := fs.Chroot(subdir) + _, err := fs.Stat(subdir) + if err != nil { + log.Fatalf("Error while reading subdir %s: %s", subdir, err) + } + + fs, err = fs.Chroot(subdir) if err != nil { log.Fatal(err) } diff --git a/pkg/helpers/file_test.go b/pkg/helpers/file_test.go new file mode 100644 index 0000000..822e7cd --- /dev/null +++ b/pkg/helpers/file_test.go @@ -0,0 +1,27 @@ +package helpers + +// run: make test + +import ( + "testing" +) + +func TestCloneDir(t *testing.T) { + + // Use current dir as test repo, navigate two folders up because we are in /pkg/helpers + _, fs := CloneDir("https://github.com/snipem/monako.git", "master", "", "") + + root, err := fs.Chroot(".") + + if err != nil { + t.Error(err) + } + + files, err := root.ReadDir(".") + + if err != nil { + if len(files) == 0 { + t.Errorf("No files checked out") + } + } +} diff --git a/test/config.local.yaml b/test/config.local.yaml new file mode 100644 index 0000000..aec653c --- /dev/null +++ b/test/config.local.yaml @@ -0,0 +1,20 @@ +--- + baseURL : "https://example.com/" + title : "Local Test Page" + + whitelist: + - ".md" + - ".adoc" + - ".jpg" + - ".jpeg" + - ".svg" + - ".gif" + - ".png" + + origins: + + # Files have to be commited to appear! + - src: file://. + branch: develop-add-tests + docdir: test/test_docs + targetdir: docs/test/ diff --git a/test/config.menu.local.md b/test/config.menu.local.md new file mode 100644 index 0000000..79b1994 --- /dev/null +++ b/test/config.menu.local.md @@ -0,0 +1,8 @@ +--- +headless: true +--- + +- **Test docs** + - [Asciidoc]({{}}) + - [Markdown]({{}}) +
\ No newline at end of file diff --git a/test/test_docs/profile.png b/test/test_docs/profile.png new file mode 100644 index 0000000..fb1ac53 Binary files /dev/null and b/test/test_docs/profile.png differ diff --git a/test/test_docs/subfolder/subfolderprofile.png b/test/test_docs/subfolder/subfolderprofile.png new file mode 100644 index 0000000..a17584c Binary files /dev/null and b/test/test_docs/subfolder/subfolderprofile.png differ diff --git a/test/test_docs/test_doc_asciidoc.adoc b/test/test_docs/test_doc_asciidoc.adoc new file mode 100644 index 0000000..512cb00 --- /dev/null +++ b/test/test_docs/test_doc_asciidoc.adoc @@ -0,0 +1,79 @@ +# Asciidoc First Level +:toc: + +## Asciidoc Second Level + +Ihr naht euch wieder, schwankende Gestalten! Die früh sich einst dem trüben +Blick gezeigt. Versuch’ ich wohl euch diesmal fest zu halten? Fühl’ ich +mein Herz noch jenem Wahn geneigt? Ihr drängt euch zu! nun gut, so mögt ihr +walten. Wie ihr aus Dunst und Nebel um mich steigt. Mein Busen fühlt sich +jugendlich erschüttert. + +```go + if err != nil { + if len(files) == 0 { + t.Errorf("No files checked out") + } + } +``` + +.Picture in same folder +image:profile.png[Picture in same folder] + +Vom Zauberhauch der euren Zug umwittert. Ihr bringt mit +euch die Bilder froher Tage. Und manche liebe Schatten steigen auf Gleich einer +alten, halbverklungnen Sage. Kommt erste Lieb’ und Freundschaft mit herauf Der +Schmerz wird neu, es wiederholt die Klage. Des Lebens labyrinthisch irren Lauf, +Und nennt die Guten, die, um schöne Stunden Vom Glück getäuscht, vor mir +hinweggeschwunden. + +### Asciidoc Third Level with Ditaa Diagramm + +[ditaa] +.... + +-------------+ + | Asciidoctor |-------+ + | diagram | | + +-------------+ | PNG out + ^ | + | ditaa in | + | v + +--------+ +--------+----+ /---------------\ + | | --+ Asciidoctor +--> | | + | Text | +-------------+ | Beautiful | + |Document| | !magic! | | Output | + | {d}| | | | | + +---+----+ +-------------+ \---------------/ + : ^ + | Lots of work | + +-----------------------------------+ +.... + +Ihr naht euch wieder, schwankende Gestalten! Die früh sich einst dem trüben +Blick gezeigt. Versuch’ ich wohl euch diesmal fest zu halten? Fühl’ ich +mein Herz noch jenem Wahn geneigt? Ihr drängt euch zu! nun gut, so mögt ihr +walten. Wie ihr aus Dunst und Nebel um mich steigt. Mein Busen fühlt sich +jugendlich erschüttert. Vom Zauberhauch der euren Zug umwittert. Ihr bringt mit +euch die Bilder froher Tage. Und manche liebe Schatten steigen auf Gleich einer +alten, halbverklungnen Sage. Kommt erste Lieb’ und Freundschaft mit herauf Der +Schmerz wird neu, es wiederholt die Klage. Des Lebens labyrinthisch irren Lauf, +Und nennt die Guten, die, um schöne Stunden Vom Glück getäuscht, vor mir +hinweggeschwunden. + +.Picture in sub folder +image:subfolder/subfolderprofile.png[Picture in sub folder] + +### Mermaid Example + +{{< mermaid >}} +sequenceDiagram + Alice->>Bob: Hello Bob, how are you? + alt is sick + Bob->>Alice: Not so good :( + else is well + Bob->>Alice: Feeling fresh like a daisy + end + opt Extra response + Bob->>Alice: Thanks for asking + end +{{< /mermaid >}} diff --git a/test/test_docs/test_doc_markdown.md b/test/test_docs/test_doc_markdown.md new file mode 100644 index 0000000..95eba82 --- /dev/null +++ b/test/test_docs/test_doc_markdown.md @@ -0,0 +1,71 @@ +# Markdown Doc 1 + +Remember these docs have to be commited in order to appear! + +## Markdown Doc 2 + +[Link to Website](https://github.com/snipem/monako.git) + +Ihr naht euch wieder, schwankende Gestalten! Die früh sich einst dem trüben +Blick gezeigt. Versuch’ ich wohl euch diesmal fest zu halten? Fühl’ ich +mein Herz noch jenem Wahn geneigt? Ihr drängt euch zu! nun gut, so mögt ihr +walten. Wie ihr aus Dunst und [Nebel](https://de.wikipedia.org/wiki/Nebel) um mich steigt. Mein Busen fühlt sich +jugendlich erschüttert. Vom Zauberhauch der euren Zug umwittert. Ihr bringt mit +euch die Bilder froher Tage. Und manche liebe Schatten steigen auf Gleich einer +alten, halbverklungnen Sage. Kommt erste Lieb’ und Freundschaft mit herauf Der +Schmerz wird neu, es wiederholt die Klage. Des Lebens labyrinthisch irren Lauf, +Und nennt die Guten, die, um schöne Stunden Vom Glück getäuscht, vor mir +hinweggeschwunden. + +![Picture in same folder](profile.png) + +### Markdown Doc 3 + +Ihr naht euch wieder, schwankende Gestalten! Die früh sich einst dem trüben +Blick gezeigt. Versuch’ ich wohl euch diesmal fest zu halten? Fühl’ ich +mein Herz noch jenem Wahn geneigt? Ihr drängt euch zu! nun gut, so mögt ihr +walten. Wie ihr aus Dunst und Nebel um mich steigt. Mein Busen fühlt sich +jugendlich erschüttert. Vom Zauberhauch der euren Zug umwittert. Ihr bringt mit +euch die Bilder froher Tage. Und manche liebe Schatten steigen auf Gleich einer +alten, halbverklungnen Sage. Kommt erste Lieb’ und Freundschaft mit herauf Der +Schmerz wird neu, es wiederholt die Klage. Des Lebens labyrinthisch irren Lauf, +Und nennt die Guten, die, um schöne Stunden Vom Glück getäuscht, vor mir +hinweggeschwunden. + +#### Markdown Doc 4 + +```go + if err != nil { + if len(files) == 0 { + t.Errorf("No files checked out") + } + } +``` + +Ihr naht euch wieder, schwankende Gestalten! Die früh sich einst dem trüben +Blick gezeigt. Versuch’ ich wohl euch diesmal fest zu halten? Fühl’ ich +mein Herz noch jenem Wahn geneigt? Ihr drängt euch zu! nun gut, so mögt ihr +walten. Wie ihr aus Dunst und Nebel um mich steigt. Mein Busen fühlt sich +jugendlich erschüttert. Vom Zauberhauch der euren Zug umwittert. Ihr bringt mit +euch die Bilder froher Tage. Und manche liebe Schatten steigen auf Gleich einer +alten, halbverklungnen Sage. Kommt erste Lieb’ und Freundschaft mit herauf Der +Schmerz wird neu, es wiederholt die Klage. Des Lebens labyrinthisch irren Lauf, +Und nennt die Guten, die, um schöne Stunden Vom Glück getäuscht, vor mir +hinweggeschwunden. + +![Picture in sub folder](subfolder/subfolderprofile.png) + +### Mermaid Example + +{{< mermaid >}} +sequenceDiagram + Alice->>Bob: Hello Bob, how are you? + alt is sick + Bob->>Alice: Not so good :( + else is well + Bob->>Alice: Feeling fresh like a daisy + end + opt Extra response + Bob->>Alice: Thanks for asking + end +{{< /mermaid >}}