diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c9bdc93..7ccd611a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ [#260]: https://github.com/sass/dart-sass/issues/260 +### Node API + +* Allow both the `data` and `file` options to be passed to `render()` and + `renderSync()` at once. The `data` option will be used as the contents of the + stylesheet, and the `file` option will be used as the path for error reporting + and relative imports. This matches Node Sass's behavior. + ## 1.0.0-rc.1 * Add support for importing an `_index.scss` or `_index.sass` file when diff --git a/lib/src/node.dart b/lib/src/node.dart index 0e61bf50..bb91cddc 100644 --- a/lib/src/node.dart +++ b/lib/src/node.dart @@ -89,11 +89,6 @@ Future _renderAsync(RenderOptions options) async { var start = new DateTime.now(); CompileResult result; if (options.data != null) { - if (options.file != null) { - throw new ArgumentError( - "options.data and options.file may not both be set."); - } - result = await compileStringAsync(options.data, nodeImporter: _parseImporter(options, start), functions: _parseFunctions(options, asynch: true), @@ -102,7 +97,7 @@ Future _renderAsync(RenderOptions options) async { useSpaces: options.indentType != 'tab', indentWidth: _parseIndentWidth(options.indentWidth), lineFeed: _parseLineFeed(options.linefeed), - url: 'stdin'); + url: options.file == null ? 'stdin' : p.toUri(options.file).toString()); } else if (options.file != null) { result = await compileAsync(options.file, nodeImporter: _parseImporter(options, start), @@ -136,11 +131,6 @@ RenderResult _renderSync(RenderOptions options) { var start = new DateTime.now(); CompileResult result; if (options.data != null) { - if (options.file != null) { - throw new ArgumentError( - "options.data and options.file may not both be set."); - } - result = compileString(options.data, nodeImporter: _parseImporter(options, start), functions: DelegatingList.typed(_parseFunctions(options)), @@ -149,7 +139,9 @@ RenderResult _renderSync(RenderOptions options) { useSpaces: options.indentType != 'tab', indentWidth: _parseIndentWidth(options.indentWidth), lineFeed: _parseLineFeed(options.linefeed), - url: 'stdin'); + url: options.file == null + ? 'stdin' + : p.toUri(options.file).toString()); } else if (options.file != null) { result = compile(options.file, nodeImporter: _parseImporter(options, start), diff --git a/test/node_api_test.dart b/test/node_api_test.dart index 2aa34852..8f1cefd6 100644 --- a/test/node_api_test.dart +++ b/test/node_api_test.dart @@ -69,13 +69,6 @@ a { }''')); }); - test("data and file may not both be set", () { - var error = - renderSyncError(new RenderOptions(data: "x {y: z}", file: sassPath)); - expect(error.toString(), - contains('options.data and options.file may not both be set.')); - }); - test("one of data and file must be set", () { var error = renderSyncError(new RenderOptions()); expect(error.toString(), @@ -186,6 +179,37 @@ a { }); }); + group("with both data and file", () { + test("uses the data parameter as the source", () { + expect(renderSync(new RenderOptions(data: "x {y: z}", file: sassPath)), + equalsIgnoringWhitespace('x { y: z; }')); + }); + + test("doesn't require the file path to exist", () { + expect( + renderSync(new RenderOptions( + data: "x {y: z}", file: p.join(sandbox, 'non-existent.scss'))), + equalsIgnoringWhitespace('x { y: z; }')); + }); + + test("imports relative to the file path", () async { + await writeTextFile(p.join(sandbox, 'importee.scss'), 'x {y: z}'); + expect( + renderSync( + new RenderOptions(data: "@import 'importee'", file: sassPath)), + equalsIgnoringWhitespace('x { y: z; }')); + }); + + test("reports errors from the file path", () { + var error = + renderSyncError(new RenderOptions(data: "x {y: }", file: sassPath)); + expect( + error.toString(), + equals("Error: Expected expression.\n" + " $sassPath 1:7 root stylesheet")); + }); + }); + group("the result object", () { test("includes the filename", () { var result = sass.renderSync(new RenderOptions(file: sassPath));