Skip to content

Commit

Permalink
Add support for the data option to the JS API (#159)
Browse files Browse the repository at this point in the history
Also add renderString to the Dart API.

Partially addresses #7
  • Loading branch information
nex3 authored Jul 7, 2017
1 parent 91ebf98 commit 8f836df
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 24 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@

### Node JS API

* Add support for `lineFeed`, `indentWidth`, and `indentType` options to
* Add support for `data`, `lineFeed`, `indentWidth`, and `indentType` options to
`render()` and `renderSync()`.

### Dart API

* Add a `renderString()` method for rendering Sass source that's not in a file
on disk.

## 1.0.0-beta.1

* Drop support for the reference combinator. This has been removed from the
Expand Down
29 changes: 28 additions & 1 deletion lib/sass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,34 @@ import 'src/sync_package_resolver.dart';
///
/// [SyncPackageResolver]: https://www.dartdocs.org/documentation/package_resolver/latest/package_resolver/SyncPackageResolver-class.html
///
/// Finally throws a [SassException] if conversion fails.
/// Throws a [SassException] if conversion fails.
String render(String path,
{bool color: false, SyncPackageResolver packageResolver}) =>
r.render(path, color: color, packageResolver: packageResolver);

/// Converts [source] to CSS and returns the result.
///
/// If [indented] is `true`, this parses [source] using indented syntax;
/// otherwise (and by default) it uses SCSS. If [color] is `true`, this will use
/// terminal colors in warnings.
///
/// If [packageResolver] is provided, it's used to resolve `package:` imports.
/// Otherwise, they aren't supported. It takes a [SyncPackageResolver][] from
/// the `package_resolver` package.
///
/// [SyncPackageResolver]: https://www.dartdocs.org/documentation/package_resolver/latest/package_resolver/SyncPackageResolver-class.html
///
/// The [url] indicates the location from which [source] was loaded. It may may
/// be a [String] or a [Uri].
///
/// Throws a [SassException] if conversion fails.
String renderString(String source,
{bool indented: false,
bool color: false,
SyncPackageResolver packageResolver,
url}) =>
r.renderString(source,
indented: indented,
color: color,
packageResolver: packageResolver,
url: url);
49 changes: 37 additions & 12 deletions lib/src/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@ void main() {
void _render(RenderOptions options,
void callback(RenderError error, RenderResult result)) {
try {
var result = newRenderResult(render(options.file,
useSpaces: options.indentType != 'tab',
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed)));
callback(null, result);
callback(null, _doRender(options));
} on SassException catch (error) {
// TODO: populate the error more thoroughly if possible.
callback(newRenderError(message: error.message), null);
callback(newRenderError(error.message), null);
} catch (error) {
callback(newRenderError(error.toString()), null);
}
}

Expand All @@ -58,15 +56,42 @@ void _render(RenderOptions options,
/// [render]: https://github.com/sass/node-sass#options
RenderResult _renderSync(RenderOptions options) {
try {
return newRenderResult(render(options.file,
useSpaces: options.indentType != 'tab',
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed)));
return _doRender(options);
} on SassException catch (error) {
// TODO: populate the error more thoroughly if possible.
jsThrow(newRenderError(message: error.message));
throw "unreachable";
jsThrow(newRenderError(error.message));
} catch (error) {
jsThrow(newRenderError(error.toString()));
}
throw "unreachable";
}

/// Converts Sass to CSS.
///
/// Unlike [_render] and [_renderSync], this doesn't do any special handling for
/// Dart exceptions.
RenderResult _doRender(RenderOptions options) {
String output;
if (options.data != null) {
if (options.file != null) {
throw new ArgumentError(
"options.data and options.file may not both be set.");
}

output = renderString(options.data,
useSpaces: options.indentType != 'tab',
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed));
} else if (options.file != null) {
output = render(options.file,
useSpaces: options.indentType != 'tab',
indentWidth: _parseIndentWidth(options.indentWidth),
lineFeed: _parseLineFeed(options.linefeed));
} else {
throw new ArgumentError("Either options.data or options.file must be set.");
}

return newRenderResult(output);
}

/// Parses the indentation width into an [int].
Expand Down
4 changes: 2 additions & 2 deletions lib/src/node/render_error.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class RenderError {
{String message, int line, int column, int status, String file});
}

RenderError newRenderError(
{String message, int line, int column, int status, String file}) {
RenderError newRenderError(String message,
{int line, int column, int status, String file}) {
var error = new RenderError._(
message: message, line: line, column: column, status: status, file: file);
setToString(error, () => "Error: $message");
Expand Down
7 changes: 6 additions & 1 deletion lib/src/node/render_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import 'package:js/js.dart';
@anonymous
class RenderOptions {
external String get file;
external String get data;
external String get indentType;
external dynamic get indentWidth;
external String get linefeed;

external factory RenderOptions(
{String file, String indentType, indentWidth, String linefeed});
{String file,
String data,
String indentType,
indentWidth,
String linefeed});
}
31 changes: 24 additions & 7 deletions lib/src/render.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,33 @@ import 'visitor/serialize.dart';
/// Like [render] in `lib/sass.dart`, but provides more options to support the
/// node-sass compatible API.
String render(String path,
{bool color: false,
{bool color: false,
SyncPackageResolver packageResolver,
bool useSpaces: true,
int indentWidth,
LineFeed lineFeed}) =>
renderString(readFile(path),
indented: p.extension(path) == '.sass',
color: color,
packageResolver: packageResolver,
useSpaces: useSpaces,
indentWidth: indentWidth,
lineFeed: lineFeed,
url: p.toUri(path));

/// Like [renderString] in `lib/sass.dart`, but provides more options to support
/// the node-sass compatible API.
String renderString(String source,
{bool indented: false,
bool color: false,
SyncPackageResolver packageResolver,
bool useSpaces: true,
int indentWidth,
LineFeed lineFeed}) {
var contents = readFile(path);
var url = p.toUri(path);
var sassTree = p.extension(path) == '.sass'
? new Stylesheet.parseSass(contents, url: url, color: color)
: new Stylesheet.parseScss(contents, url: url, color: color);
LineFeed lineFeed,
url}) {
var sassTree = indented
? new Stylesheet.parseSass(source, url: url, color: color)
: new Stylesheet.parseScss(source, url: url, color: color);
var cssTree =
evaluate(sassTree, color: color, packageResolver: packageResolver);
return toCss(cssTree,
Expand Down
36 changes: 36 additions & 0 deletions test/node_api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,42 @@ a {
}'''));
});

test("supports relative imports for a file", () async {
var importerPath = p.join(sandbox, 'importer.scss');
await writeTextFile(importerPath, '@import "test"');
expect(_renderSync(new RenderOptions(file: importerPath)), equals('''
a {
b: c;
}'''));
});

test("renders a string", () {
expect(_renderSync(new RenderOptions(data: "a {b: c}")), equals('''
a {
b: c;
}'''));
});

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(),
contains('Either options.data or options.file must be set.'));
});

test("rejects both a file and a string", () {
expect(_renderSync(new RenderOptions(data: "a {b: c}")), equals('''
a {
b: c;
}'''));
});

test("allows tab indentation", () {
expect(_renderSync(new RenderOptions(file: sassPath, indentType: 'tab')),
equals('''
Expand Down

0 comments on commit 8f836df

Please sign in to comment.