22 DEFAULT_EXPRESSION ,
33 LEADING_HYPHEN ,
44 NAME_EXPRESSION ,
5+ PARAM_EXPRESSION ,
56 RETURN_EXPRESSION ,
67 TYPE_EXPRESSION ,
78} from '../constants.mjs' ;
@@ -33,10 +34,14 @@ function createMeta(entry) {
3334 if ( added_in || n_api_version || deprecated_in || removed_in ) {
3435 return {
3536 changes,
36- added : makeArrayIfNotAlready ( added_in ) ,
37- napiVersion : makeArrayIfNotAlready ( n_api_version ) ,
38- deprecated : makeArrayIfNotAlready ( deprecated_in ) ,
39- removed : makeArrayIfNotAlready ( removed_in ) ,
37+ added : added_in ? makeArrayIfNotAlready ( added_in ) : undefined ,
38+ napiVersion : n_api_version
39+ ? makeArrayIfNotAlready ( n_api_version )
40+ : undefined ,
41+ deprecated : deprecated_in
42+ ? makeArrayIfNotAlready ( deprecated_in )
43+ : undefined ,
44+ removed : removed_in ? makeArrayIfNotAlready ( removed_in ) : undefined ,
4045 } ;
4146 }
4247
@@ -51,27 +56,30 @@ function createMeta(entry) {
5156function createSection ( entry , head ) {
5257 const text = textJoin ( head . children ) ;
5358
54- // TODO check if type or name can be undefined
5559 return {
5660 textRaw : text ,
5761 type : head . data . type ,
58- name : head . data . name ,
62+ name : text . toLowerCase ( ) . replaceAll ( ' ' , '_' ) ,
63+ displayName : head . data . name ,
5964 meta : createMeta ( entry ) ,
65+ introduced_in : entry . introduced_in ,
6066 } ;
6167}
6268
6369/**
64- *
65- * @param {Array<import('../types.d.ts').List } values TODO type
70+ * @param { string } textRaw Something like `new buffer.Blob([sources[, options]])`
71+ * @param {Array<import('../types.d.ts').List } values
6672 * @returns {import('../types.d.ts').MethodSignature }
6773 */
68- function parseSignature ( values ) {
74+ function parseSignature ( textRaw , values ) {
6975 /**
7076 * @type {import('../types.d.ts').MethodSignature }
7177 */
72- const signature = { } ;
78+ const signature = {
79+ params : [ ] ,
80+ } ;
7381
74- signature . params = values . filter ( value => {
82+ const rawParameters = values . filter ( value => {
7583 if ( value . name === 'return' ) {
7684 signature . return = value ;
7785 return false ;
@@ -80,7 +88,127 @@ function parseSignature(values) {
8088 return true ;
8189 } ) ;
8290
83- // TODO the unfortunate logic
91+ /**
92+ * Extract a list of the signatures from the method's declaration
93+ * @example `[sources[, options]]`
94+ */
95+ let [ , declaredParameters ] = textRaw . match ( PARAM_EXPRESSION ) || [ ] ;
96+
97+ if ( ! declaredParameters ) {
98+ return ;
99+ }
100+
101+ /**
102+ * @type {string[] }
103+ * @example ['sources[,', 'options]]']
104+ */
105+ declaredParameters = declaredParameters . split ( ',' ) ;
106+
107+ let optionalDepth = 0 ;
108+ const optionalCharDict = { '[' : 1 , ' ' : 0 , ']' : - 1 } ;
109+
110+ declaredParameters . forEach ( ( declaredParameter , i ) => {
111+ /**
112+ * @example 'length]]'
113+ * @example 'arrayBuffer['
114+ * @example '[sources['
115+ * @example 'end'
116+ */
117+ declaredParameter = declaredParameter . trim ( ) ;
118+
119+ if ( ! declaredParameter ) {
120+ throw new Error ( `Empty parameter slot: ${ textRaw } ` ) ;
121+ }
122+
123+ // We need to find out if this parameter is optional or not. We can tell this
124+ // if we're wrapped in brackets, so let's look for them.
125+
126+ let pos ;
127+ for ( pos = 0 ; pos < declaredParameter . length ; pos ++ ) {
128+ const levelChange = optionalCharDict [ declaredParameter [ pos ] ] ;
129+
130+ if ( levelChange === undefined ) {
131+ break ;
132+ }
133+
134+ optionalDepth += levelChange ;
135+ }
136+
137+ // Cut off any trailing brackets
138+ declaredParameter = declaredParameter . substring ( pos ) ;
139+
140+ const isParameterOptional = optionalDepth > 0 ;
141+
142+ for ( pos = declaredParameter . length - 1 ; pos >= 0 ; pos -- ) {
143+ const levelChange = optionalCharDict [ declaredParameter [ pos ] ] ;
144+
145+ if ( levelChange === undefined ) {
146+ break ;
147+ }
148+
149+ optionalDepth += levelChange ;
150+ }
151+
152+ // Cut off any leading brackets
153+ declaredParameter = declaredParameter . substring ( 0 , pos + 1 ) ;
154+
155+ // Default value of this parameter in the method's declaration
156+ let defaultValue ;
157+
158+ const equalSignPos = declaredParameter . indexOf ( '=' ) ;
159+ if ( equalSignPos !== - 1 ) {
160+ // We have a default value, save it and then cut it off of the signature
161+ defaultValue = declaredParameter . substring ( equalSignPos , 1 ) . trim ( ) ;
162+ declaredParameter = declaredParameter . substring ( 0 , equalSignPos ) ;
163+ console . log ( 'eq' , declaredParameter ) ;
164+ }
165+
166+ let parameter = rawParameters [ i ] ;
167+ if ( ! parameter || declaredParameter !== parameter . name ) {
168+ // If we're here then the method likely has shared signatures
169+ // Something like, `new Console(stdout[, stderr][, ignoreErrors])` and
170+ // `new Console(options)`
171+ parameter = undefined ;
172+
173+ // Try finding a parameter this is being shared with
174+ for ( const otherParam of rawParameters ) {
175+ if ( declaredParameter === otherParam . name ) {
176+ // Found a matching one
177+ // TODO break?
178+ parameter = otherParam ;
179+ } else if ( otherParam . options ) {
180+ // Found a matching one in the parameter's options
181+ for ( const option of otherParam . options ) {
182+ if ( declaredParameter === option . name ) {
183+ parameter = Object . assign ( { } , option ) ;
184+ break ;
185+ }
186+ }
187+ }
188+ }
189+
190+ if ( ! parameter ) {
191+ // Couldn't find the shared one, I have no idea what this case is but we'll see
192+ if ( declaredParameter . startsWith ( '...' ) ) {
193+ parameter = { name : declaredParameter } ;
194+ } else {
195+ throw new Error (
196+ `Invalid param "${ declaredParameter } "\n` + ` > ${ textRaw } `
197+ ) ;
198+ }
199+ }
200+ }
201+
202+ if ( isParameterOptional ) {
203+ parameter . optional = true ;
204+ }
205+
206+ if ( defaultValue ) {
207+ parameter . default = defaultValue ;
208+ }
209+
210+ signature . params . push ( parameter ) ;
211+ } ) ;
84212
85213 return signature ;
86214}
@@ -93,9 +221,6 @@ function textJoin(nodes) {
93221 return nodes
94222 . map ( node => {
95223 switch ( node . type ) {
96- case 'linkReference' :
97- console . error ( `todo link reference` ) ;
98- return `TODO` ;
99224 case `strong` :
100225 return `**${ textJoin ( node . children ) } **` ;
101226 case `emphasis` :
@@ -122,10 +247,9 @@ function parseListItem(child) {
122247 */
123248 const current = { } ;
124249
125- // TODO this
126- // current.textRaw = child.children
127- // .filter(node => node.type !== 'list')
128- // .map(node => node.)
250+ current . textRaw = textJoin (
251+ child . children . filter ( node => node . type !== 'list' )
252+ ) ;
129253
130254 if ( ! current . textRaw ) {
131255 throw new Error ( `empty list item: ${ JSON . stringify ( child ) } ` ) ;
@@ -159,7 +283,7 @@ function parseListItem(child) {
159283 const [ , defaultValue ] = text . match ( DEFAULT_EXPRESSION ) || [ ] ;
160284 if ( defaultValue ) {
161285 current . default = defaultValue . replace ( / \. $ / , '' ) ;
162- text = text . parseListItem ( DEFAULT_EXPRESSION , '' ) ;
286+ text = text . replace ( DEFAULT_EXPRESSION , '' ) ;
163287 }
164288
165289 // Add remaining text to the desc
@@ -257,8 +381,7 @@ function handleEntry(entry, parentSection) {
257381 case 'ctor' :
258382 case 'classMethod' :
259383 case 'method' : {
260- const signature = parseSignature ( values ) ;
261- section . signatures = [ signature ] ;
384+ section . signatures = [ parseSignature ( section . textRaw , values ) ] ;
262385
263386 break ;
264387 }
@@ -330,7 +453,7 @@ function handleEntry(entry, parentSection) {
330453 * @param {import('../types.d.ts').Section } parentSection
331454 */
332455 const makeChildrenTopLevelIfMisc = ( section , parentSection ) => {
333- if ( parentSection . type = == 'misc' ) {
456+ if ( parentSection . type ! == 'misc' ) {
334457 return ;
335458 }
336459
0 commit comments