diff --git a/.agents/skills/migrate-to-rstack-cli/references/prettier.md b/.agents/skills/migrate-to-rstack-cli/references/prettier.md index ace4303..8303012 100644 --- a/.agents/skills/migrate-to-rstack-cli/references/prettier.md +++ b/.agents/skills/migrate-to-rstack-cli/references/prettier.md @@ -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. diff --git a/packages/rstack/src/fmt/discovery.ts b/packages/rstack/src/fmt/discovery.ts index 591560f..122e21c 100644 --- a/packages/rstack/src/fmt/discovery.ts +++ b/packages/rstack/src/fmt/discovery.ts @@ -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)); diff --git a/packages/rstack/src/fmt/ignore.ts b/packages/rstack/src/fmt/ignore.ts index 09b33bc..41f80bf 100644 --- a/packages/rstack/src/fmt/ignore.ts +++ b/packages/rstack/src/fmt/ignore.ts @@ -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)); }; diff --git a/packages/rstack/tests/fmt/ignore.test.ts b/packages/rstack/tests/fmt/ignore.test.ts index 0bfc14b..63501dd 100644 --- a/packages/rstack/tests/fmt/ignore.test.ts +++ b/packages/rstack/tests/fmt/ignore.test.ts @@ -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', () => { @@ -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); diff --git a/rstack.config.ts b/rstack.config.ts index 0753840..f451cc2 100644 --- a/rstack.config.ts +++ b/rstack.config.ts @@ -40,7 +40,6 @@ define.lint(async () => { }); define.fmt({ - ignorePatterns: ['**/dist/**', 'pnpm-lock.yaml'], printWidth: 100, singleQuote: true, sortPackageJson: true, diff --git a/website/docs/en/guide/formatting.mdx b/website/docs/en/guide/formatting.mdx index 130f858..3ed9eb6 100644 --- a/website/docs/en/guide/formatting.mdx +++ b/website/docs/en/guide/formatting.mdx @@ -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): diff --git a/website/docs/zh/guide/formatting.mdx b/website/docs/zh/guide/formatting.mdx index 53bc43c..4ba9925 100644 --- a/website/docs/zh/guide/formatting.mdx +++ b/website/docs/zh/guide/formatting.mdx @@ -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` 中的字段排序: