diff options
-rw-r--r-- | commands/hugo.go | 2 | ||||
-rw-r--r-- | commands/new.go | 12 | ||||
-rw-r--r-- | commands/new_site.go | 2 | ||||
-rw-r--r-- | create/content.go | 392 | ||||
-rw-r--r-- | create/content_template_handler.go | 149 | ||||
-rw-r--r-- | create/content_test.go | 205 | ||||
-rw-r--r-- | deps/deps.go | 2 | ||||
-rw-r--r-- | hugofs/glob/glob.go | 168 | ||||
-rw-r--r-- | hugofs/glob/glob_test.go | 35 | ||||
-rw-r--r-- | hugolib/content_factory.go | 181 | ||||
-rw-r--r-- | hugolib/content_factory_test.go | 60 | ||||
-rw-r--r-- | hugolib/filesystems/basefs.go | 36 | ||||
-rw-r--r-- | hugolib/hugo_sites.go | 7 | ||||
-rw-r--r-- | hugolib/pages_capture_test.go | 2 | ||||
-rw-r--r-- | hugolib/site.go | 8 | ||||
-rw-r--r-- | langs/i18n/translationProvider.go | 2 | ||||
-rw-r--r-- | source/content_directory_test.go | 2 | ||||
-rw-r--r-- | source/filesystem_test.go | 2 | ||||
-rw-r--r-- | source/sourceSpec.go | 36 |
19 files changed, 857 insertions, 446 deletions
diff --git a/commands/hugo.go b/commands/hugo.go index 4fd20a0f4..c19756008 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -870,7 +870,7 @@ func (c *commandeer) newWatcher(pollIntervalStr string, dirList ...string) (*wat livereload.ForceRefresh() } case err := <-watcher.Errors(): - if err != nil { + if err != nil && !os.IsNotExist(err) { c.logger.Errorln("Error while watching:", err) } } diff --git a/commands/new.go b/commands/new.go index 7affd3547..c5b5cd182 100644 --- a/commands/new.go +++ b/commands/new.go @@ -80,17 +80,7 @@ func (n *newCmd) newContent(cmd *cobra.Command, args []string) error { return newUserError("path needs to be provided") } - createPath := args[0] - - var kind string - - createPath, kind = newContentPathSection(c.hugo(), createPath) - - if n.contentType != "" { - kind = n.contentType - } - - return create.NewContent(c.hugo(), kind, createPath) + return create.NewContent(c.hugo(), n.contentType, args[0]) } func mkdir(x ...string) { diff --git a/commands/new_site.go b/commands/new_site.go index 71097b8ff..11e9ce40a 100644 --- a/commands/new_site.go +++ b/commands/new_site.go @@ -102,7 +102,7 @@ func (n *newSiteCmd) doNewSite(fs *hugofs.Fs, basepath string, force bool) error // Create a default archetype file. helpers.SafeWriteToDisk(filepath.Join(archeTypePath, "default.md"), - strings.NewReader(create.ArchetypeTemplateTemplate), fs.Source) + strings.NewReader(create.DefaultArchetypeTemplateTemplate), fs.Source) jww.FEEDBACK.Printf("Congratulations! Your new Hugo site is created in %s.\n\n", basepath) jww.FEEDBACK.Println(nextStepsText()) diff --git a/create/content.go b/create/content.go index ea065423e..714939f4c 100644 --- a/create/content.go +++ b/create/content.go @@ -16,11 +16,14 @@ package create import ( "bytes" + "fmt" "io" "os" "path/filepath" "strings" + "github.com/gohugoio/hugo/hugofs/glob" + "github.com/gohugoio/hugo/common/paths" "github.com/pkg/errors" @@ -33,125 +36,136 @@ import ( "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib" "github.com/spf13/afero" - jww "github.com/spf13/jwalterweatherman" ) -// NewContent creates a new content file in the content directory based upon the -// given kind, which is used to lookup an archetype. -func NewContent( - sites *hugolib.HugoSites, kind, targetPath string) error { - targetPath = filepath.Clean(targetPath) - ext := paths.Ext(targetPath) - ps := sites.PathSpec - archetypeFs := ps.BaseFs.SourceFilesystems.Archetypes.Fs - sourceFs := ps.Fs.Source - - jww.INFO.Printf("attempting to create %q of %q of ext %q", targetPath, kind, ext) +const ( + // DefaultArchetypeTemplateTemplate is the template used in 'hugo new site' + // and the template we use as a fall back. + DefaultArchetypeTemplateTemplate = `--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- - archetypeFilename, isDir := findArchetype(ps, kind, ext) - contentPath, s := resolveContentPath(sites, sourceFs, targetPath) +` +) - if isDir { +// NewContent creates a new content file in h (or a full bundle if the archetype is a directory) +// in targetPath. +func NewContent(h *hugolib.HugoSites, kind, targetPath string) error { + cf := hugolib.NewContentFactory(h) - langFs, err := hugofs.NewLanguageFs(sites.LanguageSet(), archetypeFs) - if err != nil { - return err - } - - cm, err := mapArcheTypeDir(ps, langFs, archetypeFilename) - if err != nil { - return err - } + if kind == "" { + kind = cf.SectionFromFilename(targetPath) + } - if cm.siteUsed { - if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil { - return err - } - } + b := &contentBuilder{ + archeTypeFs: h.PathSpec.BaseFs.Archetypes.Fs, + sourceFs: h.PathSpec.Fs.Source, + ps: h.PathSpec, + h: h, + cf: cf, - name := filepath.Base(targetPath) - return newContentFromDir(archetypeFilename, sites, sourceFs, cm, name, contentPath) + kind: kind, + targetPath: targetPath, } - // Building the sites can be expensive, so only do it if really needed. - siteUsed := false + ext := paths.Ext(targetPath) - if archetypeFilename != "" { + b.setArcheTypeFilenameToUse(ext) - var err error - siteUsed, err = usesSiteVar(archetypeFs, archetypeFilename) - if err != nil { - return err - } + if b.isDir { + return b.buildDir() } - if siteUsed { - if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil { - return err - } + if ext == "" { + return errors.Errorf("failed to resolve %q to a archetype template", targetPath) } - content, err := executeArcheTypeAsTemplate(s, "", kind, targetPath, archetypeFilename) - if err != nil { - return err - } + return b.buildFile() + +} + +type contentBuilder struct { + archeTypeFs afero.Fs + sourceFs afero.Fs + + ps *helpers.PathSpec + h *hugolib.HugoSites + cf hugolib.ContentFactory - if err := helpers.SafeWriteToDisk(contentPath, bytes.NewReader(content), s.Fs.Source); err != nil { + // Builder state + archetypeFilename string + targetPath string + kind string + isDir bool + dirMap archetypeMap +} + +func (b *contentBuilder) buildDir() error { + // Split the dir into content files and the rest. + if err := b.mapArcheTypeDir(); err != nil { return err } - jww.FEEDBACK.Println(contentPath, "created") + var contentTargetFilenames []string + var baseDir string - editor := s.Cfg.GetString("newContentEditor") - if editor != "" { - jww.FEEDBACK.Printf("Editing %s with %q ...\n", targetPath, editor) - - editorCmd := append(strings.Fields(editor), contentPath) - cmd, err := hexec.SafeCommand(editorCmd[0], editorCmd[1:]...) + for _, fi := range b.dirMap.contentFiles { + targetFilename := filepath.Join(b.targetPath, strings.TrimPrefix(fi.Meta().Path, b.archetypeFilename)) + abs, err := b.cf.CreateContentPlaceHolder(targetFilename) if err != nil { return err } - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + if baseDir == "" { + baseDir = strings.TrimSuffix(abs, targetFilename) + } - return cmd.Run() + contentTargetFilenames = append(contentTargetFilenames, abs) } - return nil -} + var contentInclusionFilter *glob.FilenameFilter + if !b.dirMap.siteUsed { + // We don't need to build everything. + contentInclusionFilter = glob.NewFilenameFilterForInclusionFunc(func(filename string) bool { + for _, cn := range contentTargetFilenames { + if strings.HasPrefix(cn, filename) { + return true + } + } + return false + }) -func targetSite(sites *hugolib.HugoSites, fi hugofs.FileMetaInfo) *hugolib.Site { - for _, s := range sites.Sites { - if fi.Meta().Lang == s.Language().Lang { - return s + } + + if err := b.h.Build(hugolib.BuildCfg{SkipRender: true, ContentInclusionFilter: contentInclusionFilter}); err != nil { + return err + } + + for i, filename := range contentTargetFilenames { + if err := b.applyArcheType(filename, b.dirMap.contentFiles[i].Meta().Path); err != nil { + return err } } - return sites.Sites[0] -} -func newContentFromDir( - archetypeDir string, - sites *hugolib.HugoSites, - targetFs afero.Fs, - cm archetypeMap, name, targetPath string) error { - for _, f := range cm.otherFiles { + // Copy the rest as is. + for _, f := range b.dirMap.otherFiles { meta := f.Meta() filename := meta.Path - // Just copy the file to destination. + in, err := meta.Open() if err != nil { return errors.Wrap(err, "failed to open non-content file") } - targetFilename := filepath.Join(targetPath, strings.TrimPrefix(filename, archetypeDir)) - + targetFilename := filepath.Join(baseDir, b.targetPath, strings.TrimPrefix(filename, b.archetypeFilename)) targetDir := filepath.Dir(targetFilename) - if err := targetFs.MkdirAll(targetDir, 0777); err != nil && !os.IsExist(err) { - return errors.Wrapf(err, "failed to create target directory for %s:", targetDir) + + if err := b.sourceFs.MkdirAll(targetDir, 0o777); err != nil && !os.IsExist(err) { + return errors.Wrapf(err, "failed to create target directory for %q", targetDir) } - out, err := targetFs.Create(targetFilename) + out, err := b.sourceFs.Create(targetFilename) if err != nil { return err } @@ -164,41 +178,81 @@ func newContentFromDir( in.Close() out.Close() } + return nil +} - for _, f := range cm.contentFiles { - filename := f.Meta().Path - s := targetSite(sites, f) - targetFilename := filepath.Join(targetPath, strings.TrimPrefix(filename, archetypeDir)) +func (b *contentBuilder) buildFile() error { + contentPlaceholderAbsFilename, err := b.cf.CreateContentPlaceHolder(b.targetPath) + if err != nil { + return err + } - content, err := executeArcheTypeAsTemplate(s, name, archetypeDir, targetFilename, filename) - if err != nil { - return errors.Wrap(err, "failed to execute archetype template") - } + usesSite, err := b.usesSiteVar(b.archetypeFilename) + if err != nil { + return err + } - if err := helpers.SafeWriteToDisk(targetFilename, bytes.NewReader(content), targetFs); err != nil { - return errors.Wrap(err, "failed to save results") - } + var contentInclusionFilter *glob.FilenameFilter + if !usesSite { + // We don't need to build everything. + contentInclusionFilter = glob.NewFilenameFilterForInclusionFunc(func(filename string) bool { + return strings.HasPrefix(contentPlaceholderAbsFilename, filename) + }) } - jww.FEEDBACK.Println(targetPath, "created") + if err := b.h.Build(hugolib.BuildCfg{SkipRender: true, ContentInclusionFilter: contentInclusionFilter}); err != nil { + return err + } - return nil + if err := b.applyArcheType(contentPlaceholderAbsFilename, b.archetypeFilename); err != nil { + return err + } + + b.h.Log.Infof("Content %q created", contentPlaceholderAbsFilename) + + return b.openInEditorIfConfigured(contentPlaceholderAbsFilename) } -type archetypeMap struct { - // These needs to be parsed and executed as Go templates. - contentFiles []hugofs.FileMetaInfo - // These are just copied to destination. - otherFiles []hugofs.FileMetaInfo - // If the templates needs a fully built site. This can potentially be - // expensive, so only do when needed. - siteUsed bool +func (b *contentBuilder) setArcheTypeFilenameToUse(ext string) { + var pathsToCheck []string + + if b.kind != "" { + pathsToCheck = append(pathsToCheck, b.kind+ext) + } + pathsToCheck = append(pathsToCheck, "default"+ext, "default") + + for _, p := range pathsToCheck { + fi, err := b.archeTypeFs.Stat(p) + if err == nil { + b.archetypeFilename = p + b.isDir = fi.IsDir() + return + } + } + } -func mapArcheTypeDir( - ps *helpers.PathSpec, - fs afero.Fs, - archetypeDir string) (archetypeMap, error) { +func (b *contentBuilder) applyArcheType(contentFilename, archetypeFilename string) error { + p := b.h.GetContentPage(contentFilename) + if p == nil { + panic(fmt.Sprintf("[BUG] no Page found for %q", contentFilename)) + } + + f, err := b.sourceFs.Create(contentFilename) + if err != nil { + return err + } + defer f.Close() + + if archetypeFilename == "" { + return b.cf.AppplyArchetypeTemplate(f, p, b.kind, DefaultArchetypeTemplateTemplate) + } + + return b.cf.AppplyArchetypeFilename(f, p, b.kind, archetypeFilename) + +} + +func (b *contentBuilder) mapArcheTypeDir() error { var m archetypeMap walkFn := func(path string, fi hugofs.FileMetaInfo, err error) error { @@ -215,7 +269,7 @@ func mapArcheTypeDir( if files.IsContentFile(path) { m.contentFiles = append(m.contentFiles, fil) if !m.siteUsed { - m.siteUsed, err = usesSiteVar(fs, path) + m.siteUsed, err = b.usesSiteVar(path) if err != nil { return err } @@ -230,120 +284,60 @@ func mapArcheTypeDir( walkCfg := hugofs.WalkwayConfig{ WalkFn: walkFn, - Fs: fs, - Root: archetypeDir, + Fs: b.archeTypeFs, + Root: b.archetypeFilename, } w := hugofs.NewWalkway(walkCfg) if err := w.Walk(); err != nil { - return m, errors.Wrapf(err, "failed to walk archetype dir %q", archetypeDir) + return errors.Wrapf(err, "failed to walk archetype dir %q", b.archetypeFilename) } - return m, nil -} + b.dirMap = m -func usesSiteVar(fs afero.Fs, filename string) (bool, error) { - f, err := fs.Open(filename) - if err != nil { - return false, errors.Wrap(err, "failed to open archetype file") - } - defer f.Close() - return helpers.ReaderContains(f, []byte(".Site")), nil + return nil } -// Resolve the target content path. -func resolveContentPath(sites *hugolib.HugoSites, fs afero.Fs, targetPath string) (string, *hugolib.Site) { - targetDir := filepath.Dir(targetPath) - first := sites.Sites[0] - - var ( - s *hugolib.Site - siteContentDir string - ) - - // Try the filename: my-post.en.md - for _, ss := range sites.Sites { - if strings.Contains(targetPath, "."+ss.Language().Lang+".") { - s = ss - break - } - } - - var dirLang string - - for _, dir := range sites.BaseFs.Content.Dirs { - meta := dir.Meta() - contentDir := meta.Filename - - if !strings.HasSuffix(contentDir, helpers.FilePathSeparator) { - contentDir += helpers.FilePathSeparator - } - - if strings.HasPrefix(targetPath, contentDir) { - siteContentDir = contentDir - dirLang = meta.Lang - break - } +func (b *contentBuilder) openInEditorIfConfigured(filename string) error { + editor := b.h.Cfg.GetString("newContentEditor") + if editor == "" { + return nil } - if s == nil && dirLang != "" { - for _, ss := range sites.Sites { - if ss.Lang() == dirLang { - s = ss - break - } - } - } + b.h.Log.Infof("Editing %q with %q ...\n", filename, editor) - if s == nil { - s = first + cmd, err := hexec.SafeCommand(editor, filename) + if err != nil { + return err } - if targetDir != "" && targetDir != "." { - exists, _ := helpers.Exists(targetDir, fs) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr - if exists { - return targetPath, s - } - } + return cmd.Run() +} - if siteContentDir == "" { +func (b *contentBuilder) usesSiteVar(filename string) (bool, error) { + if filename == "" { + return false, nil } - - if siteContentDir != "" { - pp := filepath.Join(siteContentDir, strings.TrimPrefix(targetPath, siteContentDir)) - return s.PathSpec.AbsPathify(pp), s - } else { - var contentDir string - for _, dir := range sites.BaseFs.Content.Dirs { - contentDir = dir.Meta().Filename - if dir.Meta().Lang == s.Lang() { - break - } - } - return s.PathSpec.AbsPathify(filepath.Join(contentDir, targetPath)), s + bb, err := afero.ReadFile(b.archeTypeFs, filename) + if err != nil { + return false, errors.Wrap(err, "failed to open archetype file") } -} -// FindArchetype takes a given kind/archetype of content and returns the path -// to the archetype in the archetype filesystem, blank if none found. -func findArchetype(ps *helpers.PathSpec, kind, ext string) (outpath string, isDir bool) { - fs := ps.BaseFs.Archetypes.Fs + return bytes.Contains(bb, []byte(".Site")) || bytes.Contains(bb, []byte("site.")), nil - var pathsToCheck []string - - if kind != "" { - pathsToCheck = append(pathsToCheck, kind+ext) - } - pathsToCheck = append(pathsToCheck, "default"+ext, "default") - - for _, p := range pathsToCheck { - fi, err := fs.Stat(p) - if err == nil { - return p, fi.IsDir() - } - } +} - return "", false +type archetypeMap struct { + // These needs to be parsed and executed as Go templates. + contentFiles []hugofs.FileMetaInfo + // These are just copied to destination. + otherFiles []hugofs.FileMetaInfo + // If the templates needs a fully built site. This can potentially be + // expensive, so only do when needed. + siteUsed bool } diff --git a/create/content_template_handler.go b/create/content_template_handler.go deleted file mode 100644 index 09cf4c0a5..000000000 --- a/create/content_template_handler.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2017 The Hugo Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package create - -import ( - "bytes" - "fmt" - "path/filepath" - "strings" - "time" - - "github.com/gohugoio/hugo/common/paths" - - "github.com/pkg/errors" - - "github.com/gohugoio/hugo/helpers" - "github.com/gohugoio/hugo/source" - - "github.com/gohugoio/hugo/hugolib" - "github.com/gohugoio/hugo/tpl" - "github.com/spf13/afero" -) - -// ArchetypeFileData represents the data available to an archetype template. -type ArchetypeFileData struct { - // The archetype content type, either given as --kind option or extracted - // from the target path's section, i.e. "blog/mypost.md" will resolve to - // "blog". - Type string - - // The current date and time as a RFC3339 formatted string, suitable for use in front matter. - Date string - - // The Site, fully equipped with all the pages etc. Note: This will only be set if it is actually - // used in the archetype template. Also, if this is a multilingual setup, - // this site is the site that best matches the target content file, based - // on the presence of language code in the filename. - Site *hugolib.SiteInfo - - // Name will in most cases be the same as TranslationBaseName, e.g. "my-post". - // But if that value is "index" (bundles), the Name is instead the owning folder. - // This is the value you in most cases would want to use to construct the title in your - // archetype template. - Name string - - // The target content file. Note that the .Content will be empty, as that - // has not been created yet. - source.File -} - -const ( - // ArchetypeTemplateTemplate is used as initial template when adding an archetype template. - ArchetypeTemplateTemplate = `--- -title: "{{ replace .Name "-" " " | title }}" -date: {{ .Date }} -draft: true ---- - -` -) - -var ( - archetypeShortcodeReplacementsPre = strings.NewReplacer( - "{{<", "{x{<", - "{{%", "{x{%", - ">}}", ">}x}", - "%}}", "%}x}") - - archetypeShortcodeReplacementsPost = strings.NewReplacer( - "{x{<", "{{<", - "{x{%", "{{%", - ">}x}", ">}}", - "%}x}", "%}}") -) - -func executeArcheTypeAsTemplate(s *hugolib.Site, name, kind, targetPath, archetypeFilename string) ([]byte, error) { - var ( - archetypeContent []byte - archetypeTemplate []byte - err error - ) - - f, err := s.SourceSpec.NewFileInfoFrom(targetPath, targetPath) - if err != nil { - return nil, err - } - - if name == "" { - name = f.TranslationBaseName() - - if name == "index" || name == "_index" { - // Page bundles; the directory name will hopefully have a better name. - dir := strings.TrimSuffix(f.Dir(), helpers.FilePathSeparator) - _, name = filepath.Split(dir) - } - } - - data := ArchetypeFileData{ - Type: kind, - Date: time.Now().Format(time.RFC3339), - Name: name, - File: f, - Site: s.Info, - } - - if archetypeFilename == "" { - // TODO(bep) archetype revive the issue about wrong tpl funcs arg order - archetypeTemplate = []byte(ArchetypeTemplateTemplate) - } else { - archetypeTemplate, err = afero.ReadFile(s.BaseFs.Archetypes.Fs, archetypeFilename) - if err != nil { - return nil, fmt.Errorf("failed to read archetype file %s", err) - } - - } - - // The archetype template may contain shortcodes, and these does not play well - // with the Go templates. Need to set some temporary delimiters. - archetypeTemplate = []byte(archetypeShortcodeReplacementsPre.Replace(string(archetypeTemplate))) - - // Reuse the Hugo template setup to get the template funcs properly set up. - templateHandler := s.Deps.Tmpl().(tpl.TemplateManager) - templateName := paths.Filename(archetypeFilename) - if err := templateHandler.AddTemplate("_text/"+templateName, string(archetypeTemplate)); err != nil { - return nil, errors.Wrapf(err, "Failed to parse archetype file %q:", archetypeFilename) - } - - templ, _ := templateHandler.Lookup(templateName) - - var buff bytes.Buffer - if err := templateHandler.Execute(templ, &buff, data); err != nil { - return nil, errors.Wrapf(err, "Failed to process archetype file %q:", archetypeFilename) - } - - archetypeContent = []byte(archetypeShortcodeReplacementsPost.Replace(buff.String())) - - return archetypeContent, nil -} diff --git a/create/content_test.go b/create/content_test.go index 38ff7de8d..d40634083 100644 --- a/create/content_test.go +++ b/create/content_test.go @@ -34,27 +34,31 @@ import ( "github.com/spf13/afero" ) +// TODO(bep) clean this up. Export the test site builder in Hugolib or something. func TestNewContent(t *testing.T) { cases := []struct { + name string kind string path string expected []string }{ - {"post", "post/sample-1.md", []string{`title = "Post Arch title"`, `test = "test1"`, "date = \"2015-01-12T19:20:04-07:00\""}}, - {"post", "post/org-1.org", []string{`#+title: ORG-1`}}, - {"emptydate", "post/sample-ed.md", []string{`title = "Empty Date Arch title"`, `test = "test1"`}}, - {"stump", "stump/sample-2.md", []string{`title: "Sample 2"`}}, // no archetype file - {"", "sample-3.md", []string{`title: "Sample 3"`}}, // no archetype - {"product", "product/sample-4.md", []string{`title = "SAMPLE-4"`}}, // empty archetype front matter - {"lang", "post/lang-1.md", []string{`Site Lang: en|Name: Lang 1|i18n: Hugo Rocks!`}}, - {"lang", "post/lang-2.en.md", []string{`Site Lang: en|Name: Lang 2|i18n: Hugo Rocks!`}}, - {"lang", "content/post/lang-3.nn.md", []string{`Site Lang: nn|Name: Lang 3|i18n: Hugo Rokkar!`}}, - {"lang", "content_nn/post/lang-4.md", []string{`Site Lang: nn|Name: Lang 4|i18n: Hugo Rokkar!`}}, - {"lang", "content_nn/post/lang-5.en.md", []string{`Site Lang: en|Name: Lang 5|i18n: Hugo Rocks!`}}, - {"lang", "post/my-bundle/index.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, - {"lang", "post/my-bundle/index.en.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, - {"lang", "content/post/my-bundle/index.nn.md", []string{`Site Lang: nn|Name: My Bundle|i18n: Hugo Rokkar!`}}, - {"shortcodes", "shortcodes/go.md", []string{ + {"Post", "post", "post/sample-1.md", []string{`title = "Post Arch title"`, `test = "test1"`, "date = \"2015-01-12T19:20:04-07:00\""}}, + {"Post org-mode", "post", "post/org-1.org", []string{`#+title: ORG-1`}}, + {"Empty date", "emptydate", "post/sample-ed.md", []string{`title = "Empty Date Arch title"`, `test = "test1"`}}, + {"Archetype file not found", "stump", "stump/sample-2.md", []string{`title: "Sample 2"`}}, // no archetype file + {"No archetype", "", "sample-3.md", []string{`title: "Sample 3"`}}, // no archetype + {"Empty archetype", "product", "product/sample-4.md", []string{`title = "SAMPLE-4"`}}, // empty archetype front matter + {"Filenames", "filenames", "content/mypage/index.md", []string{"title = \"INDEX\"\n+++\n\n\nContentBaseName: mypage"}}, + {"Lang 1", "lang", "post/lang-1.md", []string{`Site Lang: en|Name: Lang 1|i18n: Hugo Rocks!`}}, + {"Lang 2", "lang", "post/lang-2.en.md", []string{`Site Lang: en|Name: Lang 2|i18n: Hugo Rocks!`}}, + {"Lang nn file", "lang", "content/post/lang-3.nn.md", []string{`Site Lang: nn|Name: Lang 3|i18n: Hugo Rokkar!`}}, + {"Lang nn dir", "lang", "content_nn/post/lang-4.md", []string{`Site Lang: nn|Name: Lang 4|i18n: Hugo Rokkar!`}}, + {"Lang en in nn dir", "lang", "content_nn/post/lang-5.en.md", []string{`Site Lang: en|Name: Lang 5|i18n: Hugo Rocks!`}}, + {"Lang en default", "lang", "post/my-bundle/index.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, + {"Lang en file", "lang", "post/my-bundle/index.en.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo |