The Rome Toolchain
About Rome
Rome is a formatter, linter, bundler, and more for JavaScript, TypeScript, JSON, HTML, Markdown, and CSS.
Rome is designed to replace Babel, ESLint, webpack, Prettier, Jest, and others.
Rome unifies functionality that has previously been separate tools. Building upon a shared base allows us to provide a cohesive experience for processing code, displaying errors, parallelizing work, caching, and configuration.
Rome has strong conventions and aims to have minimal configuration. Read more about our project philosophy.
Rome is written in Rust.
Rome has first-class IDE support, with a sophisticated parser that represents the source text in full fidelity and top-notch error recovery.
Rome is MIT licensed and moderated under the Contributor Covenant Code of Conduct.
Getting Started
Rome works on Linux, macOS, and Windows.
For all operating systems, we support both x86_64 and ARM architectures.
Install Rome using any of the following methods.
Install official Rome VS Code extension
You can use Rome by installing the VS Code extension from the marketplace.
Rome currently doesn’t support other editors than VS Code. Let us know if you would like support for another editor.
Install Rome CLI
Install rome
using your preferred node package manager. We require a minimum Node version of v14.18.
NOTE: we recommend not installing the binary globally, instead please install the binary locally to your project. You can also use
npx
,pnpm dlx
oryarn dlx
to run[email protected]
.
Package manager | Instructions |
---|---|
npm | npm i -D [email protected] |
pnpm | pnpm add -D [email protected] |
yarn | yarn add -D [email protected] |
If you install the CLI locally, use the scripts field of your package.json to run Rome. For instance:
{
"scripts": {
"format": "rome format ."
}
}
Then you can run:
npm run format
yarn format
pnpm format
Install Rome in your CI pipeline
GitHub Actions
Please refer to the setup-rome
action documentation for more information about its configuration:
steps:
- uses: rome/setup-[email protected]
with:
version: latest
- run: rome --help
Installation on any other CI
You can download and install the binary directly using curl
:
curl -L https://github.com/rome/tools/releases/download/latest/rome-<OS>-<ARCH> -o rome
chmod +x rome
Where <OS>
and <ARCH>
follow the Node.js syntax convention:
<OS>
is one of the following values:win32
,darwin
orlinux
<ARCH>
is one of the following values:arm64
orx64
NOTE: For Windows Subsystem for Linux (WSL), please use
linux
as your OS
win32 | darwin | linux | |
---|---|---|---|
arm64 | win32-arm64 | darwin-arm64 | linux-arm64 |
x64 | win32-x64 | darwin-x64 | linux-x64 |
Please make sure to choose the correct architecture from the releases page.
Post-Installation
- check the formatter section for options and commands;
- check the options available in the VS Code extension
Development Status
Rome is being rewritten in Rust, so it doesn’t support all the intended features.
Rome is currently only supported as a formatter for JavaScript and TypeScript.**
We plan on covering the following areas:
- Bundling
- Compiling
- Documentation Generation
- Formatting
- Linting
- Minification
- Testing
- Type Checking
- … and more
Language Support
Language | Parsing | Formatting | Linting |
---|---|---|---|
JavaScript | ✅ | ✅ | ✅ |
TypeScript | ✅ | ✅ | ✅ |
JSX | ✅ | ✅️ | ✅ |
JSON | 🚫 | 🚫 | 🚫 |
HTML | 🚫 | 🚫 | 🚫 |
CSS | 🚫 | 🚫 | 🚫 |
Markdown | 🚫 | 🚫 | 🚫 |
JavaScript support
Rome supports only the official syntax. The team starts developments of the new syntax when a proposal reaches Stage 3.
Rome supports ES2022 version of the language.
TypeScript support
Rome doesn’t support decorators (the old proposal). Rome’s parser will ignore them as if they were comments. This means that programs with decorators are still valid, but they won’t benefit all the underlying features such as formatter, analyzers, etc.
CLI
Rome CLI offers some options that can be used with all commands:
OPTIONS:
--no-colors Disable the formatting of markup (print everything as plain text)
Commands
rome ci
This command will:
- run the formatter in check mode
- run the linter in check mode
rome init
This command assists in the creation of a new Rome project. The command will ask few questions about coding style and configuration extension.
Actions that are performed:
rome.json
is created that serves as your project configuration.
The command only works on projects that don’t have Rome configuration.
Formatter
You can use the formatter via our VS Code extension or by downloading our CLI directly from our release page.
WARNING: The CLI and VS Code extension are packaged with separate binaries, which means that if you don’t use our default options, you will have to pass them to both the extension AND the CLI.
This is a temporary choice to allow people to play with our formatter. This will change in the near future.
Formatter options
Our formatter is really strict and has support for only a few options:
- indent style, you can choose between tabs or spaces; Rome’s default is tabs
- quantity of spaces, applied only if you choose spaces as indent style;
- line width, which is the number of characters that fit in a single line; Rome’s default is
80
Use the formatter via VSCode extension
The extension allows you to change the default formatter options.
For easy access to the available options, navigate to the settings menu of the VSCode extension and type: @ext:rome.rome
.
Plus, you can try an additional feature that allows you to format code with syntax errors.
This is an opt-in feature that allows developers to experiment with a formatter that can work with an error resilient parser.
WARNING: all options are marked as BETA because this might change, once we will add support of a configuration file
If you want to set Rome as your default formatter, you can do so by opening the command palette and select Format Document With ...
, then Configure Default Formatter
and finally select Rome
. The option will appear only for documents that Rome supports.
Use the formatter with the CLI
You can start by running the CLI with the --help
flag:
rome format --help
Which will show you the options available at the moment:
Rome Formatter
USAGE:
rome format [OPTIONS] <INPUTS...>
INPUTS can be one or more filesystem path, each pointing to a single file or an entire directory to be searched recursively for supported files
OPTIONS:
--write Write the output of the formatter to the files instead of printing the diff to the console
--skip-errors Skip over files containing syntax errors instead of returning an error
--indent-style <tabs|space> Determine whether the formatter should use tabs or spaces for indentation (default: tabs)
--indent-size <number> If the indentation style is set to spaces, determine how many spaces should be used for indentation (default: 2)
--line-width <number> Determine how many characters the formatter is allowed to print in a single line (default: 80)
--quote-style <single|double> Determine whether the formatter should use single or double quotes for strings (default: double)
Suppression
There are times when a developer wants to keep a specific formatting.
You can achieve this by adding a suppression comment right before the syntax node (expressions, statements, etc.).
Suppression comments have the following format:
// rome-ignore format: <explanation>
Where
rome-ignore
is the start of a suppression comment;format:
suppresses the formatting;<explanation>
is an explanation why the formatting is disabled;
Here’s an example of how a code will look like before and after the formatter does its job:
Before running the formatter
const expr =
// rome-ignore format: the array should not be formatted
[
(2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, -(f+n)/(f-n), -(2*f*n)/(f-n),
0, 0, -1, 0,
];
const expr = [
(2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, -(f+n)/(f-n), -(2*f*n)/(f-n),
0, 0, -1, 0,
];
After running the formatter
const expr =
// rome-ignore format: the array should not be formatted
[
(2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, -(f+n)/(f-n), -(2*f*n)/(f-n),
0, 0, -1, 0,
];
const expr = [
(2 * n) / (r - l),
0,
(r + l) / (r - l),
0,
0,
(2 * n) / (t - b),
(t + b) / (t - b),
0,
0,
0,
-(f + n) / (f - n),
-(2 * f * n) / (f - n),
0,
0,
-1,
0,
];
As you can see the first array, which has a suppression comment, is left untouched!
Differences with Prettier/dprint
Our formatter uses a CST to implement its algorithms, as opposed to Prettier or dprint, which use an AST. This means that it has to deal with a different set of problems e.g. comments and how to place them.
As you might know, comments can appear almost everywhere inside a program, which can make the implementation of a formatter more difficult.
In a CST, comments are attached to tokens, so it’s possible to extract this information when inspecting a single node.
Considering these assumptions, the Rome team had to create some heuristics and concepts in order to consistently format comments inside a program.
Comments
The placements of some comments might be different, for example in JavaScript functions and JavaScript classes.
A function has a “head” and a “body”:
- the head is where we define the name of the function and its signature (its parameters, return type, etc.);
- the body is where we define the implementation of the function, usually - but not only - inside a block
{}
;
Our formatter marks a function head as a hard group, while the body is a normal group. This means that all the comments inside the head are “pushed out” and moved outside it, making the formatting always consistent.
Here’s an example against Prettier/dprint, we place comments inside the head of a function:
function // something
a(b, c) {
let a = "f";
}
function a(b, c) // something
{
let a = "f";
}
This how Rome and Prettier format this code:
// Rome
function a(b, c) {
// something
let a = "f";
}
function a(b, c) {
// something
let a = "f";
}
// Prettier/dprint
function // something
a(b, c) {
let a = "f";
}
function a(b, c) {
// something
let a = "f";
}
Please check our playground and its result
Migration from other formatters
Rome doesn’t support a lot of options like other web formatters, which means that particular styles won’t be available to all developers.
To migrate from suppression comments of the old formatter, it’s recommended to run a global search and replace against the code base and replace the formatting comment with:
// rome-ignore format: migration from <name_of_former_formatter>
Then, you are free to change the reason of the suppression that you want.
Run the formatter and make sure that the code that was ignored is still the same.
Linter
You can use the linter via our VS Code extension or by downloading our CLI directly from our release page.
WARNING: The CLI and VS Code extension are packaged with separate binaries, which means that if you don’t use our default options, you will have to pass them to both the extension AND the CLI.
This is a temporary choice to allow people to play with our linter. This will change in the near future.
Use the linter via VSCode extension
The feature is opt-in, and you’d need to enable the following options:
analysis.enableDiagnostics
analysis.enableCodeActions
Use the linter via CLI
You can start by running the CLI with the --help
flag:
rome check --help
Which will show you the options available at the moment:
USAGE:
rome check <INPUTS...>
INPUTS can be one or more filesystem path, each pointing to a single file or an entire directory to be searched recursively for supported files
OPTIONS:
--apply Apply safe fixes
--max-diagnostics Cap the amount of diagnostics displayed - default 20
Rules
At the moment only a few rules are implemented as the linting / analysis infrastructure is being built.
See the full list of rules.
All rules are enabled by default, and cannot be disabled. Suppressions can be used to hide specific lint errors.
Project Configuration
The configuration file is considered optional, Rome has good defaults. Use the configuration file to change those defaults.
The configuration file must be placed at the root of your project, usually at the same directory level of your package.json
. The name of the file must be rome.json
.
All properties are optional, you can even have an empty config!
We are deliberately lean with the supported configuration. We do not include options just for the sake of personalization. We aim to offer everything out of the box and only introduce configuration if absolutely necessary.
{
"formatter": {
"identStyle": "tab",
"lineWidth": 120
},
"linter": {
"enabled": false
}
}
Properties
linter.enabled
Enables Rome’s linter
Default:
true
linter.rules.recommended
Enables the recommended rules for all the groups.
Default:
true
linter.rules.js
A list of rules for JavaScript
category.
linter.rules.js.recommended
Enables the recommended rules for the category JavaScript
.
linter.rules.js.rules
A map with the name of the rule as key, and their configuration as value. Check rule configuration section. for more details.
Example:
{
"linter": {
"enabled": true,
"rules": {
"js": {
"rules": {
"noDebugger": "off"
}
}
}
}
}
linter.rules.ts
A list of rules for TypeScript
category.
linter.rules.ts.recommended
Enables the recommended rules for the category TypeScript
.
linter.rules.ts.rules
A map with the name of the rule as key, and their configuration as value. Check rule configuration section. for more details.
Example:
{
"linter": {
"enabled": true,
"rules": {
"ts": {
"rules": {
"useShorthandArrayType": "off"
}
}
}
}
}
linter.rules.jsx
A list of rules for JSX
category.
linter.rules.jsx.recommended
Enables the recommended rules for the category JSX
.
linter.rules.jsx.rules
A map with the name of the rule as key, and their configuration as value. Check rule configuration section. for more details.
Example:
{
"linter": {
"enabled": true,
"rules": {
"jsx": {
"rules": {
"noCommentText": "off"
}
}
}
}
}
linter.rules.regex
A list of rules for Regex
category.
linter.rules.regex.recommended
Enables the recommended rules for the category Regex
.
linter.rules.regex.rules
A map with the name of the rule as key, and their configuration as value. Check rule configuration section. for more details.
Example:
{
"linter": {
"enabled": true,
"rules": {
"regex": {
"rules": {
"noMultipleSpacesInRegularExpressionLiterals": "off"
}
}
}
}
}
formatter.enabled
Enables Rome’s formatter
Default:
true
format.indentStyle
The style of the indentation. It can be "tab"
or "space"
.
Default:
tab
Rome’s default is "tab"
.
format.indentSize
How big the indentation should be.
format.lineWidth
How many characters can be written on a single line.
Default:
80
javascript.formatter.quoteStyle
The type of quote used when representing string literals. It can be single
or double
.
Default:
double
Configure a rule
A rule can be configured for multiple purposes:
- change the severity of their diagnostics;
- turn the rule off;
- pass possible options to customize the rule;
Turn a rule off
Just add "off"
as value inside its configuration. For example:
{
"linter": {
"enabled": true,
"rules": {
"jsx": {
"rules": {
"noCommentText": "off"
}
},
"regex": {
"rules": {
"noMultipleSpacesInRegularExpressionLiterals": "off"
}
}
}
}
}
Change severity of diagnostics
Most of Rome’s rules will emit an error, but you are free to change their severity. Just add "warn"
as value of the rule. Example:
{
"linter": {
"enabled": true,
"rules": {
"jsx": {
"rules": {
"noCommentText": "warn"
}
},
"regex": {
"rules": {
"noMultipleSpacesInRegularExpressionLiterals": "warn"
}
}
}
}
}
This is useful in cases there’s being a refactor going on and there’s need to make the CI passing.
Pass options to a rule
Not all the rules require options, but when they do accept some, you can pass them by shaping the value of the rule in a different way.
{
"linter": {
"enabled": true,
"rules": {
"jsx": {
"rules": {
"noCommentText": {
"level": "warn",
"options": {}
}
}
}
}
}
}
level
will indicate the severity of the diagnostic, valid values are:"off"
,"warn"
and"error"
;options
is a wildcard value, meaning that will change based on the rule;
Philosophy
This list includes general ethos the project should abide by. This list is not comprehensive. Some of these are obvious but are stated for completeness.
Project Management
- Set clear expectations. Make project intent and decisions known well in advance. Nothing should be a surprise.
- Clear messaging of decisions. The team might evaluate options and make decisions using private channels. While the team will try to keep discussions using public channels like GitHub Discussions or Discord, frequent private check-in are the norm, due to the nature of the private company. When decisions occur via private channels, the team has to commit to communicate these decisions using the public channels.
Technical
- Errors should suggest fixes and hints where possible. These should be inferred and filtered from usage to reduce surfacing irrelevant and unhelpful messages.
- Unique and specific error messages. No generic error messages. This not only helps users understand what went wrong, but should provide maintainers with a unique call site and the necessary information to debug.
- Optimise API. Question the existence of all options and flags. Are they necessary? Can they be combined? How can we reduce code branching?
- Reduce jargon. Don’t assume that users will understand specific terminology. Strive to provide clear meaning for experts and beginners. For example, use “character” where you would traditionally use “token” when producing parser errors.
- Utilize verbosity when naming commands and flags. No unnecessary and confusing abbreviations.
- Use inclusive terminology. Use gender-neutral pronouns. No ableist slurs. No usage of terms that could be considered insensitive.
- Build for generic clients. Don’t assume that output will only be consumed by a terminal and using ANSI codes. Use abstractions that could be generalized for viewing in an IDE, browser, or other environments.
- Terminal output should be unambiguous. When designing terminal output, don’t purely rely on formatting cues such as color. Always use a combination of formatting, symbols, and spacing. If all ANSI codes are stripped, all the output should still be understood.
Filename:Line:Columnpages/UserLoginPage.js:8:8 Categorylint/jsx-a11y/altText ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Message × Provide alt text when using img, area, input type='image', and object
elements.
Code Frame 6 │ return <span className="App">
7 │ <header className="App-header">
> 8 │ <img src={logo2} className="App-logo" />
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9 │ <p>
10 │ Edit <code>src/App.js</code> and save to reload.
Advice i Meaningful alternative text on elements helps users relying on screen
readers to understand content's purpose within a page.