Hugo module import of dart sass css framework

I’ve been using hugo modules in my theme for a while now to bring down my themes CSS framework (bulma). This worked great under libsass and the older version that I was using as I could just mount the sass folder in my assets path and @import away.

But now bulma is all about the @use and @forward so I installed dart sass and am attempting to migrate but I’ve hit a snag in that no matter what I try the ToCSS process can’t find the @use’d file. “Can’t find stylesheet to import.” is the error.

I’m about to give up and move it to be the responsibility of npm but I wondered if anyone has a different solution?

Looking closely at it, I remember my theme includes all it’s runtime files (bulma, viewerjs, fontawesome) using hugo modules. Is it just better to use npm for those? I like the way hugo pulls them all for you so you don’t have to faff with npm.

Without any sample config or code all I can say is “WHERE is ToCSS looking for @use’d files”? There are configuration options to add other folders than the location of your current processed file. includePaths in the docs.

Yeah, these work if I’m using the NPM route as the framework files exist under “node_modules/bulma” but when using hugo modules they exist in some nebulous virtual area that only really exists at build time.

I can @import from the mounted location with something like @import "../bulma/component/media" for example but that doesn’t work when you swap that for a @use.

That nebulous existing area exists in the confines of GoHugo too. So if your postcss says “includePaths is assets/some/folder” and your module mounts the files in “assets/some/folder” then postcss/tocss will find them if you refer to them from that “includePath root”.

Don’t get me wrong, but you are describing a Blackbox here and the cat is very alive for me. Show some example code with real existing paths and mounts and we might see where you are going wrong.

I have the experience that the “hardcore” version of ../../../../some/folder/from/root always works in uses and imports, so that might be your first attempt. Your initial SASS/SCSS file is the local path and everything from there is relative.

As long as you use sass and postcss from within Hugo all these mounts are “real” for the system… Not in VSCode, but that might be fixed with some more configuration that is not relevant for now.

Ok, wall of code :slight_smile:

Given an import like this:

# themes config.toml
[[module.imports]]
path = "github.com/jgthms/bulma"
  [[module.imports.mounts]]
  source = "sass"
  target = "assets/sass/bulma"

and a SASS entrypoint file like this:

# assets/sass/main.scss
@use "utilities" with (
    $family-primary: '"Raleway", "Helvetica", "Arial", sans-serif',
    $family-secondary: '"Nunito", "Helvetica", "Arial", sans-serif',

    $radius: 0.25rem,
);

Processed using a template configuration like this:

{{ $sass := resources.Get "sass/main.scss" }}
{{ $opts := dict 
  "outputStyle" "compressed"
  "transpiler" "dartsass"
  "targetPath" "main.css"
  "includePaths" (slice "assets/sass/bulma/sass")
}}
{{ $style := $sass | css.Sass $opts }}
<link rel="stylesheet" type="text/css" href="{{ $style.RelPermalink }}"
      crossorigin="anonymous">

I receive the following error:

ERROR TOCSS-DART: failed to transform "/sass/main.scss" (text/x-scss): "/Users/ME/Projects/Personal/site-hugo-theme/assets/sass/main.scss:1:0": Can't find stylesheet to import.

If I instead use an @import line like this:

@import "utilities"

in my main.scss file I get no error and a css file containing processed css - though it’s non-functional for my purposes as bulma is all sass modules now.

If I instead use an NPM version of Bulma and add a correct include path for that location it also works.

You mounted the folder sass of bulma to the folder assets/sass/bulma and then in the includePaths you told sass o use the folder sass in the mount sass/bulma resulting in assets/sass/bulma/sass/ for ToCss. BUT… it’s in bulma :wink:

so:

"includePaths" (slice "assets/sass/bulma")

might fix it. maybe use the debug function in sass to debug from within your styles…

But from what I see you double-mount your sass folder… as in assets/sass/bulma/sass/sass in the path ToCss is working with.

Sadly I spotted that just now, had a mini eureka moment, and then found that the correct path (the one you identified) also doesn’t work :frowning:

Windows support question: Did you restart the server? When in doubt always restart the Hugo server. Especially with style pipes.

By the way, why do you mount it? I would add it via package.json and then use node_modules as includePaths and refer to the full path from there. That feels more portable, if you are already using package.json for your site.

I think that might be the way I go. I figured I’d use modules as it seem more “go” then having to ensure a working node environment. That said, because of my usage of PostCss I’m having to run a package.json anyway.

EDIT. Having given it a brief look I remember now that I also found it was a super simple way to just include files/assets such as images or fonts in the build - and that getting my scss to bring them in automatically just wasn’t working.

1 Like

In general, I always add the following to my config/_default/module.toml configuration:

[[mounts]]
source = "node_modules"
target = "assets/node_modules"

this way all the resources functions of GoHugo can access the files in node_modules. Fonts, SVG, and images work fine this way.

I’m assuming that has to go in the main site project as opposed to the theme module? Since putting it in the theme module (where I think makes the most sense) causes the whole thing to fall over :smiley:

Yeah… I am myself working on a weird system to overcome this limitation. But until then put everything relevant into the root package.json :wink: Have a look at wireit, but that is very “offtopic” in regards to Hugo. You might be able to load npm scripts from packages “down” to the root package with that.

Ok, this is very definitely why I went down the route of using modules to bring 3rd party projects in. Having to spread stuff that is specifically theme related into the main site project is not really what I want to do.

