diff --git a/script/__snapshots__/migrate-test-e2e.ts.snap b/script/__snapshots__/migrate-test-e2e.ts.snap index 6d87dfbb0..156d5ff46 100644 --- a/script/__snapshots__/migrate-test-e2e.ts.snap +++ b/script/__snapshots__/migrate-test-e2e.ts.snap @@ -115,6 +115,14 @@ exports[`expected file changes > .prettierignore 1`] = ` exports[`expected file changes > README.md 1`] = ` "--- a/README.md +++ b/README.md +@@ ... @@ +

Create TypeScript App

+ +-

Quickstart-friendly TypeScript template with comprehensive, configurable, opinionated tooling. ❤️‍🔥

++

A very lovely package. Hooray!

+ +

+ @@ ... @@ Thanks! 💖 @@ -225,6 +233,15 @@ exports[`expected file changes > knip.json 1`] = ` exports[`expected file changes > package.json 1`] = ` "--- a/package.json +++ b/package.json +@@ ... @@ + { + "name": "create-typescript-app", + "version": "1.78.0", +- "description": "Quickstart-friendly TypeScript template with comprehensive, configurable, opinionated tooling. ❤️‍🔥", ++ "description": "A very lovely package. Hooray!", + "repository": { + "type": "git", + "url": "https://github.com/JoshuaKGoldberg/create-typescript-app" @@ ... @@ "lint-staged": "15.2.11", "markdownlint": "0.37.2", diff --git a/src/next/base.ts b/src/next/base.ts index a1d7750f1..b212851ad 100644 --- a/src/next/base.ts +++ b/src/next/base.ts @@ -17,6 +17,7 @@ import { readGuide } from "../shared/options/createOptionDefaults/readGuide.js"; import { readPackageData } from "../shared/packages.js"; import { tryCatchLazyValueAsync } from "../shared/tryCatchLazyValueAsync.js"; import { AllContributorsData } from "../shared/types.js"; +import { readDescription } from "./readDescription.js"; import { readDocumentation } from "./readDocumentation.js"; import { swallowError } from "./utils/swallowError.js"; @@ -193,7 +194,7 @@ export const base = createBase({ author, bin: async () => (await packageData()).bin, contributors: allContributors, - description: async () => (await packageData()).description, + description: async () => await readDescription(packageData), documentation, email: async () => readEmails(npmDefaults, packageAuthor), funding: readFunding, diff --git a/src/next/blocks/packageData.ts b/src/next/blocks/packageData.ts index ed6bfc23a..a72bf3adc 100644 --- a/src/next/blocks/packageData.ts +++ b/src/next/blocks/packageData.ts @@ -1,10 +1,4 @@ -import { createRequire } from "node:module"; - -const require = createRequire(import.meta.url); - -const packageData = - // Importing from above src/ would expand the TS build rootDir - require("../../../package.json") as typeof import("../../../package.json"); +import { sourcePackageJson } from "./sourcePackageJson.js"; export function getPackageDependencies(...names: string[]) { return Object.fromEntries( @@ -32,7 +26,7 @@ function getPackageInner( key: "dependencies" | "devDependencies", name: string, ) { - const inner = packageData[key]; + const inner = sourcePackageJson[key]; return inner[name as keyof typeof inner] as string | undefined; } diff --git a/src/next/blocks/sourcePackageJson.ts b/src/next/blocks/sourcePackageJson.ts new file mode 100644 index 000000000..75867f05d --- /dev/null +++ b/src/next/blocks/sourcePackageJson.ts @@ -0,0 +1,7 @@ +import { createRequire } from "node:module"; + +const require = createRequire(import.meta.url); + +export const sourcePackageJson = + // Importing from above src/ would expand the TS build rootDir + require("../../../package.json") as typeof import("../../../package.json"); diff --git a/src/next/readDescription.test.ts b/src/next/readDescription.test.ts new file mode 100644 index 000000000..7d98e765c --- /dev/null +++ b/src/next/readDescription.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it, vi } from "vitest"; + +import { readDescription } from "./readDescription.js"; + +const mockSourcePackageJsonDescription = vi.fn<() => string>(); + +vi.mock("./blocks/sourcePackageJson", () => ({ + sourcePackageJson: { + get description() { + return mockSourcePackageJsonDescription(); + }, + }, +})); + +describe("finalize", () => { + it("returns undefined when the description matches the current package.json description", async () => { + const existing = "Same description."; + + mockSourcePackageJsonDescription.mockReturnValueOnce(existing); + + const documentation = await readDescription(() => + Promise.resolve({ + description: existing, + }), + ); + + expect(documentation).toBeUndefined(); + }); + + it("filters known headings when .github/DEVELOPMENT.md exists", async () => { + const updated = "Updated description."; + + mockSourcePackageJsonDescription.mockReturnValueOnce( + "Existing description", + ); + + const documentation = await readDescription(() => + Promise.resolve({ + description: updated, + }), + ); + + expect(documentation).toBe(updated); + }); +}); diff --git a/src/next/readDescription.ts b/src/next/readDescription.ts new file mode 100644 index 000000000..f5a307e29 --- /dev/null +++ b/src/next/readDescription.ts @@ -0,0 +1,11 @@ +import { PartialPackageData } from "../shared/types.js"; +import { sourcePackageJson } from "./blocks/sourcePackageJson.js"; + +export async function readDescription( + getPackageData: () => Promise, +) { + const { description: inferred } = await getPackageData(); + const { description: existing } = sourcePackageJson; + + return existing === inferred ? undefined : inferred; +} diff --git a/src/shared/options/createOptionDefaults/index.ts b/src/shared/options/createOptionDefaults/index.ts index 369c0d864..48a46fd81 100644 --- a/src/shared/options/createOptionDefaults/index.ts +++ b/src/shared/options/createOptionDefaults/index.ts @@ -5,6 +5,7 @@ import lazyValue from "lazy-value"; import * as fs from "node:fs/promises"; import npmUser from "npm-user"; +import { readDescription } from "../../../next/readDescription.js"; import { readPackageData } from "../../packages.js"; import { tryCatchAsync } from "../../tryCatchAsync.js"; import { tryCatchLazyValueAsync } from "../../tryCatchLazyValueAsync.js"; @@ -33,7 +34,7 @@ export function createOptionDefaults(promptedOptions?: PromptedOptions) { author: async () => (await packageAuthor()).author ?? (await npmDefaults())?.name, bin: async () => (await packageData()).bin, - description: async () => (await packageData()).description, + description: async () => await readDescription(packageData), email: async () => readEmails(npmDefaults, packageAuthor), funding: async () => await tryCatchAsync(async () =>