Skip to content

Commit f91a7f3

Browse files
authored
fix(content): ensure underscore ignores only child paths of the content directory. (#6330)
* test: add test fixture * test: add cc config file * migrate to unit test instead * fix: only include child folders in ignore list * chore: changeset
1 parent 5e86b01 commit f91a7f3

File tree

3 files changed

+81
-54
lines changed

3 files changed

+81
-54
lines changed

.changeset/tiny-geckos-reply.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Ensure prefixed underscore ignores only child paths of the content directory.

packages/astro/src/content/utils.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,12 @@ export function getEntryInfo({
160160

161161
export function getEntryType(
162162
entryPath: string,
163-
paths: Pick<ContentPaths, 'config'>
163+
paths: Pick<ContentPaths, 'config' | 'contentDir'>
164164
): 'content' | 'config' | 'ignored' | 'unsupported' {
165165
const { ext, base } = path.parse(entryPath);
166166
const fileUrl = pathToFileURL(entryPath);
167167

168-
if (hasUnderscoreInPath(fileUrl) || isOnIgnoreList(base)) {
168+
if (hasUnderscoreBelowContentDirectoryPath(fileUrl, paths.contentDir) || isOnIgnoreList(base)) {
169169
return 'ignored';
170170
} else if ((contentFileExts as readonly string[]).includes(ext)) {
171171
return 'content';
@@ -180,8 +180,11 @@ function isOnIgnoreList(fileName: string) {
180180
return ['.DS_Store'].includes(fileName);
181181
}
182182

183-
function hasUnderscoreInPath(fileUrl: URL): boolean {
184-
const parts = fileUrl.pathname.split('/');
183+
function hasUnderscoreBelowContentDirectoryPath(
184+
fileUrl: URL,
185+
contentDir: ContentPaths['contentDir']
186+
): boolean {
187+
const parts = fileUrl.pathname.replace(contentDir.pathname, '').split('/');
185188
for (const part of parts) {
186189
if (part.startsWith('_')) return true;
187190
}

packages/astro/test/units/content-collections/get-entry-type.test.js

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,83 @@ import { getEntryType } from '../../../dist/content/utils.js';
22
import { expect } from 'chai';
33
import { fileURLToPath } from 'node:url';
44

5-
describe('Content Collections - getEntryType', () => {
6-
const contentDir = new URL('src/content/', import.meta.url);
7-
const contentPaths = {
8-
config: {
9-
url: new URL('src/content/config.ts', import.meta.url),
10-
exists: true,
5+
const fixtures = [
6+
{
7+
title: 'Without any underscore above the content directory tree',
8+
contentPaths: {
9+
config: {
10+
url: new URL('src/content/config.ts', import.meta.url),
11+
exists: true,
12+
},
13+
contentDir: new URL('src/content/', import.meta.url),
14+
},
15+
},
16+
{
17+
title: 'With underscore levels above the content directory tree',
18+
contentPaths: {
19+
config: {
20+
url: new URL('_src/content/config.ts', import.meta.url),
21+
exists: true,
22+
},
23+
contentDir: new URL('_src/content/', import.meta.url),
1124
},
12-
};
25+
},
26+
];
1327

14-
it('Returns "content" for Markdown files', () => {
15-
for (const entryPath of ['blog/first-post.md', 'blog/first-post.mdx']) {
16-
const entry = fileURLToPath(new URL(entryPath, contentDir));
17-
const type = getEntryType(entry, contentPaths);
18-
expect(type).to.equal('content');
19-
}
20-
});
28+
describe('Content Collections - getEntryType', () => {
29+
fixtures.forEach(({ title, contentPaths }) => {
30+
describe(title, () => {
31+
it('Returns "content" for Markdown files', () => {
32+
for (const entryPath of ['blog/first-post.md', 'blog/first-post.mdx']) {
33+
const entry = fileURLToPath(new URL(entryPath, contentPaths.contentDir));
34+
const type = getEntryType(entry, contentPaths);
35+
expect(type).to.equal('content');
36+
}
37+
});
2138

22-
it('Returns "content" for Markdown files in nested directories', () => {
23-
for (const entryPath of ['blog/2021/01/01/index.md', 'blog/2021/01/01/index.mdx']) {
24-
const entry = fileURLToPath(new URL(entryPath, contentDir));
25-
const type = getEntryType(entry, contentPaths);
26-
expect(type).to.equal('content');
27-
}
28-
});
39+
it('Returns "content" for Markdown files in nested directories', () => {
40+
for (const entryPath of ['blog/2021/01/01/index.md', 'blog/2021/01/01/index.mdx']) {
41+
const entry = fileURLToPath(new URL(entryPath, contentPaths.contentDir));
42+
const type = getEntryType(entry, contentPaths);
43+
expect(type).to.equal('content');
44+
}
45+
});
2946

30-
it('Returns "config" for config files', () => {
31-
const entry = fileURLToPath(contentPaths.config.url);
32-
const type = getEntryType(entry, contentPaths);
33-
expect(type).to.equal('config');
34-
});
47+
it('Returns "config" for config files', () => {
48+
const entry = fileURLToPath(contentPaths.config.url);
49+
const type = getEntryType(entry, contentPaths);
50+
expect(type).to.equal('config');
51+
});
3552

36-
it('Returns "unsupported" for non-Markdown files', () => {
37-
const entry = fileURLToPath(new URL('blog/robots.txt', contentDir));
38-
const type = getEntryType(entry, contentPaths);
39-
expect(type).to.equal('unsupported');
40-
});
53+
it('Returns "unsupported" for non-Markdown files', () => {
54+
const entry = fileURLToPath(new URL('blog/robots.txt', contentPaths.contentDir));
55+
const type = getEntryType(entry, contentPaths);
56+
expect(type).to.equal('unsupported');
57+
});
4158

42-
it('Returns "ignored" for .DS_Store', () => {
43-
const entry = fileURLToPath(new URL('blog/.DS_Store', contentDir));
44-
const type = getEntryType(entry, contentPaths);
45-
expect(type).to.equal('ignored');
46-
});
59+
it('Returns "ignored" for .DS_Store', () => {
60+
const entry = fileURLToPath(new URL('blog/.DS_Store', contentPaths.contentDir));
61+
const type = getEntryType(entry, contentPaths);
62+
expect(type).to.equal('ignored');
63+
});
4764

48-
it('Returns "ignored" for unsupported files using an underscore', () => {
49-
const entry = fileURLToPath(new URL('blog/_draft-robots.txt', contentDir));
50-
const type = getEntryType(entry, contentPaths);
51-
expect(type).to.equal('ignored');
52-
});
65+
it('Returns "ignored" for unsupported files using an underscore', () => {
66+
const entry = fileURLToPath(new URL('blog/_draft-robots.txt', contentPaths.contentDir));
67+
const type = getEntryType(entry, contentPaths);
68+
expect(type).to.equal('ignored');
69+
});
5370

54-
it('Returns "ignored" when using underscore on file name', () => {
55-
const entry = fileURLToPath(new URL('blog/_first-post.md', contentDir));
56-
const type = getEntryType(entry, contentPaths);
57-
expect(type).to.equal('ignored');
58-
});
71+
it('Returns "ignored" when using underscore on file name', () => {
72+
const entry = fileURLToPath(new URL('blog/_first-post.md', contentPaths.contentDir));
73+
const type = getEntryType(entry, contentPaths);
74+
expect(type).to.equal('ignored');
75+
});
5976

60-
it('Returns "ignored" when using underscore on directory name', () => {
61-
const entry = fileURLToPath(new URL('blog/_draft/first-post.md', contentDir));
62-
const type = getEntryType(entry, contentPaths);
63-
expect(type).to.equal('ignored');
77+
it('Returns "ignored" when using underscore on directory name', () => {
78+
const entry = fileURLToPath(new URL('blog/_draft/first-post.md', contentPaths.contentDir));
79+
const type = getEntryType(entry, contentPaths);
80+
expect(type).to.equal('ignored');
81+
});
82+
});
6483
});
6584
});

0 commit comments

Comments
 (0)