From 86b0d0e599f8940689eb552a8493c04ced298e19 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 24 Oct 2025 18:12:37 +0200 Subject: [PATCH] wire VSC api to blog creation date logic --- .../src/__tests__/feed.test.ts | 18 +++++++++-- .../src/blogUtils.ts | 14 +++------ packages/docusaurus-utils/src/vcsUtils.ts | 30 +++++++++++++++---- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index 7241282e1d..b4f26041b3 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -8,7 +8,10 @@ import {jest} from '@jest/globals'; import path from 'path'; import fs from 'fs-extra'; -import {DEFAULT_PARSE_FRONT_MATTER} from '@docusaurus/utils'; +import { + DEFAULT_PARSE_FRONT_MATTER, + DEFAULT_VCS_CONFIG, +} from '@docusaurus/utils'; import {fromPartial} from '@total-typescript/shoehorn'; import {normalizePluginOptions} from '@docusaurus/utils-validation'; import tree from 'tree-node-cli'; @@ -51,7 +54,7 @@ function getBlogContentPaths(siteDir: string): BlogContentPaths { } async function testGenerateFeeds( - context: LoadContext, + contextInput: LoadContext, optionsInput: Options, ): Promise { const options = validateOptions({ @@ -62,6 +65,17 @@ async function testGenerateFeeds( options: optionsInput, }); + const context: LoadContext = { + ...contextInput, + siteConfig: { + ...contextInput.siteConfig, + future: { + ...contextInput.siteConfig?.future, + experimental_vcs: DEFAULT_VCS_CONFIG, + }, + }, + }; + const contentPaths = getBlogContentPaths(context.siteDir); const authorsMap = await getAuthorsMap({ contentPaths, diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 3647a34550..e6951f8e20 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -19,7 +19,6 @@ import { Globby, groupTaggedItems, getTagVisibility, - getFileCommitDate, getContentPathList, isUnlisted, isDraft, @@ -225,6 +224,7 @@ async function processBlogSourceFile( siteConfig: { baseUrl, markdown: {parseFrontMatter}, + future: {experimental_vcs: vcs}, }, siteDir, i18n, @@ -285,17 +285,11 @@ async function processBlogSourceFile( return parsedBlogFileName.date; } - try { - const result = await getFileCommitDate(blogSourceAbsolute, { - age: 'oldest', - includeAuthor: false, - }); - - return result.date; - } catch (err) { - logger.warn(err); + const result = await vcs.getFileCreationInfo(blogSourceAbsolute); + if (result == null) { return (await fs.stat(blogSourceAbsolute)).birthtime; } + return new Date(result.timestamp); } const date = await getDate(); diff --git a/packages/docusaurus-utils/src/vcsUtils.ts b/packages/docusaurus-utils/src/vcsUtils.ts index 640163da1b..7802d8944c 100644 --- a/packages/docusaurus-utils/src/vcsUtils.ts +++ b/packages/docusaurus-utils/src/vcsUtils.ts @@ -5,16 +5,36 @@ * LICENSE file in the root directory of this source tree. */ -import {getFileCommitDate} from './gitUtils'; +import { + FileNotTrackedError, + getFileCommitDate, + GitNotFoundError, +} from './gitUtils'; import {getLastUpdate} from './lastUpdateUtils'; import type {VcsConfig} from '@docusaurus/types'; export const DEFAULT_VCS_CONFIG: VcsConfig = { getFileCreationInfo: async (filePath: string) => { - return getFileCommitDate(filePath, { - age: 'oldest', - includeAuthor: true, - }); + try { + return await getFileCommitDate(filePath, { + age: 'oldest', + includeAuthor: true, + }); + } catch (error) { + // TODO Docusaurus v4: remove this logic using exceptions for control flow + // We add this logic to make it similar to getLastUpdate() that also + // returns null in these case and does not throw + if (error instanceof GitNotFoundError) { + return null; + } else if (error instanceof FileNotTrackedError) { + return null; + } else { + throw new Error( + `An error occurred when trying to get the last update date`, + {cause: error}, + ); + } + } }, getFileLastUpdateInfo: async (filePath: string) => { // TODO non-ideal integration but good enough for now