refactor, create getLocalizedSource()

This commit is contained in:
sebastienlorber 2024-01-04 20:08:49 +01:00
parent ecf6888840
commit e9b20ca990
5 changed files with 107 additions and 51 deletions

View file

@ -26,6 +26,8 @@ import {
getContentPathList,
isUnlisted,
isDraft,
filterFilesWithLocaleExtension,
getLocalizedSource,
} from '@docusaurus/utils';
import {validateBlogPostFrontMatter} from './frontMatter';
import {type AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors';
@ -208,13 +210,19 @@ async function parseBlogPostMarkdownFile({
const defaultReadingTime: ReadingTimeFunction = ({content, options}) =>
readingTime(content, options).minutes;
async function processBlogSourceFile(
blogSourceRelative: string,
contentPaths: BlogContentPaths,
context: LoadContext,
options: PluginOptions,
authorsMap?: AuthorsMap,
): Promise<BlogPost | undefined> {
async function processBlogSourceFile({
blogSourceRelative,
contentPaths,
context,
options,
authorsMap,
}: {
blogSourceRelative: string;
contentPaths: BlogContentPaths;
context: LoadContext;
options: PluginOptions;
authorsMap?: AuthorsMap;
}): Promise<BlogPost | undefined> {
const {
siteConfig: {
baseUrl,
@ -231,21 +239,30 @@ async function processBlogSourceFile(
editUrl,
} = options;
// TODO remove this in favor of getLocalizedSource
// Lookup in localized folder in priority
const blogDirPath = await getFolderContainingFile(
getContentPathList(contentPaths),
blogSourceRelative,
);
const blogSourceAbsolute = path.join(blogDirPath, blogSourceRelative);
const {
source: blogSource,
// contentPath: blogDirPath
} = await getLocalizedSource({
relativeSource: blogSourceRelative,
contentPaths,
locale: context.i18n.currentLocale,
});
const {frontMatter, content, contentTitle, excerpt} =
await parseBlogPostMarkdownFile({
filePath: blogSourceAbsolute,
filePath: blogSource,
parseFrontMatter,
});
const aliasedSource = aliasedSitePath(blogSourceAbsolute, siteDir);
const aliasedSource = aliasedSitePath(blogSource, siteDir);
const draft = isDraft({frontMatter});
const unlisted = isUnlisted({frontMatter});
@ -274,14 +291,14 @@ async function processBlogSourceFile(
}
try {
const result = getFileCommitDate(blogSourceAbsolute, {
const result = getFileCommitDate(blogSource, {
age: 'oldest',
includeAuthor: false,
});
return result.date;
} catch (err) {
logger.warn(err);
return (await fs.stat(blogSourceAbsolute)).birthtime;
return (await fs.stat(blogSource)).birthtime;
}
}
@ -302,7 +319,7 @@ async function processBlogSourceFile(
function getBlogEditUrl() {
const blogPathRelative = path.relative(
blogDirPath,
path.resolve(blogSourceAbsolute),
path.resolve(blogSource),
);
if (typeof editUrl === 'function') {
@ -374,28 +391,36 @@ export async function generateBlogPosts(
return [];
}
const blogSourceFiles = await Globby(include, {
cwd: contentPaths.contentPath,
ignore: exclude,
});
async function getBlogSourceFiles() {
const files = await Globby(include, {
cwd: contentPaths.contentPath,
ignore: exclude,
});
return filterFilesWithLocaleExtension({
files,
locales: context.i18n.locales,
});
}
const blogSourceFiles = await getBlogSourceFiles();
const authorsMap = await getAuthorsMap({
contentPaths,
authorsMapPath: options.authorsMapPath,
});
async function doProcessBlogSourceFile(blogSourceFile: string) {
async function doProcessBlogSourceFile(blogSourceRelative: string) {
try {
return await processBlogSourceFile(
blogSourceFile,
return await processBlogSourceFile({
blogSourceRelative,
contentPaths,
context,
options,
authorsMap,
);
});
} catch (err) {
throw new Error(
`Processing of blog source file path=${blogSourceFile} failed.`,
`Processing of blog source file path=${blogSourceRelative} failed.`,
{cause: err as Error},
);
}

View file

@ -72,6 +72,7 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
* preserved as-is. Default values will be applied when generating metadata
*/
export type BlogPostFrontMatter = {
// TODO Docusaurus v4: remove
/**
* @deprecated Use `slug` instead.
*/

View file

@ -21,7 +21,7 @@ import {
parseMarkdownFile,
isUnlisted,
isDraft,
getLocalizedSourcePath,
getLocalizedSource,
filterFilesWithLocaleExtension,
} from '@docusaurus/utils';
import {validatePageFrontMatter} from './frontMatter';
@ -95,7 +95,7 @@ export default function pluginContentPages(
async function processPageSourceFile(
relativeSource: string,
): Promise<Metadata | undefined> {
const source = await getLocalizedSourcePath({
const {source} = await getLocalizedSource({
relativeSource,
contentPaths,
locale: context.i18n.currentLocale,

View file

@ -127,13 +127,13 @@ function addLocaleExtension(filePath: string, locale: string) {
return path.join(dir, `${name}.${locale}${ext}`);
}
/**
* Returns the first existing localized path of a content file
* @param relativeSource
* @param contentPaths
* @param locale
*/
export async function getLocalizedSourcePath({
type LocalizedSource = {
contentPath: string;
source: string;
type: 'locale-extension' | 'locale-folder' | 'original';
};
function getLocalizedSourceCandidates({
relativeSource,
contentPaths,
locale,
@ -141,38 +141,68 @@ export async function getLocalizedSourcePath({
relativeSource: string;
contentPaths: ContentPaths;
locale: string;
}): Promise<string> {
}): LocalizedSource[] {
// docs/myDoc.fr.md
const localeExtensionSource = path.join(
contentPaths.contentPath,
addLocaleExtension(relativeSource, locale),
);
const localeExtensionSource: LocalizedSource = {
contentPath: contentPaths.contentPath,
source: path.join(
contentPaths.contentPath,
addLocaleExtension(relativeSource, locale),
),
type: 'locale-extension',
};
// i18n/fr/docs/current/myDoc.md
const i18nFolderSource = path.join(
contentPaths.contentPathLocalized,
relativeSource,
);
const i18nFolderSource: LocalizedSource = {
contentPath: contentPaths.contentPath,
source: path.join(contentPaths.contentPathLocalized, relativeSource),
type: 'locale-folder',
};
// docs/myDoc.md
const originalSource = path.join(contentPaths.contentPath, relativeSource);
const originalSource: LocalizedSource = {
contentPath: contentPaths.contentPath,
source: path.join(contentPaths.contentPath, relativeSource),
type: 'original',
};
// Order matters
const possibleSources = [
localeExtensionSource,
i18nFolderSource,
originalSource,
];
return [localeExtensionSource, i18nFolderSource, originalSource];
}
/**
* Returns the first existing localized path of a content file
* @param relativeSource
* @param contentPaths
* @param locale
*/
export async function getLocalizedSource({
relativeSource,
contentPaths,
locale,
}: {
relativeSource: string;
contentPaths: ContentPaths;
locale: string;
}): Promise<LocalizedSource> {
// docs/myDoc.fr.md
const candidates = getLocalizedSourceCandidates({
relativeSource,
contentPaths,
locale,
});
// TODO can we avoid/optimize this by passing all the files we know as param?
const localizedSource = await findAsyncSequential(
possibleSources,
fs.pathExists,
const localizedSource = await findAsyncSequential(candidates, (candidate) =>
fs.pathExists(candidate.source),
);
if (!localizedSource) {
throw new Error(
`Unexpected error, couldn't find any existing file at ${originalSource}`,
`Unexpected error, couldn't find any localized source for file at ${path.join(
contentPaths.contentPath,
relativeSource,
)}`,
);
}

View file

@ -34,7 +34,7 @@ export {
updateTranslationFileMessages,
getPluginI18nPath,
localizePath,
getLocalizedSourcePath,
getLocalizedSource,
filterFilesWithLocaleExtension,
} from './i18nUtils';
export {