diff --git a/ignis/app.py b/ignis/app.py
index fe6ec39..dc63087 100644
--- a/ignis/app.py
+++ b/ignis/app.py
@@ -168,7 +168,7 @@ class IgnisApp(Gtk.Application, IgnisGObject):
"""
Apply a CSS/SCSS/SASS style from a path.
If ``style_path`` has a ``.sass`` or ``.scss`` extension, it will be automatically compiled.
- Requires ``dart-sass`` for SASS/SCSS compilation.
+ Requires either ``dart-sass`` or ``grass-sass`` for SASS/SCSS compilation.
Args:
style_path: Path to the .css/.scss/.sass file.
diff --git a/ignis/exceptions.py b/ignis/exceptions.py
index f3a2ed5..e803171 100644
--- a/ignis/exceptions.py
+++ b/ignis/exceptions.py
@@ -227,7 +227,7 @@ class GstPluginNotFoundError(Exception):
class SassCompilationError(Exception):
"""
- Raised when Dart Sass compilation fails.
+ Raised when the Sass compilation fails.
"""
def __init__(self, stderr: str, *args: object) -> None:
@@ -239,19 +239,19 @@ class SassCompilationError(Exception):
"""
- required, read-only
- The stderr output from Dart Sass.
+ The stderr output from the Sass compiler.
"""
return self._stderr
-class DartSassNotFoundError(Exception):
+class SassNotFoundError(Exception):
"""
- Raised when Dart Sass is not found.
+ Raised when a compatible Sass compiler is not found.
"""
def __init__(self, *args: object) -> None:
super().__init__(
- "Dart Sass not found! To compile SCSS/SASS, install dart-sass", *args
+ "Sass compiler not found! To compile SCSS/SASS, install either dart-sass or grass-sass", *args
)
diff --git a/ignis/utils/sass.py b/ignis/utils/sass.py
index 9bd829d..a891d85 100644
--- a/ignis/utils/sass.py
+++ b/ignis/utils/sass.py
@@ -1,14 +1,26 @@
import os
+import shutil
import subprocess
-from ignis.exceptions import SassCompilationError, DartSassNotFoundError
+import typing
+from ignis.exceptions import SassCompilationError, SassNotFoundError
TEMP_DIR = "/tmp/ignis"
COMPILED_CSS = f"{TEMP_DIR}/compiled.css"
os.makedirs(TEMP_DIR, exist_ok=True)
+# resolve Sass compiler paths and pick a default one
+# "sass" (dart-sass) is the default,
+# "grass" is an API-compatible drop-in replacement
+known_compilers = typing.Literal["sass", "grass"]
+sass_compilers = {}
+for cmd in typing.get_args(known_compilers):
+ path = shutil.which(cmd)
+ if path:
+ sass_compilers[cmd] = path
+
-def compile_file(path: str) -> str:
- result = subprocess.run(["sass", path, COMPILED_CSS], capture_output=True)
+def compile_file(path: str, compiler_path: str) -> str:
+ result = subprocess.run([compiler_path, path, COMPILED_CSS], capture_output=True)
if result.returncode != 0:
raise SassCompilationError(result.stderr.decode())
@@ -17,9 +29,9 @@ def compile_file(path: str) -> str:
return file.read()
-def compile_string(string: str) -> str:
+def compile_string(string: str, compiler_path: str) -> str:
process = subprocess.Popen(
- ["sass", "--stdin"],
+ [compiler_path, "--stdin"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
@@ -32,28 +44,38 @@ def compile_string(string: str) -> str:
return stdout.decode()
-def sass_compile(path: str | None = None, string: str | None = None) -> str:
+def sass_compile(path: str | None = None, string: str | None = None, compiler: known_compilers | None = None) -> str:
"""
Compile a SASS/SCSS file or string.
- Requires `Dart Sass `_.
+ Requires either `Dart Sass `_
+ or `Grass `_.
Args:
path: The path to the SASS/SCSS file.
string: A string with SASS/SCSS style.
+ compiler: The desired Sass compiler, either ``sass`` or ``grass``.
Raises:
TypeError: If neither of the arguments is provided.
- DartSassNotFoundError: If Dart Sass not found.
+ SassNotFoundError: If no Sass compiler is available.
SassCompilationError: If an error occurred while compiling SASS/SCSS.
"""
- if not os.path.exists("/bin/sass"):
- raise DartSassNotFoundError()
+ if not sass_compilers:
+ raise SassNotFoundError()
+
+ if compiler and compiler not in sass_compilers:
+ raise SassNotFoundError()
+
+ if compiler:
+ compiler_path = sass_compilers[compiler]
+ else:
+ compiler_path = next(iter(sass_compilers.values()))
if string:
- return compile_string(string)
+ return compile_string(string, compiler_path)
elif path:
- return compile_file(path)
+ return compile_file(path, compiler_path)
else:
raise TypeError("sass_compile() requires at least one positional argument")