@@ -50,13 +50,35 @@ const out = module.exports.docs;
5050
5151const combinedFiles = [ ] ;
5252for ( const file of files ) {
53- const comments = dox . parseComments ( fs . readFileSync ( `./${ file } ` , 'utf8' ) , { raw : true } ) ;
54- comments . file = file ;
55- combinedFiles . push ( comments ) ;
53+ try {
54+ const comments = dox . parseComments ( fs . readFileSync ( `./${ file } ` , 'utf8' ) , { raw : true } ) ;
55+ comments . file = file ;
56+ combinedFiles . push ( comments ) ;
57+ } catch ( err ) {
58+ // show log of which file has thrown a error for easier debugging
59+ console . error ( "Error while trying to parseComments for " , file ) ;
60+ throw err ;
61+ }
5662}
5763
5864parse ( ) ;
5965
66+ /**
67+ * @typedef {Object } PropContext
68+ * @property {boolean } [isStatic] Defines wheter the current property is a static property (not mutually exlusive with "isInstance")
69+ * @property {boolean } [isInstance] Defines wheter the current property is a instance property (not mutually exlusive with "isStatic")
70+ * @property {boolean } [isFunction] Defines wheter the current property is meant to be a function
71+ * @property {string } [constructor] Defines the Constructor (or rather path) the current property is on
72+ * @property {boolean } [constructorWasUndefined] Defined wheter the "constructor" property was defined by "dox", but was set to "undefined"
73+ * @property {string } [type] Defines the type the property is meant to be
74+ * @property {string } [name] Defines the current Properties name
75+ * @property {Object } [return] The full object for a "@return" jsdoc tag
76+ * @property {string } [string] Defines the full string the property will be listed as
77+ * @property {string } [anchorId] Defines the Anchor ID to be used for linking
78+ * @property {string } [description] Defines the Description the property will be listed with
79+ * @property {string } [deprecated] Defines wheter the current Property is signaled as deprecated
80+ */
81+
6082function parse ( ) {
6183 for ( const props of combinedFiles ) {
6284 let name = props . file .
@@ -88,43 +110,67 @@ function parse() {
88110 if ( prop . ignore || prop . isPrivate ) {
89111 continue ;
90112 }
91-
113+
114+ /** @type {PropContext } */
92115 const ctx = prop . ctx || { } ;
116+
117+ // somehow in "dox", it is named "receiver" sometimes, not "constructor"
118+ // this is used as a fall-back if the handling below does not overwrite it
119+ if ( "receiver" in ctx ) {
120+ ctx . constructor = ctx . receiver ;
121+ delete ctx . receiver ;
122+ }
123+
124+ // in some cases "dox" has "ctx.constructor" defined but set to "undefined", which will later be used for setting "ctx.string"
125+ if ( "constructor" in ctx && ctx . constructor === undefined ) {
126+ ctx . constructorWasUndefined = true ;
127+ }
128+
93129 for ( const tag of prop . tags ) {
94130 switch ( tag . type ) {
95131 case 'receiver' :
96132 ctx . constructor = tag . string ;
97133 break ;
98134 case 'property' :
99135 ctx . type = 'property' ;
136+
137+ // somewhere since 6.0 the "string" property came back, which was gone with 4.5
100138 let str = tag . string ;
139+
101140 const match = str . match ( / ^ { \w + } / ) ;
102141 if ( match != null ) {
103142 ctx . type = match [ 0 ] . substring ( 1 , match [ 0 ] . length - 1 ) ;
104143 str = str . replace ( / ^ { \w + } \s * / , '' ) ;
105144 }
106145 ctx . name = str ;
107- ctx . string = `${ ctx . constructor } .prototype.${ ctx . name } ` ;
108146 break ;
109147 case 'type' :
110148 ctx . type = Array . isArray ( tag . types ) ? tag . types . join ( '|' ) : tag . types ;
111149 break ;
112150 case 'static' :
113151 ctx . type = 'property' ;
114- ctx . static = true ;
115- ctx . name = tag . string ;
116- ctx . string = ` ${ data . name } . ${ ctx . name } ` ;
152+ ctx . isStatic = true ;
153+ // dont take " string" as "name" from here, because jsdoc definitions of "static" do not have parameters, also its defined elsewhere anyway
154+ // ctx.name = tag.string ;
117155 break ;
118156 case 'function' :
119157 ctx . type = 'function' ;
120- ctx . static = true ;
158+ ctx . isStatic = true ;
121159 ctx . name = tag . string ;
122- ctx . string = `${ data . name } .${ ctx . name } ()` ;
160+ // extra parameter to make function definitions independant of where "@function" is defined
161+ // like "@static" could have overwritten "ctx.string" again if defined after "@function"
162+ ctx . isFunction = true ;
123163 break ;
124164 case 'return' :
125- tag . return = tag . description ?
126- md . parse ( tag . description ) . replace ( / ^ < p > / , '' ) . replace ( / < \/ p > $ / , '' ) :
165+ tag . description = tag . description ?
166+ md . parse ( tag . description ) . replace ( / ^ < p > / , '' ) . replace ( / < \/ p > \n ? $ / , '' ) :
127167 '' ;
168+
169+ // dox does not add "void" / "undefined" to types, so in the documentation it would result in a empty "«»"
170+ if ( tag . string . includes ( 'void' ) || tag . string . includes ( 'undefined' ) ) {
171+ tag . types . push ( "void" ) ;
172+ }
173+
128174 ctx . return = tag ;
129175 break ;
130176 case 'inherits' :
@@ -133,6 +179,10 @@ function parse() {
133179 case 'event' :
134180 case 'param' :
135181 ctx [ tag . type ] = ( ctx [ tag . type ] || [ ] ) ;
182+ // the following is required, because in newer "dox" version "null" is not included in "types" anymore, but a seperate property
183+ if ( tag . nullable ) {
184+ tag . types . push ( 'null' ) ;
185+ }
136186 if ( tag . types ) {
137187 tag . types = tag . types . join ( '|' ) ;
138188 }
@@ -147,26 +197,49 @@ function parse() {
147197 case 'method' :
148198 ctx . type = 'method' ;
149199 ctx . name = tag . string ;
150- ctx . string = ` ${ ctx . constructor } .prototype. ${ ctx . name } ()` ;
200+ ctx . isFunction = true ;
151201 break ;
152202 case 'memberOf' :
153203 ctx . constructor = tag . parent ;
154- ctx . string = `${ ctx . constructor } .prototype.${ ctx . name } ` ;
155- if ( ctx . type === 'method' ) {
156- ctx . string += '()' ;
157- }
158204 break ;
159205 case 'constructor' :
160- ctx . string = tag . string + '()' ;
206+ ctx . string = tag . string ;
161207 ctx . name = tag . string ;
208+ ctx . isFunction = true ;
209+ break ;
210+ case 'instance' :
211+ ctx . isInstance = true ;
212+ break ;
213+ case 'deprecated' :
214+ ctx . deprecated = true ;
215+ break ;
162216 }
163217 }
164218
219+ if ( ctx . isInstance && ctx . isStatic ) {
220+ console . warn ( `Property "${ ctx . name } " in "${ ctx . constructor } " has both instance and static JSDOC markings (most likely both @instance and @static)! (File: "${ props . file } ")` ) ;
221+ }
222+
223+ // the following if-else-if statement is in this order, because there are more "instance" methods thans static
224+ // the following condition will be true if "isInstance = true" or if "isInstance = false && isStatic = false" AND "ctx.string" are empty or not defined
225+ // if "isStatic" and "isInstance" are falsy and "ctx.string" is not falsy, then rely on the "ctx.string" set by "dox"
226+ if ( ctx . isInstance || ( ! ctx . isStatic && ! ctx . isInstance && ( ! ctx . string || ctx . constructorWasUndefined ) ) ) {
227+ ctx . string = `${ ctx . constructor } .prototype.${ ctx . name } ` ;
228+ } else if ( ctx . isStatic ) {
229+ ctx . string = `${ ctx . constructor } .${ ctx . name } ` ;
230+ }
231+
232+ // add "()" to the end of the string if function
233+ if ( ( ctx . isFunction || ctx . type === "method" ) && ! ctx . string . endsWith ( "()" ) ) {
234+ ctx . string = ctx . string + "()" ;
235+ }
236+
237+ // fixing up "something.prototypemissingdot" to "something.prototype.missingdot"
165238 if ( / \. p r o t o t y p e [ ^ . ] / . test ( ctx . string ) ) {
166239 ctx . string = `${ ctx . constructor } .prototype.${ ctx . name } ` ;
167240 }
168241
169- // Backwards compat
242+ // Backwards compat anchors
170243 if ( typeof ctx . constructor === 'string' ) {
171244 ctx . anchorId = `${ ctx . constructor . toLowerCase ( ) } _${ ctx . constructor } -${ ctx . name } ` ;
172245 } else if ( typeof ctx . receiver === 'string' ) {
@@ -178,9 +251,6 @@ function parse() {
178251 ctx . description = prop . description . full .
179252 replace ( / < b r \/ > / ig, ' ' ) .
180253 replace ( / & g t ; / ig, '>' ) ;
181- if ( ctx . description . includes ( 'function capitalize' ) ) {
182- console . log ( '\n\n-------\n\n' , ctx ) ;
183- }
184254 ctx . description = md . parse ( ctx . description ) ;
185255
186256 data . props . push ( ctx ) ;
0 commit comments