build method

  1. @override
Future build(
  1. BuildStep buildStep
)

Generates the outputs for a given BuildStep.

Implementation

@override
Future build(BuildStep buildStep) async {
  final inputId = buildStep.inputId;

  if (p.basename(inputId.path).startsWith('_')) {
    // Do not produce any output for .scss partials.
    log.fine('skipping partial file: $inputId');
    return;
  }

  // Compile the css.
  log.fine('compiling file: ${inputId.uri.toString()}');
  final compileResult = await sass.compileStringToResultAsync(
    await buildStep.readAsString(inputId),
    syntax: sass.Syntax.forPath(inputId.path),
    importers: [BuildImporter(buildStep)],
    style: _getValidOutputStyle(),
    url: inputId.uri,
    sourceMap: _generateSourceMaps,
  );

  var cssOutput = compileResult.css;
  final sourceMapId = inputId.changeExtension('.css.map');

  if (_generateSourceMaps) {
    // Add the source mapping information to the generated css
    final import = p.url.basename(sourceMapId.path);
    cssOutput += '\n\n/*# sourceMappingURL=$import */';
  }

  Future<void> writeCss() async {
    final outputId = inputId.changeExtension(_outputExtension);
    await buildStep.writeAsString(outputId, '$cssOutput\n');
    log.fine('wrote css file: ${outputId.path}');
  }

  Future<void> writeSourceMaps() async {
    final map = compileResult.sourceMap!.toJson();

    // We need to replace source map uris to reflect the paths generated by
    // Dart's build system.
    final sources = List<String>.of(map['sources']);
    for (var i = 0; i < sources.length; i++) {
      final uri = Uri.tryParse(sources[i]);
      if (uri == null) continue;

      final asset = AssetId.resolve(uri, from: inputId);
      if (p.url.isWithin('lib', asset.path)) {
        // The source is in lib/, which means that webdev and friends will
        // serve it under `/packages/<package>/<source_in_lib>`
        sources[i] = p.url.join('packages', asset.package,
            p.url.relative(asset.path, from: 'lib'));
      } else if (asset.package == inputId.package) {
        // Assets from the root package are included if they're in web/, so
        // we might have a chance to still recover the source.
        if (p.url.isWithin('web', asset.path)) {
          sources[i] = p.url.relative(asset.path, from: 'web');
        }
      }
    }

    map['sources'] = sources;
    await buildStep.writeAsString(sourceMapId, json.encode(map));
  }

  await Future.wait([
    writeCss(),
    if (_generateSourceMaps) writeSourceMaps(),
  ]);
}