Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions scripts/mintlify-post-processing/file-processing/file-processing.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const APPENDED_ARTICLES_PATH = path.join(
__dirname,
"../appended-articles.json"
);
const METHOD_ORDER_PATH = path.join(__dirname, "..", "method-order.json");

// Controlled via env var so we can re-enable Panel injection when needed.
const PANELS_ENABLED = process.env.MINTLIFY_INCLUDE_PANELS === "true";
Expand Down Expand Up @@ -1959,6 +1960,40 @@ function cleanupSortFieldSignature(dir) {
}
}

/**
* Fix truncated intersection types in ParamField type attributes.
* TypeDoc renders (Partial<T> & { id: string })[] as "Partial<...> & object[]".
*/
function cleanupTruncatedParamTypes(dir) {
if (!fs.existsSync(dir)) return;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
cleanupTruncatedParamTypes(entryPath);
} else if (
entry.isFile() &&
(entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
) {
let content = fs.readFileSync(entryPath, "utf-8");
let modified = false;

if (content.includes('type="Partial<...> & object[]"')) {
content = content.replace(
/type="Partial<\.\.\.> & object\[\]"/g,
'type="(Partial<T> & { id: string })[]"'
);
modified = true;
}

if (modified) {
fs.writeFileSync(entryPath, content, "utf-8");
console.log(`Cleaned truncated param type: ${path.relative(DOCS_DIR, entryPath)}`);
}
}
}
}

/**
* Main function
*/
Expand Down Expand Up @@ -2004,6 +2039,127 @@ function deleteTypesAfterProcessing(docsDir) {
}
}

/**
* Load method-order.json config.
* Keys are MDX base filenames (e.g. "entities"), values are ordered method name arrays.
*/
function loadMethodOrderConfig() {
if (!fs.existsSync(METHOD_ORDER_PATH)) return {};
return JSON.parse(fs.readFileSync(METHOD_ORDER_PATH, "utf-8"));
}

/**
* Reorder method blocks inside an MDX file according to a given ordered list.
*
* The file is split on `***` horizontal-rule separators into sections. Sections
* whose first `### name()` heading matches an entry in `orderedNames` are
* reordered accordingly; unlisted method sections keep their relative order
* and appear after explicitly ordered ones.
*
* Type-definition sections that are displaced between the `## ... Methods`
* heading and the first method are relocated to after the footer (where
* `## Type Definitions` lives), so they appear under the correct TOC group.
*/
function reorderMethods(content, orderedNames) {
const sections = content.split(/\n*\*{3}\n*/);
const HR = "\n\n***\n\n";

const methodRe = /^### (\w+)\(\)/m;
const methodsHeadingRe = /^## .+ Methods$/m;

const tagged = sections.map((text) => ({
text,
methodName: (text.match(methodRe) || [])[1] || null,
hasMethodsHeading: methodsHeadingRe.test(text),
}));

const firstMethodIdx = tagged.findIndex((t) => t.methodName);
if (firstMethodIdx === -1) return { content, modified: false };

let lastMethodIdx = -1;
for (let i = tagged.length - 1; i >= 0; i--) {
if (tagged[i].methodName) {
lastMethodIdx = i;
break;
}
}

const headingIdx = tagged.findIndex((t) => t.hasMethodsHeading);
const displacedStart = headingIdx !== -1 ? headingIdx + 1 : firstMethodIdx;

const header = tagged.slice(0, displacedStart);
const displaced = tagged.slice(displacedStart, firstMethodIdx);
const middle = tagged.slice(firstMethodIdx, lastMethodIdx + 1);
const footer = tagged.slice(lastMethodIdx + 1);

const methods = middle.filter((t) => t.methodName);
const stray = middle.filter((t) => !t.methodName);

const orderMap = new Map(orderedNames.map((n, i) => [n, i]));
const origOrder = methods.map((m) => m.methodName).join(",");

methods.sort((a, b) => {
const ai = orderMap.has(a.methodName)
? orderMap.get(a.methodName)
: orderedNames.length + methods.indexOf(a);
const bi = orderMap.has(b.methodName)
? orderMap.get(b.methodName)
: orderedNames.length + methods.indexOf(b);
return ai - bi;
});

const newOrder = methods.map((m) => m.methodName).join(",");
if (origOrder === newOrder && displaced.length === 0 && stray.length === 0) {
return { content, modified: false };
}

const ordered = [
...header,
...methods,
...footer,
...displaced,
...stray,
];

return { content: ordered.map((t) => t.text).join(HR), modified: true };
}

/**
* Apply method ordering to MDX files whose base name matches a key in method-order.json.
*/
function applyMethodOrdering(dir) {
const config = loadMethodOrderConfig();
if (Object.keys(config).length === 0) return;

if (!fs.existsSync(dir)) return;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
applyMethodOrdering(entryPath);
} else if (
entry.isFile() &&
(entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
) {
const baseName = path.basename(entry.name, path.extname(entry.name));
const orderedNames = config[baseName];
if (!orderedNames) continue;

const content = fs.readFileSync(entryPath, "utf-8");
const { content: updated, modified } = reorderMethods(
content,
orderedNames
);
if (modified) {
fs.writeFileSync(entryPath, updated, "utf-8");
console.log(
`Reordered methods: ${path.relative(DOCS_DIR, entryPath)}`
);
}
}
}
}

function main() {
console.log("Processing TypeDoc MDX files for Mintlify...\n");

Expand Down Expand Up @@ -2033,6 +2189,9 @@ function main() {
// Clean up SortField signature specifically (before general signature cleanup)
cleanupSortFieldSignature(DOCS_DIR);

// Fix truncated intersection types in ParamField type attributes
cleanupTruncatedParamTypes(DOCS_DIR);

// Clean up signatures: fix truncated generics, simplify keyof constraints, break long lines
applySignatureCleanup(DOCS_DIR);

Expand All @@ -2050,6 +2209,9 @@ function main() {
// Group type definitions under a parent heading
applyTypeDefinitionGrouping(DOCS_DIR);

// Reorder methods according to method-order.json
applyMethodOrdering(DOCS_DIR);

// Link type names in Type Declarations sections to their corresponding headings
applyTypeDeclarationLinking(DOCS_DIR);

Expand Down
16 changes: 16 additions & 0 deletions scripts/mintlify-post-processing/method-order.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"entities": [
"get",
"list",
"filter",
"create",
"bulkCreate",
"importEntities",
"update",
"updateMany",
"bulkUpdate",
"delete",
"deleteMany",
"subscribe"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"DeleteManyResult",
"DeleteResult",
"ImportResult",
"SortField"
"SortField",
"UpdateManyResult"
]
3 changes: 2 additions & 1 deletion scripts/mintlify-post-processing/types-to-expose.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
"IntegrationsModule",
"CoreIntegrations",
"SortField",
"SsoModule"
"SsoModule",
"UpdateManyResult"
]
Loading
Loading