mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 07:37:19 +02:00
feat(blog): authors page (#10216)
Co-authored-by: OzakIOne <OzakIOne@users.noreply.github.com> Co-authored-by: sebastien <lorber.sebastien@gmail.com> Co-authored-by: slorber <slorber@users.noreply.github.com>
This commit is contained in:
parent
50f9fce29b
commit
f356e29938
56 changed files with 1670 additions and 706 deletions
|
@ -1 +0,0 @@
|
|||
{"a": 2}
|
|
@ -1 +0,0 @@
|
|||
a: 2
|
|
@ -1 +0,0 @@
|
|||
{"a": 1}
|
|
@ -1 +0,0 @@
|
|||
a: 1
|
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/dataFile.json
generated
Normal file
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/dataFile.json
generated
Normal file
|
@ -0,0 +1 @@
|
|||
{"content": "json"}
|
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/dataFile.yml
generated
Normal file
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/dataFile.yml
generated
Normal file
|
@ -0,0 +1 @@
|
|||
content: original yaml
|
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/invalid.yml
generated
Normal file
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/invalid.yml
generated
Normal file
|
@ -0,0 +1 @@
|
|||
}{{{{12434665¨£%£%%£%£}}}}
|
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/localized/dataFile.yml
generated
Normal file
1
packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/localized/dataFile.yml
generated
Normal file
|
@ -0,0 +1 @@
|
|||
content: localized yaml
|
|
@ -10,7 +10,7 @@ import {
|
|||
findFolderContainingFile,
|
||||
getFolderContainingFile,
|
||||
getDataFilePath,
|
||||
getDataFileData,
|
||||
readDataFile,
|
||||
} from '../dataFileUtils';
|
||||
|
||||
describe('getDataFilePath', () => {
|
||||
|
@ -125,46 +125,40 @@ describe('getDataFilePath', () => {
|
|||
});
|
||||
|
||||
describe('getDataFileData', () => {
|
||||
const fixturesDir = path.join(__dirname, '__fixtures__/dataFiles/actualData');
|
||||
function readDataFile(filePath: string) {
|
||||
return getDataFileData(
|
||||
{
|
||||
filePath,
|
||||
contentPaths: {contentPath: fixturesDir, contentPathLocalized: ''},
|
||||
fileType: 'test',
|
||||
},
|
||||
(content) => {
|
||||
// @ts-expect-error: good enough
|
||||
if (content.a !== 1) {
|
||||
throw new Error('Nope');
|
||||
}
|
||||
return content;
|
||||
},
|
||||
function testFile(filePath: string) {
|
||||
const contentPath = path.join(
|
||||
__dirname,
|
||||
'__fixtures__/dataFiles/dataFiles',
|
||||
);
|
||||
const contentPathLocalized = path.join(contentPath, 'localized');
|
||||
return readDataFile({
|
||||
filePath,
|
||||
contentPaths: {contentPath, contentPathLocalized},
|
||||
});
|
||||
}
|
||||
|
||||
it('returns undefined for nonexistent file', async () => {
|
||||
await expect(readDataFile('nonexistent.yml')).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('read valid yml author file', async () => {
|
||||
await expect(readDataFile('valid.yml')).resolves.toEqual({a: 1});
|
||||
await expect(testFile('nonexistent.yml')).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('read valid json author file', async () => {
|
||||
await expect(readDataFile('valid.json')).resolves.toEqual({a: 1});
|
||||
await expect(testFile('dataFile.json')).resolves.toEqual({
|
||||
content: 'json',
|
||||
});
|
||||
});
|
||||
|
||||
it('fail to read invalid yml', async () => {
|
||||
await expect(
|
||||
readDataFile('bad.yml'),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Nope"`);
|
||||
it('read valid yml author file using localized source in priority', async () => {
|
||||
await expect(testFile('dataFile.yml')).resolves.toEqual({
|
||||
content: 'localized yaml',
|
||||
});
|
||||
});
|
||||
|
||||
it('fail to read invalid json', async () => {
|
||||
it('throw for invalid file', async () => {
|
||||
await expect(
|
||||
readDataFile('bad.json'),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Nope"`);
|
||||
testFile('invalid.yml'),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"The file at "packages/docusaurus-utils/src/__tests__/__fixtures__/dataFiles/dataFiles/invalid.yml" looks invalid (not Yaml nor JSON)."`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -43,31 +43,28 @@ export async function getDataFilePath({
|
|||
}
|
||||
|
||||
/**
|
||||
* Looks up for a data file in the content paths, returns the object validated
|
||||
* and normalized according to the `validate` callback.
|
||||
* Looks up for a data file in the content paths
|
||||
* Favors the localized content path over the base content path
|
||||
* Currently supports Yaml and JSON data files
|
||||
* It is the caller responsibility to validate and normalize the resulting data
|
||||
*
|
||||
* @returns `undefined` when file not found
|
||||
* @throws Throws when validation fails, displaying a helpful context message.
|
||||
* @throws Throws when data file can't be parsed
|
||||
*/
|
||||
export async function getDataFileData<T>(
|
||||
params: DataFileParams & {
|
||||
/** Used for the "The X file looks invalid" message. */
|
||||
fileType: string;
|
||||
},
|
||||
validate: (content: unknown) => T,
|
||||
): Promise<T | undefined> {
|
||||
export async function readDataFile(params: DataFileParams): Promise<unknown> {
|
||||
const filePath = await getDataFilePath(params);
|
||||
if (!filePath) {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
const contentString = await fs.readFile(filePath, {encoding: 'utf8'});
|
||||
const unsafeContent = Yaml.load(contentString);
|
||||
// TODO we shouldn't validate here: it makes validation harder to test
|
||||
return validate(unsafeContent);
|
||||
return Yaml.load(contentString);
|
||||
} catch (err) {
|
||||
logger.error`The ${params.fileType} file at path=${filePath} looks invalid.`;
|
||||
throw err;
|
||||
const msg = logger.interpolate`The file at path=${path.relative(
|
||||
process.cwd(),
|
||||
filePath,
|
||||
)} looks invalid (not Yaml nor JSON).`;
|
||||
throw new Error(msg, {cause: err as Error});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ export {escapeShellArg} from './shellUtils';
|
|||
export {loadFreshModule} from './moduleUtils';
|
||||
export {
|
||||
getDataFilePath,
|
||||
getDataFileData,
|
||||
readDataFile,
|
||||
getContentPathList,
|
||||
findFolderContainingFile,
|
||||
getFolderContainingFile,
|
||||
|
|
|
@ -45,6 +45,7 @@ export type TagsListItem = Tag & {
|
|||
/** What the tag's own page should know about the tag. */
|
||||
export type TagModule = TagsListItem & {
|
||||
/** The tags list page's permalink. */
|
||||
// TODO move this global value to a shared docs/blog bundle
|
||||
allTagsPath: string;
|
||||
/** Is this tag unlisted? (when it only contains unlisted items) */
|
||||
unlisted: boolean;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue