From 9a7e307232b313f81a0c2d16f02be80234f3780d Mon Sep 17 00:00:00 2001 From: Pamela Lozano Date: Mon, 20 Nov 2023 16:11:08 -0800 Subject: [PATCH] Add calculation interpolation migrator. --- CHANGELOG.md | 7 +++ CONTRIBUTING.md | 2 - lib/src/migrators/calc_interpolation.dart | 53 +++++++++++++++++++ lib/src/runner.dart | 2 + pubspec.yaml | 2 +- test/migrators/README.md | 4 ++ .../calc_remove_interpolation.hrx | 13 +++++ .../clamp_remove_interpolation.hrx | 7 +++ .../max_remove_interpolation.hrx | 7 +++ .../min_remove_interpolation.hrx | 7 +++ 10 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 lib/src/migrators/calc_interpolation.dart create mode 100644 test/migrators/calc_interpolation/calc_remove_interpolation.hrx create mode 100644 test/migrators/calc_interpolation/clamp_remove_interpolation.hrx create mode 100644 test/migrators/calc_interpolation/max_remove_interpolation.hrx create mode 100644 test/migrators/calc_interpolation/min_remove_interpolation.hrx diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e76fec..c1bcb24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.8.0 + +### Calc Functions Interpolation Migrator + +* Removes interpolation in calculation functions `calc()`, `clamp()`, `min()`, and `max()`. + See the [scss/function-calculation-no-interpolation](https://github.com/stylelint-scss/stylelint-scss/tree/master/src/rules/function-calculation-no-interpolation) rule for more information. + ## 1.7.3 * Fixes a bug where path arguments on the command line were incorrectly treated diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81b540a..8989ad2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,5 +54,3 @@ review. In addition, because these models were trained indiscriminately and non-consensually on open-source code with a variety of licenses, it's not obvious that we have the moral or legal right to redistribute code they generate. - - diff --git a/lib/src/migrators/calc_interpolation.dart b/lib/src/migrators/calc_interpolation.dart new file mode 100644 index 0000000..0500d99 --- /dev/null +++ b/lib/src/migrators/calc_interpolation.dart @@ -0,0 +1,53 @@ +// Copyright 2023 Google LLC +// +// 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:sass_api/sass_api.dart'; + +import '../migration_visitor.dart'; +import '../migrator.dart'; +import '../patch.dart'; + +/// Removes interpolation in calculation functions. +class CalculationInterpolationMigrator extends Migrator { + final name = "calc-interpolation"; + final description = r"Removes interpolation in calculation functions" + r"`calc()`, `clamp()`, `min()`, and `max()`"; + + @override + Map migrateFile( + ImportCache importCache, Stylesheet stylesheet, Importer importer) { + var visitor = + _CalculationInterpolationVisitor(importCache, migrateDependencies); + var result = visitor.run(stylesheet, importer); + missingDependencies.addAll(visitor.missingDependencies); + return result; + } +} + +class _CalculationInterpolationVisitor extends MigrationVisitor { + _CalculationInterpolationVisitor( + ImportCache importCache, bool migrateDependencies) + : super(importCache, migrateDependencies); + + @override + void visitCalculationExpression(CalculationExpression node) { + const calcFunctions = ['calc', 'clamp', 'min', 'max']; + final interpolation = RegExp(r'^#{.*\s*}'); + if (calcFunctions.contains(node.name)) { + for (var arg in node.arguments) { + for (var match in interpolation.allMatches(arg.toString())) { + var noInterpolation = match[0].toString().substring(2, match.end - 1); + var interpolationSpan = + node.span.file.span(arg.span.start.offset, arg.span.end.offset); + if (interpolationSpan.text == match[0].toString()) { + addPatch(Patch(interpolationSpan, noInterpolation)); + } + } + } + } + super.visitCalculationExpression(node); + } +} diff --git a/lib/src/runner.dart b/lib/src/runner.dart index 610e8ff..e58631a 100644 --- a/lib/src/runner.dart +++ b/lib/src/runner.dart @@ -13,6 +13,7 @@ import 'package:source_span/source_span.dart'; import 'package:term_glyph/term_glyph.dart' as glyph; import 'io.dart'; +import 'migrators/calc_interpolation.dart'; import 'migrators/division.dart'; import 'migrators/media_logic.dart'; import 'migrators/module.dart'; @@ -54,6 +55,7 @@ class MigratorRunner extends CommandRunner> { abbr: 'v', help: 'Print more information.', negatable: false) ..addFlag('version', help: 'Print the version of the Sass migrator.', negatable: false); + addCommand(CalculationInterpolationMigrator()); addCommand(DivisionMigrator()); addCommand(MediaLogicMigrator()); addCommand(ModuleMigrator()); diff --git a/pubspec.yaml b/pubspec.yaml index a43b69a..f8a9e0f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass_migrator -version: 1.7.3 +version: 1.8.0 description: A tool for running migrations on Sass files homepage: https://github.com/sass/migrator diff --git a/test/migrators/README.md b/test/migrators/README.md index 24df6a6..b5dfca1 100644 --- a/test/migrators/README.md +++ b/test/migrators/README.md @@ -28,3 +28,7 @@ not contain a file if it would not be changed by the migrator. The migration's expected standard output should be included in a file named `log.txt`. Its standard error should be included in a file called `error.txt` if the migration fails, or `warning.txt` if it completes successfully. + +## Testing +Run `dart run grinder pkg-compile-snapshot-dev` for compiling the latest changes of code, +`dart test` for running all tests and `dart test -x node` to run all tests except the node tests. diff --git a/test/migrators/calc_interpolation/calc_remove_interpolation.hrx b/test/migrators/calc_interpolation/calc_remove_interpolation.hrx new file mode 100644 index 0000000..1ca1499 --- /dev/null +++ b/test/migrators/calc_interpolation/calc_remove_interpolation.hrx @@ -0,0 +1,13 @@ +<==> input/entrypoint.scss +$c: 1; +.a { .b: calc(#{$c + 1}); } + +// Nested +.a { .b: calc(max(#{$c, 2})); } + +<==> output/entrypoint.scss +$c: 1; +.a { .b: calc($c + 1); } + +// Nested +.a { .b: calc(max($c, 2)); } diff --git a/test/migrators/calc_interpolation/clamp_remove_interpolation.hrx b/test/migrators/calc_interpolation/clamp_remove_interpolation.hrx new file mode 100644 index 0000000..aeaec2d --- /dev/null +++ b/test/migrators/calc_interpolation/clamp_remove_interpolation.hrx @@ -0,0 +1,7 @@ +<==> input/entrypoint.scss +$c: 1; +.a { .b: clamp(#{$c}); } + +<==> output/entrypoint.scss +$c: 1; +.a { .b: clamp($c); } diff --git a/test/migrators/calc_interpolation/max_remove_interpolation.hrx b/test/migrators/calc_interpolation/max_remove_interpolation.hrx new file mode 100644 index 0000000..f767618 --- /dev/null +++ b/test/migrators/calc_interpolation/max_remove_interpolation.hrx @@ -0,0 +1,7 @@ +<==> input/entrypoint.scss +$c: 1; +.a { .b: max(#{$c, 3}); } + +<==> output/entrypoint.scss +$c: 1; +.a { .b: max($c, 3); } diff --git a/test/migrators/calc_interpolation/min_remove_interpolation.hrx b/test/migrators/calc_interpolation/min_remove_interpolation.hrx new file mode 100644 index 0000000..cb0ecbf --- /dev/null +++ b/test/migrators/calc_interpolation/min_remove_interpolation.hrx @@ -0,0 +1,7 @@ +<==> input/entrypoint.scss +$c: 1; +.a { .b: min(#{$c, 3}); } + +<==> output/entrypoint.scss +$c: 1; +.a { .b: min($c, 3); }