func createSortTestPages(num int) Pages { pages := make(Pages, num) info := newSiteInfo(siteBuilderCfg{baseURL: "http://base", language: helpers.NewDefaultLanguage()}) for i := 0; i < num; i++ { pages[i] = &Page{ Node: Node{ URLPath: URLPath{ Section: "z", URL: fmt.Sprintf("http://base/x/y/p%d.html", i), }, Site: &info, }, Source: Source{File: *source.NewFile(filepath.FromSlash(fmt.Sprintf("/x/y/p%d.md", i)))}, } w := 5 if i%2 == 0 { w = 10 } pages[i].fuzzyWordCount = i pages[i].Weight = w pages[i].Description = "initial" } return pages }
func TestPageCount(t *testing.T) { testCommonResetState() hugofs.InitMemFs() viper.Set("uglyURLs", false) viper.Set("paginate", 10) s := &Site{ Source: &source.InMemorySource{ByteSource: urlFakeSource}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "indexes/blue.html", indexTemplate); err != nil { t.Fatalf("Failed to build site: %s", err) } _, err := hugofs.Destination().Open("public/blue") if err != nil { t.Errorf("No indexed rendered.") } for _, s := range []string{ "public/sd1/foo/index.html", "public/sd2/index.html", "public/sd3/index.html", "public/sd4.html", } { if _, err := hugofs.Destination().Open(filepath.FromSlash(s)); err != nil { t.Errorf("No alias rendered: %s", s) } } }
func TestRobotsTXTOutput(t *testing.T) { testCommonResetState() hugofs.InitMemFs() viper.Set("baseurl", "http://auth/bub/") viper.Set("enableRobotsTXT", true) s := &Site{ Source: &source.InMemorySource{ByteSource: weightedSources}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "robots.txt", robotTxtTemplate); err != nil { t.Fatalf("Failed to build site: %s", err) } robotsFile, err := hugofs.Destination().Open("public/robots.txt") if err != nil { t.Fatalf("Unable to locate: robots.txt") } robots := helpers.ReaderToBytes(robotsFile) if !bytes.HasPrefix(robots, []byte("User-agent: Googlebot")) { t.Errorf("Robots file should start with 'User-agentL Googlebot'. %s", robots) } }
func TestSkipRender(t *testing.T) { testCommonResetState() hugofs.InitMemFs() sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc1.html"), Content: []byte("---\nmarkup: markdown\n---\n# title\nsome *content*")}, {Name: filepath.FromSlash("sect/doc2.html"), Content: []byte("<!doctype html><html><body>more content</body></html>")}, {Name: filepath.FromSlash("sect/doc3.md"), Content: []byte("# doc3\n*some* content")}, {Name: filepath.FromSlash("sect/doc4.md"), Content: []byte("---\ntitle: doc4\n---\n# doc4\n*some content*")}, {Name: filepath.FromSlash("sect/doc5.html"), Content: []byte("<!doctype html><html>{{ template \"head\" }}<body>body5</body></html>")}, {Name: filepath.FromSlash("sect/doc6.html"), Content: []byte("<!doctype html><html>{{ template \"head_abs\" }}<body>body5</body></html>")}, {Name: filepath.FromSlash("doc7.html"), Content: []byte("<html><body>doc7 content</body></html>")}, {Name: filepath.FromSlash("sect/doc8.html"), Content: []byte("---\nmarkup: md\n---\n# title\nsome *content*")}, } viper.Set("defaultExtension", "html") viper.Set("verbose", true) viper.Set("canonifyURLs", true) viper.Set("baseURL", "http://auth/bub") s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, targets: targetList{page: &target.PagePub{UglyURLs: true}}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "_default/single.html", "{{.Content}}", "head", "<head><script src=\"script.js\"></script></head>", "head_abs", "<head><script src=\"/script.js\"></script></head>"); err != nil { t.Fatalf("Failed to build site: %s", err) } tests := []struct { doc string expected string }{ {filepath.FromSlash("sect/doc1.html"), "\n\n<h1 id=\"title\">title</h1>\n\n<p>some <em>content</em></p>\n"}, {filepath.FromSlash("sect/doc2.html"), "<!doctype html><html><body>more content</body></html>"}, {filepath.FromSlash("sect/doc3.html"), "\n\n<h1 id=\"doc3\">doc3</h1>\n\n<p><em>some</em> content</p>\n"}, {filepath.FromSlash("sect/doc4.html"), "\n\n<h1 id=\"doc4\">doc4</h1>\n\n<p><em>some content</em></p>\n"}, {filepath.FromSlash("sect/doc5.html"), "<!doctype html><html><head><script src=\"script.js\"></script></head><body>body5</body></html>"}, {filepath.FromSlash("sect/doc6.html"), "<!doctype html><html><head><script src=\"http://auth/bub/script.js\"></script></head><body>body5</body></html>"}, {filepath.FromSlash("doc7.html"), "<html><body>doc7 content</body></html>"}, {filepath.FromSlash("sect/doc8.html"), "\n\n<h1 id=\"title\">title</h1>\n\n<p>some <em>content</em></p>\n"}, } for _, test := range tests { file, err := hugofs.Destination().Open(test.doc) if err != nil { t.Fatalf("Did not find %s in target.", test.doc) } content := helpers.ReaderToString(file) if content != test.expected { t.Errorf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content) } } }
func TestDraftAndFutureRender(t *testing.T) { testCommonResetState() hugofs.InitMemFs() sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc1.md"), Content: []byte("---\ntitle: doc1\ndraft: true\npublishdate: \"2414-05-29\"\n---\n# doc1\n*some content*")}, {Name: filepath.FromSlash("sect/doc2.md"), Content: []byte("---\ntitle: doc2\ndraft: true\npublishdate: \"2012-05-29\"\n---\n# doc2\n*some content*")}, {Name: filepath.FromSlash("sect/doc3.md"), Content: []byte("---\ntitle: doc3\ndraft: false\npublishdate: \"2414-05-29\"\n---\n# doc3\n*some content*")}, {Name: filepath.FromSlash("sect/doc4.md"), Content: []byte("---\ntitle: doc4\ndraft: false\npublishdate: \"2012-05-29\"\n---\n# doc4\n*some content*")}, } siteSetup := func(t *testing.T) *Site { s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, Language: helpers.NewDefaultLanguage(), } if err := buildSiteSkipRender(s); err != nil { t.Fatalf("Failed to build site: %s", err) } return s } viper.Set("baseURL", "http://auth/bub") // Testing Defaults.. Only draft:true and publishDate in the past should be rendered s := siteSetup(t) if len(s.AllPages) != 1 { t.Fatal("Draft or Future dated content published unexpectedly") } // only publishDate in the past should be rendered viper.Set("buildDrafts", true) s = siteSetup(t) if len(s.AllPages) != 2 { t.Fatal("Future Dated Posts published unexpectedly") } // drafts should not be rendered, but all dates should viper.Set("buildDrafts", false) viper.Set("buildFuture", true) s = siteSetup(t) if len(s.AllPages) != 2 { t.Fatal("Draft posts published unexpectedly") } // all 4 should be included viper.Set("buildDrafts", true) viper.Set("buildFuture", true) s = siteSetup(t) if len(s.AllPages) != 4 { t.Fatal("Drafts or Future posts not included as expected") } //setting defaults back viper.Set("buildDrafts", false) viper.Set("buildFuture", false) }
func TestAbsURLify(t *testing.T) { testCommonResetState() viper.Set("defaultExtension", "html") hugofs.InitMemFs() sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc1.html"), Content: []byte("<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>")}, {Name: filepath.FromSlash("blue/doc2.html"), Content: []byte("---\nf: t\n---\n<!doctype html><html><body>more content</body></html>")}, } for _, baseURL := range []string{"http://auth/bub", "http://base", "//base"} { for _, canonify := range []bool{true, false} { viper.Set("canonifyURLs", canonify) viper.Set("baseURL", baseURL) s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, targets: targetList{page: &target.PagePub{UglyURLs: true}}, Language: helpers.NewDefaultLanguage(), } t.Logf("Rendering with baseURL %q and canonifyURLs set %v", viper.GetString("baseURL"), canonify) if err := buildAndRenderSite(s, "blue/single.html", templateWithURLAbs); err != nil { t.Fatalf("Failed to build site: %s", err) } tests := []struct { file, expected string }{ {"blue/doc2.html", "<a href=\"%s/foobar.jpg\">Going</a>"}, {"sect/doc1.html", "<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>"}, } for _, test := range tests { file, err := hugofs.Destination().Open(filepath.FromSlash(test.file)) if err != nil { t.Fatalf("Unable to locate rendered content: %s", test.file) } content := helpers.ReaderToString(file) expected := test.expected if strings.Contains(expected, "%s") { expected = fmt.Sprintf(expected, baseURL) } if !canonify { expected = strings.Replace(expected, baseURL, "", -1) } if content != expected { t.Errorf("AbsURLify with baseURL %q content expected:\n%q\ngot\n%q", baseURL, expected, content) } } } } }
func createTestSite(pageSources []source.ByteSource) *Site { hugofs.InitMemFs() return &Site{ Source: &source.InMemorySource{ByteSource: pageSources}, Language: helpers.NewDefaultLanguage(), } }
func loadDefaultSettings() { viper.SetDefault("cleanDestinationDir", false) viper.SetDefault("watch", false) viper.SetDefault("metaDataFormat", "toml") viper.SetDefault("disable404", false) viper.SetDefault("disableRSS", false) viper.SetDefault("disableSitemap", false) viper.SetDefault("disableRobotsTXT", false) viper.SetDefault("contentDir", "content") viper.SetDefault("layoutDir", "layouts") viper.SetDefault("staticDir", "static") viper.SetDefault("archetypeDir", "archetypes") viper.SetDefault("publishDir", "public") viper.SetDefault("dataDir", "data") viper.SetDefault("i18nDir", "i18n") viper.SetDefault("themesDir", "themes") viper.SetDefault("defaultLayout", "post") viper.SetDefault("buildDrafts", false) viper.SetDefault("buildFuture", false) viper.SetDefault("buildExpired", false) viper.SetDefault("uglyURLs", false) viper.SetDefault("verbose", false) viper.SetDefault("ignoreCache", false) viper.SetDefault("canonifyURLs", false) viper.SetDefault("relativeURLs", false) viper.SetDefault("removePathAccents", false) viper.SetDefault("taxonomies", map[string]string{"tag": "tags", "category": "categories"}) viper.SetDefault("permalinks", make(PermalinkOverrides, 0)) viper.SetDefault("sitemap", Sitemap{Priority: -1, Filename: "sitemap.xml"}) viper.SetDefault("defaultExtension", "html") viper.SetDefault("pygmentsStyle", "monokai") viper.SetDefault("pygmentsUseClasses", false) viper.SetDefault("pygmentsCodeFences", false) viper.SetDefault("pygmentsOptions", "") viper.SetDefault("disableLiveReload", false) viper.SetDefault("pluralizeListTitles", true) viper.SetDefault("preserveTaxonomyNames", false) viper.SetDefault("forceSyncStatic", false) viper.SetDefault("footnoteAnchorPrefix", "") viper.SetDefault("footnoteReturnLinkContents", "") viper.SetDefault("newContentEditor", "") viper.SetDefault("paginate", 10) viper.SetDefault("paginatePath", "page") viper.SetDefault("blackfriday", helpers.NewBlackfriday(viper.GetViper())) viper.SetDefault("rSSUri", "index.xml") viper.SetDefault("sectionPagesMenu", "") viper.SetDefault("disablePathToLower", false) viper.SetDefault("hasCJKLanguage", false) viper.SetDefault("enableEmoji", false) viper.SetDefault("pygmentsCodeFencesGuessSyntax", false) viper.SetDefault("useModTimeAsFallback", false) viper.SetDefault("currentContentLanguage", helpers.NewDefaultLanguage()) viper.SetDefault("defaultContentLanguage", "en") viper.SetDefault("defaultContentLanguageInSubdir", false) viper.SetDefault("enableMissingTranslationPlaceholders", false) viper.SetDefault("enableGitInfo", false) }
func TestOrderedPages(t *testing.T) { testCommonResetState() hugofs.InitMemFs() viper.Set("baseURL", "http://auth/bub") s := &Site{ Source: &source.InMemorySource{ByteSource: weightedSources}, Language: helpers.NewDefaultLanguage(), } if err := buildSiteSkipRender(s); err != nil { t.Fatalf("Failed to process site: %s", err) } if s.Sections["sect"][0].Weight != 2 || s.Sections["sect"][3].Weight != 6 { t.Errorf("Pages in unexpected order. First should be '%d', got '%d'", 2, s.Sections["sect"][0].Weight) } if s.Sections["sect"][1].Page.Title != "Three" || s.Sections["sect"][2].Page.Title != "Four" { t.Errorf("Pages in unexpected order. Second should be '%s', got '%s'", "Three", s.Sections["sect"][1].Page.Title) } bydate := s.Pages.ByDate() if bydate[0].Title != "One" { t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "One", bydate[0].Title) } rev := bydate.Reverse() if rev[0].Title != "Three" { t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "Three", rev[0].Title) } bypubdate := s.Pages.ByPublishDate() if bypubdate[0].Title != "One" { t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "One", bypubdate[0].Title) } rbypubdate := bypubdate.Reverse() if rbypubdate[0].Title != "Three" { t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "Three", rbypubdate[0].Title) } bylength := s.Pages.ByLength() if bylength[0].Title != "One" { t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "One", bylength[0].Title) } rbylength := bylength.Reverse() if rbylength[0].Title != "Four" { t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "Four", rbylength[0].Title) } }
func newMultiLingualFromSites(sites ...*Site) (*Multilingual, error) { languages := make(helpers.Languages, len(sites)) for i, s := range sites { if s.Language == nil { return nil, errors.New("Missing language for site") } languages[i] = s.Language } return &Multilingual{Languages: languages, DefaultLang: helpers.NewDefaultLanguage()}, nil }
func setupLinkingMockSite(t *testing.T) *Site { hugofs.InitMemFs() sources := []source.ByteSource{ {Name: filepath.FromSlash("index.md"), Content: []byte("")}, {Name: filepath.FromSlash("rootfile.md"), Content: []byte("")}, {Name: filepath.FromSlash("root-image.png"), Content: []byte("")}, {Name: filepath.FromSlash("level2/2-root.md"), Content: []byte("")}, {Name: filepath.FromSlash("level2/index.md"), Content: []byte("")}, {Name: filepath.FromSlash("level2/common.md"), Content: []byte("")}, // {Name: filepath.FromSlash("level2b/2b-root.md"), Content: []byte("")}, // {Name: filepath.FromSlash("level2b/index.md"), Content: []byte("")}, // {Name: filepath.FromSlash("level2b/common.md"), Content: []byte("")}, {Name: filepath.FromSlash("level2/2-image.png"), Content: []byte("")}, {Name: filepath.FromSlash("level2/common.png"), Content: []byte("")}, {Name: filepath.FromSlash("level2/level3/3-root.md"), Content: []byte("")}, {Name: filepath.FromSlash("level2/level3/index.md"), Content: []byte("")}, {Name: filepath.FromSlash("level2/level3/common.md"), Content: []byte("")}, {Name: filepath.FromSlash("level2/level3/3-image.png"), Content: []byte("")}, {Name: filepath.FromSlash("level2/level3/common.png"), Content: []byte("")}, } viper.Set("baseurl", "http://auth/") viper.Set("DefaultExtension", "html") viper.Set("UglyURLs", false) viper.Set("PluralizeListTitles", false) viper.Set("CanonifyURLs", false) viper.Set("blackfriday", // TODO(bep) see https://github.com/spf13/viper/issues/261 map[string]interface{}{ strings.ToLower("sourceRelativeLinksProjectFolder"): "/docs"}) site := &Site{ Source: &source.InMemorySource{ByteSource: sources}, Language: helpers.NewDefaultLanguage(), } if err := buildSiteSkipRender(site); err != nil { t.Fatalf("Failed to build site: %s", err) } return site }
func TestPagePaths(t *testing.T) { testCommonResetState() viper.Set("defaultExtension", "html") siteParmalinksSetting := PermalinkOverrides{ "post": ":year/:month/:day/:title/", } tests := []struct { content string path string hasPermalink bool expected string }{ {simplePage, "content/post/x.md", false, "content/post/x.html"}, {simplePageWithURL, "content/post/x.md", false, "simple/url/index.html"}, {simplePageWithSlug, "content/post/x.md", false, "content/post/simple-slug.html"}, {simplePageWithDate, "content/post/x.md", true, "2013/10/15/simple/index.html"}, {UTF8Page, "content/post/x.md", false, "content/post/x.html"}, {UTF8PageWithURL, "content/post/x.md", false, "ラーメン/url/index.html"}, {UTF8PageWithSlug, "content/post/x.md", false, "content/post/ラーメン-slug.html"}, {UTF8PageWithDate, "content/post/x.md", true, "2013/10/15/ラーメン/index.html"}, } for _, test := range tests { p, _ := NewPageFrom(strings.NewReader(test.content), filepath.FromSlash(test.path)) info := newSiteInfo(siteBuilderCfg{language: helpers.NewDefaultLanguage()}) p.Node.Site = &info if test.hasPermalink { p.Node.Site.Permalinks = siteParmalinksSetting } expectedTargetPath := filepath.FromSlash(test.expected) expectedFullFilePath := filepath.FromSlash(test.path) if p.TargetPath() != expectedTargetPath { t.Errorf("%s => TargetPath expected: '%s', got: '%s'", test.content, expectedTargetPath, p.TargetPath()) } if p.FullFilePath() != expectedFullFilePath { t.Errorf("%s => FullFilePath expected: '%s', got: '%s'", test.content, expectedFullFilePath, p.FullFilePath()) } } }
func TestSitemapOutput(t *testing.T) { testCommonResetState() viper.Set("baseurl", "http://auth/bub/") s := &Site{ Source: &source.InMemorySource{ByteSource: weightedSources}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "sitemap.xml", SITEMAP_TEMPLATE); err != nil { t.Fatalf("Failed to build site: %s", err) } sitemapContent := readDestination(t, "public/sitemap.xml") if !strings.HasPrefix(sitemapContent, "<?xml") { t.Errorf("Sitemap file should start with <?xml. %s", sitemapContent) } }
func TestFutureExpirationRender(t *testing.T) { testCommonResetState() hugofs.InitMemFs() sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc3.md"), Content: []byte("---\ntitle: doc1\nexpirydate: \"2400-05-29\"\n---\n# doc1\n*some content*")}, {Name: filepath.FromSlash("sect/doc4.md"), Content: []byte("---\ntitle: doc2\nexpirydate: \"2000-05-29\"\n---\n# doc2\n*some content*")}, } siteSetup := func(t *testing.T) *Site { s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, Language: helpers.NewDefaultLanguage(), } if err := buildSiteSkipRender(s); err != nil { t.Fatalf("Failed to build site: %s", err) } return s } viper.Set("baseURL", "http://auth/bub") s := siteSetup(t) if len(s.AllPages) != 1 { if len(s.AllPages) > 1 { t.Fatal("Expired content published unexpectedly") } if len(s.AllPages) < 1 { t.Fatal("Valid content expired unexpectedly") } } if s.AllPages[0].Title == "doc2" { t.Fatal("Expired content published unexpectedly") } }
func TestPermalinkExpansion(t *testing.T) { page, err := NewPageFrom(strings.NewReader(simplePageJSON), "blue/test-page.md") info := newSiteInfo(siteBuilderCfg{language: helpers.NewDefaultLanguage()}) page.Site = &info if err != nil { t.Fatalf("failed before we began, could not parse SIMPLE_PAGE_JSON: %s", err) } for _, item := range testdataPermalinks { if !item.valid { continue } pp := pathPattern(item.spec) result, err := pp.Expand(page) if err != nil { t.Errorf("failed to expand page: %s", err) continue } if result != item.expandsTo { t.Errorf("expansion mismatch!\n\tExpected: %q\n\tReceived: %q", item.expandsTo, result) } } }
func TestWeightedTaxonomies(t *testing.T) { testCommonResetState() hugofs.InitMemFs() sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc1.md"), Content: pageWithWeightedTaxonomies2}, {Name: filepath.FromSlash("sect/doc2.md"), Content: pageWithWeightedTaxonomies1}, {Name: filepath.FromSlash("sect/doc3.md"), Content: pageWithWeightedTaxonomies3}, } taxonomies := make(map[string]string) taxonomies["tag"] = "tags" taxonomies["category"] = "categories" viper.Set("baseURL", "http://auth/bub") viper.Set("taxonomies", taxonomies) s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, Language: helpers.NewDefaultLanguage(), } if err := buildSiteSkipRender(s); err != nil { t.Fatalf("Failed to process site: %s", err) } if s.Taxonomies["tags"]["a"][0].Page.Title != "foo" { t.Errorf("Pages in unexpected order, 'foo' expected first, got '%v'", s.Taxonomies["tags"]["a"][0].Page.Title) } if s.Taxonomies["categories"]["d"][0].Page.Title != "bar" { t.Errorf("Pages in unexpected order, 'bar' expected first, got '%v'", s.Taxonomies["categories"]["d"][0].Page.Title) } if s.Taxonomies["categories"]["e"][0].Page.Title != "bza" { t.Errorf("Pages in unexpected order, 'bza' expected first, got '%v'", s.Taxonomies["categories"]["e"][0].Page.Title) } }
func _TestPageTargetUgly(t *testing.T) { testCommonResetState() viper.Set("DefaultExtension", "html") viper.Set("UglyURLs", true) s := &Site{ targets: targetList{page: &target.PagePub{UglyURLs: true, PublishDir: "public"}}, Source: &source.InMemorySource{ByteSource: fakeSource}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s); err != nil { t.Fatalf("Failed to build site: %s", err) } expected := "foo/bar/file.md (renderer: markdown)\n canonical => public/foo/bar/file.html\n\n" + "alias/test/file1.md (renderer: markdown)\n" + " canonical => public/alias/test/file1.html\n" + " alias1/ => public/alias1/index.html\n" + " alias-2/ => public/alias-2/index.html\n\n" + "public/section/somecontent.html (renderer: n/a)\n canonical => public/section/somecontent.html\n\n" checkShowPlanExpected(t, s, expected) }
func createSitesFromConfig() ([]*Site, error) { var sites []*Site multilingual := viper.GetStringMap("Languages") if len(multilingual) == 0 { sites = append(sites, newSite(helpers.NewDefaultLanguage())) } if len(multilingual) > 0 { var err error languages, err := toSortedLanguages(multilingual) if err != nil { return nil, fmt.Errorf("Failed to parse multilingual config: %s", err) } for _, lang := range languages { sites = append(sites, newSite(lang)) } } return sites, nil }
func newMultiLingualDefaultLanguage() *Multilingual { return newMultiLingualForLanguage(helpers.NewDefaultLanguage()) }
func doTestCrossrefs(t *testing.T, relative, uglyURLs bool) { testCommonResetState() baseURL := "http://foo/bar" viper.Set("defaultExtension", "html") viper.Set("baseURL", baseURL) viper.Set("uglyURLs", uglyURLs) viper.Set("verbose", true) var refShortcode string var expectedBase string var expectedURLSuffix string var expectedPathSuffix string if relative { refShortcode = "relref" expectedBase = "/bar" } else { refShortcode = "ref" expectedBase = baseURL } if uglyURLs { expectedURLSuffix = ".html" expectedPathSuffix = ".html" } else { expectedURLSuffix = "/" expectedPathSuffix = "/index.html" } sources := []source.ByteSource{ { Name: filepath.FromSlash("sect/doc1.md"), Content: []byte(fmt.Sprintf(`Ref 2: {{< %s "sect/doc2.md" >}}`, refShortcode)), }, // Issue #1148: Make sure that no P-tags is added around shortcodes. { Name: filepath.FromSlash("sect/doc2.md"), Content: []byte(fmt.Sprintf(`**Ref 1:** {{< %s "sect/doc1.md" >}} THE END.`, refShortcode)), }, // Issue #1753: Should not add a trailing newline after shortcode. { Name: filepath.FromSlash("sect/doc3.md"), Content: []byte(fmt.Sprintf(`**Ref 1:**{{< %s "sect/doc3.md" >}}.`, refShortcode)), }, } s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, targets: targetList{page: &target.PagePub{UglyURLs: uglyURLs}}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "_default/single.html", "{{.Content}}"); err != nil { t.Fatalf("Failed to build site: %s", err) } if len(s.AllPages) != 3 { t.Fatalf("Expected 3 got %d pages", len(s.AllPages)) } tests := []struct { doc string expected string }{ {filepath.FromSlash(fmt.Sprintf("sect/doc1%s", expectedPathSuffix)), fmt.Sprintf("<p>Ref 2: %s/sect/doc2%s</p>\n", expectedBase, expectedURLSuffix)}, {filepath.FromSlash(fmt.Sprintf("sect/doc2%s", expectedPathSuffix)), fmt.Sprintf("<p><strong>Ref 1:</strong></p>\n\n%s/sect/doc1%s\n\n<p>THE END.</p>\n", expectedBase, expectedURLSuffix)}, {filepath.FromSlash(fmt.Sprintf("sect/doc3%s", expectedPathSuffix)), fmt.Sprintf("<p><strong>Ref 1:</strong>%s/sect/doc3%s.</p>\n", expectedBase, expectedURLSuffix)}, } for _, test := range tests { file, err := hugofs.Destination().Open(test.doc) if err != nil { t.Fatalf("Did not find %s in target: %s", test.doc, err) } content := helpers.ReaderToString(file) if content != test.expected { t.Fatalf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content) } } }
func doTestShouldAlwaysHaveUglyURLs(t *testing.T, uglyURLs bool) { testCommonResetState() viper.Set("defaultExtension", "html") viper.Set("verbose", true) viper.Set("baseURL", "http://auth/bub") viper.Set("disableSitemap", false) viper.Set("disableRSS", false) viper.Set("rssURI", "index.xml") viper.Set("blackfriday", map[string]interface{}{ "plainIDAnchors": true}) viper.Set("uglyURLs", uglyURLs) sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc1.md"), Content: []byte("---\nmarkup: markdown\n---\n# title\nsome *content*")}, {Name: filepath.FromSlash("sect/doc2.md"), Content: []byte("---\nurl: /ugly.html\nmarkup: markdown\n---\n# title\ndoc2 *content*")}, } s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, targets: targetList{page: &target.PagePub{UglyURLs: uglyURLs, PublishDir: "public"}}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "index.html", "Home Sweet {{ if.IsHome }}Home{{ end }}.", "_default/single.html", "{{.Content}}{{ if.IsHome }}This is not home!{{ end }}", "404.html", "Page Not Found.{{ if.IsHome }}This is not home!{{ end }}", "rss.xml", "<root>RSS</root>", "sitemap.xml", "<root>SITEMAP</root>"); err != nil { t.Fatalf("Failed to build site: %s", err) } var expectedPagePath string if uglyURLs { expectedPagePath = "public/sect/doc1.html" } else { expectedPagePath = "public/sect/doc1/index.html" } tests := []struct { doc string expected string }{ {filepath.FromSlash("public/index.html"), "Home Sweet Home."}, {filepath.FromSlash(expectedPagePath), "\n\n<h1 id=\"title\">title</h1>\n\n<p>some <em>content</em></p>\n"}, {filepath.FromSlash("public/404.html"), "Page Not Found."}, {filepath.FromSlash("public/index.xml"), "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n<root>RSS</root>"}, {filepath.FromSlash("public/sitemap.xml"), "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n<root>SITEMAP</root>"}, // Issue #1923 {filepath.FromSlash("public/ugly.html"), "\n\n<h1 id=\"title\">title</h1>\n\n<p>doc2 <em>content</em></p>\n"}, } for _, p := range s.Pages { assert.False(t, p.IsHome) } for _, test := range tests { content := readDestination(t, test.doc) if content != test.expected { t.Errorf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content) } } }
func newHugoSitesDefaultLanguage() (*HugoSites, error) { return newHugoSitesFromSourceAndLanguages(nil, helpers.Languages{helpers.NewDefaultLanguage()}) }
func doTestSectionNaming(t *testing.T, canonify, uglify, pluralize bool) { hugofs.InitMemFs() testCommonResetState() viper.Set("baseURL", "http://auth/sub/") viper.Set("defaultExtension", "html") viper.Set("uglyURLs", uglify) viper.Set("pluralizeListTitles", pluralize) viper.Set("canonifyURLs", canonify) var expectedPathSuffix string if uglify { expectedPathSuffix = ".html" } else { expectedPathSuffix = "/index.html" } sources := []source.ByteSource{ {Name: filepath.FromSlash("sect/doc1.html"), Content: []byte("doc1")}, {Name: filepath.FromSlash("Fish and Chips/doc2.html"), Content: []byte("doc2")}, {Name: filepath.FromSlash("ラーメン/doc3.html"), Content: []byte("doc3")}, } s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, targets: targetList{page: &target.PagePub{UglyURLs: uglify}}, Language: helpers.NewDefaultLanguage(), } if err := buildAndRenderSite(s, "_default/single.html", "{{.Content}}", "_default/list.html", "{{ .Title }}"); err != nil { t.Fatalf("Failed to build site: %s", err) } tests := []struct { doc string pluralAware bool expected string }{ {filepath.FromSlash(fmt.Sprintf("sect/doc1%s", expectedPathSuffix)), false, "doc1"}, {filepath.FromSlash(fmt.Sprintf("sect%s", expectedPathSuffix)), true, "Sect"}, {filepath.FromSlash(fmt.Sprintf("fish-and-chips/doc2%s", expectedPathSuffix)), false, "doc2"}, {filepath.FromSlash(fmt.Sprintf("fish-and-chips%s", expectedPathSuffix)), true, "Fish and Chips"}, {filepath.FromSlash(fmt.Sprintf("ラーメン/doc3%s", expectedPathSuffix)), false, "doc3"}, {filepath.FromSlash(fmt.Sprintf("ラーメン%s", expectedPathSuffix)), true, "ラーメン"}, } for _, test := range tests { file, err := hugofs.Destination().Open(test.doc) if err != nil { t.Fatalf("Did not find %s in target: %s", test.doc, err) } content := helpers.ReaderToString(file) if test.pluralAware && pluralize { test.expected = inflect.Pluralize(test.expected) } if content != test.expected { t.Errorf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content) } } }
func TestShortcodesInSite(t *testing.T) { testCommonResetState() baseURL := "http://foo/bar" viper.Set("DefaultExtension", "html") viper.Set("DefaultContentLanguage", "en") viper.Set("baseurl", baseURL) viper.Set("UglyURLs", false) viper.Set("verbose", true) viper.Set("pygmentsuseclasses", true) viper.Set("pygmentscodefences", true) tests := []struct { contentPath string content string outFile string expected string }{ {"sect/doc1.md", `a{{< b >}}c`, filepath.FromSlash("sect/doc1/index.html"), "<p>abc</p>\n"}, // Issue #1642: Multiple shortcodes wrapped in P // Deliberately forced to pass even if they maybe shouldn't. {"sect/doc2.md", `a {{< b >}} {{< c >}} {{< d >}} e`, filepath.FromSlash("sect/doc2/index.html"), "<p>a</p>\n\n<p>b<br />\nc\nd</p>\n\n<p>e</p>\n"}, {"sect/doc3.md", `a {{< b >}} {{< c >}} {{< d >}} e`, filepath.FromSlash("sect/doc3/index.html"), "<p>a</p>\n\n<p>b<br />\nc</p>\n\nd\n\n<p>e</p>\n"}, {"sect/doc4.md", `a {{< b >}} {{< b >}} {{< b >}} {{< b >}} {{< b >}} `, filepath.FromSlash("sect/doc4/index.html"), "<p>a\nb\nb\nb\nb\nb</p>\n"}, // #2192 #2209: Shortcodes in markdown headers {"sect/doc5.md", `# {{< b >}} ## {{% c %}}`, filepath.FromSlash("sect/doc5/index.html"), "\n\n<h1 id=\"hahahugoshortcode-1hbhb\">b</h1>\n\n<h2 id=\"hahahugoshortcode-2hbhb\">c</h2>\n"}, // #2223 pygments {"sect/doc6.md", "\n```bash\nb: {{< b >}} c: {{% c %}}\n```\n", filepath.FromSlash("sect/doc6/index.html"), "b: b c: c\n</code></pre></div>\n"}, // #2249 {"sect/doc7.ad", `_Shortcodes:_ *b: {{< b >}} c: {{% c %}}*`, filepath.FromSlash("sect/doc7/index.html"), "<div class=\"paragraph\">\n<p><em>Shortcodes:</em> <strong>b: b c: c</strong></p>\n</div>\n"}, {"sect/doc8.rst", `**Shortcodes:** *b: {{< b >}} c: {{% c %}}*`, filepath.FromSlash("sect/doc8/index.html"), "<div class=\"document\">\n\n\n<p><strong>Shortcodes:</strong> <em>b: b c: c</em></p>\n</div>"}, {"sect/doc9.mmark", ` --- menu: main: parent: 'parent' --- **Shortcodes:** *b: {{< b >}} c: {{% c %}}*`, filepath.FromSlash("sect/doc9/index.html"), "<p><strong>Shortcodes:</strong> <em>b: b c: c</em></p>\n"}, // Issue #1229: Menus not available in shortcode. {"sect/doc10.md", `--- menu: main: identifier: 'parent' tags: - Menu --- **Menus:** {{< menu >}}`, filepath.FromSlash("sect/doc10/index.html"), "<p><strong>Menus:</strong> 1</p>\n"}, // Issue #2323: Taxonomies not available in shortcode. {"sect/doc11.md", `--- tags: - Bugs --- **Tags:** {{< tags >}}`, filepath.FromSlash("sect/doc11/index.html"), "<p><strong>Tags:</strong> 2</p>\n"}, } sources := make([]source.ByteSource, len(tests)) for i, test := range tests { sources[i] = source.ByteSource{Name: filepath.FromSlash(test.contentPath), Content: []byte(test.content)} } s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, targets: targetList{page: &target.PagePub{UglyURLs: false}}, Language: helpers.NewDefaultLanguage(), } addTemplates := func(templ tpl.Template) error { templ.AddTemplate("_default/single.html", "{{.Content}}") templ.AddInternalShortcode("b.html", `b`) templ.AddInternalShortcode("c.html", `c`) templ.AddInternalShortcode("d.html", `d`) templ.AddInternalShortcode("menu.html", `{{ len (index .Page.Menus "main").Children }}`) templ.AddInternalShortcode("tags.html", `{{ len .Page.Site.Taxonomies.tags }}`) return nil } sites, err := newHugoSites(s) if err != nil { t.Fatalf("Failed to build site: %s", err) } if err = sites.Build(BuildCfg{withTemplate: addTemplates}); err != nil { t.Fatalf("Failed to build site: %s", err) } for _, test := range tests { if strings.HasSuffix(test.contentPath, ".ad") && !helpers.HasAsciidoc() { fmt.Println("Skip Asciidoc test case as no Asciidoc present.") continue } else if strings.HasSuffix(test.contentPath, ".rst") && !helpers.HasRst() { fmt.Println("Skip Rst test case as no rst2html present.") continue } else if strings.Contains(test.expected, "code") && !helpers.HasPygments() { fmt.Println("Skip Pygments test case as no pygments present.") continue } file, err := hugofs.Destination().Open(test.outFile) if err != nil { t.Fatalf("Did not find %s in target: %s", test.outFile, err) } content := helpers.ReaderToString(file) if !strings.Contains(content, test.expected) { t.Fatalf("%s content expected:\n%q\ngot:\n%q", test.outFile, test.expected, content) } } }
func TestGroupedPages(t *testing.T) { testCommonResetState() defer func() { if r := recover(); r != nil { fmt.Println("Recovered in f", r) } }() hugofs.InitMemFs() viper.Set("baseURL", "http://auth/bub") s := &Site{ Source: &source.InMemorySource{ByteSource: groupedSources}, Language: helpers.NewDefaultLanguage(), } if err := buildSiteSkipRender(s); err != nil { t.Fatalf("Failed to build site: %s", err) } rbysection, err := s.Pages.GroupBy("Section", "desc") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if rbysection[0].Key != "sect3" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "sect3", rbysection[0].Key) } if rbysection[1].Key != "sect2" { t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "sect2", rbysection[1].Key) } if rbysection[2].Key != "sect1" { t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "sect1", rbysection[2].Key) } if rbysection[0].Pages[0].Title != "Four" { t.Errorf("PageGroup has an unexpected page. First group's pages should have '%s', got '%s'", "Four", rbysection[0].Pages[0].Title) } if len(rbysection[2].Pages) != 2 { t.Errorf("PageGroup has unexpected number of pages. Third group should have '%d' pages, got '%d' pages", 2, len(rbysection[2].Pages)) } bytype, err := s.Pages.GroupBy("Type", "asc") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if bytype[0].Key != "sect1" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "sect1", bytype[0].Key) } if bytype[1].Key != "sect2" { t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "sect2", bytype[1].Key) } if bytype[2].Key != "sect3" { t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "sect3", bytype[2].Key) } if bytype[2].Pages[0].Title != "Four" { t.Errorf("PageGroup has an unexpected page. Third group's data should have '%s', got '%s'", "Four", bytype[0].Pages[0].Title) } if len(bytype[0].Pages) != 2 { t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(bytype[2].Pages)) } bydate, err := s.Pages.GroupByDate("2006-01", "asc") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if bydate[0].Key != "0001-01" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "0001-01", bydate[0].Key) } if bydate[1].Key != "2012-01" { t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "2012-01", bydate[1].Key) } if bydate[2].Key != "2012-04" { t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "2012-04", bydate[2].Key) } if bydate[2].Pages[0].Title != "Three" { t.Errorf("PageGroup has an unexpected page. Third group's pages should have '%s', got '%s'", "Three", bydate[2].Pages[0].Title) } if len(bydate[0].Pages) != 2 { t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(bydate[2].Pages)) } bypubdate, err := s.Pages.GroupByPublishDate("2006") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if bypubdate[0].Key != "2012" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "2012", bypubdate[0].Key) } if bypubdate[1].Key != "0001" { t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "0001", bypubdate[1].Key) } if bypubdate[0].Pages[0].Title != "Three" { t.Errorf("PageGroup has an unexpected page. Third group's pages should have '%s', got '%s'", "Three", bypubdate[0].Pages[0].Title) } if len(bypubdate[0].Pages) != 3 { t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 3, len(bypubdate[0].Pages)) } byparam, err := s.Pages.GroupByParam("my_param", "desc") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if byparam[0].Key != "foo" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "foo", byparam[0].Key) } if byparam[1].Key != "baz" { t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "baz", byparam[1].Key) } if byparam[2].Key != "bar" { t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "bar", byparam[2].Key) } if byparam[2].Pages[0].Title != "Three" { t.Errorf("PageGroup has an unexpected page. Third group's pages should have '%s', got '%s'", "Three", byparam[2].Pages[0].Title) } if len(byparam[0].Pages) != 2 { t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(byparam[0].Pages)) } _, err = s.Pages.GroupByParam("not_exist") if err == nil { t.Errorf("GroupByParam didn't return an expected error") } byOnlyOneParam, err := s.Pages.GroupByParam("only_one") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if len(byOnlyOneParam) != 1 { t.Errorf("PageGroup array has unexpected elements. Group length should be '%d', got '%d'", 1, len(byOnlyOneParam)) } if byOnlyOneParam[0].Key != "yes" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "yes", byOnlyOneParam[0].Key) } byParamDate, err := s.Pages.GroupByParamDate("my_date", "2006-01") if err != nil { t.Fatalf("Unable to make PageGroup array: %s", err) } if byParamDate[0].Key != "2010-05" { t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "2010-05", byParamDate[0].Key) } if byParamDate[1].Key != "1979-05" { t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "1979-05", byParamDate[1].Key) } if byParamDate[1].Pages[0].Title != "One" { t.Errorf("PageGroup has an unexpected page. Second group's pages should have '%s', got '%s'", "One", byParamDate[1].Pages[0].Title) } if len(byParamDate[0].Pages) != 2 { t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(byParamDate[2].Pages)) } }
func TestPermalink(t *testing.T) { testCommonResetState() tests := []struct { file string base template.URL slug string url string uglyURLs bool canonifyURLs bool expectedAbs string expectedRel string }{ {"x/y/z/boofar.md", "", "", "", false, false, "/x/y/z/boofar/", "/x/y/z/boofar/"}, {"x/y/z/boofar.md", "", "", "", false, false, "/x/y/z/boofar/", "/x/y/z/boofar/"}, // Issue #1174 {"x/y/z/boofar.md", "http://gopher.com/", "", "", false, true, "http://gopher.com/x/y/z/boofar/", "/x/y/z/boofar/"}, {"x/y/z/boofar.md", "http://gopher.com/", "", "", true, true, "http://gopher.com/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "", "boofar", "", false, false, "/x/y/z/boofar/", "/x/y/z/boofar/"}, {"x/y/z/boofar.md", "http://barnew/", "", "", false, false, "http://barnew/x/y/z/boofar/", "/x/y/z/boofar/"}, {"x/y/z/boofar.md", "http://barnew/", "boofar", "", false, false, "http://barnew/x/y/z/boofar/", "/x/y/z/boofar/"}, {"x/y/z/boofar.md", "", "", "", true, false, "/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "", "", "", true, false, "/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "", "boofar", "", true, false, "/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "http://barnew/", "", "", true, false, "http://barnew/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "http://barnew/", "boofar", "", true, false, "http://barnew/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", true, false, "http://barnew/boo/x/y/z/boofar.html", "/boo/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", false, true, "http://barnew/boo/x/y/z/boofar/", "/x/y/z/boofar/"}, {"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", false, false, "http://barnew/boo/x/y/z/boofar/", "/boo/x/y/z/boofar/"}, {"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", true, true, "http://barnew/boo/x/y/z/boofar.html", "/x/y/z/boofar.html"}, {"x/y/z/boofar.md", "http://barnew/boo", "boofar", "", true, true, "http://barnew/boo/x/y/z/boofar.html", "/x/y/z/boofar.html"}, // test URL overrides {"x/y/z/boofar.md", "", "", "/z/y/q/", false, false, "/z/y/q/", "/z/y/q/"}, } viper.Set("defaultExtension", "html") for i, test := range tests { viper.Set("uglyURLs", test.uglyURLs) viper.Set("canonifyURLs", test.canonifyURLs) info := newSiteInfo(siteBuilderCfg{baseURL: string(test.base), language: helpers.NewDefaultLanguage()}) p := &Page{ Node: Node{ URLPath: URLPath{ Section: "z", URL: test.url, }, Site: &info, }, Source: Source{File: *source.NewFile(filepath.FromSlash(test.file))}, } if test.slug != "" { p.update(map[string]interface{}{ "slug": test.slug, }) } u, err := p.Permalink() if err != nil { t.Errorf("Test %d: Unable to process permalink: %s", i, err) } expected := test.expectedAbs if u != expected { t.Errorf("Test %d: Expected abs url: %s, got: %s", i, expected, u) } u, err = p.RelPermalink() if err != nil { t.Errorf("Test %d: Unable to process permalink: %s", i, err) } expected = test.expectedRel if u != expected { t.Errorf("Test %d: Expected rel url: %s, got: %s", i, expected, u) } } }