diff options
Diffstat (limited to 'create/content_template_handler.go')
-rw-r--r-- | create/content_template_handler.go | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/create/content_template_handler.go b/create/content_template_handler.go new file mode 100644 index 000000000..02598d4d3 --- /dev/null +++ b/create/content_template_handler.go @@ -0,0 +1,148 @@ +// 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/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, kind, targetPath, archetypeFilename string) ([]byte, error) { + + var ( + archetypeContent []byte + archetypeTemplate []byte + err error + ) + + ps, err := helpers.NewPathSpec(s.Deps.Fs, s.Deps.Cfg) + if err != nil { + return nil, err + } + sp := source.NewSourceSpec(ps, ps.Fs.Source) + + f := sp.NewFileInfo("", targetPath, false, nil) + + 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.TemplateHandler) + templateName := "_text/" + helpers.Filename(archetypeFilename) + if err := templateHandler.AddTemplate(templateName, string(archetypeTemplate)); err != nil { + return nil, fmt.Errorf("Failed to parse archetype file %q: %s", archetypeFilename, err) + } + + templ, _ := templateHandler.Lookup(templateName) + + var buff bytes.Buffer + if err := templ.Execute(&buff, data); err != nil { + return nil, fmt.Errorf("Failed to process archetype file %q: %s", archetypeFilename, err) + } + + archetypeContent = []byte(archetypeShortcodeReplacementsPost.Replace(buff.String())) + + return archetypeContent, nil + +} |