refactor(v2): blog/docs: add more context in error messages (#4989)

* refactor(v2): blog/docs: add more context in error messages

* more error handling
This commit is contained in:
Sébastien Lorber 2021-06-16 20:16:55 +02:00 committed by GitHub
parent b54ec72389
commit 1b0acc5547
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 178 additions and 116 deletions

View file

@ -55,6 +55,19 @@ function toUrl({date, link}: DateLink) {
.replace(/-/g, '/')}/${link}`;
}
function formatBlogPostDate(locale: string, date: Date): string {
try {
return new Intl.DateTimeFormat(locale, {
day: 'numeric',
month: 'long',
year: 'numeric',
timeZone: 'UTC',
}).format(date);
} catch (e) {
throw new Error(`Can't format blog post date "${date}"`);
}
}
export async function generateBlogFeed(
contentPaths: BlogContentPaths,
context: LoadContext,
@ -131,123 +144,126 @@ export async function generateBlogPosts(
const blogPosts: BlogPost[] = [];
async function processBlogSourceFile(blogSourceFile: string) {
// Lookup in localized folder in priority
const blogDirPath = await getFolderContainingFile(
getContentPathList(contentPaths),
blogSourceFile,
);
const source = path.join(blogDirPath, blogSourceFile);
const {
frontMatter: unsafeFrontMatter,
content,
contentTitle,
excerpt,
} = await parseMarkdownFile(source, {removeContentTitle: true});
const frontMatter = validateBlogPostFrontMatter(unsafeFrontMatter);
const aliasedSource = aliasedSitePath(source, siteDir);
const blogFileName = path.basename(blogSourceFile);
if (frontMatter.draft && process.env.NODE_ENV === 'production') {
return;
}
if (frontMatter.id) {
console.warn(
chalk.yellow(
`"id" header option is deprecated in ${blogFileName} file. Please use "slug" option instead.`,
),
);
}
let date: Date | undefined;
// Extract date and title from filename.
const dateFilenameMatch = blogFileName.match(DATE_FILENAME_PATTERN);
let linkName = blogFileName.replace(/\.mdx?$/, '');
if (dateFilenameMatch) {
const [, dateString, name] = dateFilenameMatch;
// Always treat dates as UTC by adding the `Z`
date = new Date(`${dateString}Z`);
linkName = name;
}
// Prefer user-defined date.
if (frontMatter.date) {
date = frontMatter.date;
}
// Use file create time for blog.
date = date ?? (await fs.stat(source)).birthtime;
const formattedDate = formatBlogPostDate(i18n.currentLocale, date);
const title = frontMatter.title ?? contentTitle ?? linkName;
const description = frontMatter.description ?? excerpt ?? '';
const slug =
frontMatter.slug ||
(dateFilenameMatch ? toUrl({date, link: linkName}) : linkName);
const permalink = normalizeUrl([baseUrl, routeBasePath, slug]);
function getBlogEditUrl() {
const blogPathRelative = path.relative(blogDirPath, path.resolve(source));
if (typeof editUrl === 'function') {
return editUrl({
blogDirPath: posixPath(path.relative(siteDir, blogDirPath)),
blogPath: posixPath(blogPathRelative),
permalink,
locale: i18n.currentLocale,
});
} else if (typeof editUrl === 'string') {
const isLocalized = blogDirPath === contentPaths.contentPathLocalized;
const fileContentPath =
isLocalized && options.editLocalizedFiles
? contentPaths.contentPathLocalized
: contentPaths.contentPath;
const contentPathEditUrl = normalizeUrl([
editUrl,
posixPath(path.relative(siteDir, fileContentPath)),
]);
return getEditUrl(blogPathRelative, contentPathEditUrl);
} else {
return undefined;
}
}
blogPosts.push({
id: frontMatter.slug ?? title,
metadata: {
permalink,
editUrl: getBlogEditUrl(),
source: aliasedSource,
title,
description,
date,
formattedDate,
tags: frontMatter.tags ?? [],
readingTime: showReadingTime ? readingTime(content).minutes : undefined,
truncated: truncateMarker?.test(content) || false,
},
});
}
await Promise.all(
blogSourceFiles.map(async (blogSourceFile: string) => {
// Lookup in localized folder in priority
const blogDirPath = await getFolderContainingFile(
getContentPathList(contentPaths),
blogSourceFile,
);
const source = path.join(blogDirPath, blogSourceFile);
const {
frontMatter: unsafeFrontMatter,
content,
contentTitle,
excerpt,
} = await parseMarkdownFile(source, {removeContentTitle: true});
const frontMatter = validateBlogPostFrontMatter(unsafeFrontMatter);
const aliasedSource = aliasedSitePath(source, siteDir);
const blogFileName = path.basename(blogSourceFile);
if (frontMatter.draft && process.env.NODE_ENV === 'production') {
return;
}
if (frontMatter.id) {
console.warn(
chalk.yellow(
`"id" header option is deprecated in ${blogFileName} file. Please use "slug" option instead.`,
try {
return await processBlogSourceFile(blogSourceFile);
} catch (e) {
console.error(
chalk.red(
`Processing of blog source file failed for path "${blogSourceFile}"`,
),
);
throw e;
}
let date: Date | undefined;
// Extract date and title from filename.
const dateFilenameMatch = blogFileName.match(DATE_FILENAME_PATTERN);
let linkName = blogFileName.replace(/\.mdx?$/, '');
if (dateFilenameMatch) {
const [, dateString, name] = dateFilenameMatch;
// Always treat dates as UTC by adding the `Z`
date = new Date(`${dateString}Z`);
linkName = name;
}
// Prefer user-defined date.
if (frontMatter.date) {
date = frontMatter.date;
}
// Use file create time for blog.
date = date ?? (await fs.stat(source)).birthtime;
const formattedDate = new Intl.DateTimeFormat(i18n.currentLocale, {
day: 'numeric',
month: 'long',
year: 'numeric',
timeZone: 'UTC',
}).format(date);
const title = frontMatter.title ?? contentTitle ?? linkName;
const description = frontMatter.description ?? excerpt ?? '';
const slug =
frontMatter.slug ||
(dateFilenameMatch ? toUrl({date, link: linkName}) : linkName);
const permalink = normalizeUrl([baseUrl, routeBasePath, slug]);
function getBlogEditUrl() {
const blogPathRelative = path.relative(
blogDirPath,
path.resolve(source),
);
if (typeof editUrl === 'function') {
return editUrl({
blogDirPath: posixPath(path.relative(siteDir, blogDirPath)),
blogPath: posixPath(blogPathRelative),
permalink,
locale: i18n.currentLocale,
});
} else if (typeof editUrl === 'string') {
const isLocalized = blogDirPath === contentPaths.contentPathLocalized;
const fileContentPath =
isLocalized && options.editLocalizedFiles
? contentPaths.contentPathLocalized
: contentPaths.contentPath;
const contentPathEditUrl = normalizeUrl([
editUrl,
posixPath(path.relative(siteDir, fileContentPath)),
]);
return getEditUrl(blogPathRelative, contentPathEditUrl);
} else {
return undefined;
}
}
blogPosts.push({
id: frontMatter.slug ?? title,
metadata: {
permalink,
editUrl: getBlogEditUrl(),
source: aliasedSource,
title,
description,
date,
formattedDate,
tags: frontMatter.tags ?? [],
readingTime: showReadingTime
? readingTime(content).minutes
: undefined,
truncated: truncateMarker?.test(content) || false,
},
});
}),
);