Skip to content

Commit 79cd25f

Browse files
fix: correct README.md parsing without an existing Usage h2 (#2143)
## PR Checklist - [x] Addresses an existing open issue: fixes #2140 - [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 https://github.com/JoshuaKGoldberg/prune-github-notifications didn't have a `## Usage` in its README.md, and instead of allowing all content until the next relevant h2 or end-of-file, the option was defaulting to `undefined`. This reminds me that `blockREADME` hardcodes a `## Usage` in there - that's not an assumption I want to keep. But removing that assumption can be a followup. 🎁
1 parent aabe4e8 commit 79cd25f

File tree

2 files changed

+76
-20
lines changed

2 files changed

+76
-20
lines changed

src/options/readReadmeExplainer.test.ts

+63-7
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ describe(readReadmeExplainer, () => {
3737
This is my project.
3838
3939
## Usage
40-
.`),
40+
41+
...`),
4142
);
4243

4344
expect(actual).toEqual("This is my project.");
@@ -52,7 +53,8 @@ This is my project.
5253
It is good.
5354
5455
## Usage
55-
.`),
56+
57+
...`),
5658
);
5759

5860
expect(actual).toEqual("This is my project.\nIt is good.");
@@ -80,7 +82,8 @@ This is my project.
8082
It is good.
8183
8284
## Usage
83-
.`),
85+
86+
...`),
8487
);
8588

8689
expect(actual).toEqual("This is my project.\nIt is good.");
@@ -108,7 +111,8 @@ This is my project.
108111
It is good.
109112
110113
## Usage
111-
.`),
114+
115+
...`),
112116
);
113117

114118
expect(actual).toEqual("## What?\n\nThis is my project.\nIt is good.");
@@ -129,7 +133,8 @@ It is good.
129133
> See here.
130134
131135
## Usage
132-
.`),
136+
137+
...`),
133138
);
134139

135140
expect(actual).toEqual(
@@ -152,7 +157,8 @@ This is my project.
152157
It is good.
153158
154159
## Usage
155-
.`),
160+
161+
...`),
156162
);
157163

158164
expect(actual).toEqual("## What?\n\nThis is my project.\nIt is good.");
@@ -175,7 +181,57 @@ It is good.
175181
> See here.
176182
177183
## Usage
178-
.`),
184+
185+
...`),
186+
);
187+
188+
expect(actual).toEqual(
189+
"## What?\n\nThis is my project.\nIt is good.\n\n> See here.",
190+
);
191+
});
192+
193+
it("returns existing content before a non-Usage h2 when the Usage h2 does not exist", async () => {
194+
const actual = await readReadmeExplainer(() =>
195+
Promise.resolve(`
196+
<a href="http://npmjs.com/package/create-typescript-app"><img alt="📦 npm version" src="https://img.shields.io/npm/v/create-typescript-app?color=21bb42&label=%F0%9F%93%A6%20npm" /></a>
197+
<img alt="💪 TypeScript: Strict" src="https://img.shields.io/badge/%F0%9F%92%AA_typescript-strict-21bb42.svg" />
198+
</p>
199+
200+
<img align="right" alt="Project logo: the TypeScript blue square with rounded corners, but a plus sign instead of 'TS'" height="128" src="./docs/create-typescript-app.png" width="128">
201+
202+
## What?
203+
204+
This is my project.
205+
It is good.
206+
207+
> See here.
208+
209+
## Contributing
210+
211+
...`),
212+
);
213+
214+
expect(actual).toEqual(
215+
"## What?\n\nThis is my project.\nIt is good.\n\n> See here.",
216+
);
217+
});
218+
219+
it("returns existing content until the end of the file when no subsequent h2 exists", async () => {
220+
const actual = await readReadmeExplainer(() =>
221+
Promise.resolve(`
222+
<a href="http://npmjs.com/package/create-typescript-app"><img alt="📦 npm version" src="https://img.shields.io/npm/v/create-typescript-app?color=21bb42&label=%F0%9F%93%A6%20npm" /></a>
223+
<img alt="💪 TypeScript: Strict" src="https://img.shields.io/badge/%F0%9F%92%AA_typescript-strict-21bb42.svg" />
224+
</p>
225+
226+
<img align="right" alt="Project logo: the TypeScript blue square with rounded corners, but a plus sign instead of 'TS'" height="128" src="./docs/create-typescript-app.png" width="128">
227+
228+
## What?
229+
230+
This is my project.
231+
It is good.
232+
233+
> See here.
234+
`),
179235
);
180236

181237
expect(actual).toEqual(

src/options/readReadmeExplainer.ts

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1+
const lastTagMatchers = [`">`, "/p>", "/>"];
2+
13
export async function readReadmeExplainer(getReadme: () => Promise<string>) {
24
const readme = await getReadme();
35

4-
const indexOfUsageH2 = /## Usage/.exec(readme)?.index ?? readme.indexOf("##");
5-
if (indexOfUsageH2 === -1) {
6-
return undefined;
7-
}
8-
9-
const beforeUsageH2 = readme.slice(0, indexOfUsageH2);
10-
11-
const [indexOfLastTag, lastTagMatcher] = lastLastIndexOf(beforeUsageH2, [
12-
`">`,
13-
"/p>",
14-
"/>",
15-
]);
6+
const indexOfFirstH2 = readme.indexOf("##");
7+
const indexOfUsageH2 = /## Usage/.exec(readme)?.index;
8+
const beforeH2s = readme.slice(0, indexOfUsageH2 ?? indexOfFirstH2);
9+
const [indexOfLastTag, lastTagMatcher] = lastLastIndexOf(
10+
beforeH2s,
11+
lastTagMatchers,
12+
);
1613
if (!lastTagMatcher) {
1714
return undefined;
1815
}
1916

17+
const endingIndex =
18+
indexOfUsageH2 ?? /## (?:Contrib|Develop)/.exec(readme)?.index;
19+
2020
return readme
21-
.slice(indexOfLastTag + lastTagMatcher.length, indexOfUsageH2)
21+
.slice(indexOfLastTag + lastTagMatcher.length, endingIndex)
2222
.trim();
2323
}
2424

0 commit comments

Comments
 (0)