// Copyright 2016 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 'dart:convert'; import 'dart:io'; import 'package:charcode/charcode.dart'; import 'package:cli_pkg/cli_pkg.dart' as pkg; import 'package:grinder/grinder.dart'; import 'package:path/path.dart' as p; import 'package:source_span/source_span.dart'; import 'grind/synchronize.dart'; export 'grind/bazel.dart'; export 'grind/benchmark.dart'; export 'grind/sanity_check.dart'; export 'grind/synchronize.dart'; void main(List args) { pkg.humanName.value = "Dart Sass"; pkg.botName.value = "Sass Bot"; pkg.botEmail.value = "sass.bot.beep.boop@gmail.com"; pkg.executables.value = {"sass": "bin/sass.dart"}; pkg.chocolateyNuspec.value = _nuspec; pkg.homebrewRepo.value = "sass/homebrew-sass"; pkg.homebrewFormula.value = "sass.rb"; pkg.jsRequires.value = {"chokidar": "chokidar", "readline": "readline"}; pkg.jsModuleMainLibrary.value = "lib/src/node.dart"; pkg.npmPackageJson.fn = () => json.decode(File("package/package.json").readAsStringSync()) as Map; pkg.npmReadme.fn = () => _readAndResolveMarkdown("package/README.npm.md"); pkg.standaloneName.value = "dart-sass"; pkg.githubUser.value = Platform.environment["GH_USER"]; pkg.githubPassword.value = Platform.environment["GH_TOKEN"]; pkg.githubReleaseNotes.fn = () => "To install Sass ${pkg.version}, download one of the packages below " "and [add it to your PATH][], or see [the Sass website][] for full " "installation instructions.\n" "\n" "[add it to your PATH]: https://katiek2.github.io/path-doc/\n" "[the Sass website]: https://sass-lang.com/install\n" "\n" "# Changes\n" "\n" "${pkg.githubReleaseNotes.defaultValue}"; pkg.addAllTasks(); grind(args); } @DefaultTask('Compile async code and reformat.') @Depends(format, synchronize) void all() {} @Task('Run the Dart formatter.') void format() { Pub.run('dart_style', script: 'format', arguments: [ '--overwrite', '--fix', for (var dir in existingSourceDirs) dir.path ]); } @Task('Installs dependencies from npm.') void npmInstall() => run(Platform.isWindows ? "npm.cmd" : "npm", arguments: ["install"]); @Task('Runs the tasks that are required for running tests.') @Depends(format, synchronize, "pkg-npm-dev", npmInstall, "pkg-standalone-dev") void beforeTest() {} String get _nuspec => """ sass Sass Natalie Weizenbaum nex3 https://github.com/sass/dart-sass https://github.com/sass/dart-sass/blob/${pkg.version}/LICENSE https://cdn.rawgit.com/sass/sass-site/f99ee33e4f688e244c7a5902c59d61f78daccc55/source/assets/img/logos/logo-seal.png https://github.com/sass/dart-sass/issues **Sass makes CSS fun again**. Sass is an extension of CSS, adding nested rules, variables, mixins, selector inheritance, and more. It's translated to well-formatted, standard CSS using the command line tool or a web-framework plugin. This package is Dart Sass, the new Dart implementation of Sass. Sass makes CSS fun again. css preprocessor style sass Copyright ${DateTime.now().year} Google, Inc. """; final _readAndResolveRegExp = RegExp( r"^$", multiLine: true); /// Reads a Markdown file from [path] and resolves include directives. /// /// Include directives have the syntax `""`, /// which must appear on its own line. PATH is a relative file: URL to another /// Markdown file, and HEADER is the name of a header in that file whose /// contents should be included as-is. String _readAndResolveMarkdown(String path) => File(path) .readAsStringSync() .replaceAllMapped(_readAndResolveRegExp, (match) { String included; try { included = File(p.join(p.dirname(path), p.fromUri(match[1]))) .readAsStringSync(); } catch (error) { _matchError(match, error.toString(), url: p.toUri(path)); } Match headerMatch; try { headerMatch = "# ${match[2]}".allMatches(included).first; } on StateError { _matchError(match, "Could not find header.", url: p.toUri(path)); } var headerLevel = 0; var index = headerMatch.start; while (index >= 0 && included.codeUnitAt(index) == $hash) { headerLevel++; index--; } // The section goes until the next header of the same level, or the end // of the document. var sectionEnd = included.indexOf("#" * headerLevel, headerMatch.end); if (sectionEnd == -1) sectionEnd = included.length; return included.substring(headerMatch.end, sectionEnd).trim(); }); /// Throws a nice [SourceSpanException] associated with [match]. void _matchError(Match match, String message, {Object url}) { var file = SourceFile.fromString(match.input, url: url); throw SourceSpanException(message, file.span(match.start, match.end)); }