mirror of
https://github.com/danog/dart-sass.git
synced 2024-12-11 00:29:41 +01:00
6ad67a6f28
This un-reverts pull request #320 from sass/remove-path-workaround,
which was reverted by commit 0fb5d25ee2
.
321 lines
11 KiB
Dart
321 lines
11 KiB
Dart
// Copyright 2017 Google Inc. Use of this source code is governed by an
|
|
// MIT-style license that can be found in the LICENSE file or at
|
|
// https://opensource.org/licenses/MIT.
|
|
|
|
@TestOn('node')
|
|
@Tags(const ['node', 'dart2'])
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'package:dart2_constant/convert.dart' as convert;
|
|
import 'package:js/js.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:source_maps/source_maps.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'package:sass/sass.dart' as dartSass;
|
|
|
|
import '../ensure_npm_package.dart';
|
|
import '../hybrid.dart';
|
|
import '../utils.dart';
|
|
import 'api.dart';
|
|
import 'utils.dart';
|
|
|
|
/// A [Codec] that encodes and decodes UTF-8-encoded JSON.
|
|
var _jsonUtf8 = convert.json.fuse(convert.utf8);
|
|
|
|
void main() {
|
|
setUpAll(ensureNpmPackage);
|
|
useSandbox();
|
|
|
|
group("a basic invocation", () {
|
|
String css;
|
|
Map<String, Object> map;
|
|
setUp(() {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}", sourceMap: true, outFile: "out.css"));
|
|
css = convert.utf8.decode(result.css);
|
|
map = _jsonUtf8.decode(result.map) as Map<String, Object>;
|
|
});
|
|
|
|
test("includes correct mappings", () {
|
|
SingleMapping expectedMap;
|
|
dartSass.compileString("a {b: c}", sourceMap: (map) => expectedMap = map);
|
|
expectedMap.targetUrl = "out.css";
|
|
|
|
expect(map, containsPair("mappings", expectedMap.toJson()["mappings"]));
|
|
});
|
|
|
|
test("includes the name of the output file", () {
|
|
expect(map, containsPair("file", "out.css"));
|
|
});
|
|
|
|
test("includes stdin as a source", () {
|
|
expect(map, containsPair("sources", ["stdin"]));
|
|
});
|
|
|
|
test("includes a source map comment", () {
|
|
expect(css, endsWith("\n\n/*# sourceMappingURL=out.css.map */"));
|
|
});
|
|
});
|
|
|
|
group("the sources list", () {
|
|
test("contains a relative path to an input file", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, 'a {b: c}');
|
|
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path, sourceMap: true, outFile: p.join(sandbox, 'out.css')));
|
|
expect(map, containsPair("sources", ["test.scss"]));
|
|
});
|
|
|
|
test("makes the path relative to outFile", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, 'a {b: c}');
|
|
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path,
|
|
sourceMap: true,
|
|
outFile: p.join(p.dirname(sandbox), 'dir/out.css')));
|
|
expect(
|
|
map,
|
|
containsPair("sources", [
|
|
p.toUri(p.join("..", p.basename(sandbox), "test.scss")).toString()
|
|
]));
|
|
});
|
|
|
|
test("contains an imported file's path", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, '''
|
|
@import "other";
|
|
a {b: c}
|
|
''');
|
|
|
|
await writeTextFile(p.join(sandbox, 'other.scss'), 'x {y: z}');
|
|
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path, sourceMap: true, outFile: p.join(sandbox, 'out.css')));
|
|
expect(map, containsPair("sources", ["other.scss", "test.scss"]));
|
|
});
|
|
|
|
test("contains the resolved path of a file imported via includePaths",
|
|
() async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, '''
|
|
@import "other";
|
|
a {b: c}
|
|
''');
|
|
|
|
await createDirectory(p.join(sandbox, 'subdir'));
|
|
await writeTextFile(p.join(sandbox, 'subdir/other.scss'), 'x {y: z}');
|
|
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path,
|
|
sourceMap: true,
|
|
includePaths: [p.join(sandbox, 'subdir')],
|
|
outFile: p.join(sandbox, 'out.css')));
|
|
expect(map, containsPair("sources", ["subdir/other.scss", "test.scss"]));
|
|
});
|
|
|
|
test("contains a URL handled by an importer", () {
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
data: '''
|
|
@import "other";
|
|
a {b: c}
|
|
''',
|
|
importer: allowInterop(
|
|
(_, __) => new NodeImporterResult(contents: 'x {y: z}')),
|
|
sourceMap: true,
|
|
outFile: 'out.css'));
|
|
expect(map, containsPair("sources", ["other", "stdin"]));
|
|
});
|
|
});
|
|
|
|
group("doesn't emit the source map", () {
|
|
test("without sourceMap", () {
|
|
var result = sass
|
|
.renderSync(new RenderOptions(data: "a {b: c}", outFile: "out.css"));
|
|
expect(result.map, isNull);
|
|
expect(convert.utf8.decode(result.css), isNot(contains("/*#")));
|
|
});
|
|
|
|
test("with sourceMap: false", () {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}", sourceMap: false, outFile: "out.css"));
|
|
expect(result.map, isNull);
|
|
expect(convert.utf8.decode(result.css), isNot(contains("/*#")));
|
|
});
|
|
|
|
test("without outFile", () {
|
|
var result =
|
|
sass.renderSync(new RenderOptions(data: "a {b: c}", sourceMap: true));
|
|
expect(result.map, isNull);
|
|
expect(convert.utf8.decode(result.css), isNot(contains("/*#")));
|
|
});
|
|
});
|
|
|
|
group("with a string sourceMap and no outFile", () {
|
|
test("emits a source map", () {
|
|
var result = sass.renderSync(
|
|
new RenderOptions(data: "a {b: c}", sourceMap: "out.css.map"));
|
|
var map = _jsonUtf8.decode(result.map) as Map<String, Object>;
|
|
expect(map, containsPair("sources", ["stdin"]));
|
|
});
|
|
|
|
test("derives the target URL from the input file", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, 'a {b: c}');
|
|
|
|
var result = sass.renderSync(new RenderOptions(
|
|
file: p.join(sandbox, "test.scss"), sourceMap: "out.css.map"));
|
|
var map = _jsonUtf8.decode(result.map) as Map<String, Object>;
|
|
expect(
|
|
map,
|
|
containsPair(
|
|
"file", p.toUri(p.join(sandbox, "test.css")).toString()));
|
|
});
|
|
|
|
test("derives the target URL from the input file without an extension",
|
|
() async {
|
|
var path = p.join(sandbox, 'test');
|
|
await writeTextFile(path, 'a {b: c}');
|
|
|
|
var result = sass.renderSync(new RenderOptions(
|
|
file: p.join(sandbox, "test"), sourceMap: "out.css.map"));
|
|
var map = _jsonUtf8.decode(result.map) as Map<String, Object>;
|
|
expect(
|
|
map,
|
|
containsPair(
|
|
"file", p.toUri(p.join(sandbox, "test.css")).toString()));
|
|
});
|
|
|
|
test("derives the target URL from stdin", () {
|
|
var result = sass.renderSync(
|
|
new RenderOptions(data: "a {b: c}", sourceMap: "out.css.map"));
|
|
var map = _jsonUtf8.decode(result.map) as Map<String, Object>;
|
|
expect(map, containsPair("file", "stdin.css"));
|
|
});
|
|
});
|
|
|
|
test("with omitSourceMapUrl, doesn't include a source map comment", () {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}",
|
|
sourceMap: true,
|
|
outFile: "out.css",
|
|
omitSourceMapUrl: true));
|
|
expect(result.map, isNotNull);
|
|
expect(convert.utf8.decode(result.css), isNot(contains("/*#")));
|
|
});
|
|
|
|
group("with a string sourceMap", () {
|
|
test("uses it in the source map comment", () {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}", sourceMap: "map", outFile: "out.css"));
|
|
expect(result.map, isNotNull);
|
|
expect(convert.utf8.decode(result.css),
|
|
endsWith("\n\n/*# sourceMappingURL=map */"));
|
|
});
|
|
|
|
test("makes the source map comment relative to the outfile", () {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}", sourceMap: "map", outFile: "dir/out.css"));
|
|
expect(result.map, isNotNull);
|
|
expect(convert.utf8.decode(result.css),
|
|
endsWith("\n\n/*# sourceMappingURL=../map */"));
|
|
});
|
|
|
|
test("makes the file field relative to the source map location", () {
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
data: "a {b: c}", sourceMap: "dir/map", outFile: "out.css"));
|
|
expect(map, containsPair("file", "../out.css"));
|
|
});
|
|
|
|
test("makes the source map comment relative even if the path is absolute",
|
|
() {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}", sourceMap: p.absolute("map"), outFile: "out.css"));
|
|
expect(result.map, isNotNull);
|
|
expect(convert.utf8.decode(result.css),
|
|
endsWith("\n\n/*# sourceMappingURL=map */"));
|
|
});
|
|
|
|
test("makes the sources list relative to the map location", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, 'a {b: c}');
|
|
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path, sourceMap: p.join(sandbox, 'map'), outFile: 'out.css'));
|
|
expect(map, containsPair("sources", ["test.scss"]));
|
|
});
|
|
});
|
|
|
|
group("with sourceMapContents", () {
|
|
test("includes the source contents in the source map", () {
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
data: "a {b: c}",
|
|
sourceMap: true,
|
|
outFile: "out.css",
|
|
sourceMapContents: true));
|
|
expect(map, containsPair("sourcesContent", ["a {b: c}"]));
|
|
});
|
|
|
|
test("includes an imported file's contents in the source map", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
var scss = '''
|
|
@import "other";
|
|
a {b: c}
|
|
''';
|
|
await writeTextFile(path, scss);
|
|
|
|
await writeTextFile(p.join(sandbox, 'other.scss'), 'x {y: z}');
|
|
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path,
|
|
sourceMap: true,
|
|
outFile: 'out.css',
|
|
sourceMapContents: true));
|
|
expect(map, containsPair("sourcesContent", ["x {y: z}", scss]));
|
|
});
|
|
});
|
|
|
|
test("with sourceMapEmbed includes the source map in the CSS", () {
|
|
var result = sass.renderSync(new RenderOptions(
|
|
data: "a {b: c}",
|
|
sourceMap: true,
|
|
outFile: "out.css",
|
|
sourceMapEmbed: true));
|
|
|
|
var map = embeddedSourceMap(convert.utf8.decode(result.css));
|
|
expect(map, equals(_jsonUtf8.decode(result.map)));
|
|
});
|
|
|
|
group("with sourceMapRoot", () {
|
|
test("includes the root as-is in the map", () {
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
data: "a {b: c}",
|
|
sourceMap: true,
|
|
outFile: 'out.css',
|
|
sourceMapRoot: 'some random string'));
|
|
expect(map, containsPair("sourceRoot", "some random string"));
|
|
});
|
|
|
|
test("doesn't modify the source URLs", () async {
|
|
var path = p.join(sandbox, 'test.scss');
|
|
await writeTextFile(path, 'a {b: c}');
|
|
|
|
var root = p.toUri(p.dirname(sandbox)).toString();
|
|
var map = _renderSourceMap(new RenderOptions(
|
|
file: path,
|
|
sourceMap: true,
|
|
outFile: p.join(sandbox, 'out.css'),
|
|
sourceMapRoot: root));
|
|
expect(map, containsPair("sourceRoot", root));
|
|
expect(map, containsPair("sources", ["test.scss"]));
|
|
});
|
|
});
|
|
}
|
|
|
|
/// Renders [options] and returns the decoded source map.
|
|
Map<String, Object> _renderSourceMap(RenderOptions options) =>
|
|
_jsonUtf8.decode(sass.renderSync(options).map) as Map<String, Object>;
|