mirror of
https://github.com/danog/sass-site.git
synced 2024-12-12 17:37:36 +01:00
d1e2f25a3c
Closes #549.
456 lines
15 KiB
Plaintext
456 lines
15 KiB
Plaintext
---
|
|
title: "Migrator"
|
|
table_of_contents: true
|
|
introduction: >
|
|
The Sass migrator automatically updates your Sass files to help you move on to
|
|
the latest and greatest version of the language. Each of its commands migrates
|
|
a single feature, to give you as much control as possible over what you update
|
|
and when.
|
|
---
|
|
|
|
## Usage
|
|
|
|
To use the Sass migrator, tell it [which migration][] you want to run and what
|
|
Sass files you want to migrate:
|
|
|
|
[which migration]: #migrations
|
|
|
|
```
|
|
sass-migrator <migration> <entrypoint.scss...>
|
|
```
|
|
|
|
By default, the migrator will only change files that you explicitly pass on the
|
|
command line. Passing the [`--migrate-deps` option][] tells the migrator to also
|
|
change all the stylesheets that are loaded using the [`@use` rule][],
|
|
[`@forward` rule][], or [`@import` rule][]. And if you want to do a test run to
|
|
see what changes will be made without actually saving them, you can pass
|
|
<code>[--dry-run][] [--verbose][]</code> (or `-nv` for short).
|
|
|
|
[`--migrate-deps` option]: #migrate-deps
|
|
[`@use` rule]: ../at-rules/use
|
|
[`@forward` rule]: ../at-rules/forward
|
|
[`@import` rule]: ../at-rules/import
|
|
[--dry-run]: #dry-run
|
|
[--verbose]: #verbose
|
|
|
|
<%= partial 'code-snippets/example-module-migrator' %>
|
|
|
|
## Installation
|
|
|
|
You can install the Sass migrator from most of the same places that you can
|
|
install [Dart Sass](/dart-sass):
|
|
|
|
### Standalone
|
|
|
|
You can install the Sass migrator on Windows, Mac, or Linux by downloading the
|
|
package for your operating system [from GitHub][] and [adding it to your
|
|
`PATH`][].
|
|
|
|
[from GitHub]: <%= release_url(:migrator) %>
|
|
[adding it to your `PATH`]: https://katiek2.github.io/path-doc/
|
|
|
|
### npm
|
|
|
|
If you use Node.js, you can also install the Sass migrator using [npm][] by
|
|
running
|
|
|
|
[npm]: https://www.npmjs.com
|
|
|
|
```
|
|
npm install -g sass-migrator
|
|
```
|
|
|
|
### Chocolatey
|
|
|
|
If you use [the Chocolatey package manager][] for Windows, you can install the
|
|
Sass migrator by running
|
|
|
|
[the Chocolatey package manager]: https://chocolatey.org
|
|
|
|
```
|
|
choco install sass-migrator
|
|
```
|
|
|
|
### Homebrew
|
|
|
|
If you use [the Homebrew package manager][] for Mac OS X, you can install Dart
|
|
Sass by running
|
|
|
|
[the Homebrew package manager]: https://brew.sh
|
|
|
|
```
|
|
brew install sass/sass/migrator
|
|
```
|
|
|
|
## Global Options
|
|
|
|
These options are available for all migrators.
|
|
|
|
### `--migrate-deps`
|
|
|
|
This option (abbreviated `-d`) tells the migrator to change not just the
|
|
stylesheets that are explicitly passed on the command line, but also any
|
|
stylesheets that they depend on using the [`@use` rule][], [`@forward` rule][],
|
|
or [`@import` rule][].
|
|
|
|
```shellsession
|
|
$ sass-migrator module --verbose style.scss
|
|
Migrating style.scss
|
|
$ sass-migrator module --verbose --migrate-deps style.scss
|
|
Migrating style.scss
|
|
Migrating _theme.scss
|
|
Migrating _fonts.scss
|
|
Migrating _grid.scss
|
|
```
|
|
|
|
<% heads_up do %>
|
|
The [module migrator][] assumes that any stylesheet that is depended on using
|
|
a [`@use` rule][] or a [`@forward` rule][] has already been migrated to the
|
|
module system, so it won't attempt to migrate them, even when the
|
|
`--migrate-deps` option is passed.
|
|
|
|
[module migrator]: #module
|
|
[`@use` rule]: ../at-rules/use
|
|
[`@forward` rule]: ../at-rules/forward
|
|
<% end %>
|
|
|
|
### `--load-path`
|
|
|
|
This option (abbreviated `-I`) tells the migrator a [load path][] where it
|
|
should look for stylesheets. It can be passed multiple times to provide multiple
|
|
load paths. Earlier load paths will take precedence over later ones.
|
|
|
|
Dependencies loaded from load paths are assumed to be third-party libraries, so
|
|
the migrator will not migrate them even when the [`--migrate-deps` option][] is
|
|
passed.
|
|
|
|
[load path]: ../at-rules/use#load-paths
|
|
|
|
### `--dry-run`
|
|
|
|
This flag (abbreviated `-n`) tells the migrator not to save any changes to
|
|
disk. It instead prints the list of files that it would have changed. This is
|
|
commonly paired with the [`--verbose` option][] to print the contents of the
|
|
changes that would have been made as well.
|
|
|
|
[`--verbose` option]: #verbose
|
|
|
|
```shellsession
|
|
$ sass-migrator module --dry-run --migrate-deps style.scss
|
|
Dry run. Logging migrated files instead of overwriting...
|
|
|
|
style.scss
|
|
_theme.scss
|
|
_fonts.scss
|
|
_grid.scss
|
|
```
|
|
|
|
#### `--no-unicode`
|
|
|
|
This flag tells the Sass migrator only to emit ASCII characters to the terminal
|
|
as part of error messages. By default, or if `--unicode` is passed, the migrator
|
|
will emit non-ASCII characters for these messages. This flag does not affect the
|
|
CSS output.
|
|
|
|
```shellsession
|
|
$ sass-migrator --no-unicode module style.scss
|
|
line 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'.
|
|
,
|
|
1 | @import "typography";
|
|
| ^^^^^^^^^^^^
|
|
'
|
|
Migration failed!
|
|
$ sass-migrator --unicode module style.scss
|
|
line 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'.
|
|
╷
|
|
1 │ @import "typography";
|
|
│ ^^^^^^^^^^^^
|
|
╵
|
|
Migration failed!
|
|
```
|
|
|
|
### `--verbose`
|
|
|
|
This flag (abbreviated `-v`) tells the migrator to print extra information to
|
|
the console. By default, it just prints the name of files that are changed, but
|
|
when combined with the [`--dry-run` option][] it also prints those files' new
|
|
contents.
|
|
|
|
[`--dry-run` option]: #dry-run
|
|
|
|
<%# Indent this because otherwise the table-of-contents generator interprets
|
|
the `===` as a heading. %>
|
|
|
|
$ sass-migrator module --verbose --dry-run style.scss
|
|
Dry run. Logging migrated files instead of overwriting...
|
|
<==> style.scss
|
|
@use "bootstrap" with (
|
|
$body-bg: #000,
|
|
$body-color: #111
|
|
);
|
|
|
|
@include bootstrap.media-breakpoint-up(sm) {
|
|
.navbar {
|
|
display: block;
|
|
}
|
|
}
|
|
$ sass-migrator module --verbose style.scss
|
|
Migrating style.scss
|
|
|
|
## Migrations
|
|
|
|
### Division
|
|
|
|
This migration converts stylesheets that use [`/` as division] to use the
|
|
built-in `math.div` function instead.
|
|
|
|
[`/` as division]: ../breaking-changes/slash-div
|
|
|
|
#### `--pessimistic`
|
|
|
|
By default, the migrator converts `/` operations to `math.div` even when it
|
|
isn't sure that it will be division when evaluated. It only leaves them as-is
|
|
when it can statically determine that they're doing something else (such as when
|
|
there's no SassScript involved, or when one of the operands is a string). The
|
|
`math.div` function currently functions identically to the `/` operator, so
|
|
this is safe to do, but may result in new warnings if one of the arguments to
|
|
`math.div` at runtime is not a number.
|
|
|
|
If you want to avoid this behavior, you can pass the `--pessimistic` flag. With
|
|
this flag, the migrator will only convert `/` operations that it knows for sure
|
|
are doing division. This will prevent any unnecessary `math.div` conversions,
|
|
but it's likely to leave some division unmigrated if it can't be statically
|
|
determined.
|
|
|
|
### Module
|
|
|
|
This migration converts stylesheets that use the old [`@import` rule][] to load
|
|
dependencies so that they use the Sass module system via the [`@use` rule][]
|
|
instead. It doesn't just naïvely change `@import`s to `@use`s—it updates
|
|
stylesheets intelligently so that they keep working the same way they did
|
|
before, including:
|
|
|
|
* Adding namespaces to uses of members (variables, mixins, and functions) from
|
|
other modules.
|
|
|
|
* Adding new `@use` rules to stylesheets that were using members without
|
|
importing them.
|
|
|
|
* Converting overridden default variables to [`with` clauses][].
|
|
|
|
[`with` clauses]: ../at-rules/use#configuration
|
|
|
|
* Automatically removing `-` and `_` prefixes from members that are used from
|
|
other files (because otherwise they'd be considered [private][] and could only
|
|
be used in the module they're declared).
|
|
|
|
[private]: ../at-rules/use#private-members
|
|
|
|
* Converting [nested imports][] to use the [`meta.load-css()` mixin][] instead.
|
|
|
|
[nested imports]: ../at-rules/import#nesting
|
|
[`meta.load-css()` mixin]: ../modules/meta#load-css
|
|
|
|
<% heads_up do %>
|
|
Because the module migrator may need to modify both member definitions *and*
|
|
member names, it's important to either run it with the [`--migrate-deps`
|
|
option][] or ensure that you pass it all the stylesheets in your package or
|
|
application.
|
|
|
|
[`--migrate-deps` option]: #migrate-deps
|
|
<% end %>
|
|
|
|
<%= partial 'code-snippets/example-module-migrator' %>
|
|
|
|
#### Loading Dependencies
|
|
|
|
The module migrator needs to be able to read all of the stylesheets depended on
|
|
by the ones it's migrating, even if the [`--migrate-deps` option][] is not
|
|
passed. If the migrator fails to find a dependency, you'll get an error.
|
|
|
|
```shellsession
|
|
$ ls .
|
|
style.scss node_modules
|
|
$ sass-migrator module style.scss
|
|
Error: Could not find Sass file at 'dependency'.
|
|
,
|
|
1 | @import "dependency";
|
|
| ^^^^^^^^^^^^
|
|
'
|
|
style.scss 1:9 root stylesheet
|
|
Migration failed!
|
|
$ sass-migrator --load-path node_modules module style.scss
|
|
```
|
|
|
|
If you use a [load path][] when compiling your stylesheets, make sure to pass
|
|
that to the migrator using the [`--load-path` option][].
|
|
|
|
Unfortunately, the migrator does not support custom importers, but it does have
|
|
built-in support for resolving URLs starting with `~` by searching in
|
|
`node_modules`, similar to [what Webpack supports][].
|
|
|
|
[load path]: ../at-rules/use#load-paths
|
|
[`--load-path` option]: #load-path
|
|
[what Webpack supports]: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules
|
|
|
|
#### `--remove-prefix`
|
|
|
|
This option (abbreviated `-p`) takes an identifier prefix to remove from the
|
|
beginning of all variable, mixin, and function names when they're migrated.
|
|
Members that don't start with this prefix will remain unchanged.
|
|
|
|
The [`@import` rule][] put all top-level members in one global scope, so when it
|
|
was the standard way of loading stylesheets, everyone was incentivized to add
|
|
prefixes to all their member names to avoid accidentally redefining some other
|
|
stylesheet's. The module system solves this problem, so it's useful to
|
|
automatically strip those old prefixes now that they're unnecessary.
|
|
|
|
```shellsession
|
|
$ cat style.scss
|
|
@import "theme";
|
|
|
|
@mixin app-inverted {
|
|
color: $app-bg-color;
|
|
background-color: $app-color;
|
|
}
|
|
$ sass-migrator --migrate-deps module --remove-prefix=app- style.scss
|
|
$ cat style.scss
|
|
@import "theme";
|
|
|
|
@mixin inverted {
|
|
color: theme.$bg-color;
|
|
background-color: theme.$color;
|
|
}
|
|
```
|
|
|
|
When you pass this option, the migrator will also generate an [import-only
|
|
stylesheet][] that [forwards][] all the members with the prefix added back, to
|
|
preserve backwards-compatibility for users who were importing the library.
|
|
|
|
[import-only stylesheet]: ../at-rules/import#import-only-files
|
|
[forwards]: ../at-rules/forward
|
|
|
|
This option may be passed multiple times, or with multiple values separated by
|
|
commas. Each prefix will be removed from any members that have it. If a member
|
|
matches multiple prefixes, the longest matching prefix will be removed.
|
|
|
|
#### `--forward`
|
|
|
|
This option tells the migrator which members to forward using the [`@forward`
|
|
rule][]. It supports the following settings:
|
|
|
|
* `none` (the default) doesn't forward any members.
|
|
|
|
* `all` forwards all members except those that started with `-` or `_` in the
|
|
original stylesheet, since that was commonly used to mark a package-private
|
|
member before the module system was introduced.
|
|
|
|
* `prefixed` forwards only members that begin with the prefix passed to the
|
|
[`--remove-prefix` option][]. This option may only be used in conjunction with
|
|
the `--remove-prefix` option.
|
|
|
|
[`--remove-prefix` option]: #remove-prefix
|
|
|
|
All files that are passed explicitly on the command line will forward members
|
|
that are transitively loaded by those files using the `@import` rule. Files
|
|
loaded using the [`--migrate-deps` option][] will not forward any new members.
|
|
This option is particularly useful when migrating a Sass library, because it
|
|
ensures that users of that library will still be able to access all the members
|
|
it defines.
|
|
|
|
```shellsession
|
|
$ cat _index.scss
|
|
@import "theme";
|
|
@import "typography";
|
|
@import "components";
|
|
$ sass-migrator --migrate-deps module --forward=all style.scss
|
|
$ cat _index.scss
|
|
@forward "theme";
|
|
@forward "typography";
|
|
@forward "components";
|
|
```
|
|
|
|
### Namespace
|
|
|
|
This migration allows you to easily change the [namespaces][] of the `@use`
|
|
rules in a stylesheet. This is useful if the namespaces that the module migrator
|
|
generates to resolve conflicts are non-ideal, or if you don't want to use the
|
|
default namespace that Sass determines based on the rule's URL.
|
|
|
|
[namespaces]: ../at-rules/use#choosing-a-namespace
|
|
|
|
#### `--rename`
|
|
|
|
You can tell the migrator which namespace(s) you want it to change by passing
|
|
expressions to the `--rename` option.
|
|
|
|
These expressions are of the form `<old-namespace> to <new-namespace>` or
|
|
`url <rule-url> to <new-namespace>`. In these expressions, `<old-namespace>` and
|
|
`<rule-url>` are [regular expressions][] which match against the entirety of the
|
|
existing namespace or the `@use` rule's URL, respectively.
|
|
|
|
[regular expressions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
|
|
|
For simple use cases, this just looks like `--rename 'old to new'`, which would
|
|
rename a `@use` rule with the namespace `old` to instead be `new`.
|
|
|
|
However, you can also do this to accomplish more complicated renames. For
|
|
instance, say that you previously had a stylesheet that looked like this:
|
|
|
|
```scss
|
|
@import "components/button/lib/mixins";
|
|
@import "components/input/lib/mixins";
|
|
@import "components/table/lib/mixins";
|
|
// ...
|
|
```
|
|
|
|
Since all of these URLs would have the default namespace `mixins` when migrated
|
|
to `@use` rules, the module migrator may end up generating something like this:
|
|
|
|
```scss
|
|
@use "components/button/lib/mixins" as button-lib-mixins;
|
|
@use "components/input/lib/mixins" as input-lib-mixins;
|
|
@use "components/table/lib/mixins" as table-lib-mixins;
|
|
// ...
|
|
```
|
|
|
|
This is valid code since the namespaces don't conflict, but they're way more
|
|
complicated than they need to be. The relevant part of the URL is the component
|
|
name, so we can use the namespace migrator to extract that part out.
|
|
|
|
If we run the namespace migrator with
|
|
`--rename 'url components/(\w+)/lib/mixins to \1'`, we'll end up with:
|
|
|
|
```scss
|
|
@use "components/button/lib/mixins" as button;
|
|
@use "components/input/lib/mixins" as input;
|
|
@use "components/table/lib/mixins" as table;
|
|
// ...
|
|
```
|
|
|
|
The rename script here says to find all of the `@use` rules whose URLs look like
|
|
`components/(\w+)/lib/mixins` (`\w+` in a regular expression means to match any
|
|
word of one or more characters). The `\1` in the output clause means to
|
|
substitute in the contents of the first set of parentheses in the regular
|
|
expression (called a [group][]).
|
|
|
|
[group]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges
|
|
|
|
If you wish to apply multiple renames, you can pass the `--rename` option
|
|
multiple times, or separate them with a semicolon or a line break. Only the
|
|
first rename that applies to a given rule will be used, so you could pass
|
|
something like `--rename 'a to b; b to a'` to swap the namespaces `a` and `b`.
|
|
|
|
#### `--force`
|
|
|
|
By default, if two or more `@use` rules have the same namespace after the
|
|
migration, the migrator will fail, and no changes will be made.
|
|
|
|
In this case, you'll usually want to adjust your `--rename` script to avoid
|
|
creating conflicts, but if you'd prefer to force the migration, you can instead
|
|
pass `--force`.
|
|
|
|
With `--force`, if any conflicts are encountered, the first `@use` rule will
|
|
get its preferred namespace, while subsequent `@use` rules with the same
|
|
preferred namespace will instead have a numerical suffix added to them.
|