2022-02-09 08:04:57 -05:00
// Copyright 2021 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 dartsass_test
import (
2022-05-15 05:40:34 -04:00
"strings"
2022-02-09 08:04:57 -05:00
"testing"
2023-06-16 02:17:42 -04:00
"github.com/bep/logg"
2022-05-15 05:40:34 -04:00
qt "github.com/frankban/quicktest"
2024-02-29 13:05:23 -05:00
"github.com/gohugoio/hugo/htesting"
2022-02-09 08:04:57 -05:00
"github.com/gohugoio/hugo/hugolib"
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass"
)
func TestTransformIncludePaths ( t * testing . T ) {
2022-12-19 12:49:02 -05:00
t . Parallel ( )
2022-02-09 08:04:57 -05:00
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / scss / main . scss --
@ import "moo" ;
-- node_modules / foo / _moo . scss --
$ moolor : # fff ;
moo {
color : $ moolor ;
}
-- config . toml --
-- layouts / index . html --
{ { $ cssOpts := ( dict "includePaths" ( slice "node_modules/foo" ) "transpiler" "dartsass" ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts | minify } }
T1 : { { $ r . Content } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
2022-02-10 13:49:20 -05:00
T : t ,
2022-02-09 08:04:57 -05:00
TxtarString : files ,
NeedsOsFS : true ,
} ) . Build ( )
b . AssertFileContent ( "public/index.html" , ` T1: moo { color:#fff} ` )
}
func TestTransformImportRegularCSS ( t * testing . T ) {
2022-12-19 12:49:02 -05:00
t . Parallel ( )
2022-02-09 08:04:57 -05:00
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / scss / _moo . scss --
$ moolor : # fff ;
moo {
color : $ moolor ;
}
-- assets / scss / another . css --
-- assets / scss / main . scss --
@ import "moo" ;
@ import "regular.css" ;
@ import "moo" ;
@ import "another.css" ;
/* foo */
-- assets / scss / regular . css --
-- config . toml --
-- layouts / index . html --
{ { $ r := resources . Get "scss/main.scss" | toCSS ( dict "transpiler" "dartsass" ) } }
T1 : { { $ r . Content | safeHTML } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
2022-02-10 13:49:20 -05:00
T : t ,
2022-02-09 08:04:57 -05:00
TxtarString : files ,
NeedsOsFS : true ,
} ,
) . Build ( )
// Dart Sass does not follow regular CSS import, but they
// get pulled to the top.
b . AssertFileContent ( "public/index.html" , ` T1 : @ import "regular.css" ;
@ import "another.css" ;
moo {
color : # fff ;
}
2023-02-23 19:23:36 -05:00
2022-02-09 08:04:57 -05:00
moo {
color : # fff ;
}
2023-02-23 19:23:36 -05:00
2022-02-09 08:04:57 -05:00
/* foo */ ` )
}
2023-06-08 10:17:12 -04:00
func TestTransformImportIndentedSASS ( t * testing . T ) {
t . Parallel ( )
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / scss / _moo . sass --
# main
color : blue
-- assets / scss / main . scss --
@ import "moo" ;
/* foo */
-- config . toml --
-- layouts / index . html --
{ { $ r := resources . Get "scss/main.scss" | toCSS ( dict "transpiler" "dartsass" ) } }
T1 : { { $ r . Content | safeHTML } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
} ,
) . Build ( )
b . AssertFileContent ( "public/index.html" , "T1: #main {\n color: blue;\n}\n\n/* foo */" )
}
2023-02-23 19:23:36 -05:00
// Issue 10592
func TestTransformImportMountedCSS ( t * testing . T ) {
t . Parallel ( )
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / main . scss --
@ import "import-this-file.css" ;
@ import "foo/import-this-mounted-file.css" ;
@ import "compile-this-file" ;
@ import "foo/compile-this-mounted-file" ;
a { color : main - scss ; }
-- assets / _compile - this - file . css --
a { color : compile - this - file - css ; }
-- assets / _import - this - file . css --
a { color : import - this - file - css ; }
-- foo / _compile - this - mounted - file . css --
a { color : compile - this - mounted - file - css ; }
-- foo / _import - this - mounted - file . css --
a { color : import - this - mounted - file - css ; }
-- layouts / index . html --
{ { - $ opts := dict "transpiler" "dartsass" } }
{ { - with resources . Get "main.scss" | toCSS $ opts } } { { . Content | safeHTML } } { { end } }
-- config . toml --
disableKinds = [ ' RSS ',' sitemap ',' taxonomy ',' term ',' page ',' section ' ]
[ [ module . mounts ] ]
source = ' assets '
target = ' assets '
[ [ module . mounts ] ]
source = ' foo '
target = ' assets / foo '
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
} ,
) . Build ( )
b . AssertFileContent ( "public/index.html" , `
@ import "import-this-file.css" ;
@ import "foo/import-this-mounted-file.css" ;
a {
color : compile - this - file - css ;
}
a {
color : compile - this - mounted - file - css ;
}
a {
color : main - scss ;
}
` )
}
2022-02-09 08:04:57 -05:00
func TestTransformThemeOverrides ( t * testing . T ) {
2022-12-19 12:49:02 -05:00
t . Parallel ( )
2022-02-09 08:04:57 -05:00
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / scss / components / _boo . scss --
$ boolor : green ;
boo {
color : $ boolor ;
}
-- assets / scss / components / _moo . scss --
$ moolor : # ccc ;
moo {
color : $ moolor ;
}
-- config . toml --
theme = ' mytheme '
-- layouts / index . html --
{ { $ cssOpts := ( dict "includePaths" ( slice "node_modules/foo" ) "transpiler" "dartsass" ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts | minify } }
T1 : { { $ r . Content } }
-- themes / mytheme / assets / scss / components / _boo . scss --
$ boolor : orange ;
boo {
color : $ boolor ;
}
-- themes / mytheme / assets / scss / components / _imports . scss --
@ import "moo" ;
@ import "_boo" ;
@ import "_zoo" ;
-- themes / mytheme / assets / scss / components / _moo . scss --
$ moolor : # fff ;
moo {
color : $ moolor ;
}
-- themes / mytheme / assets / scss / components / _zoo . scss --
$ zoolor : pink ;
zoo {
color : $ zoolor ;
}
-- themes / mytheme / assets / scss / main . scss --
@ import "components/imports" ;
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
2022-02-10 13:49:20 -05:00
T : t ,
2022-02-09 08:04:57 -05:00
TxtarString : files ,
NeedsOsFS : true ,
} ,
) . Build ( )
b . AssertFileContent ( "public/index.html" , ` T1: moo { color:#ccc}boo { color:green}zoo { color:pink} ` )
}
2022-03-17 12:22:34 -04:00
func TestTransformLogging ( t * testing . T ) {
2022-12-19 12:49:02 -05:00
t . Parallel ( )
2022-03-17 12:22:34 -04:00
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / scss / main . scss --
@ warn "foo" ;
@ debug "bar" ;
-- config . toml --
disableKinds = [ "term" , "taxonomy" , "section" , "page" ]
-- layouts / index . html --
{ { $ cssOpts := ( dict "transpiler" "dartsass" ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts } }
T1 : { { $ r . Content } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
2023-06-16 02:17:42 -04:00
LogLevel : logg . LevelInfo ,
2022-03-17 12:22:34 -04:00
} ) . Build ( )
2023-06-16 02:17:42 -04:00
b . AssertLogMatches ( ` Dart Sass: foo ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:1:0: bar ` )
2022-03-17 12:22:34 -04:00
}
2022-05-15 05:40:34 -04:00
func TestTransformErrors ( t * testing . T ) {
2022-12-19 12:49:02 -05:00
t . Parallel ( )
2022-05-15 05:40:34 -04:00
if ! dartsass . Supports ( ) {
t . Skip ( )
}
c := qt . New ( t )
const filesTemplate = `
-- config . toml --
-- assets / scss / components / _foo . scss --
/* comment line 1 */
$ foocolor : # ccc ;
foo {
color : $ foocolor ;
}
-- assets / scss / main . scss --
/* comment line 1 */
/* comment line 2 */
@ import "components/foo" ;
/* comment line 4 */
$ maincolor : # eee ;
body {
color : $ maincolor ;
}
-- layouts / index . html --
{ { $ cssOpts := dict "transpiler" "dartsass" } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts | minify } }
T1 : { { $ r . Content } }
`
c . Run ( "error in main" , func ( c * qt . C ) {
b , err := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : c ,
TxtarString : strings . Replace ( filesTemplate , "$maincolor: #eee;" , "$maincolor #eee;" , 1 ) ,
NeedsOsFS : true ,
} ) . BuildE ( )
b . Assert ( err , qt . IsNotNil )
b . Assert ( err . Error ( ) , qt . Contains , ` main.scss:8:13": ` )
b . Assert ( err . Error ( ) , qt . Contains , ` : expected ":". ` )
fe := b . AssertIsFileError ( err )
b . Assert ( fe . ErrorContext ( ) , qt . IsNotNil )
b . Assert ( fe . ErrorContext ( ) . Lines , qt . DeepEquals , [ ] string { " $maincolor #eee;" , "" , "body {" , "\tcolor: $maincolor;" , "}" } )
b . Assert ( fe . ErrorContext ( ) . ChromaLexer , qt . Equals , "scss" )
} )
c . Run ( "error in import" , func ( c * qt . C ) {
b , err := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : c ,
TxtarString : strings . Replace ( filesTemplate , "$foocolor: #ccc;" , "$foocolor #ccc;" , 1 ) ,
NeedsOsFS : true ,
} ) . BuildE ( )
b . Assert ( err , qt . IsNotNil )
b . Assert ( err . Error ( ) , qt . Contains , ` _foo.scss:2:10": ` )
b . Assert ( err . Error ( ) , qt . Contains , ` : expected ":". ` )
fe := b . AssertIsFileError ( err )
b . Assert ( fe . ErrorContext ( ) , qt . IsNotNil )
b . Assert ( fe . ErrorContext ( ) . Lines , qt . DeepEquals , [ ] string { "/* comment line 1 */" , "$foocolor #ccc;" , "" , "foo {" } )
b . Assert ( fe . ErrorContext ( ) . ChromaLexer , qt . Equals , "scss" )
} )
}
2022-12-19 12:49:02 -05:00
func TestOptionVars ( t * testing . T ) {
t . Parallel ( )
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- assets / scss / main . scss --
@ use "hugo:vars" ;
body {
body {
background : url ( vars . $ image ) no - repeat center / cover ;
2022-12-21 03:17:51 -05:00
font - family : vars . $ font ;
2023-02-23 19:23:36 -05:00
}
2022-12-19 12:49:02 -05:00
}
p {
color : vars . $ color1 ;
font - size : vars . $ font_size ;
}
b {
color : vars . $ color2 ;
}
-- layouts / index . html --
{ { $ image := "images/hero.jpg" } }
2022-12-21 03:17:51 -05:00
{ { $ font := "Hugo's New Roman" } }
{ { $ vars := dict "$color1" "blue" "$color2" "green" "font_size" "24px" "image" $ image "font" $ font } }
2022-12-19 12:49:02 -05:00
{ { $ cssOpts := ( dict "transpiler" "dartsass" "outputStyle" "compressed" "vars" $ vars ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts } }
T1 : { { $ r . Content } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
} ) . Build ( )
2022-12-21 03:17:51 -05:00
b . AssertFileContent ( "public/index.html" , ` T1: body body { background:url(images/hero.jpg) no-repeat center/cover;font-family:Hugo's New Roman}p { color:blue;font-size:24px}b { color:green} ` )
2022-12-19 12:49:02 -05:00
}
func TestOptionVarsParams ( t * testing . T ) {
t . Parallel ( )
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- config . toml --
[ params ]
[ params . sassvars ]
color1 = "blue"
color2 = "green"
font_size = "24px"
image = "images/hero.jpg"
-- assets / scss / main . scss --
@ use "hugo:vars" ;
body {
body {
background : url ( vars . $ image ) no - repeat center / cover ;
2023-02-23 19:23:36 -05:00
}
2022-12-19 12:49:02 -05:00
}
p {
color : vars . $ color1 ;
font - size : vars . $ font_size ;
}
b {
color : vars . $ color2 ;
}
-- layouts / index . html --
{ { $ vars := site . Params . sassvars } }
{ { $ cssOpts := ( dict "transpiler" "dartsass" "outputStyle" "compressed" "vars" $ vars ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts } }
T1 : { { $ r . Content } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
} ) . Build ( )
b . AssertFileContent ( "public/index.html" , ` T1: body body { background:url(images/hero.jpg) no-repeat center/cover}p { color:blue;font-size:24px}b { color:green} ` )
}
2023-02-12 14:53:30 -05:00
func TestVarsCasting ( t * testing . T ) {
t . Parallel ( )
if ! dartsass . Supports ( ) {
t . Skip ( )
}
files := `
-- config . toml --
disableKinds = [ "term" , "taxonomy" , "section" , "page" ]
[ params ]
[ params . sassvars ]
color_hex = "#fff"
color_rgb = "rgb(255, 255, 255)"
color_hsl = "hsl(0, 0%, 100%)"
dimension = "24px"
percentage = "10%"
flex = "5fr"
2023-02-21 12:32:09 -05:00
name = "Hugo"
url = "https://gohugo.io"
integer = 32
float = 3.14
2023-02-12 14:53:30 -05:00
-- assets / scss / main . scss --
@ use "hugo:vars" ;
@ use "sass:meta" ;
@ debug meta . type - of ( vars . $ color_hex ) ;
@ debug meta . type - of ( vars . $ color_rgb ) ;
@ debug meta . type - of ( vars . $ color_hsl ) ;
@ debug meta . type - of ( vars . $ dimension ) ;
@ debug meta . type - of ( vars . $ percentage ) ;
@ debug meta . type - of ( vars . $ flex ) ;
2023-02-21 12:32:09 -05:00
@ debug meta . type - of ( vars . $ name ) ;
@ debug meta . type - of ( vars . $ url ) ;
@ debug meta . type - of ( vars . $ not_a_number ) ;
@ debug meta . type - of ( vars . $ integer ) ;
@ debug meta . type - of ( vars . $ float ) ;
@ debug meta . type - of ( vars . $ a_number ) ;
2023-02-12 14:53:30 -05:00
-- layouts / index . html --
{ { $ vars := site . Params . sassvars } }
2023-02-21 12:32:09 -05:00
{ { $ vars = merge $ vars ( dict "not_a_number" ( "32xxx" | css . Quoted ) "a_number" ( "234" | css . Unquoted ) ) } }
2023-02-12 14:53:30 -05:00
{ { $ cssOpts := ( dict "transpiler" "dartsass" "vars" $ vars ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts } }
T1 : { { $ r . Content } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
2023-06-16 02:17:42 -04:00
LogLevel : logg . LevelInfo ,
2023-02-12 14:53:30 -05:00
} ) . Build ( )
2023-06-16 02:17:42 -04:00
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:3:0: color ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:4:0: color ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:5:0: color ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:6:0: number ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:7:0: number ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:8:0: number ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:9:0: string ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:10:0: string ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:11:0: string ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:12:0: number ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:13:0: number ` )
b . AssertLogMatches ( ` Dart Sass: .*assets.*main.scss:14:0: number ` )
2023-02-12 14:53:30 -05:00
}
2024-02-29 13:05:23 -05:00
// Note: This test is more or less duplicated in both of the SCSS packages (libsass and dartsass).
func TestBootstrap ( t * testing . T ) {
t . Parallel ( )
if ! dartsass . Supports ( ) {
t . Skip ( )
}
if ! htesting . IsCI ( ) {
t . Skip ( "skip (slow) test in non-CI environment" )
}
files := `
-- hugo . toml --
disableKinds = [ "term" , "taxonomy" , "section" , "page" ]
[ module ]
[ [ module . imports ] ]
path = "github.com/gohugoio/hugo-mod-bootstrap-scss/v5"
-- go . mod --
module github . com / gohugoio / tests / testHugoModules
-- assets / scss / main . scss --
@ import "bootstrap/bootstrap" ;
-- layouts / index . html --
{ { $ cssOpts := ( dict "transpiler" "dartsass" ) } }
{ { $ r := resources . Get "scss/main.scss" | toCSS $ cssOpts } }
Styles : { { $ r . RelPermalink } }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
TxtarString : files ,
NeedsOsFS : true ,
} ) . Build ( )
b . AssertFileContent ( "public/index.html" , "Styles: /scss/main.css" )
}
2024-09-13 18:54:23 -04:00
// Issue 12849
func TestDirectoryIndexes ( t * testing . T ) {
t . Parallel ( )
2024-09-15 18:10:37 -04:00
if ! dartsass . Supports ( ) {
t . Skip ( )
}
2024-09-13 18:54:23 -04:00
files := `
-- hugo . toml --
disableKinds = [ ' page ',' section ',' rss ',' sitemap ',' taxonomy ',' term ' ]
[ [ module . mounts ] ]
source = ' assets '
target = ' assets '
[ [ module . imports ] ]
path = "github.com/gohugoio/hugoTestModule2"
[ [ module . imports . mounts ] ]
source = "miscellaneous/sass"
target = "assets/sass"
-- go . mod --
module hugo - github - issue - 12849
-- layouts / index . html --
{ { $ opts := dict "transpiler" "dartsass" "outputStyle" "compressed" } }
{ { ( resources . Get "sass/main.scss" | toCSS $ opts ) . Content } }
-- assets / sass / main . scss --
@ use "foo" ; // directory with index file from OS file system
@ use "bar" ; // directory with index file from module mount
-- assets / sass / foo / _index . scss --
. foo { color : red ; }
`
b := hugolib . NewIntegrationTestBuilder (
hugolib . IntegrationTestConfig {
T : t ,
NeedsOsFS : true ,
TxtarString : files ,
} ) . Build ( )
b . AssertFileContent ( "public/index.html" , ".foo{color:red}.bar{color:green}" )
}