diff --git a/package.json b/package.json index e978369..d108d3f 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "dependencies": { "clone": "^2.1.2", "loader-utils": "^1.2.3", - "querystring": "^0.2.0" + "querystring": "^0.2.0", + "vue-docgen-api": "^4.1.1" }, "devDependencies": { "@babel/cli": "^7.7.0", @@ -48,13 +49,12 @@ "prettier": "^1.19.1", "rimraf": "^3.0.0", "vue": "^2.6.10", - "vue-docgen-api": "^4.0.0", "vue-loader": "^15.7.2", "vue-template-compiler": "^2.6.10", "webpack": "^4.41.2" }, "peerDependencies": { - "vue-docgen-api": "^3.26.0", + "vue-docgen-api": ">=3", "webpack": ">=4" }, "scripts": { diff --git a/src/index.js b/src/index.js index 600d30d..eebaab6 100644 --- a/src/index.js +++ b/src/index.js @@ -18,6 +18,7 @@ module.exports = async function(content, map) { const ext = this.resourcePath .replace(/^[\s\S]*\.([^.]+)$/, '$1') .toLowerCase() + const isSFC = ext === 'vue' try { @@ -28,21 +29,25 @@ module.exports = async function(content, map) { // vue-loader, we need to read file to get the source code. const infoOrPromise = isSFC ? docgen.parse(this.resourcePath, options.docgenOptions) - : docgen.parseSource(content, this.resourcePath, options.docgenOptions) + : attemptMultiParse(content, this.resourcePath, options.docgenOptions) // `parse` is async since vue-docgen-api@4. - const info = + const allInfo = [].concat( infoOrPromise instanceof Promise ? await infoOrPromise : infoOrPromise + ) - // The default value 'component' is for SFC(vue-loader)'s export name. - const ident = - (info.exportName !== 'default' && info.exportName) || 'component' - - const exportStatement = `;(${ident}.options = ${ident}.options || {}).__docgenInfo = ${JSON.stringify( - info - )}\n` + let fullExportStatement = '' + for (let i = 0; i < allInfo.length; i++) { + const info = allInfo[i] + const ident = + (info.exportName !== 'default' && info.exportName) || 'component' + const exportStatement = `;(${ident}.options = ${ident}.options || {}).__docgenInfo = ${JSON.stringify( + info + )}\n` + fullExportStatement += `${exportStatement}` + } - const js = content + '\n' + exportStatement + const js = content + '\n' + fullExportStatement callback(null, js, map) } catch (e) { @@ -55,3 +60,8 @@ module.exports = async function(content, map) { callback(null, content, map) } } + +function attemptMultiParse(content, path, options) { + if (docgen.parseMulti) return docgen.parseMulti(path, options) + else return docgen.parseSource(content, path, options) +} diff --git a/test/__snapshots__/loader.spec.js.snap b/test/__snapshots__/loader.spec.js.snap index 24f6ce5..4a5d920 100644 --- a/test/__snapshots__/loader.spec.js.snap +++ b/test/__snapshots__/loader.spec.js.snap @@ -45,3 +45,47 @@ Object { "tags": Object {}, } `; + +exports[`Injects docgen result non-SFC with multiple exports 1`] = ` +Object { + "description": "", + "exportName": "MyButton1", + "props": Array [ + Object { + "defaultValue": Object { + "func": false, + "value": "-1", + }, + "description": "Foo the number.", + "name": "foo", + "tags": Object {}, + "type": Object { + "name": "number", + }, + }, + ], + "tags": Object {}, +} +`; + +exports[`Injects docgen result non-SFC with multiple exports 2`] = ` +Object { + "description": "", + "exportName": "MyButton2", + "props": Array [ + Object { + "defaultValue": Object { + "func": false, + "value": "-1", + }, + "description": "Foo the number.", + "name": "foo", + "tags": Object {}, + "type": Object { + "name": "number", + }, + }, + ], + "tags": Object {}, +} +`; diff --git a/test/fixtures/basicMulti.vue.js b/test/fixtures/basicMulti.vue.js new file mode 100644 index 0000000..d7ef241 --- /dev/null +++ b/test/fixtures/basicMulti.vue.js @@ -0,0 +1,30 @@ +import Vue from 'vue' + +export const MyButton1 = { + props: { + /** + * Foo the number. + */ + foo: { + type: Number, + default: -1 + } + }, + template: '{{foo}}' +} + +export const MyButton2 = { + props: { + /** + * Foo the number. + */ + foo: { + type: Number, + default: -1 + } + }, + template: '{{foo}}' +} + +// NOTE: vue-docgen-api cannot handle default exports (is it expected behavor or bug? idk...) +// export default MyButton diff --git a/test/loader.spec.js b/test/loader.spec.js index fe10e8a..5918cf7 100644 --- a/test/loader.spec.js +++ b/test/loader.spec.js @@ -22,3 +22,23 @@ it('Injects docgen result for non-SFC', async () => { expect(output).toMatch(docgenPattern) expect(JSON.parse(output.match(docgenPattern)[1])).toMatchSnapshot() }) + +it('Injects docgen result non-SFC with multiple exports', async () => { + const fixture = './fixtures/basicMulti.vue.js' + + const stats = await compiler(fixture) + const output = stats.toJson().modules.find(mod => mod.name.includes(fixture)) + .source + + const buttonExports = ['MyButton1', 'MyButton2'] + + const createDocgenPattern = exportName => + `^.*${exportName}.*\\.__docgenInfo\\s?=\\s?(\\{[\\s\\S]*?})$` + const match1 = new RegExp(createDocgenPattern(buttonExports[0]), 'm') + const match2 = new RegExp(createDocgenPattern(buttonExports[1]), 'm') + + expect(output).toMatch(match1) + expect(output).toMatch(match2) + expect(JSON.parse(output.match(match1)[1])).toMatchSnapshot() + expect(JSON.parse(output.match(match2)[1])).toMatchSnapshot() +})