ref: 166483fe1227b0c59c6b4d88cfdfaf7d7b0d79c5
parent: f01505c910a325acc18742ac6b3637aa01975e37
author: Bjørn Erik Pedersen <[email protected]>
date: Fri Jul 20 11:02:35 EDT 2018
resource/scss: Add IncludePaths config option Takes paths relative to the current working dir. Fixes #4921
--- a/hugolib/filesystems/basefs.go
+++ b/hugolib/filesystems/basefs.go
@@ -244,8 +244,7 @@
var dirnames []string
for _, dir := range d.Dirnames {
dirname := filepath.Join(dir, from)
-
- if _, err := hugofs.Os.Stat(dirname); err == nil {
+ if _, err := d.SourceFs.Stat(dirname); err == nil {
dirnames = append(dirnames, dirname)
}
}
--- a/hugolib/page_bundler_capture_test.go
+++ b/hugolib/page_bundler_capture_test.go
@@ -90,8 +90,9 @@
}
assert := require.New(t)
- ps, workDir := newTestBundleSymbolicSources(t)
+ ps, clean, workDir := newTestBundleSymbolicSources(t)
sourceSpec := source.NewSourceSpec(ps, ps.BaseFs.Content.Fs)
+ defer clean()
fileStore := &storeFilenames{}
logger := loggers.NewErrorLogger()
--- a/hugolib/page_bundler_test.go
+++ b/hugolib/page_bundler_test.go
@@ -14,13 +14,10 @@
package hugolib
import (
- "io/ioutil"
-
"github.com/gohugoio/hugo/common/loggers"
"os"
"runtime"
- "strings"
"testing"
"github.com/gohugoio/hugo/helpers"
@@ -325,7 +322,9 @@
}
assert := require.New(t)
- ps, workDir := newTestBundleSymbolicSources(t)
+ ps, clean, workDir := newTestBundleSymbolicSources(t)
+ defer clean()
+
cfg := ps.Cfg
fs := ps.Fs
@@ -667,7 +666,7 @@
return fs, cfg
}
-func newTestBundleSymbolicSources(t *testing.T) (*helpers.PathSpec, string) {
+func newTestBundleSymbolicSources(t *testing.T) (*helpers.PathSpec, func(), string) {
assert := require.New(t)
// We need to use the OS fs for this.
cfg := viper.New()
@@ -675,14 +674,9 @@
fs.Destination = &afero.MemMapFs{}
loadDefaultSettingsFor(cfg)
- workDir, err := ioutil.TempDir("", "hugosym")
+ workDir, clean, err := createTempDir("hugosym")
+ assert.NoError(err)
- if runtime.GOOS == "darwin" && !strings.HasPrefix(workDir, "/private") {
- // To get the entry folder in line with the rest. This its a little bit
- // mysterious, but so be it.
- workDir = "/private" + workDir
- }
-
contentDir := "base"
cfg.Set("workingDir", workDir)
cfg.Set("contentDir", contentDir)
@@ -753,5 +747,5 @@
ps, _ := helpers.NewPathSpec(fs, cfg)
- return ps, workDir
+ return ps, clean, workDir
}
--- a/hugolib/resource_chain_test.go
+++ b/hugolib/resource_chain_test.go
@@ -14,12 +14,70 @@
package hugolib
import (
+ "os"
"path/filepath"
"testing"
+ "github.com/spf13/viper"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/gohugoio/hugo/hugofs"
+
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/resource/tocss/scss"
)
+
+func TestSCSSWithIncludePaths(t *testing.T) {
+ if !scss.Supports() {
+ t.Skip("Skip SCSS")
+ }
+ assert := require.New(t)
+ workDir, clean, err := createTempDir("hugo-scss-include")
+ assert.NoError(err)
+ defer clean()
+
+ v := viper.New()
+ v.Set("workingDir", workDir)
+ b := newTestSitesBuilder(t).WithLogger(loggers.NewWarningLogger())
+ b.WithViper(v)
+ b.WithWorkingDir(workDir)
+ // Need to use OS fs for this.
+ b.Fs = hugofs.NewDefault(v)
+
+ fooDir := filepath.Join(workDir, "node_modules", "foo")
+ scssDir := filepath.Join(workDir, "assets", "scss")
+ assert.NoError(os.MkdirAll(fooDir, 0777))
+ assert.NoError(os.MkdirAll(filepath.Join(workDir, "content", "sect"), 0777))
+ assert.NoError(os.MkdirAll(filepath.Join(workDir, "data"), 0777))
+ assert.NoError(os.MkdirAll(filepath.Join(workDir, "i18n"), 0777))
+ assert.NoError(os.MkdirAll(filepath.Join(workDir, "layouts", "shortcodes"), 0777))
+ assert.NoError(os.MkdirAll(filepath.Join(workDir, "layouts", "_default"), 0777))
+ assert.NoError(os.MkdirAll(filepath.Join(scssDir), 0777))
+
+ b.WithSourceFile(filepath.Join(fooDir, "_moo.scss"), `
+$moolor: #fff;
+
+moo {
+ color: $moolor;
+}
+`)
+
+ b.WithSourceFile(filepath.Join(scssDir, "main.scss"), `
+@import "moo";
+
+`)
+
+ b.WithTemplatesAdded("index.html", `
+{{ $cssOpts := (dict "includePaths" (slice "node_modules/foo" ) ) }}
+{{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }}
+T1: {{ $r.Content }}
+`)
+ b.Build(BuildCfg{})
+
+ b.AssertFileContent(filepath.Join(workDir, "public/index.html"), `T1: moo{color:#fff}`)
+
+}
func TestResourceChain(t *testing.T) {
t.Parallel()
--- a/hugolib/testhelpers_test.go
+++ b/hugolib/testhelpers_test.go
@@ -1,7 +1,9 @@
package hugolib
import (
+ "io/ioutil"
"path/filepath"
+ "runtime"
"testing"
"bytes"
@@ -80,6 +82,20 @@
}
return &sitesBuilder{T: t, Fs: fs, configFormat: "toml", dumper: litterOptions}
+}
+
+func createTempDir(prefix string) (string, func(), error) {
+ workDir, err := ioutil.TempDir("", prefix)
+ if err != nil {
+ return "", nil, err
+ }
+
+ if runtime.GOOS == "darwin" && !strings.HasPrefix(workDir, "/private") {
+ // To get the entry folder in line with the rest. This its a little bit
+ // mysterious, but so be it.
+ workDir = "/private" + workDir
+ }
+ return workDir, func() { os.RemoveAll(workDir) }, nil
}
func (s *sitesBuilder) Running() *sitesBuilder {
--- a/resource/tocss/scss/client.go
+++ b/resource/tocss/scss/client.go
@@ -22,12 +22,13 @@
)
type Client struct {
- rs *resource.Spec
- sfs *filesystems.SourceFilesystem
+ rs *resource.Spec
+ sfs *filesystems.SourceFilesystem
+ workFs *filesystems.SourceFilesystem
}
func New(fs *filesystems.SourceFilesystem, rs *resource.Spec) (*Client, error) {
- return &Client{sfs: fs, rs: rs}, nil
+ return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs}, nil
}
type Options struct {
@@ -37,6 +38,13 @@
// control this by setting this, e.g. "styles/main.css" will create
// a Resource with that as a base for RelPermalink etc.
TargetPath string
+
+ // Hugo automatically adds the entry directories (where the main.scss lives)
+ // for project and themes to the list of include paths sent to LibSASS.
+ // Any paths set in this setting will be appended. Note that these will be
+ // treated as relative to the working dir, i.e. no include paths outside the
+ // project/themes.
+ IncludePaths []string
// Default is nested.
// One of nested, expanded, compact, compressed.
--- a/resource/tocss/scss/tocss.go
+++ b/resource/tocss/scss/tocss.go
@@ -49,9 +49,12 @@
options := t.options
- // We may allow the end user to add IncludePaths later, if we find a use
- // case for that.
options.to.IncludePaths = t.c.sfs.RealDirs(path.Dir(ctx.SourcePath))
+
+ // Append any workDir relative include paths
+ for _, ip := range options.from.IncludePaths {
+ options.to.IncludePaths = append(options.to.IncludePaths, t.c.workFs.RealDirs(filepath.Clean(ip))...)
+ }
if ctx.InMediaType.SubType == media.SASSType.SubType {
options.to.SassSyntax = true