Skip to content

Commit 3de612e

Browse files
authored
Re-enable support for default exports (#2009)
See #2008
1 parent ce58d87 commit 3de612e

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
### JavaScript API
44

5+
* Re-enable support for `import sass from 'sass'` when loading the package from
6+
an ESM module in Node.js. However, this syntax is now deprecated; ESM users
7+
should use `import * as sass from 'sass'` instead.
8+
9+
On the browser and other ESM-only platforms, only `import * as sass from
10+
'sass'` is supported.
11+
512
* Properly export the legacy API values `TRUE`, `FALSE`, `NULL`, and `types` from
613
the ECMAScript module API.
714

tool/grind.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ void main(List<String> args) {
105105
};
106106

107107
pkg.addAllTasks();
108+
109+
afterTask("pkg-npm-dev", _addDefaultExport);
110+
afterTask("pkg-npm-release", _addDefaultExport);
111+
108112
grind(args);
109113
}
110114

@@ -247,3 +251,37 @@ dart run protoc_plugin "\$@"
247251
Platform.environment["PATH"]!
248252
}));
249253
}
254+
255+
/// After building the NPM package, add default exports to
256+
/// `build/npm/sass.node.mjs`.
257+
///
258+
/// See sass/dart-sass#2008.
259+
void _addDefaultExport() {
260+
var buffer = StringBuffer();
261+
buffer.writeln(File("build/npm/sass.node.mjs").readAsStringSync());
262+
263+
buffer.writeln("""
264+
let printedDefaultExportDeprecation = false;
265+
function defaultExportDeprecation() {
266+
if (printedDefaultExportDeprecation) return;
267+
printedDefaultExportDeprecation = true;
268+
console.error(
269+
"`import sass from 'sass'` is deprecated.\\n" +
270+
"Please use `import * as sass from 'sass'` instead.");
271+
}
272+
""");
273+
274+
buffer.writeln("export default {");
275+
for (var export in pkg.jsEsmExports.value!) {
276+
buffer.write("""
277+
get $export() {
278+
defaultExportDeprecation();
279+
return _cliPkgExports.$export;
280+
},
281+
""");
282+
}
283+
284+
buffer.writeln("};");
285+
286+
File("build/npm/sass.node.mjs").writeAsStringSync(buffer.toString());
287+
}

tool/grind/utils.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
// MIT-style license that can be found in the LICENSE file or at
33
// https://opensource.org/licenses/MIT.
44

5+
import 'dart:async';
56
import 'dart:convert';
67
import 'dart:io';
78

89
import 'package:cli_pkg/cli_pkg.dart' as pkg;
910
import 'package:grinder/grinder.dart';
1011
import 'package:path/path.dart' as p;
1112

13+
// Work around the lack of google/grinder.dart#402.
14+
import 'package:grinder/src/singleton.dart';
15+
1216
/// Options for [run] that tell Git to commit using SassBot's name and email.
1317
final sassBotEnvironment = RunOptions(environment: {
1418
"GIT_AUTHOR_NAME": pkg.botName.value,
@@ -75,3 +79,21 @@ String cloneOrCheckout(String url, String ref, {String? name}) {
7579

7680
return path;
7781
}
82+
83+
/// Registers [callback] to run after the task named [taskName].
84+
///
85+
/// This must be called after the base [taskName] is registered.
86+
void afterTask(String taskName, FutureOr<void> callback()) {
87+
// This takes advantage of the fact that Grinder's task list is mutable to
88+
// override the existing task with our new one.
89+
var index = grinder.tasks.indexWhere((task) => task.name == taskName);
90+
if (index == -1) fail("There is no task named $taskName.");
91+
92+
var oldTask = grinder.tasks[index];
93+
grinder.tasks[index] = GrinderTask(taskName,
94+
description: oldTask.description,
95+
depends: oldTask.depends, taskFunction: (TaskArgs args) async {
96+
await oldTask.execute(context, args);
97+
await callback();
98+
});
99+
}

0 commit comments

Comments
 (0)