@@ -4,16 +4,16 @@ import {
4
4
TSDocConfiguration
5
5
} from '@microsoft/tsdoc' ;
6
6
import * as fs from 'fs' ;
7
+ import * as resolve from 'resolve' ;
7
8
import * as path from 'path' ;
8
9
import * as Ajv from 'ajv' ;
9
10
10
11
const ajv : Ajv . Ajv = new Ajv ( { verbose : true } ) ;
11
12
12
13
function initializeSchemaValidator ( ) : Ajv . ValidateFunction {
13
- const jsonSchemaContent : string = fs . readFileSync ( path . join ( __dirname , 'schemas /tsdoc-config .schema.json') )
14
- . toString ( ) ;
14
+ const jsonSchemaPath : string = resolve . sync ( '@microsoft /tsdoc/schemas/tsdocconfig .schema.json', { basedir : __dirname } ) ;
15
+ const jsonSchemaContent : string = fs . readFileSync ( jsonSchemaPath ) . toString ( ) ;
15
16
const jsonSchema : object = JSON . parse ( jsonSchemaContent ) ;
16
-
17
17
return ajv . compile ( jsonSchema ) ;
18
18
}
19
19
@@ -36,25 +36,30 @@ interface IConfigJson {
36
36
}
37
37
38
38
/**
39
- * Represents an individual `tsdoc-config .json` file.
39
+ * Represents an individual `tsdocconfig .json` file.
40
40
*
41
41
* @public
42
42
*/
43
43
export class TSDocConfigFile {
44
+ public static readonly FILENAME : string = 'tsdocconfig.json' ;
45
+ public static readonly CURRENT_SCHEMA_URL : string = 'https://developer.microsoft.com/json-schemas/tsdoc/v1/tsdocconfig.schema.json' ;
46
+
44
47
private readonly _extendsFiles : TSDocConfigFile [ ] = [ ] ;
45
48
46
49
/**
47
- * The full path of the file.
50
+ * The full path of the file that was attempted to load .
48
51
*/
49
52
public readonly filePath : string ;
50
53
54
+ public readonly fileNotFound : boolean = false ;
55
+
51
56
/**
52
- * The `$schema` field from the `tsdoc-config .json` file.
57
+ * The `$schema` field from the `tsdocconfig .json` file.
53
58
*/
54
59
public readonly tsdocSchema : string ;
55
60
56
61
/**
57
- * The `extends` field from the `tsdoc-config .json` file. For the parsed file contents,
62
+ * The `extends` field from the `tsdocconfig .json` file. For the parsed file contents,
58
63
* use the `extendsFiles` property instead.
59
64
*/
60
65
public readonly extendsPaths : ReadonlyArray < string > ;
@@ -99,11 +104,11 @@ export class TSDocConfigFile {
99
104
*
100
105
* @remarks
101
106
*
102
- * This method does not process the `extends` field of `tsdoc-config .json`.
103
- * For full functionality, including discovery of the file path, use the {@link ConfigLoader }
107
+ * This method does not process the `extends` field of `tsdocconfig .json`.
108
+ * For full functionality, including discovery of the file path, use the {@link TSDocConfigFileSet }
104
109
* API instead.
105
110
*/
106
- public static loadFromFile ( jsonFilePath : string ) : TSDocConfigFile {
111
+ private static _loadSingleFile ( jsonFilePath : string ) : TSDocConfigFile {
107
112
const fullJsonFilePath : string = path . resolve ( jsonFilePath ) ;
108
113
109
114
const configJsonContent : string = fs . readFileSync ( fullJsonFilePath ) . toString ( ) ;
@@ -117,9 +122,70 @@ export class TSDocConfigFile {
117
122
+ '\nError in file: ' + jsonFilePath ) ;
118
123
}
119
124
125
+ if ( configJson . $schema !== TSDocConfigFile . CURRENT_SCHEMA_URL ) {
126
+ throw new Error ( 'Expecting JSON "$schema" field to be ' + TSDocConfigFile . CURRENT_SCHEMA_URL
127
+ + '\nError in file: ' + jsonFilePath ) ;
128
+ }
129
+
120
130
return new TSDocConfigFile ( fullJsonFilePath , configJson ) ;
121
131
}
122
132
133
+ private static _findConfigPathForFolder ( folderPath : string ) : string {
134
+ if ( folderPath ) {
135
+ let foundFolder : string = folderPath ;
136
+ for ( ; ; ) {
137
+ const tsconfigFilePath : string = path . join ( foundFolder , 'tsconfig.json' ) ;
138
+ if ( fs . existsSync ( tsconfigFilePath ) ) {
139
+ // Success
140
+ return path . join ( foundFolder , TSDocConfigFile . FILENAME ) ;
141
+ }
142
+
143
+ const previousFolder : string = foundFolder ;
144
+ foundFolder = path . dirname ( foundFolder ) ;
145
+
146
+ if ( ! foundFolder || foundFolder === previousFolder ) {
147
+ // Failed
148
+ break ;
149
+ }
150
+ }
151
+ }
152
+ return '' ;
153
+ }
154
+
155
+ private static _loadWithExtends ( configFilePath : string , alreadyVisitedPaths : Set < string > ) : TSDocConfigFile {
156
+ const hashKey : string = fs . realpathSync ( configFilePath ) ;
157
+ if ( alreadyVisitedPaths . has ( hashKey ) ) {
158
+ throw new Error ( 'Circular reference encountered for "extends" field of ' + configFilePath ) ;
159
+ }
160
+ alreadyVisitedPaths . add ( hashKey ) ;
161
+
162
+ const configFile : TSDocConfigFile = TSDocConfigFile . _loadSingleFile ( configFilePath ) ;
163
+
164
+ const configFileFolder : string = path . dirname ( configFile . filePath ) ;
165
+
166
+ for ( const extendsField of configFile . extendsPaths ) {
167
+ const resolvedExtendsPath : string = resolve . sync ( extendsField , { basedir : configFileFolder } ) ;
168
+ if ( ! fs . existsSync ( resolvedExtendsPath ) ) {
169
+ throw new Error ( 'Unable to resolve "extends" field of ' + configFilePath ) ;
170
+ }
171
+
172
+ const baseConfigFile : TSDocConfigFile = TSDocConfigFile . _loadWithExtends ( resolvedExtendsPath , alreadyVisitedPaths ) ;
173
+ configFile . addExtendsFile ( baseConfigFile ) ;
174
+ }
175
+
176
+ return configFile ;
177
+ }
178
+
179
+ /**
180
+ * For the given folder, discover the relevant tsdocconfig.json files (if any), and load them.
181
+ * @param folderPath - the path to a folder where the search should start
182
+ */
183
+ public static loadForFolder ( folderPath : string ) : TSDocConfigFile {
184
+ const rootConfigPath : string = TSDocConfigFile . _findConfigPathForFolder ( folderPath ) ;
185
+ const alreadyVisitedPaths : Set < string > = new Set < string > ( ) ;
186
+ return TSDocConfigFile . _loadWithExtends ( rootConfigPath , alreadyVisitedPaths ) ;
187
+ }
188
+
123
189
/**
124
190
* Adds an item to `TSDocConfigFile.extendsFiles`.
125
191
*/
@@ -131,10 +197,10 @@ export class TSDocConfigFile {
131
197
* Applies the settings from this config file to a TSDoc parser configuration.
132
198
* Any `extendsFile` settings will also applied.
133
199
*/
134
- public applyToParserConfiguration ( configuration : TSDocConfiguration ) : void {
200
+ public configureParser ( configuration : TSDocConfiguration ) : void {
135
201
// First apply the base config files
136
202
for ( const extendsFile of this . extendsFiles ) {
137
- extendsFile . applyToParserConfiguration ( configuration ) ;
203
+ extendsFile . configureParser ( configuration ) ;
138
204
}
139
205
140
206
// The apply this one
0 commit comments