@@ -99,8 +99,9 @@ typedef enum {
9999 VALID_NOT_IN_JS = 1 << 9 , // Not listed in examples.js
100100 VALID_INCONSISTENT_INFO = 1 << 10 , // Inconsistent info between collection and example header (stars, author...)
101101 VALID_MISSING_WEB_OUTPUT = 1 << 11 , // Missing .html/.data/.wasm/.js
102- VALID_INVALID_CATEGORY = 1 << 12 , // Not a recognized category
103- VALID_UNKNOWN_ERROR = 1 << 13 // Unknown failure case (fallback)
102+ VALID_MISSING_WEB_METADATA = 1 << 12 , // Missing .html example metadata
103+ VALID_INVALID_CATEGORY = 1 << 13 , // Not a recognized category
104+ VALID_UNKNOWN_ERROR = 1 << 14 // Unknown failure case (fallback)
104105} rlExampleValidationStatus ;
105106
106107// Example management operations
@@ -174,7 +175,10 @@ static int AddVSProjectToSolution(const char *projFile, const char *slnFile, con
174175
175176// Generate unique UUID v4 string
176177// Output format: {9A2F48CC-0DA8-47C0-884E-02E37F9BE6C1}
177- const char * GenerateUUIDv4 (void );
178+ static const char * GenerateUUIDv4 (void );
179+
180+ // Update generated Web example .html file metadata
181+ static void UpdateWebMetadata (const char * exHtmlPath , const char * exFilePath );
178182
179183//------------------------------------------------------------------------------------
180184// Program main entry point
@@ -570,6 +574,10 @@ int main(int argc, char *argv[])
570574 system (TextFormat ("make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B" , exCategory , exName ));
571575 //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exCategory, exName));
572576
577+ // Update generated .html metadata
578+ UpdateWebMetadata (TextFormat ("%s/%s/%s.html" , exBasePath , exCategory , exName ),
579+ TextFormat ("%s/%s/%s.c" , exBasePath , exCategory , exName ));
580+
573581 // Copy results to web side
574582 FileCopy (TextFormat ("%s/%s/%s.html" , exBasePath , exCategory , exName ),
575583 TextFormat ("%s/%s/%s.html" , exWebPath , exCategory , exName ));
@@ -648,6 +656,10 @@ int main(int argc, char *argv[])
648656 system (TextFormat ("%s/make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B" , exBasePath , exRecategory , exRename ));
649657 //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exRecategory, exRename));
650658
659+ // Update generated .html metadata
660+ UpdateWebMetadata (TextFormat ("%s/%s/%s.html" , exBasePath , exCategory , exName ),
661+ TextFormat ("%s/%s/%s.c" , exBasePath , exCategory , exName ));
662+
651663 // Copy results to web side
652664 FileCopy (TextFormat ("%s/%s/%s.html" , exBasePath , exRecategory , exRename ),
653665 TextFormat ("%s/%s/%s.html" , exWebPath , exRecategory , exRename ));
@@ -774,10 +786,10 @@ int main(int argc, char *argv[])
774786 char * exListUpdated = (char * )RL_CALLOC (REXM_MAX_BUFFER_SIZE , 1 );
775787 bool listUpdated = false;
776788
777- int exListLen = strlen (exList );
789+ int exListLen = ( int ) strlen (exList );
778790 strcpy (exListUpdated , exList );
779791
780- for (int i = 0 ; i < list .count ; i ++ )
792+ for (unsigned int i = 0 ; i < list .count ; i ++ )
781793 {
782794 if ((strcmp ("examples_template" , GetFileNameWithoutExt (list .paths [i ])) != 0 ) && // HACK: Skip "examples_template"
783795 (TextFindIndex (exList , GetFileNameWithoutExt (list .paths [i ])) == -1 ))
@@ -908,6 +920,23 @@ int main(int argc, char *argv[])
908920 exInfo -> status |= VALID_MISSING_WEB_OUTPUT ;
909921 }
910922
923+ // Validate: raylib.com/examples/<category>/<category>_example_name.html -> Metadata
924+ if (FileExists (TextFormat ("%s/%s/%s.html" , exWebPath , exInfo -> category , exInfo -> name )))
925+ {
926+ char * exHtmlText = LoadFileText (TextFormat ("%s/%s/%s.html" , exWebPath , exInfo -> category , exInfo -> name ));
927+
928+ if ((TextFindIndex (exHtmlText , "raylib web game" ) > -1 ) || // title
929+ (TextFindIndex (exHtmlText , "New raylib web videogame, developed using raylib videogames library" ) > -1 ) || // description
930+ (TextFindIndex (exHtmlText , "https://www.raylib.com/common/raylib_logo.png" ) > -1 ) || // image
931+ (TextFindIndex (exHtmlText , "https://www.raylib.com/games.html" ) > -1 ) || // url
932+ (TextFindIndex (exHtmlText , "https://github.com/raysan5/raylib" ) > -1 )) // source code button
933+ {
934+ exInfo -> status |= VALID_MISSING_WEB_METADATA ;
935+ }
936+
937+ UnloadFileText (exHtmlText );
938+ }
939+
911940 // NOTE: Additional validation elements
912941 // Validate: Example naming conventions: <category>/<category>_example_name, valid category
913942 if ((TextFindIndex (exInfo -> name , exInfo -> category ) == -1 ) ||
@@ -986,9 +1015,14 @@ int main(int argc, char *argv[])
9861015 // Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.js
9871016 // Solves: VALID_MISSING_WEB_OUTPUT
9881017 if ((strcmp (exInfo -> category , "others" ) != 0 ) && // Skipping "others" category
989- exInfo -> status & VALID_MISSING_WEB_OUTPUT )
1018+ (( exInfo -> status & VALID_MISSING_WEB_OUTPUT ) || ( exInfo -> status & VALID_MISSING_WEB_METADATA )) )
9901019 {
991- system (TextFormat ("%s/build_example_web.bat %s/%s" , exBasePath , exInfo -> category , exInfo -> name ));
1020+ system (TextFormat ("%s/make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B" , exBasePath , exInfo -> category , exInfo -> name ));
1021+ //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exInfo->category, exInfo->name));
1022+
1023+ // Update generated .html metadata
1024+ UpdateWebMetadata (TextFormat ("%s/%s/%s.html" , exBasePath , exCategory , exName ),
1025+ TextFormat ("%s/%s/%s.c" , exBasePath , exCategory , exName ));
9921026
9931027 // Copy results to web side
9941028 FileCopy (TextFormat ("%s/%s/%s.html" , exBasePath , exInfo -> category , exInfo -> name ),
@@ -1033,14 +1067,15 @@ int main(int argc, char *argv[])
10331067 [RDME] VALID_NOT_IN_README // Not listed in README.md
10341068 [JS] VALID_NOT_IN_JS // Not listed in examples.js
10351069 [WOUT] VALID_MISSING_WEB_OUTPUT // Missing .html/.data/.wasm/.js
1070+ [WMETA] VALID_MISSING_WEB_METADATA // Missing .html example metadata
10361071 [INFO] VALID_INCONSISTENT_INFO // Inconsistent info between collection and example header (stars, author...)
10371072 [CAT] VALID_INVALID_CATEGORY // Not a recognized category
10381073
1039- | [EXAMPLE NAME] | [C] |[CAT]|[INFO]|[PNG]|[WPNG]|[RES]|[MK] |[MKWEB]|[VCX]|[SOL]|[RDME]|[JS] |[WOUT]|
1040- |:-----------------------------|:---:|:---:|:----:|:---:|:----:|:---:|:---:|:-----:|:---:|:---:|:----:|:---:|:----:|
1041- | core_basic_window | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
1042- | shapes_colors_palette | ✘ | ✔ | ✘ | ✔ | ✘ | ✔ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | ✔ |
1043- | text_format_text | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✔ | ✘ | ✔ | ✔ | ✔ |
1074+ | [EXAMPLE NAME] | [C] |[CAT]|[INFO]|[PNG]|[WPNG]|[RES]|[MK] |[MKWEB]|[VCX]|[SOL]|[RDME]|[JS] |[WOUT]|[WMETA]|
1075+ |:-----------------------------|:---:|:---:|:----:|:---:|:----:|:---:|:---:|:-----:|:---:|:---:|:----:|:---:|:----:|:-----:|
1076+ | core_basic_window | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
1077+ | shapes_colors_palette | ✘ | ✔ | ✘ | ✔ | ✘ | ✔ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
1078+ | text_format_text | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ |
10441079 */
10451080
10461081 char * report = (char * )RL_CALLOC (REXM_MAX_BUFFER_SIZE , 1 );
@@ -1061,14 +1096,15 @@ int main(int argc, char *argv[])
10611096 repIndex += sprintf (report + repIndex , " - [SOL] : Project not included in solution file\n" );
10621097 repIndex += sprintf (report + repIndex , " - [RDME] : Not listed in README.md\n" );
10631098 repIndex += sprintf (report + repIndex , " - [JS] : Not listed in Web (examples.js)\n" );
1064- repIndex += sprintf (report + repIndex , " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n```\n" );
1099+ repIndex += sprintf (report + repIndex , " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n" );
1100+ repIndex += sprintf (report + repIndex , " - [WMETA] : Missing Web .html example metadata\n```\n" );
10651101
1066- repIndex += sprintf (report + repIndex , "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|\n" );
1067- repIndex += sprintf (report + repIndex , "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|\n" );
1102+ repIndex += sprintf (report + repIndex , "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]| \n" );
1103+ repIndex += sprintf (report + repIndex , "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:| \n" );
10681104
10691105 for (int i = 0 ; i < exCollectionCount ; i ++ )
10701106 {
1071- repIndex += sprintf (report + repIndex , "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n" ,
1107+ repIndex += sprintf (report + repIndex , "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | \n" ,
10721108 exCollection [i ].name ,
10731109 (exCollection [i ].status & VALID_MISSING_C )? "❌" : "✔" ,
10741110 (exCollection [i ].status & VALID_INVALID_CATEGORY )? "❌" : "✔" ,
@@ -1082,7 +1118,8 @@ int main(int argc, char *argv[])
10821118 (exCollection [i ].status & VALID_NOT_IN_VCXSOL )? "❌" : "✔" ,
10831119 (exCollection [i ].status & VALID_NOT_IN_README )? "❌" : "✔" ,
10841120 (exCollection [i ].status & VALID_NOT_IN_JS )? "❌" : "✔" ,
1085- (exCollection [i ].status & VALID_MISSING_WEB_OUTPUT )? "❌" : "✔" );
1121+ (exCollection [i ].status & VALID_MISSING_WEB_OUTPUT )? "❌" : "✔" ,
1122+ (exCollection [i ].status & VALID_MISSING_WEB_METADATA )? "❌" : "✔" );
10861123 }
10871124
10881125 SaveFileText (TextFormat ("%s/../tools/rexm/%s" , exBasePath , "examples_report.md" ), report );
@@ -1109,16 +1146,17 @@ int main(int argc, char *argv[])
11091146 repIndex += sprintf (reportIssues + repIndex , " - [SOL] : Project not included in solution file\n" );
11101147 repIndex += sprintf (reportIssues + repIndex , " - [RDME] : Not listed in README.md\n" );
11111148 repIndex += sprintf (reportIssues + repIndex , " - [JS] : Not listed in Web (examples.js)\n" );
1112- repIndex += sprintf (reportIssues + repIndex , " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n```\n" );
1149+ repIndex += sprintf (reportIssues + repIndex , " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n" );
1150+ repIndex += sprintf (reportIssues + repIndex , " - [WMETA] : Missing Web .html example metadata\n```\n" );
11131151
1114- repIndex += sprintf (reportIssues + repIndex , "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|\n" );
1115- repIndex += sprintf (reportIssues + repIndex , "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|\n" );
1152+ repIndex += sprintf (reportIssues + repIndex , "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]| \n" );
1153+ repIndex += sprintf (reportIssues + repIndex , "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:| \n" );
11161154
11171155 for (int i = 0 ; i < exCollectionCount ; i ++ )
11181156 {
11191157 if (exCollection [i ].status > 0 )
11201158 {
1121- repIndex += sprintf (reportIssues + repIndex , "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n" ,
1159+ repIndex += sprintf (reportIssues + repIndex , "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | \n" ,
11221160 exCollection [i ].name ,
11231161 (exCollection [i ].status & VALID_MISSING_C )? "❌" : "✔" ,
11241162 (exCollection [i ].status & VALID_INVALID_CATEGORY )? "❌" : "✔" ,
@@ -1132,7 +1170,8 @@ int main(int argc, char *argv[])
11321170 (exCollection [i ].status & VALID_NOT_IN_VCXSOL )? "❌" : "✔" ,
11331171 (exCollection [i ].status & VALID_NOT_IN_README )? "❌" : "✔" ,
11341172 (exCollection [i ].status & VALID_NOT_IN_JS )? "❌" : "✔" ,
1135- (exCollection [i ].status & VALID_MISSING_WEB_OUTPUT )? "❌" : "✔" );
1173+ (exCollection [i ].status & VALID_MISSING_WEB_OUTPUT )? "❌" : "✔" ,
1174+ (exCollection [i ].status & VALID_MISSING_WEB_METADATA )? "❌" : "✔" );
11361175 }
11371176 }
11381177
@@ -2097,7 +2136,7 @@ static int AddVSProjectToSolution(const char *projFile, const char *slnFile, con
20972136
20982137// Generate unique UUID v4 string
20992138// Output format: {9A2F48CC-0DA8-47C0-884E-02E37F9BE6C1}
2100- const char * GenerateUUIDv4 (void )
2139+ static const char * GenerateUUIDv4 (void )
21012140{
21022141 static char uuid [38 ] = { 0 };
21032142 memset (uuid , 0 , 38 );
@@ -2120,3 +2159,68 @@ const char *GenerateUUIDv4(void)
21202159
21212160 return uuid ;
21222161}
2162+
2163+ // Update generated Web example .html file metadata
2164+ static void UpdateWebMetadata (const char * exHtmlPath , const char * exFilePath )
2165+ {
2166+ if (FileExists (exHtmlPath ) && IsFileExtension (exHtmlPath , ".html" ))
2167+ {
2168+ char * fileText = LoadFileText (exHtmlPath );
2169+ char * fileTextUpdated [6 ] = { 0 }; // Pointers to multiple updated text versions
2170+
2171+ char * exText = NULL ; // Example code file, required to get description
2172+ char * * lines = NULL ; // Pointers to example code lines
2173+ int lineCount = 0 ; // Example code line count
2174+ int lineLength = 0 ; // Description line length
2175+
2176+ char exName [64 ] = { 0 }; // Example name: fileName without extension
2177+ char exCategory [16 ] = { 0 }; // Example category: core, shapes, text, textures, models, audio, shaders
2178+ char exDescription [256 ] = { 0 }; // Example description: example text line #3
2179+ char exTitle [64 ] = { 0 }; // Example title: fileName without extension, replacing underscores by spaces
2180+
2181+ memset (exName , 0 , 64 );
2182+ memset (exTitle , 0 , 64 );
2183+ memset (exDescription , 0 , 256 );
2184+ memset (exCategory , 0 , 16 );
2185+ lineLength = 0 ;
2186+
2187+ // Get example name: replace underscore by spaces
2188+ strcpy (exName , GetFileNameWithoutExt (exHtmlPath ));
2189+ strcpy (exTitle , exName );
2190+ for (int i = 0 ; (i < 256 ) && (exTitle [i ] != '\0' ); i ++ ) { if (exTitle [i ] == '_' ) exTitle [i ] = ' ' ; }
2191+
2192+ // Get example category from exName: copy until first underscore
2193+ for (int i = 0 ; (exName [i ] != '_' ); i ++ ) exCategory [i ] = exName [i ];
2194+
2195+ // Get example description: copy line #3 from example file
2196+ exText = LoadFileText (exFilePath );
2197+ lines = LoadTextLines (exText , & lineCount );
2198+ for (int i = 0 ; (lines [2 ][i ] != '\n' ) && (lines [2 ][i ] != '\r' ); i ++ ) lineLength ++ ;
2199+ strncpy (exDescription , lines [2 ] + 4 , lineLength - 4 );
2200+ UnloadFileText (exText );
2201+
2202+ // Update example.html required text
2203+ fileTextUpdated [0 ] = TextReplace (fileText , "raylib web game" , exTitle );
2204+ fileTextUpdated [1 ] = TextReplace (fileTextUpdated [0 ], "New raylib web videogame, developed using raylib videogames library" , exDescription );
2205+ fileTextUpdated [2 ] = TextReplace (fileTextUpdated [1 ], "https://www.raylib.com/common/raylib_logo.png" ,
2206+ TextFormat ("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png" , exCategory , exName ));
2207+ fileTextUpdated [3 ] = TextReplace (fileTextUpdated [2 ], "https://www.raylib.com/games.html" ,
2208+ TextFormat ("https://www.raylib.com/examples/%s/%s.html" , exCategory , exName ));
2209+ fileTextUpdated [4 ] = TextReplace (fileTextUpdated [3 ], "raylib - example" , TextFormat ("raylib - %s" , exName )); // og:site_name
2210+ fileTextUpdated [5 ] = TextReplace (fileTextUpdated [4 ], "https://github.com/raysan5/raylib" ,
2211+ TextFormat ("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c" , exCategory , exName ));
2212+
2213+ SaveFileText (exHtmlPath , fileTextUpdated [5 ]);
2214+
2215+ //LOG("INFO: [%s] Updated successfully\n",files.paths[i]);
2216+ //LOG(" - Name / Title: %s / %s\n", exName, exTitle);
2217+ //LOG(" - Description: %s\n", exDescription);
2218+ //LOG(" - URL: %s\n", TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName));
2219+ //LOG(" - URL Source: %s\n", TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName));
2220+
2221+ for (int i = 0 ; i < 6 ; i ++ ) { MemFree (fileTextUpdated [i ]); fileTextUpdated [i ] = NULL ; }
2222+
2223+ UnloadTextLines (lines );
2224+ UnloadFileText (fileText );
2225+ }
2226+ }
0 commit comments