Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(content): ensure underscore ignores only child paths of the content directory. #6330

Merged
merged 6 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tiny-geckos-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Ensure prefixed underscore ignores only child paths of the content directory.
11 changes: 7 additions & 4 deletions packages/astro/src/content/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,12 @@ export function getEntryInfo({

export function getEntryType(
entryPath: string,
paths: Pick<ContentPaths, 'config'>
paths: Pick<ContentPaths, 'config' | 'contentDir'>
): 'content' | 'config' | 'ignored' | 'unsupported' {
const { ext, base } = path.parse(entryPath);
const fileUrl = pathToFileURL(entryPath);

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

function hasUnderscoreInPath(fileUrl: URL): boolean {
const parts = fileUrl.pathname.split('/');
function hasUnderscoreBelowContentDirectoryPath(
fileUrl: URL,
contentDir: ContentPaths['contentDir']
): boolean {
const parts = fileUrl.pathname.replace(contentDir.pathname, '').split('/');
for (const part of parts) {
if (part.startsWith('_')) return true;
}
Expand Down
119 changes: 69 additions & 50 deletions packages/astro/test/units/content-collections/get-entry-type.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,83 @@ import { getEntryType } from '../../../dist/content/utils.js';
import { expect } from 'chai';
import { fileURLToPath } from 'node:url';

describe('Content Collections - getEntryType', () => {
const contentDir = new URL('src/content/', import.meta.url);
const contentPaths = {
config: {
url: new URL('src/content/config.ts', import.meta.url),
exists: true,
const fixtures = [
{
title: 'Without any underscore above the content directory tree',
contentPaths: {
config: {
url: new URL('src/content/config.ts', import.meta.url),
exists: true,
},
contentDir: new URL('src/content/', import.meta.url),
},
},
{
title: 'With underscore levels above the content directory tree',
contentPaths: {
config: {
url: new URL('_src/content/config.ts', import.meta.url),
exists: true,
},
contentDir: new URL('_src/content/', import.meta.url),
},
};
},
];

it('Returns "content" for Markdown files', () => {
for (const entryPath of ['blog/first-post.md', 'blog/first-post.mdx']) {
const entry = fileURLToPath(new URL(entryPath, contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('content');
}
});
describe('Content Collections - getEntryType', () => {
fixtures.forEach(({ title, contentPaths }) => {
describe(title, () => {
it('Returns "content" for Markdown files', () => {
for (const entryPath of ['blog/first-post.md', 'blog/first-post.mdx']) {
const entry = fileURLToPath(new URL(entryPath, contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('content');
}
});

it('Returns "content" for Markdown files in nested directories', () => {
for (const entryPath of ['blog/2021/01/01/index.md', 'blog/2021/01/01/index.mdx']) {
const entry = fileURLToPath(new URL(entryPath, contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('content');
}
});
it('Returns "content" for Markdown files in nested directories', () => {
for (const entryPath of ['blog/2021/01/01/index.md', 'blog/2021/01/01/index.mdx']) {
const entry = fileURLToPath(new URL(entryPath, contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('content');
}
});

it('Returns "config" for config files', () => {
const entry = fileURLToPath(contentPaths.config.url);
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('config');
});
it('Returns "config" for config files', () => {
const entry = fileURLToPath(contentPaths.config.url);
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('config');
});

it('Returns "unsupported" for non-Markdown files', () => {
const entry = fileURLToPath(new URL('blog/robots.txt', contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('unsupported');
});
it('Returns "unsupported" for non-Markdown files', () => {
const entry = fileURLToPath(new URL('blog/robots.txt', contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('unsupported');
});

it('Returns "ignored" for .DS_Store', () => {
const entry = fileURLToPath(new URL('blog/.DS_Store', contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});
it('Returns "ignored" for .DS_Store', () => {
const entry = fileURLToPath(new URL('blog/.DS_Store', contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});

it('Returns "ignored" for unsupported files using an underscore', () => {
const entry = fileURLToPath(new URL('blog/_draft-robots.txt', contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});
it('Returns "ignored" for unsupported files using an underscore', () => {
const entry = fileURLToPath(new URL('blog/_draft-robots.txt', contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});

it('Returns "ignored" when using underscore on file name', () => {
const entry = fileURLToPath(new URL('blog/_first-post.md', contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});
it('Returns "ignored" when using underscore on file name', () => {
const entry = fileURLToPath(new URL('blog/_first-post.md', contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});

it('Returns "ignored" when using underscore on directory name', () => {
const entry = fileURLToPath(new URL('blog/_draft/first-post.md', contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
it('Returns "ignored" when using underscore on directory name', () => {
const entry = fileURLToPath(new URL('blog/_draft/first-post.md', contentPaths.contentDir));
const type = getEntryType(entry, contentPaths);
expect(type).to.equal('ignored');
});
});
});
});