EDIT.

If I could put this

[[module.mounts]]
source = "node_modules"
target = "assets/node_modules"
[[module.mounts]]
source = "node_modules/@fortawesome/fontawesome-free/webfonts"
target = "static/fonts"
includeFiles = [
  "fa-brands-400.*",
  "fa-solid-900.*"
]

in my themes config.toml that would be great. :smiley:

This is a bug.

The Bulma Sass library leverages directory index files with its @use and @forward rules.

Directory index files allow you to do this…

@use "foo/bar";

…instead of either of these:

@use "foo/bar/_index";
@use "foo/bar/_index.scss";

When you install the Bulma Sass library using npm install or similar, its files exist in the OS file system. In this case the Dart Sass executable is able to resolve paths to directory index files as expected.

When you import the Bulma Sass library as a Hugo module, its files exist in Hugo’s virtual file system. In this case the Dart Sass executable is unable to resolve paths to directory index files because the files do not exist in the OS file system.

This should be fixable. See:

Minimal reproducible example:

git clone --single-branch -b hugo-forum-topic-51528 https://github.com/jmooring/hugo-testing hugo-forum-topic-51528
cd hugo-forum-topic-51528
hugo server

Don’t know if this is relevant for the bug, but it looks like the behavior is a different if there’s a go.mod file.

So no explicit mounts are used, but Hugo or Go take care to MAP stuff from the module cache to a place where dart sass can find it


Working config using Theme module

  • dart-sass installed as windows binary and added to path

    hugo env
    hugo v0.134.2-1c74abd26070b0c12849550c974a9f3f1e7afb06+extended windows/amd64 BuildDate=2024-09-10T10:46:33Z VendorInfo=gohugoio
    GOOS="windows"
    GOARCH="amd64"
    GOVERSION="go1.23.0"
    github.com/sass/libsass="3.6.6"
    github.com/webmproject/libwebp="v1.3.2"
    github.com/sass/dart-sass/protocol="2.7.0"
    github.com/sass/dart-sass/compiler="1.76.0"
    github.com/sass/dart-sass/implementation="1.76.0"
    

I recently created a repo that repacks the official Bulma release as a Hugo module (Theme). There is no customization but wrapping the release files in a Hugo module

see: https://github.com/irkode/bulma4hugo

With that the following works:

  • hugo.toml

    [module]
     [[module.imports]]
        path = "github.com/irkode/bulma4hugo"
    
  • baseof.html in head section

        {{ $opts := dict "transpiler" "dartsass" "targetPath" "css/bulma4hugo.css" }}
        {{ with resources.Get "bulma/bulma.scss" | toCSS $opts }}
           <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
        {{ end }}
    

also customizatiuon is possible following Customize with Sass - Bulma

  • just take the shown sass file and save to assets/custom.css

    assets/custom.css
    // Set your brand colors
    $purple: #8a4d76;
    $pink: #fa7c91;
    $brown: #757763;
    $beige-light: #d0d1cd;
    $beige-lighter: #eff0eb;
    
    // Path to Bulma's sass folder
    @use "bulma/sass" with (
      $family-primary: '"Nunito", sans-serif',
      $grey-dark: $brown,
      $grey-light: $beige-light,
      $primary: $purple,
      $link: $pink,
      $control-border-width: 2px,
      $input-shadow: none
    );
    
    // Import the Google Font
    @import url("https://fonts.googleapis.com/css?family=Nunito:400,700");
    
  • call it like this

    {{ $opts := dict "transpiler" "dartsass" "targetPath" "css/custom.css" }}
    {{ with resources.Get "custom.scss" | toCSS $opts }}
    

What Hugo 4 Bulma does

  • extracts the Bulma package bulma-1.0.2.zip to assets/bulma

  • wraps it as a hugo module

    file tree
    C:\BULMA4HUGO-1.0.2
    ├─ go.mod
    ├─ LICENSE
    ├─ README.md
    ├─ theme.toml
    └───assets
       └───bulma               <-- from here it's the original release package
           ├───css
           │   └───versions
           ├───sass
           │   ├───base
           │   ├───components
           │   ├───elements
           │   ├───form
           │   ├───grid
           │   ├───helpers
           │   ├───layout
           │   ├───themes
           │   └───utilities
           └───versions
    
1 Like

Ah, didn’t think to check that it might be a bug.

Very happy to see that it’s likely fixable :slight_smile:

This is fantastic work! Thanks very much for your efforts!

This is interesting. But I’m still not getting it working using your module :frowning: Do your instructions assume the bulma module is imported in the main site module or in another theme module?

Mmh. Tested it before I posted.

Just the two things i mentioned

  • (MISSED that) you need to turn your hugo site in a module

    hugo mod init mysite

  • addimport in hugo.toml

    No mounts needed!

  • and the pipline in baseof.html

It’s ment to be imported in the main site. In fact never tried it in theme. Noted in todo.


posted a working example based on hugo new && hugo new theme below

This example imports a GitHub repository that contains a go.mod file.

git clone --single-branch -b hugo-github-issue-12849 https://github.com/jmooring/hugo-testing hugo-github-issue-12849
cd hugo-github-issue-12849
hugo

error calling Content: TOCSS-DART: failed to transform “/sass/main.scss” (text/x-scss): “:1:1”: Can’t find stylesheet to import.