diff --git a/.gitignore b/.gitignore index 576c567..8518e0e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,9 @@ anna *.exe **/.DS_Store *.prof -ssg/ -*.txt dist/ #Test directories **/rendered/ test/**/static/ -test/**/got_sitemap.xml \ No newline at end of file +test/**/got_sitemap.xml diff --git a/cmd/anna/anna.go b/cmd/anna/anna.go index 0dc12e3..5323d75 100644 --- a/cmd/anna/anna.go +++ b/cmd/anna/anna.go @@ -66,6 +66,9 @@ func (cmd *Cmd) VanillaRender() { // Copies the contents of the 'static/' directory to 'rendered/' helper.CopyDirectoryContents(helpers.SiteDataPath+"static/", helpers.SiteDataPath+"rendered/static/") + // Copies the contents of the 'static/' directory to 'rendered/' + helper.CopyDirectoryContents(helpers.SiteDataPath+"public/", helpers.SiteDataPath+"rendered/") + e.GenerateSitemap(helpers.SiteDataPath + "rendered/sitemap.xml") e.GenerateFeed() e.GenerateJSONIndex(helpers.SiteDataPath) diff --git a/go.mod b/go.mod index 3fbc6bf..8da9c94 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.22.2 require ( github.com/PuerkitoBio/goquery v1.9.1 - github.com/cheggaaa/pb/v3 v3.1.5 github.com/mangoumbrella/goldmark-figure v1.0.0 github.com/spf13/cobra v1.8.0 github.com/yuin/goldmark v1.7.1 @@ -15,18 +14,11 @@ require ( ) require ( - github.com/VividCortex/ewma v1.2.0 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect - github.com/fatih/color v1.16.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/go.sum b/go.sum index 5ada711..8df404c 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,7 @@ github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= -github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= -github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= -github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk= -github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI= github.com/chromedp/cdproto v0.0.0-20230220211738-2b1ec77315c9 h1:wMSvdj3BswqfQOXp2R1bJOAE7xIQLt2dlMQDMf836VY= github.com/chromedp/cdproto v0.0.0-20230220211738-2b1ec77315c9/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.1 h1:CC7cC5p1BeLiiS2gfNNPwp3OaUxtRMBjfiw3E3k6dFA= @@ -16,8 +12,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= @@ -39,19 +33,9 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mangoumbrella/goldmark-figure v1.0.0 h1:L+ebP73dET0a2n68PV7m5oFJmwwH5GzRIJLgszR3fwo= github.com/mangoumbrella/goldmark-figure v1.0.0/go.mod h1:iIL+fhdmCQDpE0l/TKtGhokWzIbo5lo/Y2OIAcx6usI= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= @@ -90,9 +74,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/pkg/engine/anna_engine.go b/pkg/engine/anna_engine.go index 606a103..e68b093 100644 --- a/pkg/engine/anna_engine.go +++ b/pkg/engine/anna_engine.go @@ -123,7 +123,7 @@ func (e *Engine) GenerateJSONIndex(outFilePath string) { // It extracts data from the e.Templates slice // The index.json file is created during every VanillaRender() - jsonFile, err := os.Create(outFilePath + "/rendered/static/index.json") + jsonFile, err := os.Create(outFilePath + "rendered/static/index.json") if err != nil { e.ErrorLogger.Fatal(err) } diff --git a/pkg/engine/anna_engine_test.go b/pkg/engine/anna_engine_test.go index 45b43d1..c789fcf 100644 --- a/pkg/engine/anna_engine_test.go +++ b/pkg/engine/anna_engine_test.go @@ -132,7 +132,7 @@ func TestGenerateMergedJson(t *testing.T) { }, } - e.GenerateJSONIndex(TestDirPath + "json_index_test") + e.GenerateJSONIndex(TestDirPath + "json_index_test/") got_json, err := os.ReadFile(TestDirPath + "/json_index_test/rendered/static/index.json") if err != nil { diff --git a/pkg/helpers/helper.go b/pkg/helpers/helper.go index 7f86fb2..379ff37 100644 --- a/pkg/helpers/helper.go +++ b/pkg/helpers/helper.go @@ -1,16 +1,10 @@ package helpers import ( - "archive/zip" - "fmt" "io" "log" - "net/http" "os" - "path/filepath" "strings" - - "github.com/cheggaaa/pb/v3" ) const SiteDataPath string = "site/" @@ -87,91 +81,91 @@ func (h *Helper) CreateRenderedDir(fileOutPath string) { } } -func (h *Helper) Bootstrap() { - fmt.Println("Are you sure you want to proceed with the bootstrap process? (y/n)") - var confirm string - fmt.Scanln(&confirm) - if confirm != "y" { - fmt.Println("Bootstrap process cancelled.") - return - } - url := fmt.Sprintf("https://github.com/acmpesuecc/anna/archive/refs/tags/v%s.zip", version) - - output, err := os.Create("anna-dl.zip") - if err != nil { - fmt.Println("Error creating output file:", err) - return - } - defer output.Close() - response, err := http.Get(url) - if err != nil { - fmt.Println("Error downloading:", err) - return - } - defer response.Body.Close() - if response.StatusCode != http.StatusOK { - fmt.Println("Error: Server returned status", response.Status) - return - } - - bar := pb.Full.Start64(response.ContentLength) - defer bar.Finish() - reader := bar.NewProxyReader(response.Body) - - _, err = io.Copy(output, reader) - if err != nil { - fmt.Println("Error copying:", err) - return - } - ext(version) -} - -func ext(version string) { - zipFilePath := "anna-dl.zip" - zipFile, err := zip.OpenReader(zipFilePath) - if err != nil { - log.Fatal(err) - } - defer zipFile.Close() - for _, file := range zipFile.File { - zippedFile, err := file.Open() - if err != nil { - log.Fatal(err) - } - defer zippedFile.Close() - - extractedFilePath := filepath.Join(".", file.Name) // Extract to the current directory - if file.FileInfo().IsDir() { - err := os.MkdirAll(extractedFilePath, os.ModePerm) - if err != nil { - log.Fatal(err) - } - } else { - extractedFile, err := os.Create(extractedFilePath) - if err != nil { - log.Fatal(err) - } - defer extractedFile.Close() - - _, err = io.Copy(extractedFile, zippedFile) - if err != nil { - log.Fatal(err) - } - } - } - - // Bootstrap the base theme - helper := &Helper{ - ErrorLogger: log.New(os.Stderr, "ERROR: ", log.LstdFlags), - } - helper.CopyDirectoryContents(fmt.Sprintf("anna-%s/site/", version), "site/") - err = os.Remove("anna-dl.zip") - if err != nil { - log.Fatal("Error cleaning-up zip file:", err) - } - err = os.RemoveAll(fmt.Sprintf("anna-%s", version)) - if err != nil { - log.Fatal("Error deleting directory:", err) - } - log.Println("Bootstrapped base theme") -} +// func (h *Helper) Bootstrap() { +// fmt.Println("Are you sure you want to proceed with the bootstrap process? (y/n)") +// var confirm string +// fmt.Scanln(&confirm) +// if confirm != "y" { +// fmt.Println("Bootstrap process cancelled.") +// return +// } +// url := fmt.Sprintf("https://github.com/acmpesuecc/anna/archive/refs/tags/v%s.zip", version) + +// output, err := os.Create("anna-dl.zip") +// if err != nil { +// fmt.Println("Error creating output file:", err) +// return +// } +// defer output.Close() +// response, err := http.Get(url) +// if err != nil { +// fmt.Println("Error downloading:", err) +// return +// } +// defer response.Body.Close() +// if response.StatusCode != http.StatusOK { +// fmt.Println("Error: Server returned status", response.Status) +// return +// } + +// bar := pb.Full.Start64(response.ContentLength) +// defer bar.Finish() +// reader := bar.NewProxyReader(response.Body) + +// _, err = io.Copy(output, reader) +// if err != nil { +// fmt.Println("Error copying:", err) +// return +// } +// ext(version) +// } + +// func ext(version string) { +// zipFilePath := "anna-dl.zip" +// zipFile, err := zip.OpenReader(zipFilePath) +// if err != nil { +// log.Fatal(err) +// } +// defer zipFile.Close() +// for _, file := range zipFile.File { +// zippedFile, err := file.Open() +// if err != nil { +// log.Fatal(err) +// } +// defer zippedFile.Close() + +// extractedFilePath := filepath.Join(".", file.Name) // Extract to the current directory +// if file.FileInfo().IsDir() { +// err := os.MkdirAll(extractedFilePath, os.ModePerm) +// if err != nil { +// log.Fatal(err) +// } +// } else { +// extractedFile, err := os.Create(extractedFilePath) +// if err != nil { +// log.Fatal(err) +// } +// defer extractedFile.Close() + +// _, err = io.Copy(extractedFile, zippedFile) +// if err != nil { +// log.Fatal(err) +// } +// } +// } + +// // Bootstrap the base theme +// helper := &Helper{ +// ErrorLogger: log.New(os.Stderr, "ERROR: ", log.LstdFlags), +// } +// helper.CopyDirectoryContents(fmt.Sprintf("anna-%s/site/", version), "site/") +// err = os.Remove("anna-dl.zip") +// if err != nil { +// log.Fatal("Error cleaning-up zip file:", err) +// } +// err = os.RemoveAll(fmt.Sprintf("anna-%s", version)) +// if err != nil { +// log.Fatal("Error deleting directory:", err) +// } +// log.Println("Bootstrapped base theme") +// } diff --git a/pkg/helpers/helper_test.go b/pkg/helpers/helper_test.go index a04bf56..68529f8 100644 --- a/pkg/helpers/helper_test.go +++ b/pkg/helpers/helper_test.go @@ -3,25 +3,69 @@ package helpers_test import ( "io/fs" "log" + "os" + "slices" "testing" - "testing/fstest" + + "github.com/acmpesuecc/anna/pkg/helpers" ) -type Helper struct { - ErrorLogger *log.Logger - SiteDataPath string -} +var HelperTestDirPath = "../../test/helpers/" func TestCopyDirectoryContents(t *testing.T) { - t.Run("Testinf copying contents from A to B", func(t *testing.T) { - fsMock := fstest.MapFS{ - "index.md": {Data: []byte("# Index Page")}, - "about.md": {Data: []byte("# About Page")}, + t.Run("recursively copying directory contents", func(t *testing.T) { + helper := helpers.Helper{ + ErrorLogger: log.New(os.Stderr, "TEST ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), + } + helper.CopyDirectoryContents(HelperTestDirPath+"copy_dir/", HelperTestDirPath+"copy_dir/rendered/") + + baseDirFS := os.DirFS(HelperTestDirPath + "copy_dir/input_dir/") + TraverseDirectory(baseDirFS, t) + }) +} + +func TraverseDirectory(baseDirFS fs.FS, t *testing.T) error { + fs.WalkDir(baseDirFS, ".", func(path string, dir fs.DirEntry, err error) error { + if !dir.IsDir() { + got_file, err := os.ReadFile(HelperTestDirPath + "copy_dir/input_dir/" + path) + if err != nil { + t.Errorf("%v", err) + } + + want_file, err := os.ReadFile(HelperTestDirPath + "copy_dir/rendered/input_dir/" + path) + if err != nil { + t.Errorf("%v", err) + } + + if !slices.Equal(got_file, want_file) { + t.Errorf("The expected and generated files can be found in %s", HelperTestDirPath) + } + } + return nil + }) + return nil +} - fs.WalkDir(fsMock, ".", func(path string, d fs.DirEntry, err error) error { - return nil - }) +func TestCopyFiles(t *testing.T) { + t.Run("copy file and create nested parent directories", func(t *testing.T) { + helper := helpers.Helper{ + ErrorLogger: log.New(os.Stderr, "TEST ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), + } + helper.CopyFiles(HelperTestDirPath+"copy_files/input.txt", HelperTestDirPath+"copy_files/rendered/output.txt") + got_file, err := os.ReadFile(HelperTestDirPath + "copy_files/input.txt") + if err != nil { + t.Errorf("%v", err) + } + + want_file, err := os.ReadFile(HelperTestDirPath + "copy_files/rendered/output.txt") + if err != nil { + t.Errorf("%v", err) + } + + if !slices.Equal(got_file, want_file) { + t.Errorf("The expected and generated files can be found in %s", HelperTestDirPath) + } }) } diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index f1f5219..27870da 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -41,6 +41,7 @@ type Frontmatter struct { Description string `yaml:"description"` PreviewImage string `yaml:"previewimage"` Tags []string `yaml:"tags"` + TOC bool `yaml:"toc"` Authors []string `yaml:"authors"` // Head is specifically used for @@ -239,7 +240,7 @@ func (p *Parser) ParseMarkdownContent(filecontent string) (Frontmatter, string, var parsedMarkdown bytes.Buffer var md goldmark.Markdown - if parsedFrontmatter.Type == "post" { + if parsedFrontmatter.Type == "post" || parsedFrontmatter.TOC { md = goldmark.New( goldmark.WithParserOptions(parser.WithAutoHeadingID()), goldmark.WithExtensions( @@ -292,12 +293,12 @@ func (p *Parser) DateParse(date string) time.Time { } func (p *Parser) ParseConfig(inFilePath string) { - // Check if the configuration file exists - _, err := os.Stat(inFilePath) - if os.IsNotExist(err) { - p.Helper.Bootstrap() - return - } + // // Check if the configuration file exists + // _, err := os.Stat(inFilePath) + // if os.IsNotExist(err) { + // p.Helper.Bootstrap() + // return + // } // Read and parse the configuration file configFile, err := os.ReadFile(inFilePath) diff --git a/pkg/parser/parser_test.go b/pkg/parser/parser_test.go index 250ba97..419d8bb 100644 --- a/pkg/parser/parser_test.go +++ b/pkg/parser/parser_test.go @@ -170,3 +170,65 @@ func TestParseRobots(t *testing.T) { } }) } + +// func TestParseBacklink(t *testing.T) { + +// got_parser := parser.Parser{ +// Notes: make(map[template.URL]parser.Note), +// ErrorLogger: log.New(os.Stderr, "TEST ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), +// } + +// // creating dummy notes for testing + +// got_parser.Notes[template.URL("notes/test/test.md")] = parser.Note{ +// Frontmatter: parser.Frontmatter{ +// Title: "head note", +// Type: "note", +// Head: true, +// }, +// Body: template.HTML("This is a [[backlink]]"), +// } + +// got_parser.Notes[template.URL("notes/test/backlink.md")] = parser.Note{ +// Frontmatter: parser.Frontmatter{ +// Title: "backlink", +// Type: "note", +// }, +// Body: template.HTML("Content of note."), +// } + +// t.Run("testing backlink parsing in body of markdown files", func(t *testing.T) { + +// got_parser.ParseBacklink("notes/test/test.md") + +// want_parser := parser.Parser{ +// Notes: map[template.URL]parser.Note{ +// template.URL("notes/test/test.md"): parser.Note{ +// Frontmatter: parser.Frontmatter{ +// Title: "head note", +// Type: "note", +// Head: true, +// }, +// Body: template.HTML("This is a [[backlink]] here"), +// LinkedNoteURLs: []template.URL{"notes/test/backlink.md"}, +// }, + +// template.URL("notes/test/backlink.md"): parser.Note{ +// Frontmatter: parser.Frontmatter{ +// Title: "backlink", +// Type: "note", +// }, +// Body: template.HTML("Content of note."), +// }, +// }, +// ErrorLogger: log.New(os.Stderr, "TEST ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), +// } + +// got_list := got_parser.Notes["notes/test/test.md"].LinkedNoteURLs +// want_list := want_parser.Notes["notes/test/test.md"].LinkedNoteURLs + +// if !slices.Equal(got_list, want_list) { +// t.Errorf("got %v, want %v", got_list, want_list) +// } +// }) +// } diff --git a/pkg/parser/zettel_parser.go b/pkg/parser/zettel_parser.go index bd3902a..50aff08 100644 --- a/pkg/parser/zettel_parser.go +++ b/pkg/parser/zettel_parser.go @@ -114,11 +114,13 @@ func (p *Parser) ParseBacklink(noteURL template.URL) { MarkdownBody: note.MarkdownBody, LinkedNoteURLs: note.LinkedNoteURLs, } + // fmt.Println(p.Notes[noteURL]) } func (p *Parser) ValidateBackLink(noteTitle string) (template.URL, error) { for _, note := range p.Notes { if note.Frontmatter.Title == noteTitle { + // fmt.Println("URL: ", note.CompleteURL) return note.CompleteURL, nil } } diff --git a/site/content/developer-guide.md b/site/content/developer-guide.md new file mode 100644 index 0000000..3dc0bbb --- /dev/null +++ b/site/content/developer-guide.md @@ -0,0 +1,27 @@ +--- +date: 2024-04-28 +title: Developer Guide +type: page +toc: true +--- + +# Developer Guide + +--- + +## Contributing to Anna + +Detailed documentation for our SSG can be found: [here](https://anna-docs.netlify.app/) + +If you have git installed, clone our repository and build against the latest commit + +```sh +git clone github.com/acmpesuecc/anna; cd anna +go build +``` + +--- + +## Profiling + +The live profile data of the application can be viewed during live reload by navigating to `http://localhost:8000/debug/pprof` diff --git a/site/content/docs-update.md b/site/content/docs-update.md index c3cfeb2..3e3a5f4 100644 --- a/site/content/docs-update.md +++ b/site/content/docs-update.md @@ -4,13 +4,9 @@ title: Anna Documentation Updates type: page --- -- we are common mark compliant -- page and posts field to frontmatter -- recursively copies contents/ dir, so images and static content can be added in sub-dirs -- goldmark extension details: mermaid, toc, figure(Add caption beloe link, etc) - ## developer guide - profiling: + - live pprof during live reload - creating .pprof files diff --git a/site/content/docs.md b/site/content/docs.md index 29c2eeb..c197f81 100644 --- a/site/content/docs.md +++ b/site/content/docs.md @@ -1,87 +1,119 @@ --- -date: 2024-04-10 +date: 2024-04-28 title: Anna Documentation type: page +toc: true --- -# Anna - -```text - ___ - / | ____ ____ ____ _ - / /| | / __ \/ __ \/ __ `/ - / ___ |/ / / / / / / /_/ / -/_/ |_/_/ /_/_/ /_/\__,_/ - -A static site generator in go -``` - -Inspired by [Hugo](https://gohugo.io) and [Saaru](https://github.com/anirudhRowjee/saaru), this static site generator aims to take performance to the next level with parallel rendering, live reload and so much more, all in Go. - -Pronounced: `/ɐnĖÉ/` which means rice in Kannada šŸš - -This Project is a part of the ACM PESU-ECC's yearly [AIEP](https://acmpesuecc.github.io/aiep) program, and is maintained by [Adhesh Athrey](https://github.com/DedLad), [Nathan Paul](https://github.com/polarhive), [Anirudh Sudhir](https://github.com/anirudhsudhir), and [Aditya Hegde](https://github.com/bwaklog) - --- + ## Directory structure The ssg currently requires the following directory structure ```text -/anna -ā”œā”€ā”€ /cmd -ā”œā”€ā”€ /pkg -ā”‚Ā Ā  ā”œā”€ā”€ /engine -ā”‚Ā Ā  ā”œā”€ā”€ /helpers -ā”‚Ā Ā  ā””ā”€ā”€ /parser -ā”œā”€ā”€ /site -ā”‚ Ā Ā  ā”œā”€ā”€ /content -ā”‚ ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ /posts -ā”‚ ā”‚ ā”‚ ā”‚ ā””ā”€ā”€ sample.md -ā”‚ ā”‚ ā”‚Ā Ā  ā””ā”€ā”€ā”€ /notes -ā”‚ Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ index.md -ā”‚ ā”œā”€ā”€ /layout -ā”‚ ā”‚Ā Ā  ā”œā”€ā”€ config.yml (This file is necessary and cannot be omitted) -ā”‚ ā”‚Ā Ā  ā”œā”€ā”€ page.html (This file is necessary and cannot be omitted) -ā”‚ ā”‚Ā Ā  ā”œā”€ā”€ posts.html (This file is necessary to create a 'Posts' section) -ā”‚ ā”‚Ā Ā  ā””ā”€ā”€ā”€ /partials -ā”‚ ā”‚Ā Ā  Ā Ā  ā””ā”€ā”€ partials for page -ā”‚ ā”œā”€ā”€ /static -ā”‚ ā”‚Ā  ā”œā”€ā”€ /fonts -ā”‚ ā”‚Ā  ā”œā”€ā”€ /images -ā”‚ ā”‚Ā  ā”œā”€ā”€ plane.jpg -ā”‚ ā”‚Ā  ā”œā”€ā”€ /scripts -ā”‚ ā”‚Ā  ā””ā”€ā”€ style.css -ā”‚ Ā Ā  ā”” /rendered (This directory is created by the ssg) -ā””ā”€ā”€ /test (Stores mock data required to test the SSG) - ā”œā”€ā”€ /engine - ā”‚Ā Ā  ā”œā”€ā”€ /merged_data_test - ā”‚Ā Ā  ā”œā”€ā”€ /render_engine_generated - ā”‚Ā Ā  ā”œā”€ā”€ /render_page - ā”‚Ā Ā  ā”œā”€ā”€ /render_tags - ā”‚Ā Ā  ā””ā”€ā”€ /render_user_defined - ā””ā”€ā”€ /parser - ā”œā”€ā”€ /input - ā”œā”€ā”€ /layout - ā””ā”€ā”€ /parse_md +site +ā”œā”€ā”€ content +ā”‚Ā Ā  ā”œā”€ā”€ docs.md +ā”‚Ā Ā  ā”œā”€ā”€ index.md* +ā”‚Ā Ā  ā”œā”€ā”€ notes +ā”‚Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ anna +ā”‚Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ zettelkasten.md +ā”‚Ā Ā  ā”œā”€ā”€ posts +ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ bench.md +ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ building-anna +ā”‚Ā Ā  ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ images +ā”‚Ā Ā  ā”‚Ā Ā  ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ bench.png +ā”‚Ā Ā  ā”‚Ā Ā  ā”‚Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ wizard.gif +ā”‚Ā Ā  ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ index.md +ā”‚Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ weekly-progress +ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ week-1.md +ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ week-2.md +ā”‚Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ week-3.md +ā”œā”€ā”€ layout +ā”‚Ā Ā  ā”œā”€ā”€ config.yml* +ā”‚Ā Ā  ā”œā”€ā”€ note.html* +ā”‚Ā Ā  ā”œā”€ā”€ notes.html* +ā”‚Ā Ā  ā”œā”€ā”€ page.html* +ā”‚Ā Ā  ā”œā”€ā”€ partials +ā”‚Ā Ā  ā”‚Ā Ā  ā”œā”€ā”€ head.html +ā”‚Ā Ā  ā”œā”€ā”€ posts.html* +ā”‚Ā Ā  ā”œā”€ā”€ robots.txt* +ā”‚Ā Ā  ā”œā”€ā”€ tag-subpage.html* +ā”‚Ā Ā  ā””ā”€ā”€ tags.html* +ā”œā”€ā”€ public +ā””ā”€ā”€ static + ā”œā”€ā”€ fonts + ā”‚Ā Ā  ā”œā”€ā”€ VictorMono + ā”‚Ā Ā  ā”‚Ā Ā  ā””ā”€ā”€ victormono_italics.ttf + ā”œā”€ā”€ scripts + ā”‚Ā Ā  ā””ā”€ā”€ light.js + ā”œā”€ā”€ style.css + ā”œā”€ā”€ styles + Ā Ā  ā””ā”€ā”€ tokyo-dark.css ``` +Files marked \* are required and cannot be omitted + +Anna must be run from the parent of the site/ dir + +--- + ## Description of the directory structure - All of the site data, including the content, configuration and static files, are stores in site/. The rendered/ directory generated by ssg is also stored in site/. -- The markdown content for the site is stored in `content/` it can contain subdirectories as the folder is recursively rendered. -- Static assets such as images and fonts are stored in `static/` +- The markdown content for the site is stored in `content/`. It can contain subdirectories along with images as the folder is recursively rendered. + - The contents of this dir is rendered to the root of `rendered/` + - The `notes/` folder holds markdown notes which are rendered by a different process and include various note-specific features +- Static assets such as fonts are stored in `static/` - Scripts are stored in the `scripts/` dir in `static/` - The layout of the site is configured using html files in `layout/` - The `config.yml` file stores the configuration of the site and includes details such as the baseURL - - The `page.html` file defines the layout of a basic page of the site - - The `posts.html` file defines the layout of a page displaying all the posts of the site + - The `page.html`, `posts.html` and other necessary layouts define the structure of the various pages of the site such as posts.html, tags.html and regular pages - The layout files can be composed of smaller html files which are stored in the `partials/` folder +- Contents in `public/` are rendered to the root of `rendered/` + +--- ## Building layouts -Each layout file(except `posts.html`, `tags.html` & `notes.html`) can access any data from the entire ssg +Each layout file can access any data from the entire ssg + +The `posts.html` layout can access the following data + +- `{{.DeepDataMerge}}` +- `{{.PageURL}}` +- `{{.TemplateData}}` + +The `tags.html` page can access the following data + +- `{{.DeepDataMerge}}` +- `{{.PageURL}}` +- `{{.TemplateData}}` +- `{{.TagNames}}` + +The remaining pages can access the following data + +- `{{.DeepDataMerge}}` +- `{{.PageURL}}` + +### PageURL + +The `{{.PageURL}}` is of the form `index.html`, `posts/tech/go.html` and so on. + +### Elements stored in `DeepDataMerge` + +- `{{.DeepDataMerge.Templates}}` - A map that stores the template data of all the pages of the site for the particular url(the URL is the PageURL for the speicified page) +- `{{.DeepDataMerge.Tags}}` - A map that stores the template data of the tag sub-pages for a particular tag url +- `{{.DeepDataMerge.TagsMap}}` - A map that stores a slice of templates of all posts for a particular tag url +- `{{.DeepDataMerge.LayoutConfig}}` - Stores the layout parsed from `config.yml` +- `{{.DeepDataMerge.Posts}}` - Stores a slice of the template data of all posts +- `{{.DeepDataMerge.Notes}}` - Similar to `Posts` but for all the notes part of the site +- `{{.DeepDataMerge.LinkStore}}` - Stores a map which contains a slice of pointers to the _linked notes_. +- `{{.DeepDataMerge.JSONIndex}}` - Stores the JSON index generated for a particular site (primarily used for search and graphing of tags) + +### Accessing specific page data The URL for the current page can be accessed using `{{.PageURL}}` @@ -92,7 +124,11 @@ To access the data for a particular page, use Go templating syntax: {{$PageData.CompleteURL}} ``` -To access the page data for `posts.html`, `tags.html` and partials, set {{$PageData := .TemplateData}} +To access the page data for `posts.html`, `tags.html` and their respective partials, set + +```html +{{$PageData := .TemplateData}} +``` All of the following page data fields can be accessed in the above manner: @@ -101,51 +137,83 @@ All of the following page data fields can be accessed in the above manner: - `{{$PageData.Frontmatter.[Tagname]}}` : Returns the value of the frontmatter tag - Example: `{{$PageData.Frontmatter.Title}}` : Returns the value of the title tag - `{{$PageData.Body}}` : Returns the markdown body rendered to HTML -- `{{$PageData.Layout.[Tagname]}}`: Returns the particular configuration detail of the page - - Example: `{{$PageData.Layout.Navbar}}` : Returns a string slice with the names of all the navbar elements - -In addition to page data, the following fields can be accessed: - -- `{{.DeepDataMerge.Tags}}` - A map that stores the template of the tag sub-pages for a particular tag url -- `{{.DeepDataMerge.TagsMap}}` - A map that stores a slice of templates of all posts for a particular tag url -- `{{.DeepDataMerge.LayoutConfig}}` - Stores the layout parsed from `config.yml` -- `{{.DeepDataMerge.Posts}}` - Stores a slice of templates of all posts -- `{{.DeepDataMerge.JSONIndex}}` - Stores the JSON index generated for a particular site (primarily used for search and graphing of tags) -- `{{.DeepDataMerge.LinkStore}}` - Stores a map which contains a slice of pointers to the *linked notes*. -- `{{.DeepDataMerge.Notes}}` - Similar to `Posts` but for all the notes part of the site - -## Notes - -1. Images: To add images, add it to the 'static/' folder or a subdirectory under it. Use `/static/[imagename.format]` as the image link format in the markdown files. +--- -2. CSS: CSS can be added in the following ways: +## Frontmatter -- In an external file in the `static/` directory and linked to the layout files +Metadata such as the title of the page can be added as frontmatter to the markdown files in the YAML format. +This metadata can be accessed from the layout files with the appropriate syntax. - - To link the stylesheet, use the `baseURL` along with the relative path - - Example: `` - -- Placed inside `` tags in the `` of the layout files -- Inline with the html elements - -3. Frontmatter: Metadata such as the title of the page can be added as frontmatter to the markdown files in the YAML format. Currently, the following tags are supported: +Currently, the following frontmatter tags are supported: - `title` : The title of the current page - `date`: The date of the current page - `draft`: When set to 'true', the current page is not rendered unless the '-d' flag is used - `scripts`: Stores the page-level scripts to be added -- `type`: Sets the type of the page. Use type 'post' for posts & `note` for notes +- `type`: Sets the type of the page. Use type `page` for regular pages, `post` for posts & `note` for notes + +#### Important + +> anna will not render a page unless it contains the `type` field in the frontmatter + - `description`: Stores the description of the current post previewed in posts.html - `previewimage`: Stores the preview image of the current page - `tags`: Stores the tags of the particular page +- `toc`: When set to 'true', a table of contents is rendered for the current page + +#### Important + +> anna automatically renders a table of contents for every file of `type: post` + - `authors`: Stores (multiple) author/s of a particular page - `head`: Users need to manually specify head of the zettel in the frontmatter. Only head notes will be a part of `notes.html` -(**The above tags are Frontmatter tags**) +--- + +## Body + +Anna uses [Goldmark](https://github.com/yuin/goldmark) to render markdown files, which is CommonMark compliant + +A few useful goldmark extensions have been included: + +- [anchor](https://github.com/abhinav/goldmark-anchor) + - adds support for anchors next to all headers +- [figure](https://github.com/mangoumbrella/goldmark-figure) + - parse markdown paragraphs that start with an image into HTML `
` elements +- [mermaid](https://github.com/abhinav/goldmark-mermaid) + - adds support for [Mermaid](https://mermaid.js.org) diagrams +- [toc](https://github.com/abhinav/goldmark-toc) + - adds support for rendering a table-of-contents + +--- + +## Static assets + +### Images + +Images can be added to the `content/` dir, `public/` dir or the `static/` dir. +The contents of the `static/` and `public/` directories and the non-markdown files present in the `content/` dir are copied to `rendered/` + +The images can be referenced in the markdown files via their relative or absolute paths -4. config.yml: This file stores additional information regarding the layout of the site +### CSS + +CSS can be added in the following ways: + +- In an external file in the `static/` directory and linked to the layout files + + Example: `` + +- Placed inside `` tags in the `` of the layout files +- Inline with the html elements + +--- + +## Site configuration + +The config.yml file stores additional information regarding the layout of the site +It contains the following fields: - `navbar`: Stores the links to be added to the navbar (same name as the markdown files) - `baseURL`: Stores the base URL of the site @@ -153,8 +221,6 @@ In addition to page data, the following fields can be accessed: - `siteScripts`: Stores the javascript files to be included with every page - `author`: Stores the author of the site -(**The above tags are Layout tags**) - ### Sample `config.yml` ```yml @@ -177,91 +243,27 @@ author: Anna --- -# Notes Usage +## Notes Anna provides users with functionality of maintaining notes and sharing them. Notes opens another set of functionality for anna. Users can create under the `site/notes` directory. Besides similar use cases as a post, notes can be short snippets of information, code or even some kind of list that the users want. It supports some important aspects of [zettelkasten](https://zettelkasten.de/overview/) where users can link notes to each other, and organise similar posts in a zettel. We aren't trying to re-invent the process of making an editor that helps users maintain these zettels as there are already some fantastic applications, namely [Obsidian](https://obsidian.md/), [Ginko Writer](https://app.gingkowriter.com) and [Evergreen Notes](https://evergreennotes.com/). Our application as a rather needs to provide a generator to stitch these notes together to make it accessible on the site. -## Directory structure +### Notes directory structure ```text /notes ā”œā”€ā”€ /zettel A -ā””ā”€ā”€ /zettel B - Ā Ā  ā”œā”€ā”€ note A +ā””ā”€ā”€ /zettel B + Ā Ā  ā”œā”€ā”€ note A Ā Ā  ā”œā”€ā”€ note B - Ā Ā  ā””ā”€ā”€ note C + Ā Ā  ā””ā”€ā”€ note C ``` -## Linking Notes +### Linking Notes -Notes can be linked by using callouts in markdown files such as `[[]]`. The parser will validate these links during the runtime. It checks whether there are existing valid notes with a title matching the content of the callout. If not an error is thrown and you wont be able to compile the site. +Notes can be linked by using callouts in markdown files such as `[[]]`. The parser will validate these links during the runtime. It checks whether there are existing valid notes with a title matching the content of the callout. If not an error is thrown and you wont be able to compile the site. For example. If you have a note with the title `Note A` and you would like to reference it else where in another note (could even be part of another zettel). Then `[[Note A]]` would be the appropriate callout to use it. --- - -## Anna Usage - - -### Installing anna from releases - -Run this in the appropriate folder. Note that if you don't have a site dir with the pre-requisite layout template; anna proceeds to fetch the default site dir from our GitHub repository - -```sh -curl -L https://github.com/acmpesuecc/anna/releases/download/version-tag/releases-name.tar.gz > anna.tar.gz -tar -xvf anna.tar.gz # unzip the tar file -rm anna.tar.gz # removing the tar file - -# here you could add anna to your path if you want and use in in any directory -./anna # runs anna. The instructions are given below -``` - -### Brew taps for MacOS - -To get anna set up on your mac using brew taps, heres the repo you need to tap off from - -```sh -brew tap anna-ssg/anna -brew install anna - -# to run anna -anna -``` - -### Installing anna with go - -```sh -go run github.com/acmpesuecc/anna@v2.0.0 -``` - -### Flags for usage and purpose - -```text -Usage: - anna [flags] - -Flags: - -a, --addr string ip address to serve rendered content to (default "8000") - -d, --draft renders draft posts - -h, --help help for anna - -l, --layout validates html layouts - -p, --prof enable profiling - -s, --serve serve the rendered content - -v, --version prints current version number - -w, --webconsole wizard to setup anna -``` - - -## Contributing to Anna - -Detailed documentation for our SSG can be found: [here](https://anna-docs.netlify.app/) - -If you have git installed, clone our repository and build against the latest commit - -```sh -git clone github.com/acmpesuecc/anna; cd anna -go build -``` - diff --git a/site/content/quick-start.md b/site/content/quick-start.md new file mode 100644 index 0000000..411b150 --- /dev/null +++ b/site/content/quick-start.md @@ -0,0 +1,62 @@ +--- +date: 2024-04-28 +title: Quick Start +type: page +toc: true +--- + +# Quick Start + +--- + +## Installation + +### Installing anna from releases + +Run this in the appropriate folder. Note that if you don't have a site dir with the pre-requisite layout template; anna proceeds to fetch the default site dir from our GitHub repository + +```sh +curl -L https://github.com/acmpesuecc/anna/releases/download/version-tag/releases-name.tar.gz > anna.tar.gz +tar -xvf anna.tar.gz # unzip the tar file +rm anna.tar.gz # removing the tar file + +# here you could add anna to your path if you want and use in in any directory +./anna # runs anna. The instructions are given below +``` + +### Brew taps for MacOS + +To get anna set up on your mac using brew taps, heres the repo you need to tap off from + +```sh +brew tap anna-ssg/anna +brew install anna + +# to run anna +anna +``` + +### Installing anna with go + +```sh +go run github.com/acmpesuecc/anna@v2.0.0 +``` + +--- + +## Flags for usage and purpose + +```text +Usage: + anna [flags] + +Flags: + -a, --addr string ip address to serve rendered content to (default "8000") + -d, --draft renders draft posts + -h, --help help for anna + -l, --layout validates html layouts + -p, --prof enable profiling + -s, --serve serve the rendered content + -v, --version prints current version number + -w, --webconsole wizard to setup anna +``` diff --git a/site/layout/config.yml b/site/layout/config.yml index 39bd404..d22fb8c 100644 --- a/site/layout/config.yml +++ b/site/layout/config.yml @@ -1,6 +1,8 @@ navbar: - index + - quick-start - docs + - developer-guide - tags - notes - posts diff --git a/site/public/public.txt b/site/public/public.txt new file mode 100644 index 0000000..c799758 --- /dev/null +++ b/site/public/public.txt @@ -0,0 +1 @@ +This is a test .txt file that will be rendered to the root of rendered/ diff --git a/test/engine/json_index_test/want_index.json b/test/engine/json_index_test/want_index.json index ae28840..c563525 100644 --- a/test/engine/json_index_test/want_index.json +++ b/test/engine/json_index_test/want_index.json @@ -1 +1 @@ -{"docs.md":{"CompleteURL":"docs.html","Frontmatter":{"Title":"Anna Documentation","Date":"","Draft":false,"JSFiles":null,"Type":"","Description":"","PreviewImage":"","Tags":null,"Authors":null,"Head":false},"Tags":null}} +{"docs.md":{"CompleteURL":"docs.html","Frontmatter":{"Title":"Anna Documentation","Date":"","Draft":false,"JSFiles":null,"Type":"","Description":"","PreviewImage":"","Tags":null,"TOC":false,"Authors":null,"Head":false},"Tags":null}} diff --git a/test/helpers/copy_dir/input_dir/sub_dir2/sub_sub_dir2/file2.txt b/test/helpers/copy_dir/input_dir/sub_dir2/sub_sub_dir2/file2.txt new file mode 100644 index 0000000..d344db8 --- /dev/null +++ b/test/helpers/copy_dir/input_dir/sub_dir2/sub_sub_dir2/file2.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. diff --git a/test/helpers/copy_dir/input_dir/sub_dir_1/file1.txt b/test/helpers/copy_dir/input_dir/sub_dir_1/file1.txt new file mode 100644 index 0000000..d344db8 --- /dev/null +++ b/test/helpers/copy_dir/input_dir/sub_dir_1/file1.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. diff --git a/test/helpers/copy_files/input.txt b/test/helpers/copy_files/input.txt new file mode 100644 index 0000000..d344db8 --- /dev/null +++ b/test/helpers/copy_files/input.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper.