Repository: JoshuaKGoldberg/create-typescript-app (ts)

Issue:
🚀 Feature: Add `ignores` Addon for `blockMarkdownlint`
### Feature Request Checklist

- [x] I have pulled the latest `main` branch of the repository.
- [x] I have [searched for related issues](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aissue) and found none that matched my issue.

### Overview

Coming over from https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/pull/993#discussion_r2034081595: running `npx create-typescript-app` shouldn't remove any custom user entries in the `.markdownlintignore`.

### Additional Info

🎁 

Pull request:
feat: add ignores Addon for blockMarkdownlint
## PR Checklist

- [x] Addresses an existing open issue: fixes #2191
- [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

🎁

Patch:
diff --git a/src/blocks/blockContributorCovenant.ts b/src/blocks/blockContributorCovenant.ts
index 7ffa0dd..c830f5c 100644
--- a/src/blocks/blockContributorCovenant.ts
+++ b/src/blocks/blockContributorCovenant.ts
@@ -1,4 +1,5 @@
 import { base } from "../base.js";
+import { blockMarkdownlint } from "./blockMarkdownlint.js";
 import { blockREADME } from "./blockREADME.js";
 import { blockRemoveFiles } from "./blockRemoveFiles.js";
 
@@ -9,6 +10,9 @@ export const blockContributorCovenant = base.createBlock({
 	produce({ options }) {
 		return {
 			addons: [
+				blockMarkdownlint({
+					ignores: [".github/CODE_OF_CONDUCT.md"],
+				}),
 				blockREADME({
 					badges: [
 						{
diff --git a/src/blocks/blockMarkdownlint.ts b/src/blocks/blockMarkdownlint.ts
index fecf93d..5b58fd7 100644
--- a/src/blocks/blockMarkdownlint.ts
+++ b/src/blocks/blockMarkdownlint.ts
@@ -8,6 +8,7 @@ import { blockPackageJson } from "./blockPackageJson.js";
 import { blockRemoveWorkflows } from "./blockRemoveWorkflows.js";
 import { blockVSCode } from "./blockVSCode.js";
 import { formatIgnoreFile } from "./files/formatIgnoreFile.js";
+import { intakeFile } from "./intake/intakeFile.js";
 import { CommandPhase } from "./phases.js";
 
 export const blockMarkdownlint = base.createBlock({
@@ -17,6 +18,17 @@ export const blockMarkdownlint = base.createBlock({
 	addons: {
 		ignores: z.array(z.string()).default([]),
 	},
+	intake({ files }) {
+		const markdownlintignoreRaw = intakeFile(files, [".markdownlintignore"]);
+
+		if (!markdownlintignoreRaw) {
+			return undefined;
+		}
+
+		return {
+			ignores: markdownlintignoreRaw[0].split("\n").filter(Boolean),
+		};
+	},
 	produce({ addons }) {
 		const { ignores } = addons;
 
@@ -65,12 +77,7 @@ export const blockMarkdownlint = base.createBlock({
 					"no-inline-html": false,
 				}),
 				".markdownlintignore": formatIgnoreFile(
-					[
-						".github/CODE_OF_CONDUCT.md",
-						"CHANGELOG.md",
-						"node_modules/",
-						...ignores,
-					].sort(),
+					Array.from(new Set(["node_modules/", ...ignores])).sort(),
 				),
 			},
 			scripts: [
diff --git a/src/blocks/blockReleaseIt.ts b/src/blocks/blockReleaseIt.ts
index 0cf5f6d..c7685dd 100644
--- a/src/blocks/blockReleaseIt.ts
+++ b/src/blocks/blockReleaseIt.ts
@@ -3,6 +3,7 @@ import { z } from "zod";
 import { base } from "../base.js";
 import { getPackageDependencies } from "../data/packageData.js";
 import { resolveUses } from "./actions/resolveUses.js";
+import { blockMarkdownlint } from "./blockMarkdownlint.js";
 import { blockPackageJson } from "./blockPackageJson.js";
 import { blockREADME } from "./blockREADME.js";
 import { blockRepositorySecrets } from "./blockRepositorySecrets.js";
@@ -27,6 +28,9 @@ export const blockReleaseIt = base.createBlock({
 
 		return {
 			addons: [
+				blockMarkdownlint({
+					ignores: ["CHANGELOG.md"],
+				}),
 				blockPackageJson({
 					properties: {
 						devDependencies: getPackageDependencies(


Test patch:
diff --git a/src/blocks/blockCSpell.test.ts b/src/blocks/blockCSpell.test.ts
index cc28b55..cfb5fee 100644
--- a/src/blocks/blockCSpell.test.ts
+++ b/src/blocks/blockCSpell.test.ts
@@ -394,7 +394,7 @@ describe("blockCSpell", () => {
 			expect(actual).toBeUndefined();
 		});
 
-		it("returns compilerOptions when cspell.json contains ignorePaths and words", () => {
+		it("returns the data when cspell.json contains ignorePaths and words", () => {
 			const data = {
 				ignorePaths: ["other"],
 				words: ["abc", "def"],
diff --git a/src/blocks/blockContributorCovenant.test.ts b/src/blocks/blockContributorCovenant.test.ts
index eec073e..6e65dd9 100644
--- a/src/blocks/blockContributorCovenant.test.ts
+++ b/src/blocks/blockContributorCovenant.test.ts
@@ -13,6 +13,14 @@ describe("blockContributorCovenant", () => {
 		expect(creation).toMatchInlineSnapshot(`
 			{
 			  "addons": [
+			    {
+			      "addons": {
+			        "ignores": [
+			          ".github/CODE_OF_CONDUCT.md",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "badges": [
@@ -176,6 +184,14 @@ describe("blockContributorCovenant", () => {
 		expect(creation).toMatchInlineSnapshot(`
 			{
 			  "addons": [
+			    {
+			      "addons": {
+			        "ignores": [
+			          ".github/CODE_OF_CONDUCT.md",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "badges": [
diff --git a/src/blocks/blockMarkdownlint.test.ts b/src/blocks/blockMarkdownlint.test.ts
index c511291..3caabcf 100644
--- a/src/blocks/blockMarkdownlint.test.ts
+++ b/src/blocks/blockMarkdownlint.test.ts
@@ -1,5 +1,5 @@
-import { testBlock } from "bingo-stratum-testers";
-import { describe, expect, test } from "vitest";
+import { testBlock, testIntake } from "bingo-stratum-testers";
+import { describe, expect, it, test } from "vitest";
 
 import { blockMarkdownlint } from "./blockMarkdownlint.js";
 import { optionsBase } from "./options.fakes.js";
@@ -68,9 +68,7 @@ describe("blockMarkdownlint", () => {
 			  ],
 			  "files": {
 			    ".markdownlint.json": "{"extends":"markdownlint/style/prettier","first-line-h1":false,"no-inline-html":false}",
-			    ".markdownlintignore": ".github/CODE_OF_CONDUCT.md
-			CHANGELOG.md
-			node_modules/
+			    ".markdownlintignore": "node_modules/
 			",
 			  },
 			  "scripts": [
@@ -151,9 +149,7 @@ describe("blockMarkdownlint", () => {
 			  ],
 			  "files": {
 			    ".markdownlint.json": "{"extends":"markdownlint/style/prettier","first-line-h1":false,"no-inline-html":false}",
-			    ".markdownlintignore": ".github/CODE_OF_CONDUCT.md
-			CHANGELOG.md
-			lib/
+			    ".markdownlintignore": "lib/
 			node_modules/
 			",
 			  },
@@ -244,9 +240,7 @@ describe("blockMarkdownlint", () => {
 			  ],
 			  "files": {
 			    ".markdownlint.json": "{"extends":"markdownlint/style/prettier","first-line-h1":false,"no-inline-html":false}",
-			    ".markdownlintignore": ".github/CODE_OF_CONDUCT.md
-			CHANGELOG.md
-			node_modules/
+			    ".markdownlintignore": "node_modules/
 			",
 			  },
 			  "scripts": [
@@ -260,4 +254,36 @@ describe("blockMarkdownlint", () => {
 			}
 		`);
 	});
+
+	describe("intake", () => {
+		it("returns undefined when .markdownlintignore does not exist", () => {
+			const actual = testIntake(blockMarkdownlint, {
+				files: {},
+			});
+
+			expect(actual).toBeUndefined();
+		});
+
+		it("returns no ignores when .markdownlintignore does not contain truthy lines", () => {
+			const actual = testIntake(blockMarkdownlint, {
+				files: {
+					".markdownlintignore": ["\n"],
+				},
+			});
+
+			expect(actual).toEqual({ ignores: [] });
+		});
+
+		it("returns ignores when .markdownlintignore contains lines", () => {
+			const ignores = ["abc", "def"];
+
+			const actual = testIntake(blockMarkdownlint, {
+				files: {
+					".markdownlintignore": [ignores.join("\n") + "\n"],
+				},
+			});
+
+			expect(actual).toEqual({ ignores });
+		});
+	});
 });
diff --git a/src/blocks/blockReleaseIt.test.ts b/src/blocks/blockReleaseIt.test.ts
index b23bb2e..c520570 100644
--- a/src/blocks/blockReleaseIt.test.ts
+++ b/src/blocks/blockReleaseIt.test.ts
@@ -11,6 +11,14 @@ describe("blockReleaseIt", () => {
 		expect(creation).toMatchInlineSnapshot(`
 			{
 			  "addons": [
+			    {
+			      "addons": {
+			        "ignores": [
+			          "CHANGELOG.md",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "properties": {
@@ -159,6 +167,14 @@ describe("blockReleaseIt", () => {
 		expect(creation).toMatchInlineSnapshot(`
 			{
 			  "addons": [
+			    {
+			      "addons": {
+			        "ignores": [
+			          "CHANGELOG.md",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "properties": {