From 7c660cf5c6ab701c3356686263a96f201d3aba26 Mon Sep 17 00:00:00 2001
From: Lucas Dohmen <lucas@dohmen.io>
Date: Sun, 26 Jan 2025 17:57:45 +0100
Subject: [PATCH] Release 1.9.0 - Update dependencies

Uses the new `compile` API in Sass
---
 .github/workflows/nodejs.yml         |  5 ++--
 CHANGELOG.md                         |  7 +++++
 lib/index.js                         |  4 +--
 lib/make-sass-renderer.js            | 44 ++++++++++++++++------------
 package.json                         | 10 +++----
 test/test_sourcemap/expected.css.map |  6 +---
 6 files changed, 43 insertions(+), 33 deletions(-)

diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index 6eb634d..d5a50c1 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -7,9 +7,10 @@ jobs:
         strategy:
             matrix:
                 node-version:
-                - 14.x
                 - 18.x
-                - 19.x
+                - 20.x
+                - 22.x
+                - 23.x
         steps:
         - uses: actions/checkout@v4
         - uses: actions/setup-node@v3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35c79b2..743fd32 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,13 @@
 faucet-pipeline-sass version history
 ==================================
 
+v1.9.0
+------
+
+_2025-01-26_
+
+Maintenance release to update dependencies; no significant changes
+
 v1.8.0
 ------
 
diff --git a/lib/index.js b/lib/index.js
index 322a9ce..491a2d7 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -46,8 +46,8 @@ function makeBundler(config, assetManager, { browsers, compact, sourcemaps } = {
 			return renderSass().
 				then(autoprefix).
 				then(result => {
-					previouslyIncludedFiles = result.stats.includedFiles.
-						map(filepath => path.normalize(filepath));
+					previouslyIncludedFiles = (result.loadedUrls ?? []).
+						map(filepath => path.normalize(filepath.toString()));
 
 					let options = {};
 					if(fingerprint !== undefined) {
diff --git a/lib/make-sass-renderer.js b/lib/make-sass-renderer.js
index 5191aa0..b53eada 100644
--- a/lib/make-sass-renderer.js
+++ b/lib/make-sass-renderer.js
@@ -2,36 +2,38 @@ let sass = require("sass");
 
 module.exports = function(inputFileName, target, assetManager, sourcemaps, compact) {
 	let sassOptions = {
-		file: inputFileName,
-		outputStyle: compact ? "compressed" : "expanded",
-		includePaths: [assetManager.packagesDir],
+		style: compact ? "compressed" : "expanded",
+		loadPaths: [assetManager.packagesDir],
 		sourceMap: sourcemaps,
-		sourceMapEmbed: sourcemaps,
-		outFile: target,
 		functions: {
-			"asset-url($assetName)": assetName => {
-				let name = assetName.getValue();
+			"asset-url($assetName)": args => {
+				let name = args[0].text;
 				let mappedAssetName = assetManager.manifest.get(name);
+				if(!mappedAssetName) {
+					throw new Error(`${name} could not be found`);
+				}
 
-				/* eslint-disable indent */
-				return mappedAssetName ?
-						new sass.types.String(`url("${mappedAssetName}")`) :
-						new sass.types.Error(`${name} could not be found`);
-				/* eslint-enable indent */
+				return new sass.SassString(`url("${mappedAssetName}")`, {
+					quotes: false
+				});
 			}
 		}
 	};
 
-	return _ => renderSass(sassOptions);
+	return _ => renderSass(inputFileName, sassOptions);
 };
 
 // promisified version of sass.render
-function renderSass(options) {
+function renderSass(inputFileName, options) {
 	return new Promise((resolve, reject) => {
 		try {
 			// using synchronous rendering because it is faster
-			let result = sass.renderSync(options);
-			result.css = fixEOF(result.css);
+			let result = sass.compile(inputFileName, options);
+			if(result.sourceMap) {
+				result.css = embedSourcemap(result);
+			}
+			// every file shall end with a newline. sass doesn't seem to care
+			result.css = `${result.css}\n`;
 			resolve(result);
 		} catch(err) {
 			reject(err);
@@ -39,7 +41,11 @@ function renderSass(options) {
 	});
 }
 
-// every file shall end with a newline. sass doesn't seem to care.
-function fixEOF(buf) {
-	return Buffer.concat([buf, Buffer.from("\n")]);
+// the new API can't embed sourcemaps
+// https://github.com/sass/dart-sass/issues/1594#issuecomment-1013208452
+function embedSourcemap(result) {
+	const sm = JSON.stringify(result.sourceMap);
+	const smBase64 = Buffer.from(sm, "utf8").toString("base64");
+	const smComment = `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${smBase64}*/`; /* eslint-disable-line max-len */
+	return `${result.css}\n${smComment}`;
 }
diff --git a/package.json b/package.json
index a300af8..ec7706d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "faucet-pipeline-sass",
-	"version": "1.8.0",
+	"version": "1.9.0",
 	"description": "Sass for faucet-pipeline",
 	"main": "lib/index.js",
 	"scripts": {
@@ -19,13 +19,13 @@
 	},
 	"homepage": "https://www.faucet-pipeline.org",
 	"engines": {
-		"node": ">= 14"
+		"node": ">= 18"
 	},
 	"dependencies": {
-		"autoprefixer": "~10.4.5",
+		"autoprefixer": "~10.4.20",
 		"faucet-pipeline-core": "^2.0.0",
-		"postcss": "~8.4.12",
-		"sass": "~1.63.3"
+		"postcss": "~8.5.1",
+		"sass": "~1.83.4"
 	},
 	"devDependencies": {
 		"eslint-config-fnd": "^1.13.0",
diff --git a/test/test_sourcemap/expected.css.map b/test/test_sourcemap/expected.css.map
index a73dac1..0c9af7b 100644
--- a/test/test_sourcemap/expected.css.map
+++ b/test/test_sourcemap/expected.css.map
@@ -1,5 +1 @@
-{
-  "version": 3,
-  "names": [],
-  "mappings": "AAEA;EACC,oBAAA;EAAA,aAAA;AADD;;AAIA;EACC,YAPO;AAMR"
-}
+{"version":3,"names":[],"mappings":"AAEA;EACC,oBAAA;EAAA,aAAA;ACDD;;ADIA;EACC,YAPO;ACMR"}