11import path from "path" ;
22import createDebug from "debug" ;
3- import { Compiler , WebpackPluginInstance } from "webpack" ;
43import ts from "typescript" ;
54import * as docGen from "react-docgen-typescript" ;
65import { matcher } from "micromatch" ;
@@ -60,16 +59,61 @@ const matchGlob = (globs?: string[]) => {
6059 Boolean ( filename && matchers . find ( ( match ) => match ( filename ) ) ) ;
6160} ;
6261
62+ /** Run the docgen parser and inject the result into the output */
63+ /** This is used for webpack 4 or earlier */
64+ function processModule (
65+ parser : docGen . FileParser ,
66+ webpackModule : webpack . Module ,
67+ tsProgram : ts . Program ,
68+ loaderOptions : Required < LoaderOptions >
69+ ) {
70+ if ( ! webpackModule ) {
71+ return ;
72+ }
73+
74+ // eslint-disable-next-line
75+ // @ts -ignore: Webpack 4 type
76+ const { userRequest } = webpackModule ;
77+
78+ const componentDocs = parser . parseWithProgramProvider (
79+ userRequest ,
80+ ( ) => tsProgram
81+ ) ;
82+
83+ if ( ! componentDocs . length ) {
84+ return ;
85+ }
86+
87+ const docs = generateDocgenCodeBlock ( {
88+ filename : userRequest ,
89+ source : userRequest ,
90+ componentDocs,
91+ ...loaderOptions ,
92+ } ) . substring ( userRequest . length ) ;
93+
94+ // eslint-disable-next-line
95+ // @ts -ignore: Webpack 4 type
96+ // eslint-disable-next-line
97+ let sourceWithDocs = webpackModule . _source . _value ;
98+
99+ sourceWithDocs += `\n${ docs } \n` ;
100+
101+ // eslint-disable-next-line
102+ // @ts -ignore: Webpack 4 type
103+ // eslint-disable-next-line
104+ webpackModule . _source . _value = sourceWithDocs ;
105+ }
106+
63107/** Inject typescript docgen information into modules at the end of a build */
64- export default class DocgenPlugin implements WebpackPluginInstance {
108+ export default class DocgenPlugin implements webpack . WebpackPluginInstance {
65109 private name = "React Docgen Typescript Plugin" ;
66110 private options : PluginOptions ;
67111
68112 constructor ( options : PluginOptions = { } ) {
69113 this . options = options ;
70114 }
71115
72- apply ( compiler : Compiler ) : void {
116+ apply ( compiler : webpack . Compiler ) : void {
73117 const pluginName = "DocGenPlugin" ;
74118 const {
75119 docgenOptions,
@@ -83,12 +127,20 @@ export default class DocgenPlugin implements WebpackPluginInstance {
83127 const { exclude = [ ] , include = [ "**/**.tsx" ] } = this . options ;
84128 const isExcluded = matchGlob ( exclude ) ;
85129 const isIncluded = matchGlob ( include ) ;
130+ const webpackVersion = compiler . webpack . version ;
131+ const isWebpack5 = parseInt ( webpackVersion . split ( "." ) [ 0 ] , 10 ) >= 5 ;
86132
87133 compiler . hooks . compilation . tap ( pluginName , ( compilation ) => {
88- compilation . dependencyTemplates . set (
89- DocGenDependency ,
90- new DocGenDependency . Template ( )
91- ) ;
134+ if ( isWebpack5 ) {
135+ compilation . dependencyTemplates . set (
136+ // eslint-disable-next-line
137+ // @ts -ignore: Webpack 4 type
138+ DocGenDependency ,
139+ // eslint-disable-next-line
140+ // @ts -ignore: Webpack 4 type
141+ new DocGenDependency . Template ( )
142+ ) ;
143+ }
92144
93145 compilation . hooks . seal . tap ( pluginName , ( ) => {
94146 const modulesToProcess : [ string , webpack . Module ] [ ] = [ ] ;
@@ -122,21 +174,28 @@ export default class DocgenPlugin implements WebpackPluginInstance {
122174
123175 // 3. Process and parse each module and add the type information
124176 // as a dependency
125- modulesToProcess . forEach ( ( [ name , module ] ) =>
126- module . addDependency (
127- new DocGenDependency (
128- generateDocgenCodeBlock ( {
129- filename : name ,
130- source : name ,
131- componentDocs : docGenParser . parseWithProgramProvider (
132- name ,
133- ( ) => tsProgram
134- ) ,
135- ...generateOptions ,
136- } )
137- )
138- )
139- ) ;
177+ modulesToProcess . forEach ( ( [ name , module ] ) => {
178+ if ( isWebpack5 ) {
179+ module . addDependency (
180+ // eslint-disable-next-line
181+ // @ts -ignore: Webpack 4 type
182+ new DocGenDependency (
183+ generateDocgenCodeBlock ( {
184+ filename : name ,
185+ source : name ,
186+ componentDocs : docGenParser . parseWithProgramProvider (
187+ name ,
188+ ( ) => tsProgram
189+ ) ,
190+ ...generateOptions ,
191+ } )
192+ )
193+ ) ;
194+ } else {
195+ // Assume webpack 4 or earlier
196+ processModule ( docGenParser , module , tsProgram , generateOptions ) ;
197+ }
198+ } ) ;
140199 } ) ;
141200 } ) ;
142201 }
0 commit comments