Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/prettier.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Read this reference when the project uses the `prettier` CLI or API, `package.js
7. Delete old config and ignore files only after their behavior is represented in `define.fmt`.
8. Remove direct dependencies only when no script, config, API call, plugin peer requirement, or other tool still needs them.

`rs fmt` ignores `package-lock.json` and `pnpm-lock.yaml` by default. Drop redundant ignore entries during migration, but keep intentional negations.

`rs fmt` does not read Prettier configuration files, `.prettierignore`, or `.editorconfig`.

Keep `.editorconfig` when editors or other tools use it. Keep Prettier when application code uses APIs such as `prettier.format()`; `rs fmt` is not a drop-in replacement for the programmatic API.
Expand Down
6 changes: 2 additions & 4 deletions packages/rstack/src/fmt/discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@ const discoverFmtFiles = async ({
return [];
}

const isFmtIgnored = config.ignorePatterns.length ? createFmtIgnoreMatcher(config) : undefined;
const filePaths = isFmtIgnored
? candidates.filter((filePath) => !isFmtIgnored(filePath))
: candidates;
const isFmtIgnored = createFmtIgnoreMatcher(config);
const filePaths = candidates.filter((filePath) => !isFmtIgnored(filePath));
const resolvePlugins = createFmtPluginResolver(config.rootPath);

return filePaths.map((filePath) => createFileRequest(filePath, config, resolvePlugins));
Expand Down
12 changes: 10 additions & 2 deletions packages/rstack/src/fmt/ignore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import { relative } from 'node:path';
import fastIgnore from 'fast-ignore';
import type { ResolvedFmtConfig } from './types.ts';

/** Creates a reusable matcher for config-level ignore patterns. */
/**
* Common lock files that Prettier can format but `rs fmt` leaves to package managers.
*
* Prettier already skips other generated lock files when it cannot infer a parser, so this list
* contains only the additional defaults owned by `rs fmt`.
*/
const defaultIgnorePatterns = ['package-lock.json', 'pnpm-lock.yaml'];

/** Creates a reusable matcher for default and config-level ignore patterns. */
const createFmtIgnoreMatcher = (config: ResolvedFmtConfig): ((filePath: string) => boolean) => {
const matches = fastIgnore(config.ignorePatterns.join('\n'));
const matches = fastIgnore([...defaultIgnorePatterns, ...config.ignorePatterns].join('\n'));

return (filePath) => matches(relative(config.rootPath, filePath));
};
Expand Down
15 changes: 12 additions & 3 deletions packages/rstack/tests/fmt/ignore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,22 @@ test('matches gitignore patterns relative to the config root', () => {
test('applies negated patterns in declaration order', () => {
const isIgnored = createMatcher(['*.js', '!src/keep.js']);
const isIgnoredAgain = createMatcher(['*.js', '!src/keep.js', 'src/keep.js']);
const isReincluded = createMatcher(['dist', '!dist']);
const isIgnoredAfterReinclude = createMatcher(['dist', '!dist']);
const filePath = path.join(rootPath, 'src/keep.js');

expect(isIgnored(filePath)).toBe(false);
expect(isIgnored(path.join(rootPath, 'src/drop.js'))).toBe(true);
expect(isIgnoredAgain(filePath)).toBe(true);
expect(isReincluded(path.join(rootPath, 'dist'))).toBe(false);
expect(isIgnoredAfterReinclude(path.join(rootPath, 'dist'))).toBe(false);
});

test('ignores common lock files by default and allows explicit negation', () => {
const isIgnored = createMatcher([]);
const isIgnoredAfterReinclude = createMatcher(['!pnpm-lock.yaml']);

expect(isIgnored(path.join(rootPath, 'package-lock.json'))).toBe(true);
expect(isIgnored(path.join(rootPath, 'packages/app/pnpm-lock.yaml'))).toBe(true);
expect(isIgnoredAfterReinclude(path.join(rootPath, 'pnpm-lock.yaml'))).toBe(false);
});

test('does not let explicit files bypass ignore patterns', () => {
Expand All @@ -45,7 +54,7 @@ test('matches parent directory patterns without validation', () => {
expect(isIgnored(path.join(rootPath, 'shared/index.js'))).toBe(false);
});

test('does not ignore files when no patterns are configured', () => {
test('does not ignore other files when no patterns are configured', () => {
const isIgnored = createMatcher([]);

expect(isIgnored(path.join(rootPath, 'src/index.js'))).toBe(false);
Expand Down
1 change: 0 additions & 1 deletion rstack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ define.lint(async () => {
});

define.fmt({
ignorePatterns: ['**/dist/**', 'pnpm-lock.yaml'],
printWidth: 100,
singleQuote: true,
sortPackageJson: true,
Expand Down
14 changes: 14 additions & 0 deletions website/docs/en/guide/formatting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ define.fmt({

Patterns follow Gitignore syntax and are resolved relative to the directory containing the Rstack configuration file. Because they are applied after the files are selected, they also exclude files passed explicitly on the command line.

### Lock files

By default, `rs fmt` ignores common lock files, including `package-lock.json` and `pnpm-lock.yaml`.

To format these files, use a negated pattern to explicitly include them:

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
ignorePatterns: ['!pnpm-lock.yaml'],
});
```

## Sort package.json fields \{#sort-package-json}

Enable `sortPackageJson` to sort fields in each selected `package.json` with [`sort-package-json`](https://github.com/keithamus/sort-package-json):
Expand Down
14 changes: 14 additions & 0 deletions website/docs/zh/guide/formatting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ define.fmt({

这些模式遵循 Gitignore 语法,并且基于 Rstack 配置文件所在的目录解析。由于规则会在确定格式化范围后生效,因此也会排除命令行中显式传入的文件。

### Lock 文件 \{#lock-files}

`rs fmt` 默认忽略常见的 lock 文件,包括 `package-lock.json` 和 `pnpm-lock.yaml`。

如果你需要格式化这些文件,可以使用否定模式主动包含它们:

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
ignorePatterns: ['!pnpm-lock.yaml'],
});
```

## 排序 package.json 字段 \{#sort-package-json}

启用 `sortPackageJson` 后,`rs fmt` 会使用 [`sort-package-json`](https://github.com/keithamus/sort-package-json) 对每个待格式化的 `package.json` 中的字段排序:
Expand Down