mirror of
https://github.com/danog/dart-sass.git
synced 2025-01-22 13:51:31 +01:00
Change CompileResult.includedFiles to CompileResult.includedUrls
Rather than constructing this explicitly to match Node Sass's API, we construct it with canonical URLs and convert it into the format expected by the Node Sass API (a mix of paths and URLs) in the compatibility layer.
This commit is contained in:
parent
0e42a09fdb
commit
43b69e60a0
19
CHANGELOG.md
19
CHANGELOG.md
@ -1,3 +1,22 @@
|
||||
## 1.36.0
|
||||
|
||||
### Dart API
|
||||
|
||||
* Added `compileToResult()`, `compileStringToResult()`,
|
||||
`compileToResultAsync()`, and `compileStringToResultAsync()` methods. These
|
||||
are intended to replace the existing `compile*()` methods, which are now
|
||||
deprecated. Rather than returning a simple string, these return a
|
||||
`CompileResult` object, which will allow us to add additional information
|
||||
about the compilation without having to introduce further deprecations.
|
||||
|
||||
* Instead of passing a `sourceMaps` callback to `compile*()`, pass
|
||||
`sourceMaps: true` to `compile*ToResult()` and access
|
||||
`CompileResult.sourceMap`.
|
||||
|
||||
* The `CompileResult` object exposes a `includedUrls` object which lists the
|
||||
canonical URLs accessed during a compilation. This information was
|
||||
previously unavailable except through the JS API.
|
||||
|
||||
## 1.35.2
|
||||
|
||||
* **Potentially breaking bug fix**: Properly throw an error for Unicode ranges
|
||||
|
277
lib/sass.dart
277
lib/sass.dart
@ -11,6 +11,7 @@ import 'package:source_maps/source_maps.dart';
|
||||
import 'src/async_import_cache.dart';
|
||||
import 'src/callable.dart';
|
||||
import 'src/compile.dart' as c;
|
||||
import 'src/compile_result.dart';
|
||||
import 'src/exception.dart';
|
||||
import 'src/import_cache.dart';
|
||||
import 'src/importer.dart';
|
||||
@ -20,6 +21,7 @@ import 'src/util/nullable.dart';
|
||||
import 'src/visitor/serialize.dart';
|
||||
|
||||
export 'src/callable.dart' show Callable, AsyncCallable;
|
||||
export 'src/compile_result.dart';
|
||||
export 'src/exception.dart' show SassException;
|
||||
export 'src/importer.dart';
|
||||
export 'src/logger.dart';
|
||||
@ -28,7 +30,9 @@ export 'src/value.dart';
|
||||
export 'src/visitor/serialize.dart' show OutputStyle;
|
||||
export 'src/warn.dart' show warn;
|
||||
|
||||
/// Loads the Sass file at [path], compiles it to CSS, and returns the result.
|
||||
/// Loads the Sass file at [path], compiles it to CSS, and returns a
|
||||
/// [CompileResult] containing the CSS and additional metadata about the
|
||||
/// compilation.
|
||||
///
|
||||
/// If [color] is `true`, this will use terminal colors in warnings. It's
|
||||
/// ignored if [logger] is passed.
|
||||
@ -67,12 +71,13 @@ export 'src/warn.dart' show warn;
|
||||
/// times, further warnings for that feature are silenced. If [verbose] is true,
|
||||
/// all deprecation warnings are printed instead.
|
||||
///
|
||||
/// If [sourceMap] is passed, it's passed a [SingleMapping] that indicates which
|
||||
/// sections of the source file(s) correspond to which in the resulting CSS.
|
||||
/// It's called immediately before this method returns, and only if compilation
|
||||
/// succeeds. Note that [SingleMapping.targetUrl] will always be `null`. Users
|
||||
/// using the [SourceMap] API should be sure to add the [`source_maps`][]
|
||||
/// package to their pubspec.
|
||||
/// If [sourceMap] is `true`, [CompileResult.sourceMap] will be set to a
|
||||
/// [SingleMapping] that indicates which sections of the source file(s)
|
||||
/// correspond to which in the resulting CSS. [SingleMapping.targetUrl] will be
|
||||
/// `null`. It's up to the caller to save this mapping to disk and add a source
|
||||
/// map comment to [CompileResult.css] pointing to it. Users using the
|
||||
/// [SourceMap] API should be sure to add the [`source_maps`][] package to their
|
||||
/// pubspec.
|
||||
///
|
||||
/// [`source_maps`]: https://pub.dartlang.org/packages/source_maps
|
||||
///
|
||||
@ -83,16 +88,8 @@ export 'src/warn.dart' show warn;
|
||||
///
|
||||
/// [byte-order mark]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
|
||||
///
|
||||
/// This parameter is meant to be used as an out parameter, so that users who
|
||||
/// want access to the source map can get it. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// SingleMapping sourceMap;
|
||||
/// var css = compile(sassPath, sourceMap: (map) => sourceMap = map);
|
||||
/// ```
|
||||
///
|
||||
/// Throws a [SassException] if conversion fails.
|
||||
String compile(String path,
|
||||
CompileResult compileToResult(String path,
|
||||
{bool color = false,
|
||||
Logger? logger,
|
||||
Iterable<Importer>? importers,
|
||||
@ -102,27 +99,24 @@ String compile(String path,
|
||||
OutputStyle? style,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
void sourceMap(SingleMapping map)?,
|
||||
bool charset = true}) {
|
||||
logger ??= Logger.stderr(color: color);
|
||||
var result = c.compile(path,
|
||||
bool sourceMap = false,
|
||||
bool charset = true}) =>
|
||||
c.compile(path,
|
||||
logger: logger,
|
||||
importCache: ImportCache(
|
||||
importers: importers,
|
||||
logger: logger,
|
||||
logger: logger ?? Logger.stderr(color: color),
|
||||
loadPaths: loadPaths,
|
||||
packageConfig: packageConfig),
|
||||
functions: functions,
|
||||
style: style,
|
||||
quietDeps: quietDeps,
|
||||
verbose: verbose,
|
||||
sourceMap: sourceMap != null,
|
||||
sourceMap: sourceMap,
|
||||
charset: charset);
|
||||
result.sourceMap.andThen(sourceMap);
|
||||
return result.css;
|
||||
}
|
||||
|
||||
/// Compiles [source] to CSS and returns the result.
|
||||
/// Compiles [source] to CSS and returns a [CompileResult] containing the CSS
|
||||
/// and additional metadata about the compilation..
|
||||
///
|
||||
/// This parses the stylesheet as [syntax], which defaults to [Syntax.scss].
|
||||
///
|
||||
@ -167,12 +161,13 @@ String compile(String path,
|
||||
/// times, further warnings for that feature are silenced. If [verbose] is true,
|
||||
/// all deprecation warnings are printed instead.
|
||||
///
|
||||
/// If [sourceMap] is passed, it's passed a [SingleMapping] that indicates which
|
||||
/// sections of the source file(s) correspond to which in the resulting CSS.
|
||||
/// It's called immediately before this method returns, and only if compilation
|
||||
/// succeeds. Note that [SingleMapping.targetUrl] will always be `null`. Users
|
||||
/// using the [SourceMap] API should be sure to add the [`source_maps`][]
|
||||
/// package to their pubspec.
|
||||
/// If [sourceMap] is `true`, [CompileResult.sourceMap] will be set to a
|
||||
/// [SingleMapping] that indicates which sections of the source file(s)
|
||||
/// correspond to which in the resulting CSS. [SingleMapping.targetUrl] will be
|
||||
/// `null`. It's up to the caller to save this mapping to disk and add a source
|
||||
/// map comment to [CompileResult.css] pointing to it. Users using the
|
||||
/// [SourceMap] API should be sure to add the [`source_maps`][] package to their
|
||||
/// pubspec.
|
||||
///
|
||||
/// [`source_maps`]: https://pub.dartlang.org/packages/source_maps
|
||||
///
|
||||
@ -183,16 +178,8 @@ String compile(String path,
|
||||
///
|
||||
/// [byte-order mark]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
|
||||
///
|
||||
/// This parameter is meant to be used as an out parameter, so that users who
|
||||
/// want access to the source map can get it. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// SingleMapping sourceMap;
|
||||
/// var css = compile(sassPath, sourceMap: (map) => sourceMap = map);
|
||||
/// ```
|
||||
///
|
||||
/// Throws a [SassException] if conversion fails.
|
||||
String compileString(String source,
|
||||
CompileResult compileStringToResult(String source,
|
||||
{Syntax? syntax,
|
||||
bool color = false,
|
||||
Logger? logger,
|
||||
@ -205,16 +192,14 @@ String compileString(String source,
|
||||
Object? url,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
void sourceMap(SingleMapping map)?,
|
||||
bool charset = true,
|
||||
@Deprecated("Use syntax instead.") bool indented = false}) {
|
||||
logger ??= Logger.stderr(color: color);
|
||||
var result = c.compileString(source,
|
||||
syntax: syntax ?? (indented ? Syntax.sass : Syntax.scss),
|
||||
bool sourceMap = false,
|
||||
bool charset = true}) =>
|
||||
c.compileString(source,
|
||||
syntax: syntax,
|
||||
logger: logger,
|
||||
importCache: ImportCache(
|
||||
importers: importers,
|
||||
logger: logger,
|
||||
logger: logger ?? Logger.stderr(color: color),
|
||||
packageConfig: packageConfig,
|
||||
loadPaths: loadPaths),
|
||||
functions: functions,
|
||||
@ -223,6 +208,175 @@ String compileString(String source,
|
||||
url: url,
|
||||
quietDeps: quietDeps,
|
||||
verbose: verbose,
|
||||
sourceMap: sourceMap,
|
||||
charset: charset);
|
||||
|
||||
/// Like [compileToResult], except it runs asynchronously.
|
||||
///
|
||||
/// Running asynchronously allows this to take [AsyncImporter]s rather than
|
||||
/// synchronous [Importer]s. However, running asynchronously is also somewhat
|
||||
/// slower, so [compileToResult] should be preferred if possible.
|
||||
Future<CompileResult> compileToResultAsync(String path,
|
||||
{bool color = false,
|
||||
Logger? logger,
|
||||
Iterable<AsyncImporter>? importers,
|
||||
PackageConfig? packageConfig,
|
||||
Iterable<String>? loadPaths,
|
||||
Iterable<AsyncCallable>? functions,
|
||||
OutputStyle? style,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
bool sourceMap = false}) =>
|
||||
c.compileAsync(path,
|
||||
logger: logger,
|
||||
importCache: AsyncImportCache(
|
||||
importers: importers,
|
||||
logger: logger ?? Logger.stderr(color: color),
|
||||
loadPaths: loadPaths,
|
||||
packageConfig: packageConfig),
|
||||
functions: functions,
|
||||
style: style,
|
||||
quietDeps: quietDeps,
|
||||
verbose: verbose,
|
||||
sourceMap: sourceMap);
|
||||
|
||||
/// Like [compileStringToResult], except it runs asynchronously.
|
||||
///
|
||||
/// Running asynchronously allows this to take [AsyncImporter]s rather than
|
||||
/// synchronous [Importer]s. However, running asynchronously is also somewhat
|
||||
/// slower, so [compileStringToResult] should be preferred if possible.
|
||||
Future<CompileResult> compileStringToResultAsync(String source,
|
||||
{Syntax? syntax,
|
||||
bool color = false,
|
||||
Logger? logger,
|
||||
Iterable<AsyncImporter>? importers,
|
||||
PackageConfig? packageConfig,
|
||||
Iterable<String>? loadPaths,
|
||||
Iterable<AsyncCallable>? functions,
|
||||
OutputStyle? style,
|
||||
AsyncImporter? importer,
|
||||
Object? url,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
bool sourceMap = false,
|
||||
bool charset = true}) =>
|
||||
c.compileStringAsync(source,
|
||||
syntax: syntax,
|
||||
logger: logger,
|
||||
importCache: AsyncImportCache(
|
||||
importers: importers,
|
||||
logger: logger ?? Logger.stderr(color: color),
|
||||
packageConfig: packageConfig,
|
||||
loadPaths: loadPaths),
|
||||
functions: functions,
|
||||
style: style,
|
||||
importer: importer,
|
||||
url: url,
|
||||
quietDeps: quietDeps,
|
||||
verbose: verbose,
|
||||
sourceMap: sourceMap,
|
||||
charset: charset);
|
||||
|
||||
/// Like [compileToResult], but returns [CompileResult.css] rather than
|
||||
/// returning [CompileResult] directly.
|
||||
///
|
||||
/// If [sourceMap] is passed, it's passed a [SingleMapping] that indicates which
|
||||
/// sections of the source file(s) correspond to which in the resulting CSS.
|
||||
/// It's called immediately before this method returns, and only if compilation
|
||||
/// succeeds. Note that [SingleMapping.targetUrl] will always be `null`. Users
|
||||
/// using the [SourceMap] API should be sure to add the [`source_maps`][]
|
||||
/// package to their pubspec.
|
||||
///
|
||||
/// [`source_maps`]: https://pub.dartlang.org/packages/source_maps
|
||||
///
|
||||
/// This parameter is meant to be used as an out parameter, so that users who
|
||||
/// want access to the source map can get it. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// SingleMapping sourceMap;
|
||||
/// var css = compile(sassPath, sourceMap: (map) => sourceMap = map);
|
||||
/// ```
|
||||
@Deprecated("Use compileToResult() instead.")
|
||||
String compile(
|
||||
String path,
|
||||
{bool color = false,
|
||||
Logger? logger,
|
||||
Iterable<Importer>? importers,
|
||||
Iterable<String>? loadPaths,
|
||||
PackageConfig? packageConfig,
|
||||
Iterable<Callable>? functions,
|
||||
OutputStyle? style,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
@Deprecated("Use CompileResult.sourceMap from compileToResult() instead.")
|
||||
void sourceMap(SingleMapping map)?,
|
||||
bool charset = true}) {
|
||||
var result = compileToResult(path,
|
||||
logger: logger,
|
||||
importers: importers,
|
||||
loadPaths: loadPaths,
|
||||
packageConfig: packageConfig,
|
||||
functions: functions,
|
||||
style: style,
|
||||
quietDeps: quietDeps,
|
||||
verbose: verbose,
|
||||
sourceMap: sourceMap != null,
|
||||
charset: charset);
|
||||
result.sourceMap.andThen(sourceMap);
|
||||
return result.css;
|
||||
}
|
||||
|
||||
/// Like [compileStringToResult], but returns [CompileResult.css] rather than
|
||||
/// returning [CompileResult] directly.
|
||||
///
|
||||
/// If [sourceMap] is passed, it's passed a [SingleMapping] that indicates which
|
||||
/// sections of the source file(s) correspond to which in the resulting CSS.
|
||||
/// It's called immediately before this method returns, and only if compilation
|
||||
/// succeeds. Note that [SingleMapping.targetUrl] will always be `null`. Users
|
||||
/// using the [SourceMap] API should be sure to add the [`source_maps`][]
|
||||
/// package to their pubspec.
|
||||
///
|
||||
/// [`source_maps`]: https://pub.dartlang.org/packages/source_maps
|
||||
///
|
||||
/// This parameter is meant to be used as an out parameter, so that users who
|
||||
/// want access to the source map can get it. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// SingleMapping sourceMap;
|
||||
/// var css = compileString(sass, sourceMap: (map) => sourceMap = map);
|
||||
/// ```
|
||||
@Deprecated("Use compileStringToResult() instead.")
|
||||
String compileString(
|
||||
String source,
|
||||
{Syntax? syntax,
|
||||
bool color = false,
|
||||
Logger? logger,
|
||||
Iterable<Importer>? importers,
|
||||
PackageConfig? packageConfig,
|
||||
Iterable<String>? loadPaths,
|
||||
Iterable<Callable>? functions,
|
||||
OutputStyle? style,
|
||||
Importer? importer,
|
||||
Object? url,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
@Deprecated("Use CompileResult.sourceMap from compileStringToResult() instead.")
|
||||
void sourceMap(SingleMapping map)?,
|
||||
bool charset = true,
|
||||
@Deprecated("Use syntax instead.")
|
||||
bool indented = false}) {
|
||||
var result = compileStringToResult(source,
|
||||
syntax: syntax ?? (indented ? Syntax.sass : Syntax.scss),
|
||||
logger: logger,
|
||||
importers: importers,
|
||||
packageConfig: packageConfig,
|
||||
loadPaths: loadPaths,
|
||||
functions: functions,
|
||||
style: style,
|
||||
importer: importer,
|
||||
url: url,
|
||||
quietDeps: quietDeps,
|
||||
verbose: verbose,
|
||||
sourceMap: sourceMap != null,
|
||||
charset: charset);
|
||||
result.sourceMap.andThen(sourceMap);
|
||||
@ -234,7 +388,9 @@ String compileString(String source,
|
||||
/// Running asynchronously allows this to take [AsyncImporter]s rather than
|
||||
/// synchronous [Importer]s. However, running asynchronously is also somewhat
|
||||
/// slower, so [compile] should be preferred if possible.
|
||||
Future<String> compileAsync(String path,
|
||||
@Deprecated("Use compileToResultAsync() instead.")
|
||||
Future<String> compileAsync(
|
||||
String path,
|
||||
{bool color = false,
|
||||
Logger? logger,
|
||||
Iterable<AsyncImporter>? importers,
|
||||
@ -244,15 +400,13 @@ Future<String> compileAsync(String path,
|
||||
OutputStyle? style,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
@Deprecated("Use CompileResult.sourceMap from compileToResultAsync() instead.")
|
||||
void sourceMap(SingleMapping map)?}) async {
|
||||
logger ??= Logger.stderr(color: color);
|
||||
var result = await c.compileAsync(path,
|
||||
var result = await compileToResultAsync(path,
|
||||
logger: logger,
|
||||
importCache: AsyncImportCache(
|
||||
importers: importers,
|
||||
logger: logger,
|
||||
loadPaths: loadPaths,
|
||||
packageConfig: packageConfig),
|
||||
packageConfig: packageConfig,
|
||||
functions: functions,
|
||||
style: style,
|
||||
quietDeps: quietDeps,
|
||||
@ -267,7 +421,9 @@ Future<String> compileAsync(String path,
|
||||
/// Running asynchronously allows this to take [AsyncImporter]s rather than
|
||||
/// synchronous [Importer]s. However, running asynchronously is also somewhat
|
||||
/// slower, so [compileString] should be preferred if possible.
|
||||
Future<String> compileStringAsync(String source,
|
||||
@Deprecated("Use compileStringToResultAsync() instead.")
|
||||
Future<String> compileStringAsync(
|
||||
String source,
|
||||
{Syntax? syntax,
|
||||
bool color = false,
|
||||
Logger? logger,
|
||||
@ -280,18 +436,17 @@ Future<String> compileStringAsync(String source,
|
||||
Object? url,
|
||||
bool quietDeps = false,
|
||||
bool verbose = false,
|
||||
@Deprecated("Use CompileResult.sourceMap from compileStringToResultAsync() instead.")
|
||||
void sourceMap(SingleMapping map)?,
|
||||
bool charset = true,
|
||||
@Deprecated("Use syntax instead.") bool indented = false}) async {
|
||||
logger ??= Logger.stderr(color: color);
|
||||
var result = await c.compileStringAsync(source,
|
||||
@Deprecated("Use syntax instead.")
|
||||
bool indented = false}) async {
|
||||
var result = await compileStringToResultAsync(source,
|
||||
syntax: syntax ?? (indented ? Syntax.sass : Syntax.scss),
|
||||
logger: logger,
|
||||
importCache: AsyncImportCache(
|
||||
importers: importers,
|
||||
logger: logger,
|
||||
packageConfig: packageConfig,
|
||||
loadPaths: loadPaths),
|
||||
loadPaths: loadPaths,
|
||||
functions: functions,
|
||||
style: style,
|
||||
importer: importer,
|
||||
|
@ -5,11 +5,11 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_maps/source_maps.dart';
|
||||
|
||||
import 'ast/sass.dart';
|
||||
import 'async_import_cache.dart';
|
||||
import 'callable.dart';
|
||||
import 'compile_result.dart';
|
||||
import 'importer.dart';
|
||||
import 'importer/node.dart';
|
||||
import 'io.dart';
|
||||
@ -171,30 +171,3 @@ Future<CompileResult> _compileStylesheet(
|
||||
|
||||
return CompileResult(evaluateResult, serializeResult);
|
||||
}
|
||||
|
||||
/// The result of compiling a Sass document to CSS, along with metadata about
|
||||
/// the compilation process.
|
||||
class CompileResult {
|
||||
/// The result of evaluating the source file.
|
||||
final EvaluateResult _evaluate;
|
||||
|
||||
/// The result of serializing the CSS AST to CSS text.
|
||||
final SerializeResult _serialize;
|
||||
|
||||
/// The compiled CSS.
|
||||
String get css => _serialize.css;
|
||||
|
||||
/// The source map indicating how the source files map to [css].
|
||||
///
|
||||
/// This is `null` if source mapping was disabled for this compilation.
|
||||
SingleMapping? get sourceMap => _serialize.sourceMap;
|
||||
|
||||
/// The set that will eventually populate the JS API's
|
||||
/// `result.stats.includedFiles` field.
|
||||
///
|
||||
/// For filesystem imports, this contains the import path. For all other
|
||||
/// imports, it contains the URL passed to the `@import`.
|
||||
Set<String> get includedFiles => _evaluate.includedFiles;
|
||||
|
||||
CompileResult(this._evaluate, this._serialize);
|
||||
}
|
||||
|
@ -5,22 +5,20 @@
|
||||
// DO NOT EDIT. This file was generated from async_compile.dart.
|
||||
// See tool/grind/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: 8e813f2ead6e78899ce820e279983278809a7ea5
|
||||
// Checksum: 1a1251aa9f7312612a64760f59803568bd09a07c
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
import 'async_compile.dart';
|
||||
export 'async_compile.dart';
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_maps/source_maps.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import 'ast/sass.dart';
|
||||
import 'import_cache.dart';
|
||||
import 'callable.dart';
|
||||
import 'compile_result.dart';
|
||||
import 'importer.dart';
|
||||
import 'importer/node.dart';
|
||||
import 'io.dart';
|
||||
|
35
lib/src/compile_result.dart
Normal file
35
lib/src/compile_result.dart
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:source_maps/source_maps.dart';
|
||||
|
||||
import 'visitor/async_evaluate.dart';
|
||||
import 'visitor/serialize.dart';
|
||||
|
||||
/// The result of compiling a Sass document to CSS, along with metadata about
|
||||
/// the compilation process.
|
||||
@sealed
|
||||
class CompileResult {
|
||||
/// The result of evaluating the source file.
|
||||
final EvaluateResult _evaluate;
|
||||
|
||||
/// The result of serializing the CSS AST to CSS text.
|
||||
final SerializeResult _serialize;
|
||||
|
||||
/// The compiled CSS.
|
||||
String get css => _serialize.css;
|
||||
|
||||
/// The source map indicating how the source files map to [css].
|
||||
///
|
||||
/// This is `null` if source mapping was disabled for this compilation.
|
||||
SingleMapping? get sourceMap => _serialize.sourceMap;
|
||||
|
||||
/// The canonical URLs of all stylesheets loaded during compilation.
|
||||
Set<Uri> get includedUrls => _evaluate.includedUrls;
|
||||
|
||||
/// @nodoc
|
||||
@internal
|
||||
CompileResult(this._evaluate, this._serialize);
|
||||
}
|
@ -9,6 +9,7 @@ import 'package:source_maps/source_maps.dart';
|
||||
|
||||
import '../async_import_cache.dart';
|
||||
import '../compile.dart';
|
||||
import '../compile_result.dart';
|
||||
import '../exception.dart';
|
||||
import '../importer/filesystem.dart';
|
||||
import '../io.dart';
|
||||
|
@ -27,9 +27,8 @@ import '../utils.dart';
|
||||
/// imported by a different importer.
|
||||
///
|
||||
/// * Importers can return file paths rather than the contents of the imported
|
||||
/// file. These paths are made absolute before they're included in
|
||||
/// [EvaluateResult.includedFiles] or passed as the previous "URL" to other
|
||||
/// importers.
|
||||
/// file. These paths are made absolute before they'repassed as the previous
|
||||
/// "URL" to other importers.
|
||||
///
|
||||
/// * The working directory is always implicitly an include path.
|
||||
///
|
||||
|
@ -15,6 +15,7 @@ import 'package:tuple/tuple.dart';
|
||||
import 'ast/sass.dart';
|
||||
import 'callable.dart';
|
||||
import 'compile.dart';
|
||||
import 'compile_result.dart';
|
||||
import 'exception.dart';
|
||||
import 'io.dart';
|
||||
import 'importer/node.dart';
|
||||
@ -408,7 +409,10 @@ RenderResult _newRenderResult(
|
||||
start: start.millisecondsSinceEpoch,
|
||||
end: end.millisecondsSinceEpoch,
|
||||
duration: end.difference(start).inMilliseconds,
|
||||
includedFiles: result.includedFiles.toList()));
|
||||
includedFiles: [
|
||||
for (var url in result.includedUrls)
|
||||
if (url.scheme == 'file') p.fromUri(url) else url.toString()
|
||||
]));
|
||||
}
|
||||
|
||||
/// Returns whether source maps are enabled by [options].
|
||||
|
@ -216,12 +216,8 @@ class _EvaluateVisitor
|
||||
/// Whether we're currently building the output of a `@keyframes` rule.
|
||||
var _inKeyframes = false;
|
||||
|
||||
/// The set that will eventually populate the JS API's
|
||||
/// `result.stats.includedFiles` field.
|
||||
///
|
||||
/// For filesystem imports, this contains the import path. For all other
|
||||
/// imports, it contains the URL passed to the `@import`.
|
||||
final _includedFiles = <String>{};
|
||||
/// The canonical URLs of all stylesheets loaded during compilation.
|
||||
final _includedUrls = <Uri>{};
|
||||
|
||||
/// A map from canonical URLs for modules (or imported files) that are
|
||||
/// currently being evaluated to AST nodes whose spans indicate the original
|
||||
@ -508,18 +504,12 @@ class _EvaluateVisitor
|
||||
var url = node.span.sourceUrl;
|
||||
if (url != null) {
|
||||
_activeModules[url] = null;
|
||||
if (_asNodeSass) {
|
||||
if (url.scheme == 'file') {
|
||||
_includedFiles.add(p.fromUri(url));
|
||||
} else if (url.toString() != 'stdin') {
|
||||
_includedFiles.add(url.toString());
|
||||
}
|
||||
}
|
||||
if (!(_asNodeSass && url.toString() == 'stdin')) _includedUrls.add(url);
|
||||
}
|
||||
|
||||
var module = await _execute(importer, node);
|
||||
|
||||
return EvaluateResult(_combineCss(module), _includedFiles);
|
||||
return EvaluateResult(_combineCss(module), _includedUrls);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1577,13 +1567,17 @@ class _EvaluateVisitor
|
||||
tuple.item1, tuple.item2,
|
||||
originalUrl: tuple.item3, quiet: _quietDeps && isDependency);
|
||||
if (stylesheet != null) {
|
||||
_includedUrls.add(tuple.item2);
|
||||
return _LoadedStylesheet(stylesheet,
|
||||
importer: tuple.item1, isDependency: isDependency);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var result = await _importLikeNode(url, forImport);
|
||||
if (result != null) return result;
|
||||
if (result != null) {
|
||||
result.stylesheet.span.sourceUrl.andThen(_includedUrls.add);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (url.startsWith('package:') && isNode) {
|
||||
@ -1629,8 +1623,6 @@ class _EvaluateVisitor
|
||||
var contents = result.item1;
|
||||
var url = result.item2;
|
||||
|
||||
_includedFiles.add(url.startsWith('file:') ? p.fromUri(url) : url);
|
||||
|
||||
return _LoadedStylesheet(
|
||||
Stylesheet.parse(contents,
|
||||
url.startsWith('file') ? Syntax.forPath(url) : Syntax.scss,
|
||||
@ -3316,14 +3308,10 @@ class EvaluateResult {
|
||||
/// The CSS syntax tree.
|
||||
final CssStylesheet stylesheet;
|
||||
|
||||
/// The set that will eventually populate the JS API's
|
||||
/// `result.stats.includedFiles` field.
|
||||
///
|
||||
/// For filesystem imports, this contains the import path. For all other
|
||||
/// imports, it contains the URL passed to the `@import`.
|
||||
final Set<String> includedFiles;
|
||||
/// The canonical URLs of all stylesheets loaded during compilation.
|
||||
final Set<Uri> includedUrls;
|
||||
|
||||
EvaluateResult(this.stylesheet, this.includedFiles);
|
||||
EvaluateResult(this.stylesheet, this.includedUrls);
|
||||
}
|
||||
|
||||
/// The result of evaluating arguments to a function or mixin.
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||
// See tool/grind/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: b2321a00031707d2df699e6888a334deba39995d
|
||||
// Checksum: 5e03597bf64a5e03b483e64e4d35e4e86288bc10
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
@ -224,12 +224,8 @@ class _EvaluateVisitor
|
||||
/// Whether we're currently building the output of a `@keyframes` rule.
|
||||
var _inKeyframes = false;
|
||||
|
||||
/// The set that will eventually populate the JS API's
|
||||
/// `result.stats.includedFiles` field.
|
||||
///
|
||||
/// For filesystem imports, this contains the import path. For all other
|
||||
/// imports, it contains the URL passed to the `@import`.
|
||||
final _includedFiles = <String>{};
|
||||
/// The canonical URLs of all stylesheets loaded during compilation.
|
||||
final _includedUrls = <Uri>{};
|
||||
|
||||
/// A map from canonical URLs for modules (or imported files) that are
|
||||
/// currently being evaluated to AST nodes whose spans indicate the original
|
||||
@ -513,18 +509,12 @@ class _EvaluateVisitor
|
||||
var url = node.span.sourceUrl;
|
||||
if (url != null) {
|
||||
_activeModules[url] = null;
|
||||
if (_asNodeSass) {
|
||||
if (url.scheme == 'file') {
|
||||
_includedFiles.add(p.fromUri(url));
|
||||
} else if (url.toString() != 'stdin') {
|
||||
_includedFiles.add(url.toString());
|
||||
}
|
||||
}
|
||||
if (!(_asNodeSass && url.toString() == 'stdin')) _includedUrls.add(url);
|
||||
}
|
||||
|
||||
var module = _execute(importer, node);
|
||||
|
||||
return EvaluateResult(_combineCss(module), _includedFiles);
|
||||
return EvaluateResult(_combineCss(module), _includedUrls);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1575,13 +1565,17 @@ class _EvaluateVisitor
|
||||
var stylesheet = importCache.importCanonical(tuple.item1, tuple.item2,
|
||||
originalUrl: tuple.item3, quiet: _quietDeps && isDependency);
|
||||
if (stylesheet != null) {
|
||||
_includedUrls.add(tuple.item2);
|
||||
return _LoadedStylesheet(stylesheet,
|
||||
importer: tuple.item1, isDependency: isDependency);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var result = _importLikeNode(url, forImport);
|
||||
if (result != null) return result;
|
||||
if (result != null) {
|
||||
result.stylesheet.span.sourceUrl.andThen(_includedUrls.add);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (url.startsWith('package:') && isNode) {
|
||||
@ -1626,8 +1620,6 @@ class _EvaluateVisitor
|
||||
var contents = result.item1;
|
||||
var url = result.item2;
|
||||
|
||||
_includedFiles.add(url.startsWith('file:') ? p.fromUri(url) : url);
|
||||
|
||||
return _LoadedStylesheet(
|
||||
Stylesheet.parse(contents,
|
||||
url.startsWith('file') ? Syntax.forPath(url) : Syntax.scss,
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: sass
|
||||
version: 1.35.2
|
||||
version: 1.36.0
|
||||
description: A Sass implementation in Dart.
|
||||
author: Sass Team
|
||||
homepage: https://github.com/sass/dart-sass
|
||||
|
@ -5,7 +5,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_maps/source_maps.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_descriptor/test_descriptor.dart' as d;
|
||||
import 'package:test_process/test_process.dart';
|
||||
@ -35,9 +34,9 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
|
||||
});
|
||||
|
||||
test("contains mappings", () {
|
||||
late SingleMapping sourceMap;
|
||||
sass.compileString("a {b: 1 + 2}", sourceMap: (map) => sourceMap = map);
|
||||
expect(map, containsPair("mappings", sourceMap.toJson()["mappings"]));
|
||||
var result = sass.compileStringToResult("a {b: 1 + 2}");
|
||||
expect(map,
|
||||
containsPair("mappings", result.sourceMap!.toJson()["mappings"]));
|
||||
});
|
||||
});
|
||||
|
||||
@ -288,9 +287,9 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
|
||||
});
|
||||
|
||||
test("contains mappings in the generated CSS", () {
|
||||
late SingleMapping sourceMap;
|
||||
sass.compileString("a {b: 1 + 2}", sourceMap: (map) => sourceMap = map);
|
||||
expect(map, containsPair("mappings", sourceMap.toJson()["mappings"]));
|
||||
var result = sass.compileStringToResult("a {b: 1 + 2}");
|
||||
expect(map,
|
||||
containsPair("mappings", result.sourceMap!.toJson()["mappings"]));
|
||||
});
|
||||
|
||||
test("refers to the source file", () {
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:source_maps/source_maps.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:sass/sass.dart';
|
||||
@ -115,33 +114,27 @@ void main() {
|
||||
});
|
||||
|
||||
test("uses an importer's source map URL", () {
|
||||
late SingleMapping map;
|
||||
compileString('@import "orange";',
|
||||
importers: [
|
||||
var result = compileStringToResult('@import "orange";', importers: [
|
||||
TestImporter((url) => Uri.parse("u:$url"), (url) {
|
||||
var color = url.path;
|
||||
return ImporterResult('.$color {color: $color}',
|
||||
sourceMapUrl: Uri.parse("u:blue"), indented: false);
|
||||
})
|
||||
],
|
||||
sourceMap: (map_) => map = map_);
|
||||
]);
|
||||
|
||||
expect(map.urls, contains("u:blue"));
|
||||
expect(result.sourceMap!.urls, contains("u:blue"));
|
||||
});
|
||||
|
||||
test("uses a data: source map URL if the importer doesn't provide one", () {
|
||||
late SingleMapping map;
|
||||
compileString('@import "orange";',
|
||||
importers: [
|
||||
var result = compileStringToResult('@import "orange";', importers: [
|
||||
TestImporter((url) => Uri.parse("u:$url"), (url) {
|
||||
var color = url.path;
|
||||
return ImporterResult('.$color {color: $color}', indented: false);
|
||||
})
|
||||
],
|
||||
sourceMap: (map_) => map = map_);
|
||||
]);
|
||||
|
||||
expect(
|
||||
map.urls,
|
||||
result.sourceMap!.urls,
|
||||
contains(Uri.dataFromString(".orange {color: orange}", encoding: utf8)
|
||||
.toString()));
|
||||
});
|
||||
|
@ -226,6 +226,80 @@ a {
|
||||
});
|
||||
});
|
||||
|
||||
group("includedUrls", () {
|
||||
group("contains the entrypoint's URL", () {
|
||||
group("in compileStringToResult()", () {
|
||||
test("if it's given", () {
|
||||
var result = compileStringToResult("a {b: c}", url: "source.scss");
|
||||
expect(result.includedUrls, equals([Uri.parse("source.scss")]));
|
||||
});
|
||||
|
||||
test("unless it's not given", () {
|
||||
var result = compileStringToResult("a {b: c}");
|
||||
expect(result.includedUrls, isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
test("in compileToResult()", () async {
|
||||
await d.file("input.scss", "a {b: c};").create();
|
||||
var result = compileToResult(d.path('input.scss'));
|
||||
expect(result.includedUrls, equals([p.toUri(d.path('input.scss'))]));
|
||||
});
|
||||
});
|
||||
|
||||
test("contains a URL loaded via @import", () async {
|
||||
await d.file("_other.scss", "a {b: c}").create();
|
||||
await d.file("input.scss", "@import 'other';").create();
|
||||
var result = compileToResult(d.path('input.scss'));
|
||||
expect(result.includedUrls, contains(p.toUri(d.path('_other.scss'))));
|
||||
});
|
||||
|
||||
test("contains a URL loaded via @use", () async {
|
||||
await d.file("_other.scss", "a {b: c}").create();
|
||||
await d.file("input.scss", "@use 'other';").create();
|
||||
var result = compileToResult(d.path('input.scss'));
|
||||
expect(result.includedUrls, contains(p.toUri(d.path('_other.scss'))));
|
||||
});
|
||||
|
||||
test("contains a URL loaded via @forward", () async {
|
||||
await d.file("_other.scss", "a {b: c}").create();
|
||||
await d.file("input.scss", "@forward 'other';").create();
|
||||
var result = compileToResult(d.path('input.scss'));
|
||||
expect(result.includedUrls, contains(p.toUri(d.path('_other.scss'))));
|
||||
});
|
||||
|
||||
test("contains a URL loaded via @meta.load-css()", () async {
|
||||
await d.file("_other.scss", "a {b: c}").create();
|
||||
await d.file("input.scss", """
|
||||
@use 'sass:meta';
|
||||
@include meta.load-css('other');
|
||||
""").create();
|
||||
var result = compileToResult(d.path('input.scss'));
|
||||
expect(result.includedUrls, contains(p.toUri(d.path('_other.scss'))));
|
||||
});
|
||||
|
||||
test("contains a URL loaded via a chain of loads", () async {
|
||||
await d.file("_jupiter.scss", "a {b: c}").create();
|
||||
await d.file("_mars.scss", "@forward 'jupiter';").create();
|
||||
await d.file("_earth.scss", "@import 'mars';").create();
|
||||
await d.file("_venus.scss", "@use 'earth';").create();
|
||||
await d.file("mercury.scss", """
|
||||
@use 'sass:meta';
|
||||
@include meta.load-css('venus');
|
||||
""").create();
|
||||
var result = compileToResult(d.path('mercury.scss'));
|
||||
expect(
|
||||
result.includedUrls,
|
||||
unorderedEquals([
|
||||
p.toUri(d.path('mercury.scss')),
|
||||
p.toUri(d.path('_venus.scss')),
|
||||
p.toUri(d.path('_earth.scss')),
|
||||
p.toUri(d.path('_mars.scss')),
|
||||
p.toUri(d.path('_jupiter.scss'))
|
||||
]));
|
||||
});
|
||||
});
|
||||
|
||||
// Regression test for #1318
|
||||
test("meta.load-module() doesn't have a race condition", () async {
|
||||
await d.file("other.scss", '/**//**/').create();
|
||||
|
@ -27,7 +27,7 @@ final sources = const {
|
||||
|
||||
/// Classes that are defined in the async version of a file and used as-is in
|
||||
/// the sync version, and thus should not be copied over.
|
||||
final _sharedClasses = const ['EvaluateResult', 'CompileResult'];
|
||||
final _sharedClasses = const ['EvaluateResult'];
|
||||
|
||||
/// This is how we support both synchronous and asynchronous compilation modes.
|
||||
///
|
||||
@ -97,7 +97,6 @@ class _Visitor extends RecursiveAstVisitor<void> {
|
||||
_buffer.writeln();
|
||||
} else if (p.basename(path) == 'async_compile.dart') {
|
||||
_buffer.writeln();
|
||||
_buffer.writeln("import 'async_compile.dart';");
|
||||
_buffer.writeln("export 'async_compile.dart';");
|
||||
_buffer.writeln();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user