diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-02-17 13:04:00 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-02-24 18:59:50 +0100 |
commit | 08fdca9d9365eaf1e496a12e2af5e18617bd0e66 (patch) | |
tree | 6c6942d1b74a4160d93a997860bafd52b92025f5 /tpl/os | |
parent | 2c20f5bc00b604e72b3b7e401fbdbf9447fe3470 (diff) |
Add Markdown diagrams and render hooks for code blocks
You can now create custom hook templates for code blocks, either one for all (`render-codeblock.html`) or for a given code language (e.g. `render-codeblock-go.html`).
We also used this new hook to add support for diagrams in Hugo:
* Goat (Go ASCII Tool) is built-in and enabled by default; just create a fenced code block with the language `goat` and start draw your Ascii diagrams.
* Another popular alternative for diagrams in Markdown, Mermaid (supported by GitHub), can also be implemented with a simple template. See the Hugo documentation for more information.
Updates #7765
Closes #9538
Fixes #9553
Fixes #8520
Fixes #6702
Fixes #9558
Diffstat (limited to 'tpl/os')
-rw-r--r-- | tpl/os/init_test.go | 42 | ||||
-rw-r--r-- | tpl/os/os.go | 21 | ||||
-rw-r--r-- | tpl/os/os_test.go | 73 |
3 files changed, 42 insertions, 94 deletions
diff --git a/tpl/os/init_test.go b/tpl/os/init_test.go deleted file mode 100644 index 5d756bab2..000000000 --- a/tpl/os/init_test.go +++ /dev/null @@ -1,42 +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 os - -import ( - "testing" - - qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/deps" - "github.com/gohugoio/hugo/htesting/hqt" - "github.com/gohugoio/hugo/tpl/internal" -) - -func TestInit(t *testing.T) { - c := qt.New(t) - var found bool - var ns *internal.TemplateFuncsNamespace - - for _, nsf := range internal.TemplateFuncsNamespaceRegistry { - ns = nsf(&deps.Deps{}) - if ns.Name == name { - found = true - break - } - } - - c.Assert(found, qt.Equals, true) - ctx, err := ns.Context() - c.Assert(err, qt.IsNil) - c.Assert(ctx, hqt.IsSameType, &Namespace{}) -} diff --git a/tpl/os/os.go b/tpl/os/os.go index 43c42f5e1..8b195a527 100644 --- a/tpl/os/os.go +++ b/tpl/os/os.go @@ -19,6 +19,7 @@ import ( "errors" "fmt" _os "os" + "path/filepath" "github.com/gohugoio/hugo/deps" "github.com/spf13/afero" @@ -27,17 +28,9 @@ import ( // New returns a new instance of the os-namespaced template functions. func New(d *deps.Deps) *Namespace { - var rfs afero.Fs - if d.Fs != nil { - rfs = d.Fs.WorkingDir - if d.PathSpec != nil && d.PathSpec.BaseFs != nil { - rfs = afero.NewReadOnlyFs(afero.NewCopyOnWriteFs(d.PathSpec.BaseFs.Content.Fs, d.Fs.WorkingDir)) - } - - } - return &Namespace{ - readFileFs: rfs, + readFileFs: afero.NewReadOnlyFs(afero.NewCopyOnWriteFs(d.PathSpec.BaseFs.Content.Fs, d.PathSpec.BaseFs.Work)), + workFs: d.PathSpec.BaseFs.Work, deps: d, } } @@ -45,6 +38,7 @@ func New(d *deps.Deps) *Namespace { // Namespace provides template functions for the "os" namespace. type Namespace struct { readFileFs afero.Fs + workFs afero.Fs deps *deps.Deps } @@ -66,8 +60,9 @@ func (ns *Namespace) Getenv(key interface{}) (string, error) { // readFile reads the file named by filename in the given filesystem // and returns the contents as a string. func readFile(fs afero.Fs, filename string) (string, error) { - if filename == "" { - return "", errors.New("readFile needs a filename") + filename = filepath.Clean(filename) + if filename == "" || filename == "." || filename == string(_os.PathSeparator) { + return "", errors.New("invalid filename") } b, err := afero.ReadFile(fs, filename) @@ -101,7 +96,7 @@ func (ns *Namespace) ReadDir(i interface{}) ([]_os.FileInfo, error) { return nil, err } - list, err := afero.ReadDir(ns.deps.Fs.WorkingDir, path) + list, err := afero.ReadDir(ns.workFs, path) if err != nil { return nil, fmt.Errorf("failed to read directory %q: %s", path, err) } diff --git a/tpl/os/os_test.go b/tpl/os/os_test.go index bbc0d018c..59491e97c 100644 --- a/tpl/os/os_test.go +++ b/tpl/os/os_test.go @@ -11,34 +11,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -package os +package os_test import ( "path/filepath" "testing" - "github.com/gohugoio/hugo/config" + "github.com/gohugoio/hugo/hugolib" + "github.com/gohugoio/hugo/tpl/os" qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/deps" - "github.com/gohugoio/hugo/hugofs" - "github.com/spf13/afero" ) func TestReadFile(t *testing.T) { t.Parallel() - c := qt.New(t) - - workingDir := "/home/hugo" - v := config.New() - v.Set("workingDir", workingDir) + b := newFileTestBuilder(t).Build() - // f := newTestFuncsterWithViper(v) - ns := New(&deps.Deps{Fs: hugofs.NewMem(v)}) + // helpers.PrintFs(b.H.PathSpec.BaseFs.Work, "", _os.Stdout) - afero.WriteFile(ns.deps.Fs.Source, filepath.Join(workingDir, "/f/f1.txt"), []byte("f1-content"), 0755) - afero.WriteFile(ns.deps.Fs.Source, filepath.Join("/home", "f2.txt"), []byte("f2-content"), 0755) + ns := os.New(b.H.Deps) for _, test := range []struct { filename string @@ -53,13 +45,13 @@ func TestReadFile(t *testing.T) { result, err := ns.ReadFile(test.filename) - if b, ok := test.expect.(bool); ok && !b { - c.Assert(err, qt.Not(qt.IsNil)) + if bb, ok := test.expect.(bool); ok && !bb { + b.Assert(err, qt.Not(qt.IsNil)) continue } - c.Assert(err, qt.IsNil) - c.Assert(result, qt.Equals, test.expect) + b.Assert(err, qt.IsNil) + b.Assert(result, qt.Equals, test.expect) } } @@ -67,15 +59,8 @@ func TestFileExists(t *testing.T) { t.Parallel() c := qt.New(t) - workingDir := "/home/hugo" - - v := config.New() - v.Set("workingDir", workingDir) - - ns := New(&deps.Deps{Fs: hugofs.NewMem(v)}) - - afero.WriteFile(ns.deps.Fs.Source, filepath.Join(workingDir, "/f/f1.txt"), []byte("f1-content"), 0755) - afero.WriteFile(ns.deps.Fs.Source, filepath.Join("/home", "f2.txt"), []byte("f2-content"), 0755) + b := newFileTestBuilder(t).Build() + ns := os.New(b.H.Deps) for _, test := range []struct { filename string @@ -101,15 +86,8 @@ func TestFileExists(t *testing.T) { func TestStat(t *testing.T) { t.Parallel() - c := qt.New(t) - workingDir := "/home/hugo" - - v := config.New() - v.Set("workingDir", workingDir) - - ns := New(&deps.Deps{Fs: hugofs.NewMem(v)}) - - afero.WriteFile(ns.deps.Fs.Source, filepath.Join(workingDir, "/f/f1.txt"), []byte("f1-content"), 0755) + b := newFileTestBuilder(t).Build() + ns := os.New(b.H.Deps) for _, test := range []struct { filename string @@ -123,11 +101,28 @@ func TestStat(t *testing.T) { result, err := ns.Stat(test.filename) if test.expect == nil { - c.Assert(err, qt.Not(qt.IsNil)) + b.Assert(err, qt.Not(qt.IsNil)) continue } - c.Assert(err, qt.IsNil) - c.Assert(result.Size(), qt.Equals, test.expect) + b.Assert(err, qt.IsNil) + b.Assert(result.Size(), qt.Equals, test.expect) } } + +func newFileTestBuilder(t *testing.T) *hugolib.IntegrationTestBuilder { + files := ` +-- f/f1.txt -- +f1-content +-- home/f2.txt -- +f2-content + ` + + return hugolib.NewIntegrationTestBuilder( + hugolib.IntegrationTestConfig{ + T: t, + TxtarString: files, + WorkingDir: "/mywork", + }, + ) +} |