@@ -63,12 +63,81 @@ async function pathExists(path: string): Promise<boolean> {
6363 }
6464}
6565
66- export default async function generateContent ( ) : Promise < void > {
66+ async function shouldRegenerateFiles (
67+ contentPath : string ,
68+ generatedContentDirPath : string ,
69+ frameworkDirPath : string ,
70+ ) : Promise < boolean > {
71+ // Check if any generated files exist
72+ const treeFilePath = path . join ( generatedContentDirPath , "tree.js" ) ;
73+ const treeDtsFilePath = path . join ( generatedContentDirPath , "tree.d.ts" ) ;
74+ const frameworkIndexPath = path . join ( frameworkDirPath , "index.js" ) ;
75+ const frameworkIndexDtsPath = path . join ( frameworkDirPath , "index.d.ts" ) ;
76+
77+ const generatedFilesExist = await Promise . all ( [
78+ pathExists ( treeFilePath ) ,
79+ pathExists ( treeDtsFilePath ) ,
80+ pathExists ( frameworkIndexPath ) ,
81+ pathExists ( frameworkIndexDtsPath ) ,
82+ ] ) ;
83+
84+ // If any generated file is missing, regenerate
85+ if ( ! generatedFilesExist . every ( Boolean ) ) {
86+ return true ;
87+ }
88+
89+ // Get the modification time of the content directory
90+ const contentStats = await fs . stat ( contentPath ) ;
91+ const contentModTime = contentStats . mtime ;
92+
93+ // Check if any generated file is older than the content directory
94+ const generatedFilePaths = [
95+ treeFilePath ,
96+ treeDtsFilePath ,
97+ frameworkIndexPath ,
98+ frameworkIndexDtsPath ,
99+ ] ;
100+
101+ for ( const filePath of generatedFilePaths ) {
102+ try {
103+ const fileStats = await fs . stat ( filePath ) ;
104+ if ( fileStats . mtime < contentModTime ) {
105+ return true ;
106+ }
107+ } catch {
108+ // If we can't stat a file, regenerate to be safe
109+ return true ;
110+ }
111+ }
112+
113+ return false ;
114+ }
115+
116+ export default async function generateContent (
117+ options : { noCache ?: boolean } = { } ,
118+ ) : Promise < void > {
67119 const rootDir = await packageDirectory ( ) ;
68120 if ( ! rootDir ) {
69121 throw new Error ( "Could not find package directory" ) ;
70122 }
71123 const contentPath = path . join ( rootDir , "content" ) ;
124+ const generatedContentDirPath = path . join ( rootDir , "src/generatedContent" ) ;
125+ const frameworkDirPath = path . join ( generatedContentDirPath , "framework" ) ;
126+
127+ // Check if we should skip generation due to cache
128+ if ( ! options . noCache ) {
129+ const shouldRegenerate = await shouldRegenerateFiles (
130+ contentPath ,
131+ generatedContentDirPath ,
132+ frameworkDirPath ,
133+ ) ;
134+
135+ if ( ! shouldRegenerate ) {
136+ console . log ( "Generated content is up to date, skipping generation." ) ;
137+ return ;
138+ }
139+ }
140+
72141 const sectionDirNames = await fs . readdir ( contentPath ) ;
73142
74143 const treePayload : TreePayload = {
@@ -185,10 +254,10 @@ export default async function generateContent(): Promise<void> {
185254 }
186255 }
187256
188- const generatedContentDirPath = path . join ( rootDir , "src/generatedContent" ) ;
189- const frameworkDirPath = path . join ( generatedContentDirPath , "framework" ) ;
190257 const treeFilePath = path . join ( generatedContentDirPath , "tree.js" ) ;
258+ const treeDtsFilePath = path . join ( generatedContentDirPath , "tree.d.ts" ) ;
191259 const frameworkIndexPath = path . join ( frameworkDirPath , "index.js" ) ;
260+ const frameworkIndexDtsPath = path . join ( frameworkDirPath , "index.d.ts" ) ;
192261 const commentDisclaimer = `// File generated from "node scripts/generateContent.js", DO NOT EDIT/COMMIT` ;
193262
194263 if ( ! ( await pathExists ( generatedContentDirPath ) ) ) {
@@ -204,6 +273,29 @@ export default async function generateContent(): Promise<void> {
204273 ` ,
205274 ) ;
206275
276+ await writeDtsFile (
277+ treeDtsFilePath ,
278+ `
279+ ${ commentDisclaimer }
280+ export interface Section {
281+ sectionId: string;
282+ sectionDirName: string;
283+ title: string;
284+ }
285+
286+ export interface Snippet {
287+ sectionId: string;
288+ snippetId: string;
289+ snippetDirName: string;
290+ sectionDirName: string;
291+ title: string;
292+ }
293+
294+ export declare const sections: Section[];
295+ export declare const snippets: Snippet[];
296+ ` ,
297+ ) ;
298+
207299 if ( ! ( await pathExists ( frameworkDirPath ) ) ) {
208300 await fs . mkdir ( frameworkDirPath , { recursive : true } ) ;
209301 }
@@ -239,6 +331,18 @@ export default async function generateContent(): Promise<void> {
239331 };
240332 ` ,
241333 ) ;
334+
335+ await writeDtsFile (
336+ frameworkIndexDtsPath ,
337+ `
338+ ${ commentDisclaimer }
339+ declare const snippetsImporterByFrameworkId: {
340+ [key: string]: () => Promise<any>;
341+ };
342+
343+ export default snippetsImporterByFrameworkId;
344+ ` ,
345+ ) ;
242346}
243347
244348function dirNameToTitle ( dirName : string ) : string {
@@ -254,6 +358,13 @@ async function writeJsFile(filepath: string, jsCode: string): Promise<void> {
254358 await fs . writeFile ( filepath , codeFormatted ) ;
255359}
256360
361+ async function writeDtsFile ( filepath : string , dtsCode : string ) : Promise < void > {
362+ const codeFormatted = await prettier . format ( dtsCode , {
363+ parser : "typescript" ,
364+ } ) ;
365+ await fs . writeFile ( filepath , codeFormatted ) ;
366+ }
367+
257368async function generatePlaygroundURL (
258369 frameworkId : string ,
259370 files : File [ ] ,
0 commit comments