1
+ const fs = require ( 'fs' ) ;
2
+ const path = require ( 'path' ) ;
3
+ const cheerio = require ( 'cheerio' ) ;
4
+
5
+ /**
6
+ * Extract metadata from an HTML file
7
+ * @param {string } filePath - Path to the HTML file
8
+ * @returns {object|null } - Extracted metadata or null if invalid
9
+ */
10
+ function extractMetadata ( filePath ) {
11
+ try {
12
+ const content = fs . readFileSync ( filePath , 'utf8' ) ;
13
+ const $ = cheerio . load ( content ) ;
14
+ const filename = path . basename ( filePath ) ;
15
+
16
+ // Extract metadata from meta tags and title
17
+ const title = $ ( 'meta[name="title"]' ) . attr ( 'content' ) || $ ( 'title' ) . text ( ) || filename . replace ( / \. [ ^ / . ] + $ / , "" ) ;
18
+ const description = $ ( 'meta[name="description"]' ) . attr ( 'content' ) || '' ;
19
+ const author = $ ( 'meta[name="author"]' ) . attr ( 'content' ) || '' ;
20
+ const github = $ ( 'meta[name="github"]' ) . attr ( 'content' ) || '' ;
21
+
22
+ // Extract compatible browsers if specified
23
+ const compatibleBrowsersContent = $ ( 'meta[name="compatible-browsers"]' ) . attr ( 'content' ) ;
24
+ let compatibleBrowsers = [ ] ;
25
+ if ( compatibleBrowsersContent ) {
26
+ compatibleBrowsers = compatibleBrowsersContent . split ( ',' ) . map ( b => b . trim ( ) ) . filter ( b => b ) ;
27
+ }
28
+
29
+ // Build entry object
30
+ const entry = {
31
+ title : title . trim ( ) ,
32
+ filename : filename
33
+ } ;
34
+
35
+ if ( description ) entry . description = description . trim ( ) ;
36
+ if ( author ) entry . author = author . trim ( ) ;
37
+ if ( github ) entry . github = github . trim ( ) ;
38
+ if ( compatibleBrowsers . length > 0 ) entry . compatibleBrowsers = compatibleBrowsers ;
39
+
40
+ return entry ;
41
+ } catch ( error ) {
42
+ console . error ( `Error processing ${ filePath } :` , error . message ) ;
43
+ return null ;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Generate entries.js from all HTML files in the entries directory
49
+ */
50
+ function generateEntriesJs ( ) {
51
+ const entriesDir = 'entries' ;
52
+
53
+ if ( ! fs . existsSync ( entriesDir ) ) {
54
+ console . error ( 'Entries directory not found' ) ;
55
+ process . exit ( 1 ) ;
56
+ }
57
+
58
+ const entries = [ ] ;
59
+ const files = fs . readdirSync ( entriesDir )
60
+ . filter ( file => file . match ( / \. h t m l ? $ / i) )
61
+ . sort ( ) ; // Sort alphabetically for consistent output
62
+
63
+ console . log ( `Processing ${ files . length } HTML files...` ) ;
64
+
65
+ for ( const file of files ) {
66
+ const filePath = path . join ( entriesDir , file ) ;
67
+ const metadata = extractMetadata ( filePath ) ;
68
+
69
+ if ( metadata ) {
70
+ entries . push ( metadata ) ;
71
+ console . log ( `✅ ${ file } : ${ metadata . title } ` ) ;
72
+ } else {
73
+ console . log ( `❌ ${ file } : Failed to extract metadata` ) ;
74
+ }
75
+ }
76
+
77
+ // Sort entries by title for consistency with current entries.js
78
+ entries . sort ( ( a , b ) => a . title . localeCompare ( b . title ) ) ;
79
+
80
+ // Write JavaScript file
81
+ const jsContent = `/**
82
+ * This file is automatically generated from HTML meta tags.
83
+ * Last updated: ${ new Date ( ) . toISOString ( ) }
84
+ *
85
+ * DO NOT EDIT MANUALLY - Changes will be overwritten!
86
+ * To update entries, modify the meta tags in your HTML files.
87
+ */
88
+
89
+ const entries = ${ JSON . stringify ( entries , null , 2 ) } ;` ;
90
+
91
+ const jsOutputFile = 'entries.js' ;
92
+ fs . writeFileSync ( jsOutputFile , jsContent , 'utf8' ) ;
93
+
94
+ console . log ( `\n✅ Generated ${ jsOutputFile } with ${ entries . length } entries` ) ;
95
+
96
+ // Log any files missing metadata
97
+ const missingMetadata = files . filter ( file => {
98
+ const filePath = path . join ( entriesDir , file ) ;
99
+ const metadata = extractMetadata ( filePath ) ;
100
+ return ! metadata || ! metadata . title || ! metadata . description || ! metadata . author ;
101
+ } ) ;
102
+
103
+ if ( missingMetadata . length > 0 ) {
104
+ console . log ( `\n⚠️ Files missing complete metadata:` ) ;
105
+ missingMetadata . forEach ( file => {
106
+ const filePath = path . join ( entriesDir , file ) ;
107
+ const metadata = extractMetadata ( filePath ) ;
108
+ const missing = [ ] ;
109
+ if ( ! metadata || ! metadata . title ) missing . push ( 'title' ) ;
110
+ if ( ! metadata || ! metadata . description ) missing . push ( 'description' ) ;
111
+ if ( ! metadata || ! metadata . author ) missing . push ( 'author' ) ;
112
+ console . log ( ` ${ file } : missing ${ missing . join ( ', ' ) } ` ) ;
113
+ } ) ;
114
+ }
115
+ }
116
+
117
+ // Run the generator
118
+ generateEntriesJs ( ) ;
0 commit comments