diff --git a/scripts/build-docs.test.ts b/scripts/build-docs.test.ts index 4a467410c4..3d390b61a0 100644 --- a/scripts/build-docs.test.ts +++ b/scripts/build-docs.test.ts @@ -164,6 +164,7 @@ const baseConfig = { wrapDefault: true, collapseDefault: false, hideTitleDefault: false, + deprecatedDefault: false, }, flags: { skipGit: true, @@ -459,6 +460,7 @@ title: Simple Test wrapDefault: false, collapseDefault: false, hideTitleDefault: false, + deprecatedDefault: false, }, }), ) @@ -4346,3 +4348,159 @@ describe('API Errors Generation', () => { expect(fapi).toContain('Status Code: 400') }) }) + +describe('File deprecation', () => { + test('Should include the deprecation frontmatter in the dist file', async () => { + const { tempDir, readFile } = await createTempFiles([ + { + path: './docs/manifest.json', + content: JSON.stringify({ + navigation: [[{ title: 'API Doc', href: '/docs/api-doc' }]], + }), + }, + { + path: './docs/api-doc.mdx', + content: `--- +title: API Documentation +description: Generated API docs +deprecated: true +--- + +# API Documentation`, + }, + ]) + + await build( + await createConfig({ + ...baseConfig, + basePath: tempDir, + validSdks: ['react'], + }), + ) + + expect(await readFile('dist/api-doc.mdx')).toContain(`--- +title: API Documentation +description: Generated API docs +deprecated: true +--- + +# API Documentation`) + }) + + test('Should include the deprecation field in the manifest', async () => { + const { tempDir, readFile } = await createTempFiles([ + { + path: './docs/manifest.json', + content: JSON.stringify({ + navigation: [[{ title: 'API Doc', href: '/docs/api-doc' }]], + }), + }, + { + path: './docs/api-doc.mdx', + content: `--- +title: API Documentation +description: Generated API docs +deprecated: true +--- + +# API Documentation`, + }, + ]) + + await build( + await createConfig({ + ...baseConfig, + basePath: tempDir, + validSdks: ['react'], + }), + ) + + expect(JSON.parse(await readFile('dist/manifest.json'))).toEqual({ + navigation: [ + [ + { + href: '/docs/api-doc', + title: 'API Doc', + deprecated: true, + }, + ], + ], + }) + }) + + test('Should include the deprecation field in the group above', async () => { + const { tempDir, readFile } = await createTempFiles([ + { + path: './docs/manifest.json', + content: JSON.stringify({ + navigation: [ + [ + { + title: 'API', + items: [ + [ + { title: 'API Doc', href: '/docs/api-doc' }, + { title: 'API Doc 2', href: '/docs/api-doc-2' }, + ], + ], + }, + ], + ], + }), + }, + { + path: './docs/api-doc.mdx', + content: `--- +title: API Documentation +description: Generated API docs +deprecated: true +--- + +# API Documentation`, + }, + { + path: './docs/api-doc-2.mdx', + content: `--- +title: API Documentation 2 +description: Generated API docs 2 +deprecated: true +--- + +# API Documentation 2`, + }, + ]) + + await build( + await createConfig({ + ...baseConfig, + basePath: tempDir, + validSdks: ['react'], + }), + ) + + expect(JSON.parse(await readFile('dist/manifest.json'))).toEqual({ + navigation: [ + [ + { + title: 'API', + deprecated: true, + items: [ + [ + { + title: 'API Doc', + href: '/docs/api-doc', + deprecated: true, + }, + { + title: 'API Doc 2', + href: '/docs/api-doc-2', + deprecated: true, + }, + ], + ], + }, + ], + ], + }) + }) +}) diff --git a/scripts/build-docs.ts b/scripts/build-docs.ts index 6fe23dba18..ceb49c3a02 100644 --- a/scripts/build-docs.ts +++ b/scripts/build-docs.ts @@ -143,6 +143,7 @@ async function main() { wrapDefault: true, collapseDefault: false, hideTitleDefault: false, + deprecatedDefault: false, }, flags: { watch: args.includes('--watch'), @@ -261,7 +262,7 @@ export async function build(config: BuildConfig, store: Store = createBlankStore // Goes through and grabs the sdk scoping out of the manifest const sdkScopedManifestFirstPass = await traverseTree( - { items: userManifest, sdk: undefined as undefined | SDK[] }, + { items: userManifest, sdk: undefined as undefined | SDK[], deprecated: undefined as undefined | true }, async (item, tree) => { if (!item.href?.startsWith(config.baseDocsLink)) { return { @@ -305,6 +306,7 @@ export async function build(config: BuildConfig, store: Store = createBlankStore return { ...item, sdk, + deprecated: doc.frontmatter.deprecated, } }, async ({ items, ...details }, tree) => { @@ -350,7 +352,11 @@ export async function build(config: BuildConfig, store: Store = createBlankStore ) const sdkScopedManifest = await traverseTreeItemsFirst( - { items: sdkScopedManifestFirstPass, sdk: undefined as undefined | SDK[] }, + { + items: sdkScopedManifestFirstPass, + sdk: undefined as undefined | SDK[], + deprecated: undefined as undefined | true, + }, async (item, tree) => item, async ({ items, ...details }, tree) => { // This takes all the children items, grabs the sdks out of them, and combines that in to a list @@ -363,6 +369,8 @@ export async function build(config: BuildConfig, store: Store = createBlankStore return uniqueSDKs })() + const deprecated = items?.every((item) => item.every((item) => item.deprecated)) + // This is the sdk of the group const groupSDK = details.sdk @@ -371,12 +379,12 @@ export async function build(config: BuildConfig, store: Store = createBlankStore // If there are no children items, then we either use the group we are looking at sdks if its defined, or its parent group if (groupsItemsCombinedSDKs.length === 0) { - return { ...details, sdk: groupSDK ?? parentSDK, items } as ManifestGroup + return { ...details, sdk: groupSDK ?? parentSDK, items, deprecated } as ManifestGroup } // If all the children items have the same sdk as the group, then we don't need to set the sdk on the group if (groupsItemsCombinedSDKs.length === config.validSdks.length) { - return { ...details, sdk: undefined, items } as ManifestGroup + return { ...details, sdk: undefined, items, deprecated } as ManifestGroup } if (groupSDK !== undefined && groupSDK.length > 0) { @@ -384,6 +392,7 @@ export async function build(config: BuildConfig, store: Store = createBlankStore ...details, sdk: groupSDK, items, + deprecated, } as ManifestGroup } @@ -394,6 +403,7 @@ export async function build(config: BuildConfig, store: Store = createBlankStore // If there are children items, then we combine the sdks of the group and the children items sdks sdk: combinedSDKs, items, + deprecated, } as ManifestGroup }, (item, error) => { @@ -505,6 +515,7 @@ export async function build(config: BuildConfig, store: Store = createBlankStore icon: item.icon, target: item.target, sdk: item.sdk, + deprecated: item.deprecated === config.manifestOptions.deprecatedDefault ? undefined : item.deprecated, }), // @ts-expect-error - This traverseTree function might just be the death of me async (group) => ({ @@ -516,6 +527,7 @@ export async function build(config: BuildConfig, store: Store = createBlankStore hideTitle: group.hideTitle === config.manifestOptions.hideTitleDefault ? undefined : group.hideTitle, sdk: group.sdk, items: group.items, + deprecated: group.deprecated === config.manifestOptions.deprecatedDefault ? undefined : group.deprecated, }), ), }), diff --git a/scripts/lib/config.ts b/scripts/lib/config.ts index 82d458929e..559d7300fa 100644 --- a/scripts/lib/config.ts +++ b/scripts/lib/config.ts @@ -27,6 +27,7 @@ type BuildConfigOptions = { wrapDefault: boolean collapseDefault: boolean hideTitleDefault: boolean + deprecatedDefault: boolean } redirects?: { static: { @@ -97,6 +98,7 @@ export async function createConfig(config: BuildConfigOptions) { wrapDefault: true, collapseDefault: false, hideTitleDefault: false, + deprecatedDefault: false, }, redirects: config.redirects diff --git a/scripts/lib/manifest.ts b/scripts/lib/manifest.ts index fa2d3f27f3..ea09c23ed2 100644 --- a/scripts/lib/manifest.ts +++ b/scripts/lib/manifest.ts @@ -40,6 +40,7 @@ export type ManifestItem = { icon?: Icon target?: '_blank' sdk?: SDK[] + deprecated?: boolean } export type ManifestGroup = { @@ -51,6 +52,7 @@ export type ManifestGroup = { icon?: Icon hideTitle?: boolean sdk?: SDK[] + deprecated?: boolean } type Manifest = (ManifestItem | ManifestGroup)[][] @@ -66,6 +68,7 @@ const createManifestSchema = (config: BuildConfig) => { icon: icon.optional(), target: z.enum(['_blank']).optional(), sdk: z.array(sdk).optional(), + deprecated: z.boolean().default(config.manifestOptions.deprecatedDefault), }) .strict() @@ -79,6 +82,7 @@ const createManifestSchema = (config: BuildConfig) => { icon: icon.optional(), hideTitle: z.boolean().default(config.manifestOptions.hideTitleDefault), sdk: z.array(sdk).optional(), + deprecated: z.boolean().default(config.manifestOptions.deprecatedDefault), }) .strict() diff --git a/scripts/lib/plugins/extractFrontmatter.ts b/scripts/lib/plugins/extractFrontmatter.ts index bdbda330a6..4bb0423142 100644 --- a/scripts/lib/plugins/extractFrontmatter.ts +++ b/scripts/lib/plugins/extractFrontmatter.ts @@ -10,6 +10,7 @@ export type Frontmatter = { title: string description?: string sdk?: SDK[] + deprecated?: boolean } export const extractFrontmatter = @@ -33,7 +34,7 @@ export const extractFrontmatter = if (!('value' in node)) return if (typeof node.value !== 'string') return - const frontmatterYaml: Record<'title' | 'description' | 'sdk', string | undefined> = yaml.parse(node.value) + const frontmatterYaml = yaml.parse(node.value) const frontmatterSDKs = frontmatterYaml.sdk?.split(', ') @@ -64,6 +65,7 @@ export const extractFrontmatter = title: frontmatterYaml.title, description: frontmatterYaml.description, sdk: frontmatterSDKs, + deprecated: frontmatterYaml.deprecated === true, } }, )