Skip to content

Commit 9c84a66

Browse files
fix: allow multiline comments in blockESLint (#2101)
## PR Checklist - [x] Addresses an existing open issue: fixes #2095 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/main/.github/CONTRIBUTING.md) were taken ## Overview 🎁
1 parent 3a5ea09 commit 9c84a66

File tree

2 files changed

+153
-1
lines changed

2 files changed

+153
-1
lines changed

src/blocks/blockESLint.test.ts

+148
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,154 @@ describe("blockESLint", () => {
449449
`);
450450
});
451451

452+
test("with multiline addon rules comment", () => {
453+
const creation = testBlock(blockESLint, {
454+
addons: {
455+
rules: [
456+
{
457+
comment: "One line",
458+
entries: { a: "error" },
459+
},
460+
{
461+
comment: "Two lines\ntwo lines",
462+
entries: { a: "error" },
463+
},
464+
{
465+
comment: "Three lines\nthree lines\nthree lines",
466+
entries: { a: "error" },
467+
},
468+
],
469+
},
470+
options: optionsBase,
471+
});
472+
473+
expect(creation).toMatchInlineSnapshot(`
474+
{
475+
"addons": [
476+
{
477+
"addons": {
478+
"sections": {
479+
"Linting": {
480+
"contents": {
481+
"after": [
482+
"
483+
For example, ESLint can be run with \`--fix\` to auto-fix some lint rule complaints:
484+
485+
\`\`\`shell
486+
pnpm run lint --fix
487+
\`\`\`
488+
",
489+
],
490+
"before": "
491+
This package includes several forms of linting to enforce consistent code quality and styling.
492+
Each should be shown in VS Code, and can be run manually on the command-line:
493+
",
494+
"items": [
495+
"- \`pnpm lint\` ([ESLint](https://eslint.org) with [typescript-eslint](https://typescript-eslint.io)): Lints JavaScript and TypeScript source files",
496+
],
497+
"plural": "Read the individual documentation for each linter to understand how it can be configured and used best.",
498+
},
499+
},
500+
},
501+
},
502+
"block": [Function],
503+
},
504+
{
505+
"addons": {
506+
"jobs": [
507+
{
508+
"name": "Lint",
509+
"steps": [
510+
{
511+
"run": "pnpm lint",
512+
},
513+
],
514+
},
515+
],
516+
},
517+
"block": [Function],
518+
},
519+
{
520+
"addons": {
521+
"properties": {
522+
"devDependencies": {
523+
"@eslint/js": "9.22.0",
524+
"@types/node": "22.13.10",
525+
"eslint": "9.22.0",
526+
"typescript-eslint": "8.26.1",
527+
},
528+
"scripts": {
529+
"lint": "eslint . --max-warnings 0",
530+
},
531+
},
532+
},
533+
"block": [Function],
534+
},
535+
{
536+
"addons": {
537+
"extensions": [
538+
"dbaeumer.vscode-eslint",
539+
],
540+
"settings": {
541+
"editor.codeActionsOnSave": {
542+
"source.fixAll.eslint": "explicit",
543+
},
544+
"eslint.probe": [
545+
"javascript",
546+
"javascriptreact",
547+
"json",
548+
"jsonc",
549+
"markdown",
550+
"typescript",
551+
"typescriptreact",
552+
"yaml",
553+
],
554+
"eslint.rules.customizations": [
555+
{
556+
"rule": "*",
557+
"severity": "warn",
558+
},
559+
],
560+
},
561+
},
562+
"block": [Function],
563+
},
564+
],
565+
"files": {
566+
"eslint.config.js": "import eslint from "@eslint/js";
567+
import tseslint from "typescript-eslint";
568+
569+
export default tseslint.config(
570+
{ ignores: ["lib", "node_modules", "pnpm-lock.yaml"] },
571+
{ linterOptions: {"reportUnusedDisableDirectives":"error"} },
572+
eslint.configs.recommended,
573+
{ extends: [tseslint.configs.strictTypeChecked, tseslint.configs.stylisticTypeChecked], files: ["**/*.js", "**/*.ts"], languageOptions: {"parserOptions":{"projectService":{"allowDefaultProject":["*.config.*s"]},"tsconfigRootDir":import.meta.dirname}}, rules: {
574+
575+
// One line
576+
"a": "error",
577+
578+
// Two lines
579+
// two lines
580+
"a": "error",
581+
582+
// Three lines
583+
// three lines
584+
// three lines
585+
"a": "error",}, }
586+
);",
587+
},
588+
"scripts": [
589+
{
590+
"commands": [
591+
"pnpm lint --fix",
592+
],
593+
"phase": 3,
594+
},
595+
],
596+
}
597+
`);
598+
});
599+
452600
test("with object options.bin", () => {
453601
const creation = testBlock(blockESLint, {
454602
options: {

src/blocks/blockESLint.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ function printExtensionRules(rules: z.infer<typeof zExtensionRules>) {
279279
return [
280280
"{",
281281
...rules.flatMap((group) => [
282-
group.comment ? `\n\n// ${group.comment}\n` : "",
282+
printGroupComment(group.comment),
283283
...Object.entries(group.entries).map(
284284
([ruleName, options]) => `"${ruleName}": ${JSON.stringify(options)},`,
285285
),
@@ -288,6 +288,10 @@ function printExtensionRules(rules: z.infer<typeof zExtensionRules>) {
288288
].join("");
289289
}
290290

291+
function printGroupComment(comment: string | undefined) {
292+
return comment ? `\n\n// ${comment.replaceAll("\n", "\n// ")}\n` : "";
293+
}
294+
291295
function processForSort(line: string) {
292296
if (line.startsWith("...") || /\w+/.test(line[0])) {
293297
return `A\n${line.replaceAll(/\W+/g, "")}`;

0 commit comments

Comments
 (0)