@@ -148,6 +148,18 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
148148 }
149149
150150 apply ( compiler : webpack . Compiler ) : void {
151+ // Property compiler.version is set only starting from webpack 5
152+ const webpackVersion = compiler . webpack ?. version || "" ;
153+ const isWebpack5 = parseInt ( webpackVersion . split ( "." ) [ 0 ] , 10 ) >= 5 ;
154+
155+ if ( isWebpack5 ) {
156+ this . applyWebpack5 ( compiler ) ;
157+ } else {
158+ this . applyWebpack4 ( compiler ) ;
159+ }
160+ }
161+
162+ applyWebpack5 ( compiler : webpack . Compiler ) : void {
151163 const pluginName = "DocGenPlugin" ;
152164 const {
153165 docgenOptions,
@@ -161,29 +173,24 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
161173 const { exclude = [ ] , include = [ "**/**.tsx" ] } = this . options ;
162174 const isExcluded = matchGlob ( exclude ) ;
163175 const isIncluded = matchGlob ( include ) ;
164- // Property compiler.version is set only starting from webpack 5
165- const webpackVersion = compiler . webpack ?. version || "" ;
166- const isWebpack5 = parseInt ( webpackVersion . split ( "." ) [ 0 ] , 10 ) >= 5 ;
167176
168177 compiler . hooks . compilation . tap (
169178 pluginName ,
170179 ( compilation : webpack . Compilation ) => {
171- if ( isWebpack5 ) {
172- // Since this file is needed only for webpack 5, load it only then
173- // to simplify the implementation of the file.
174- //
175- // eslint-disable-next-line
176- const { DocGenDependency } = require ( "./dependency" ) ;
180+ // Since this file is needed only for webpack 5, load it only then
181+ // to simplify the implementation of the file.
182+ //
183+ // eslint-disable-next-line
184+ const { DocGenDependency } = require ( "./dependency" ) ;
177185
178- compilation . dependencyTemplates . set (
179- // eslint-disable-next-line
180- // @ts -ignore: Webpack 4 type
181- DocGenDependency ,
182- // eslint-disable-next-line
183- // @ts -ignore: Webpack 4 type
184- new DocGenDependency . Template ( )
185- ) ;
186- }
186+ compilation . dependencyTemplates . set (
187+ // eslint-disable-next-line
188+ // @ts -ignore: Webpack 4 type
189+ DocGenDependency ,
190+ // eslint-disable-next-line
191+ // @ts -ignore: Webpack 4 type
192+ new DocGenDependency . Template ( )
193+ ) ;
187194
188195 compilation . hooks . seal . tap ( pluginName , ( ) => {
189196 const modulesToProcess : [ string , webpack . Module ] [ ] = [ ] ;
@@ -196,6 +203,30 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
196203
197204 const nameForCondition = module . nameForCondition ( ) || "" ;
198205
206+ // Ignore modules that haven't been built yet for webpack 5
207+ if ( ! compilation . builtModules . has ( module ) ) {
208+ debugExclude ( `Ignoring un-built module: ${ nameForCondition } ` ) ;
209+ return ;
210+ }
211+
212+ // Ignore external modules
213+ // eslint-disable-next-line
214+ // @ts -ignore: Webpack 4 type
215+ if ( module . external ) {
216+ debugExclude ( `Ignoring external module: ${ nameForCondition } ` ) ;
217+ return ;
218+ }
219+
220+ // Ignore raw requests
221+ // eslint-disable-next-line
222+ // @ts -ignore: Webpack 4 type
223+ if ( ! module . rawRequest ) {
224+ debugExclude (
225+ `Ignoring module without "rawRequest": ${ nameForCondition } `
226+ ) ;
227+ return ;
228+ }
229+
199230 if ( isExcluded ( nameForCondition ) ) {
200231 debugExclude (
201232 `Module not matched in "exclude": ${ nameForCondition } `
@@ -222,38 +253,122 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
222253 // 3. Process and parse each module and add the type information
223254 // as a dependency
224255 modulesToProcess . forEach ( ( [ name , module ] ) => {
225- if ( isWebpack5 ) {
226- // Since this file is needed only for webpack 5, load it only then
227- // to simplify the implementation of the file.
228- //
256+ // Since this file is needed only for webpack 5, load it only then
257+ // to simplify the implementation of the file.
258+ //
259+ // eslint-disable-next-line
260+ const { DocGenDependency } = require ( "./dependency" ) ;
261+
262+ module . addDependency (
229263 // eslint-disable-next-line
230- const { DocGenDependency } = require ( "./dependency" ) ;
231-
232- module . addDependency (
233- // eslint-disable-next-line
234- // @ts -ignore: Webpack 4 type
235- new DocGenDependency (
236- generateDocgenCodeBlock ( {
237- filename : name ,
238- source : name ,
239- componentDocs : docGenParser . parseWithProgramProvider (
240- name ,
241- ( ) => tsProgram
242- ) ,
243- ...generateOptions ,
244- } ) . substring ( name . length )
245- )
246- ) ;
247- } else {
248- // Assume webpack 4 or earlier
249- processModule ( docGenParser , module , tsProgram , generateOptions ) ;
250- }
264+ // @ts -ignore: Webpack 4 type
265+ new DocGenDependency (
266+ generateDocgenCodeBlock ( {
267+ filename : name ,
268+ source : name ,
269+ componentDocs : docGenParser . parseWithProgramProvider (
270+ name ,
271+ ( ) => tsProgram
272+ ) ,
273+ ...generateOptions ,
274+ } ) . substring ( name . length )
275+ )
276+ ) ;
251277 } ) ;
252278 } ) ;
253279 }
254280 ) ;
255281 }
256282
283+ applyWebpack4 ( compiler : webpack . Compiler ) : void {
284+ const { docgenOptions, compilerOptions } = this . getOptions ( ) ;
285+ const parser = docGen . withCompilerOptions ( compilerOptions , docgenOptions ) ;
286+ const { exclude = [ ] , include = [ "**/**.tsx" ] } = this . options ;
287+ const isExcluded = matchGlob ( exclude ) ;
288+ const isIncluded = matchGlob ( include ) ;
289+
290+ compiler . hooks . make . tap ( this . name , ( compilation ) => {
291+ compilation . hooks . seal . tap ( this . name , ( ) => {
292+ const modulesToProcess : webpack . Module [ ] = [ ] ;
293+
294+ compilation . modules . forEach ( ( module : webpack . Module ) => {
295+ // eslint-disable-next-line
296+ // @ts -ignore: Webpack 4 type
297+ if ( ! module . built ) {
298+ // eslint-disable-next-line
299+ // @ts -ignore: Webpack 4 type
300+ debugExclude ( `Ignoring un-built module: ${ module . userRequest } ` ) ;
301+ return ;
302+ }
303+
304+ // eslint-disable-next-line
305+ // @ts -ignore: Webpack 4 type
306+ if ( module . external ) {
307+ // eslint-disable-next-line
308+ // @ts -ignore: Webpack 4 type
309+ debugExclude ( `Ignoring external module: ${ module . userRequest } ` ) ;
310+ return ;
311+ }
312+
313+ // eslint-disable-next-line
314+ // @ts -ignore: Webpack 4 type
315+ if ( ! module . rawRequest ) {
316+ debugExclude (
317+ // eslint-disable-next-line
318+ // @ts -ignore: Webpack 4 type
319+ `Ignoring module without "rawRequest": ${ module . userRequest } `
320+ ) ;
321+ return ;
322+ }
323+
324+ // eslint-disable-next-line
325+ // @ts -ignore: Webpack 4 type
326+ if ( isExcluded ( module . userRequest ) ) {
327+ debugExclude (
328+ // eslint-disable-next-line
329+ // @ts -ignore: Webpack 4 type
330+ `Module not matched in "exclude": ${ module . userRequest } `
331+ ) ;
332+ return ;
333+ }
334+
335+ // eslint-disable-next-line
336+ // @ts -ignore: Webpack 4 type
337+ if ( ! isIncluded ( module . userRequest ) ) {
338+ debugExclude (
339+ // eslint-disable-next-line
340+ // @ts -ignore: Webpack 4 type
341+ `Module not matched in "include": ${ module . userRequest } `
342+ ) ;
343+ return ;
344+ }
345+
346+ // eslint-disable-next-line
347+ // @ts -ignore: Webpack 4 type
348+ debugInclude ( module . userRequest ) ;
349+ modulesToProcess . push ( module ) ;
350+ } ) ;
351+
352+ const tsProgram = ts . createProgram (
353+ // eslint-disable-next-line
354+ // @ts -ignore: Webpack 4 type
355+ modulesToProcess . map ( ( v ) => v . userRequest ) ,
356+ compilerOptions
357+ ) ;
358+
359+ modulesToProcess . forEach ( ( m ) =>
360+ processModule ( parser , m , tsProgram , {
361+ docgenCollectionName : "STORYBOOK_REACT_CLASSES" ,
362+ setDisplayName : true ,
363+ typePropName : "type" ,
364+ } )
365+ ) ;
366+
367+ cache . save ( ) ;
368+ } ) ;
369+ } ) ;
370+ }
371+
257372 getOptions ( ) : {
258373 docgenOptions : docGen . ParserOptions ;
259374 generateOptions : {
0 commit comments