Issue with SCSS transformation

Im trying to dynamically add styles to a page by only importing the CSS for specific partials the page needs

I have tried reading from the page front matter and it works:

{{ $styles := slice (resources.Get "scss/main.scss" ) }}
{{ range $file := .Params.components }}
    {{ $path := printf "scss/partials/%s.scss" $file}}
    {{ $styles = $styles | append (resources.Get $path) }}
{{ end }}
{{ $name := "" }}
{{ if .IsHome }} {{ $name := "index" }} {{ else }} {{ $name := .Title }}{{end}}
{{ $bundle := ($styles) | resources.Concat (printf "%s.scss" $name )}}
{{ $options := (dict "outputStyle" "compressed") }}
{{ $style := $bundle | resources.ToCSS $options }}

But now I’m trying to read form the data folder

{{ with .File }}
    {{ $page := .BaseFileName }}
    {{ if eq $.Page.Type "post" }}
      {{ "post" }}
    {{ else if eq $.Page.Type "page" }}
      {{ with (index $.Site.Data.page $page)}}
        {{ $main := resources.Get "scss/main.scss" }}
        {{ $options := (dict "outputStyle" "compressed" ) }}
        {{ $s := $main | resources.ToCSS $options }}
        <style media="all">{{ $s.Content | safeCSS }}</style>

        {{ range $k, $v := . }}
          {{ $path := printf "scss/partials/%s.scss" $k }}
          {{ $path }}
          {{ $c := $.Resources.Match $path }}
          {{ $c  }}
          {{ $m2 := resources.Get "scss/main.scss" }}
          {{ $m2 }}
          {{ $s = $c | resources.ToCSS $options }}
        {{ end }}
      {{ end }}
    {{ end }}
  {{ end }}

And it fails when calling $s = $c | resources.ToCSS $options with error:

error calling ToCSS: no Resource provided in transformation

I have also tried calling $c := resources.Get $path and get the same error

What am I doing wrong? Why does the main.scss works but not the other?

Your code sample is not extensive enough to understand what is going on, but:

First code sample:

  • {{ range $file := .Params.components }} - whats in components in your params?
  • why do you concat scss files? you should have a single starting point for your stylesheet and then inside there you @import other scss files.

Second code sample:

  • what’s inside of your data folder?

I have the feeling that you try to emulate the behaviour of scss in hugo somehow. Importing all the scss files via hugo does not make much sense to me, but as I wrote, not enough information to dive deeper on your issue. Maybe you have a sample repo somewhere?

1 Like

If your directory structure contains:

assets/
└── scss/
    ├── partials/
    │   └── foo.scss
    └── main.scss
content/
├── about.md
└── _index.md

And your data file looks like this:

# data/page.toml
about = ['foo']

Then make the following changes:

diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index 419862093..7e1e9b62d 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -8,7 +8,7 @@
 
 {{ with .File }}
-  {{ $page := .BaseFileName }}
+  {{ $page := .ContentBaseName }}
   {{ if eq $.Page.Type "post" }}
     {{ "post" }}
   {{ else if eq $.Page.Type "page" }}
@@ -17,15 +17,11 @@
       {{ $options := (dict "outputStyle" "compressed" ) }}
       {{ $s := $main | resources.ToCSS $options }}
       <style media="all">{{ $s.Content | safeCSS }}</style>
-
       {{ range $k, $v := . }}
-        {{ $path := printf "scss/partials/%s.scss" $k }}
-        {{ $path }}
-        {{ $c := $.Resources.Match $path }}
-        {{ $c  }}
-        {{ $m2 := resources.Get "scss/main.scss" }}
-        {{ $m2 }}
+        {{ $path := printf "scss/partials/%s.scss" $v }}
+        {{ $c := resources.Get $path }}
         {{ $s = $c | resources.ToCSS $options }}
+        <style media="all">{{ $s.Content | safeCSS }}</style>
       {{ end }}
     {{ end }}
   {{ end }}

Why it was failing (assuming my assumptions above are correct):

  1. While ranging through the slice of values in the database for the given page, you were generating the path to the Sass file using the key ($k) instead of the value ($v).
  2. You were attempting to access global resources (in the assets directory) using the .Resources method instead of the resources function. The .Resources method is for page resources (files within a page bundle).
  3. Using resources.Match or .Resources.Match returns an array, even if there is only one element in the array.

The last change, at the top of the file, will accommodate page bundles. For example:

content/
├── about/
│   └── index.md
└── _index.md

With page bundles or sections, the .BaseFileName method returns index and _index respectively. Use the .ContentBaseName method instead.

1 Like

Hey davidsneighbour

I think you’re right. This might be my poor experience with scss making things worse

So here’s what im doing (this might be long)
Im trying to build an atomic design based Hugo theme

In the video above, Brad is using mustache and JSON to build a site by defining content in what he calls molecules in order to build an organism and so on

In my attempt to do this I have created inside my data folder a file (yaml, toml, or json) for a page and defined in there all the bits in order to build it

For example one file in my data folder looks like this:

hero:
  title: "Title"
  subtitle: "subtitle"
  image:
    path: "images/logo.png"
    alt: "Evolución Digital Logo"
cards:
  - title: "Something"
    image:
      path: "images/first.jpg"
      alt: "an alt"
    url: "another-page"
  - title: "One more"
  - title: "Marketing"
  - title: "Finance"
  - title: "Legal"
  - title: "Talent"

Here Hero is a component with its own attributes and Cards is another one that once rendered paint the entire page

My idea is to read data files with content, and iterate over each of the keys (mollecules) and include the css & js for that specific component in the actual rendered page so it only has the required css and js. I want to avoid having styles / scripts that are not used

Not sure if I explained my self
Thanks for your reply

Not sure how related it is to what you’re doing, but just passing it along: