Skip to content
2 changes: 2 additions & 0 deletions .changeset/short-apes-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
18 changes: 17 additions & 1 deletion .typedoc/__tests__/file-structure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ async function scanDirectory(type: 'file' | 'directory' = 'file') {
return arr;
}

function isTopLevelPath(filePath: string) {
return !filePath.includes('/');
}

describe('Typedoc output', () => {
it('should only have these top-level folders', async () => {
const folders = await scanDirectory('directory');
const topLevelFolders = folders.filter(isTopLevelPath);

expect(folders).toMatchInlineSnapshot(`
expect(topLevelFolders).toMatchInlineSnapshot(`
[
"backend",
"nextjs",
Expand All @@ -40,6 +45,17 @@ describe('Typedoc output', () => {
`);
});

it('should only have these nested folders', async () => {
const folders = await scanDirectory('directory');
const nestedFolders = folders.filter(folder => !isTopLevelPath(folder));

expect(nestedFolders).toMatchInlineSnapshot(`
[
"react/legacy",
]
`);
});

it('should only contain lowercase files', async () => {
const files = await scanDirectory('file');
const upperCaseFiles = files.filter(file => /[A-Z]/.test(file));
Expand Down
87 changes: 76 additions & 11 deletions .typedoc/extract-returns-and-params.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,33 @@ import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const LEGACY_HOOK_NAMES = new Set(['use-sign-in-1', 'use-sign-up-1']);

/**
* Returns legacy hook output info or null if not a legacy hook.
* @param {string} filePath
* @returns {{ outputDir: string; baseName: string } | null}
*/
function getLegacyHookTarget(filePath) {
const fileName = path.basename(filePath, '.mdx');
if (!LEGACY_HOOK_NAMES.has(fileName)) {
return null;
}
const dirName = path.dirname(filePath);
return {
outputDir: path.join(dirName, 'legacy'),
baseName: fileName.replace(/-1$/, ''),
};
}

/**
* Extracts the "## Returns" section from a markdown file and writes it to a separate file.
* @param {string} filePath - The path to the markdown file
* @param {string} content - The file content
* @param {{ outputDir: string; baseName: string } | null} legacyTarget
* @returns {boolean} True if a file was created
*/
function extractReturnsSection(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');

function extractReturnsSection(filePath, content, legacyTarget) {
// Find the "## Returns" section
const returnsStart = content.indexOf('## Returns');

Expand All @@ -34,8 +53,15 @@ function extractReturnsSection(filePath) {

// Generate the new filename: use-auth.mdx -> use-auth-return.mdx
const fileName = path.basename(filePath, '.mdx');
const dirName = path.dirname(filePath);
const newFilePath = path.join(dirName, `${fileName}-return.mdx`);
let outputBaseName = `${fileName}-return`;
let outputDir = path.dirname(filePath);
// Legacy hooks: move into legacy/ and drop the -1
if (legacyTarget) {
outputBaseName = `${legacyTarget.baseName}-return`;
outputDir = legacyTarget.outputDir;
fs.mkdirSync(outputDir, { recursive: true });
}
const newFilePath = path.join(outputDir, `${outputBaseName}.mdx`);

// Write the extracted Returns section to the new file
fs.writeFileSync(newFilePath, returnsContent, 'utf-8');
Expand All @@ -61,16 +87,25 @@ function replaceGenericTypesInParamsTable(content) {
/**
* Extracts the "## Parameters" section from a markdown file and writes it to a separate file.
* @param {string} filePath - The path to the markdown file
* @param {string} content - The file content
* @param {{ outputDir: string; baseName: string } | null} legacyTarget
* @returns {boolean} True if a file was created
*/
function extractParametersSection(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
function extractParametersSection(filePath, content, legacyTarget) {
const fileName = path.basename(filePath, '.mdx');
const dirName = path.dirname(filePath);
let outputDir = dirName;
let outputBaseName = fileName;

if (legacyTarget) {
outputDir = legacyTarget.outputDir;
outputBaseName = legacyTarget.baseName;
fs.mkdirSync(outputDir, { recursive: true });
}

// Always use -params suffix
const suffix = '-params';
const targetFileName = `${fileName}${suffix}.mdx`;
const targetFileName = `${outputBaseName}${suffix}.mdx`;
const propsFileName = `${fileName}-props.mdx`;

// Delete any existing -props file (TypeDoc-generated)
Expand Down Expand Up @@ -100,13 +135,37 @@ function extractParametersSection(filePath) {
const processedParams = replaceGenericTypesInParamsTable(paramsContent);

// Write to new file
const newFilePath = path.join(dirName, targetFileName);
const newFilePath = path.join(outputDir, targetFileName);
fs.writeFileSync(newFilePath, processedParams, 'utf-8');

console.log(`[extract-returns] Created ${path.relative(process.cwd(), newFilePath)}`);
return true;
}

/**
* Moves legacy hook docs into a legacy/ folder and removes the -1 suffix
* @param {string} filePath
* @param {{ outputDir: string; baseName: string } | null} legacyTarget
*/
function moveLegacyHookDoc(filePath, legacyTarget) {
if (!legacyTarget) {
return;
}

const legacyDir = legacyTarget.outputDir;
fs.mkdirSync(legacyDir, { recursive: true });
const legacyPath = path.join(legacyDir, `${legacyTarget.baseName}.mdx`);

if (fs.existsSync(legacyPath)) {
fs.unlinkSync(legacyPath);
}

fs.renameSync(filePath, legacyPath);
console.log(
`[extract-returns] Moved ${path.relative(process.cwd(), filePath)} -> ${path.relative(process.cwd(), legacyPath)}`,
);
}

/**
* Recursively reads all .mdx files in a directory, excluding generated files
* @param {string} dir - The directory to read
Expand Down Expand Up @@ -160,15 +219,21 @@ function main() {
let paramsCount = 0;

for (const filePath of mdxFiles) {
const content = fs.readFileSync(filePath, 'utf-8');
const legacyTarget = getLegacyHookTarget(filePath);

// Extract Returns sections
if (extractReturnsSection(filePath)) {
if (extractReturnsSection(filePath, content, legacyTarget)) {
returnsCount++;
}

// Extract Parameters sections
if (extractParametersSection(filePath)) {
if (extractParametersSection(filePath, content, legacyTarget)) {
paramsCount++;
}

// Move legacy hook docs after extraction
moveLegacyHookDoc(filePath, legacyTarget);
}

console.log(`[extract-returns] Extracted ${returnsCount} Returns sections`);
Expand Down
Loading