mirror of
https://github.com/danog/dart-sass.git
synced 2025-01-22 05:41:14 +01:00
parent
4697dcad47
commit
97f678a770
@ -16,6 +16,7 @@ import 'util/path.dart';
|
||||
main(List<String> args) async {
|
||||
var argParser = new ArgParser(allowTrailingOptions: true)
|
||||
..addOption('precision', hide: true)
|
||||
..addFlag('stdin', help: 'Read the stylesheet from stdin.')
|
||||
..addOption('style',
|
||||
abbr: 's',
|
||||
help: 'Output style.',
|
||||
@ -45,7 +46,8 @@ main(List<String> args) async {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options['help'] as bool || options.rest.isEmpty) {
|
||||
var stdinFlag = options['stdin'] as bool;
|
||||
if (options['help'] as bool || (options.rest.isEmpty && !stdinFlag)) {
|
||||
_printUsage(argParser, "Compile Sass to CSS.");
|
||||
exitCode = 64;
|
||||
return;
|
||||
@ -54,7 +56,16 @@ main(List<String> args) async {
|
||||
var color =
|
||||
options.wasParsed('color') ? options['color'] as bool : hasTerminal;
|
||||
try {
|
||||
var css = compile(options.rest.first, color: color);
|
||||
String css;
|
||||
if (stdinFlag) {
|
||||
css = compileString(await readStdin(), color: color);
|
||||
} else {
|
||||
var input = options.rest.first;
|
||||
css = input == '-'
|
||||
? compileString(await readStdin(), color: color)
|
||||
: compile(input, color: color);
|
||||
}
|
||||
|
||||
if (css.isNotEmpty) print(css);
|
||||
} on SassException catch (error, stackTrace) {
|
||||
stderr.writeln(error.toString(color: color));
|
||||
|
@ -2,6 +2,8 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
/// An output sink that writes to this process's standard error.
|
||||
class Stderr {
|
||||
/// Writes the string representation of [object] to standard error.
|
||||
@ -41,6 +43,10 @@ String get currentPath => null;
|
||||
/// the file isn't valid UTF-8.
|
||||
String readFile(String path) => null;
|
||||
|
||||
/// Reads from the standard input for the current process until it closes,
|
||||
/// returning the contents.
|
||||
Future<String> readStdin() async => null;
|
||||
|
||||
/// Returns whether a file at [path] exists.
|
||||
bool fileExists(String path) => null;
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
@ -20,6 +23,13 @@ class _Stderr {
|
||||
external void write(String text);
|
||||
}
|
||||
|
||||
@JS()
|
||||
class _Stdin {
|
||||
external String read();
|
||||
|
||||
external void on(String event, void callback([object]));
|
||||
}
|
||||
|
||||
@JS()
|
||||
class _SystemError {
|
||||
external String get message;
|
||||
@ -92,6 +102,33 @@ _readFile(String path, [String encoding]) {
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> readStdin() async {
|
||||
var completer = new Completer<String>();
|
||||
String contents;
|
||||
var innerSink = new StringConversionSink.withCallback((String result) {
|
||||
contents = result;
|
||||
completer.complete(contents);
|
||||
});
|
||||
// Node defaults all buffers to 'utf8'.
|
||||
var sink = UTF8.decoder.startChunkedConversion(innerSink);
|
||||
_stdin.on('data', allowInterop(([chunk]) {
|
||||
assert(chunk != null);
|
||||
sink.add(chunk as List<int>);
|
||||
}));
|
||||
_stdin.on('end', allowInterop(([_]) {
|
||||
// Callback for 'end' receives no args.
|
||||
assert(_ == null);
|
||||
sink.close();
|
||||
}));
|
||||
_stdin.on('error', allowInterop(([e]) {
|
||||
assert(e != null);
|
||||
stderr.writeln('Failed to read from stdin');
|
||||
stderr.writeln(e);
|
||||
completer.completeError(e);
|
||||
}));
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
/// Cleans up a Node system error's message.
|
||||
String _cleanErrorMessage(_SystemError error) {
|
||||
// The error message is of the form "$code: $text, $syscall '$path'". We just
|
||||
@ -109,6 +146,9 @@ external _Stderr get _stderr;
|
||||
|
||||
final stderr = new Stderr(_stderr);
|
||||
|
||||
@JS("process.stdin")
|
||||
external _Stdin get _stdin;
|
||||
|
||||
bool get hasTerminal => _hasTerminal ?? false;
|
||||
|
||||
bool get isWindows => _process.platform == 'win32';
|
||||
|
@ -2,13 +2,14 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../exception.dart';
|
||||
import '../util/path.dart';
|
||||
|
||||
export 'dart:io' show exitCode, FileSystemException;
|
||||
|
||||
@ -43,6 +44,12 @@ String readFile(String path) {
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> readStdin() async {
|
||||
var completer = new Completer<String>();
|
||||
completer.complete(await io.SYSTEM_ENCODING.decodeStream(io.stdin));
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
bool fileExists(String path) => new io.File(path).existsSync();
|
||||
|
||||
bool dirExists(String path) => new io.Directory(path).existsSync();
|
||||
|
@ -14,6 +14,7 @@ dependencies:
|
||||
args: "^0.13.0"
|
||||
charcode: "^1.1.0"
|
||||
collection: "^1.8.0"
|
||||
convert: "^2.0.1"
|
||||
path: "^1.0.0"
|
||||
source_span: "^1.4.0"
|
||||
string_scanner: ">=0.1.5 <2.0.0"
|
||||
|
@ -34,6 +34,49 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
|
||||
await sass.shouldExit(0);
|
||||
});
|
||||
|
||||
test("compiles from stdin with the magic path -", () async {
|
||||
var sass = await runSass(["-"]);
|
||||
sass.stdin.writeln("a {b: 1 + 2}");
|
||||
sass.stdin.close();
|
||||
expect(
|
||||
sass.stdout,
|
||||
emitsInOrder([
|
||||
"a {",
|
||||
" b: 3;",
|
||||
"}",
|
||||
]));
|
||||
await sass.shouldExit(0);
|
||||
});
|
||||
|
||||
test("compiles from stdin with --stdin", () async {
|
||||
var sass = await runSass(["--stdin"]);
|
||||
sass.stdin.writeln("a {b: 1 + 2}");
|
||||
sass.stdin.close();
|
||||
expect(
|
||||
sass.stdout,
|
||||
emitsInOrder([
|
||||
"a {",
|
||||
" b: 3;",
|
||||
"}",
|
||||
]));
|
||||
await sass.shouldExit(0);
|
||||
});
|
||||
|
||||
test("gracefully reports errors from stdin", () async {
|
||||
var sass = await runSass(["-"]);
|
||||
sass.stdin.writeln("a {b: 1 + }");
|
||||
sass.stdin.close();
|
||||
expect(
|
||||
sass.stderr,
|
||||
emitsInOrder([
|
||||
"Error: Expected expression.",
|
||||
"a {b: 1 + }",
|
||||
" ^",
|
||||
" - 1:11 root stylesheet",
|
||||
]));
|
||||
await sass.shouldExit(65);
|
||||
});
|
||||
|
||||
test("supports relative imports", () async {
|
||||
await d.file("test.scss", "@import 'dir/test'").create();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user