@@ -7,6 +7,7 @@ const path = require('path');
77
88// Configuration
99const PASSPORT_ROOT = './sample/Assets/Scripts/Passport' ;
10+ const TUTORIALS_DIR = path . join ( PASSPORT_ROOT , '_tutorials' ) ;
1011const OUTPUT_DIR = './_parsed' ;
1112const OUTPUT_FILE = path . join ( OUTPUT_DIR , 'passport-features.json' ) ;
1213const FEATURES_JSON_PATH = path . join ( PASSPORT_ROOT , 'features.json' ) ;
@@ -23,138 +24,105 @@ try {
2324
2425console . log ( 'Processing Passport features metadata...' ) ;
2526
26- // Load features.json to map script files to feature names
27- const featuresMap = { } ;
27+ // Load features.json to get feature groups and their features
28+ let featureGroups = { } ;
2829try {
2930 const featuresContent = fs . readFileSync ( FEATURES_JSON_PATH , 'utf8' ) ;
3031 const featuresJson = JSON . parse ( featuresContent ) ;
31-
32- // Create mapping of script filename to feature name
33- featuresJson . features . forEach ( ( feature ) => {
34- const [ featureName , scriptFile ] = Object . entries ( feature ) [ 0 ] ;
35- // Store both the full filename and just the filename without path
36- featuresMap [ scriptFile ] = featureName ;
37- featuresMap [ path . basename ( scriptFile ) ] = featureName ;
38- } ) ;
32+ featureGroups = featuresJson . features || { } ;
3933} catch ( error ) {
4034 console . error ( `Error reading features.json: ${ error . message } ` ) ;
4135 process . exit ( 1 ) ;
4236}
4337
44- // Platform-independent recursive file search
45- const findMetadataFiles = ( ) => {
46- const metadataFiles = [ ] ;
38+ // Find all feature group directories in _tutorials
39+ const findFeatureGroupDirectories = ( ) => {
40+ const featureGroupDirs = [ ] ;
41+
42+ if ( ! fs . existsSync ( TUTORIALS_DIR ) ) {
43+ console . warn ( `Tutorials directory does not exist: ${ TUTORIALS_DIR } ` ) ;
44+ return featureGroupDirs ;
45+ }
4746
48- const walkDir = ( dir ) => {
49- if ( ! fs . existsSync ( dir ) ) {
50- console . warn ( `Directory does not exist: ${ dir } ` ) ;
51- return ;
52- }
47+ try {
48+ const dirs = fs . readdirSync ( TUTORIALS_DIR , { withFileTypes : true } ) ;
5349
54- try {
55- const files = fs . readdirSync ( dir ) ;
56-
57- files . forEach ( ( file ) => {
58- const filePath = path . join ( dir , file ) ;
59-
60- try {
61- const stat = fs . statSync ( filePath ) ;
62-
63- if ( stat . isDirectory ( ) ) {
64- walkDir ( filePath ) ;
65- } else if ( file === 'metadata.json' ) {
66- metadataFiles . push ( filePath ) ;
67- }
68- } catch ( err ) {
69- console . warn ( `Error accessing file ${ filePath } : ${ err . message } ` ) ;
70- }
71- } ) ;
72- } catch ( err ) {
73- console . warn ( `Error reading directory ${ dir } : ${ err . message } ` ) ;
74- }
75- } ;
50+ dirs . forEach ( ( dirent ) => {
51+ if ( dirent . isDirectory ( ) ) {
52+ featureGroupDirs . push ( path . join ( TUTORIALS_DIR , dirent . name ) ) ;
53+ }
54+ } ) ;
55+ } catch ( err ) {
56+ console . warn ( `Error reading tutorials directory ${ TUTORIALS_DIR } : ${ err . message } ` ) ;
57+ }
7658
77- walkDir ( PASSPORT_ROOT ) ;
78- return metadataFiles ;
59+ return featureGroupDirs ;
7960} ;
8061
8162// Process metadata files
82- const processMetadataFiles = ( metadataFiles ) => {
63+ const processFeatureGroups = ( featureGroupDirs ) => {
8364 const featuresObject = { } ;
8465
85- metadataFiles . forEach ( ( metadataFile ) => {
86- console . log ( `Processing ${ metadataFile } ` ) ;
87-
88- // Extract feature directory
89- const featureDir = path . dirname ( metadataFile ) ;
66+ featureGroupDirs . forEach ( ( groupDir ) => {
67+ const groupName = path . basename ( groupDir ) ;
68+ console . log ( `Processing feature group: ${ groupName } ` ) ;
9069
91- // Get directory name as fallback feature name
92- const dirName = path . basename ( featureDir ) ;
70+ // Check if this group exists in features.json
71+ if ( ! featureGroups [ groupName ] ) {
72+ console . warn ( `Feature group ${ groupName } not found in features.json, skipping` ) ;
73+ return ;
74+ }
9375
94- // Try to find feature name in feature map, fallback to directory name
95- let featureName = '' ;
96- try {
97- // Look for any script file in this directory
98- const dirFiles = fs . readdirSync ( featureDir ) ;
99- const scriptFiles = dirFiles . filter ( ( file ) => file . endsWith ( '.cs' ) ) ;
100-
101- // Try to match any script file to our feature map
102- let found = false ;
103- for ( const scriptFile of scriptFiles ) {
104- if ( featuresMap [ scriptFile ] ) {
105- featureName = featuresMap [ scriptFile ] ;
106- found = true ;
107- break ;
108- }
109- }
110-
111- if ( ! found ) {
112- console . warn ( `No feature found in features.json for ${ featureDir } , using directory name` ) ;
113- featureName = dirName ;
114- }
115- } catch ( error ) {
116- console . warn ( `Error processing directory ${ featureDir } : ${ error . message } ` ) ;
117- featureName = dirName ;
76+ // Path to metadata.json in this feature group directory
77+ const metadataPath = path . join ( groupDir , 'metadata.json' ) ;
78+ if ( ! fs . existsSync ( metadataPath ) ) {
79+ console . warn ( `No metadata.json found for feature group ${ groupName } in ${ groupDir } ` ) ;
80+ return ;
11881 }
11982
120- // Create feature key (kebab-case)
121- const featureKey = featureName
83+ // Path to tutorial.md in this feature group directory
84+ const tutorialPath = path . join ( groupDir , 'tutorial.md' ) ;
85+ const tutorialExists = fs . existsSync ( tutorialPath ) ;
86+
87+ // Create the feature key (kebab-case)
88+ const featureKey = groupName
12289 . replace ( / ( [ a - z ] ) ( [ A - Z ] ) / g, '$1-$2' )
12390 . replace ( / \s + / g, '-' )
12491 . replace ( / [ ^ a - z 0 - 9 - ] / gi, '' )
12592 . toLowerCase ( ) ;
12693
12794 if ( ! featureKey ) {
128- console . warn ( `Generated empty feature key for ${ featureDir } , skipping` ) ;
95+ console . warn ( `Generated empty feature key for ${ groupName } , skipping` ) ;
12996 return ;
13097 }
13198
132- // Check for tutorial.md in the same directory
133- const tutorialPath = path . join ( featureDir , 'tutorial.md' ) ;
134- const tutorialExists = fs . existsSync ( tutorialPath ) ;
13599 const tutorialFile = tutorialExists ? `${ featureKey } .md` : null ;
136100
137101 if ( ! tutorialExists ) {
138- console . warn ( `No tutorial.md found for feature ${ featureName } in ${ featureDir } ` ) ;
102+ console . warn ( `No tutorial.md found for feature group ${ groupName } in ${ groupDir } ` ) ;
139103 }
140104
141105 // Read and process metadata
142106 try {
143- const metadataContent = fs . readFileSync ( metadataFile , 'utf8' ) ;
107+ const metadataContent = fs . readFileSync ( metadataPath , 'utf8' ) ;
144108 const metadata = JSON . parse ( metadataContent ) ;
145109
146110 // Add additional fields
147- metadata . title = metadata . title || featureName ;
111+ metadata . title = metadata . title || groupName ;
148112 metadata . sidebar_order = metadata . sidebar_order || 0 ;
149113 metadata . deprecated = metadata . deprecated || false ;
150114
115+ // Add feature group information
116+ metadata . feature_group = groupName ;
117+ metadata . features = Object . keys ( featureGroups [ groupName ] || { } ) ;
118+
151119 // Create the feature entry
152120 featuresObject [ featureKey ] = {
153121 tutorial : tutorialFile ,
154122 metadata : metadata
155123 } ;
156124 } catch ( error ) {
157- console . error ( `Error processing metadata file ${ metadataFile } : ${ error . message } ` ) ;
125+ console . error ( `Error processing metadata file ${ metadataPath } : ${ error . message } ` ) ;
158126 }
159127 } ) ;
160128
@@ -163,13 +131,13 @@ const processMetadataFiles = (metadataFiles) => {
163131
164132try {
165133 // Main execution
166- const metadataFiles = findMetadataFiles ( ) ;
134+ const featureGroupDirs = findFeatureGroupDirectories ( ) ;
167135
168- if ( metadataFiles . length === 0 ) {
169- console . warn ( 'No metadata files found. Output file will be empty.' ) ;
136+ if ( featureGroupDirs . length === 0 ) {
137+ console . warn ( 'No feature group directories found. Output file will be empty.' ) ;
170138 }
171139
172- const features = processMetadataFiles ( metadataFiles ) ;
140+ const features = processFeatureGroups ( featureGroupDirs ) ;
173141
174142 // Create the final passport-features.json
175143 fs . writeFileSync ( OUTPUT_FILE , JSON . stringify ( features , null , 2 ) ) ;
0 commit comments