Skip to content
This repository was archived by the owner on Mar 8, 2019. It is now read-only.

Commit 97d325e

Browse files
committed
Added new settings in parse
1 parent 8712d17 commit 97d325e

File tree

15 files changed

+341
-11
lines changed

15 files changed

+341
-11
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,24 @@ var vueDocs = require('vue-docgen-api');
2222
var componentInfo = vueDocs.parse(filePath);
2323
```
2424

25+
### parse(filePath)
26+
27+
| Parameter | Type | Description |
28+
| -------------- | ------ | --------------- |
29+
| filePath | string | The file path |
2530

26-
## parse(filePath \[, webpackConfig \])
31+
32+
### parseWebpack(filePath \[, webpackConfig \])
33+
34+
Has implemented [enhanced-require](https://github.com/webpack/enhanced-require)
2735

2836
| Parameter | Type | Description |
2937
| -------------- | ------ | --------------- |
3038
| filePath | string | The file path |
3139
| webpackConfig | object | Optional argument, extracts the necessary loaders to document the component. |
3240

3341

42+
3443
## Using JSDoc tags
3544

3645
You can use the following [JSDoc][] tags when documenting components, props and methods.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-docgen-api",
3-
"version": "2.0.1",
3+
"version": "2.0.2",
44
"description": "Toolbox to extract information from Vue component files for documentation generation purposes.",
55
"bugs": {
66
"url": "https://github.com/vue-styleguidist/vue-docgen-api/issues"

src/main.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import * as utils from './utils';
22
import parse from './parse';
3+
import parseWebpack from './parseWebpack';
34

4-
function defaultParse(src) {
5+
function defaultParse(src, webpackConfig) {
56
return parse(src);
67
}
78

9+
function defaultParseWebpack(src) {
10+
return parseWebpack(src);
11+
}
12+
813
export {
914
defaultParse as parse,
15+
defaultParseWebpack as parseWebpack,
1016
utils,
1117
};
1218

src/parse.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import fs from 'fs';
22
import * as utils from './utils';
33
import stateDoc from './utils/stateDoc';
44

5-
export default function parse(file, webpackConfig) {
5+
export default function parse(file) {
66
const source = fs.readFileSync(file, { encoding: 'utf-8' });
77
if (source === '') {
88
throw new Error('The document is empty');
99
}
1010
stateDoc.file = file;
11-
const component = utils.getComponent(source, file, webpackConfig);
11+
stateDoc.saveComponent(source, file);
12+
const component = utils.getSandbox(stateDoc.jscodeReqest, file).default;
1213
const vueDoc = utils.getVueDoc(stateDoc.getDoc(), component);
1314
return vueDoc;
1415
}

src/parseWebpack.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import fs from 'fs';
2+
import * as utils from './utils';
3+
import stateDoc from './utils/stateDoc';
4+
5+
export default function parseWebpack(file, webpackConfig) {
6+
const source = fs.readFileSync(file, { encoding: 'utf-8' });
7+
if (source === '') {
8+
throw new Error('The document is empty');
9+
}
10+
stateDoc.file = file;
11+
const component = utils.getComponent(source, file, webpackConfig);
12+
const vueDoc = utils.getVueDoc(stateDoc.getDoc(), component);
13+
return vueDoc;
14+
}

src/utils/getRequires.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
// Need to supply the regex test as a string for reuse in unit tests
4+
// Currently, trying to change flags throws a TypeError
5+
// Slated for change in ES6, but not possible now:
6+
// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Description
7+
const REQUIRE_ANYTHING_BASE = 'require\\s*\\(([^)]+)\\)';
8+
const REQUIRE_ANYTHING_REGEX = new RegExp(REQUIRE_ANYTHING_BASE, 'g');
9+
10+
const SIMPLE_STRING_REGEX = /^"([^"]+)"$|^'([^']+)'$/;
11+
12+
/**
13+
* Returns a list of all strings used in require(...) calls in the given source code.
14+
* If there is any other expression inside the require call, it throws an error.
15+
*
16+
* @param {string} code
17+
* @returns {Array}
18+
*/
19+
module.exports = function getRequires(code) {
20+
const requires = {};
21+
code.replace(REQUIRE_ANYTHING_REGEX, function(requireExprMatch, requiredExpr) {
22+
const requireStrMatch = SIMPLE_STRING_REGEX.exec(requiredExpr.trim());
23+
if (!requireStrMatch) {
24+
throw new Error(
25+
`Requires using expressions are not supported in examples. (Used: ${requireExprMatch})`
26+
);
27+
}
28+
const requiredString = requireStrMatch[1] ? requireStrMatch[1] : requireStrMatch[2];
29+
requires[requiredString] = requiredString;
30+
});
31+
return requires;
32+
};
33+
34+
Object.assign(module.exports, {
35+
REQUIRE_ANYTHING_BASE,
36+
REQUIRE_ANYTHING_REGEX,
37+
SIMPLE_STRING_REGEX,
38+
});

src/utils/getSandbox.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import getDocFile from './getDocFile';
2+
import stateDoc from './stateDoc';
3+
const babel = require('babel-core');
4+
const fs = require('fs');
5+
const path = require('path');
6+
const getRequires = require('./getRequires');
7+
import vm from 'vm';
8+
9+
const babelifyCode = code => {
10+
const options = {
11+
ast: false,
12+
comments: false,
13+
presets: ['babel-preset-es2015'],
14+
};
15+
return babel.transform(code, options);
16+
};
17+
18+
function clone(obj) {
19+
if (null == obj || 'object' != typeof obj) return obj;
20+
var copy = obj.constructor();
21+
for (var attr in obj) {
22+
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
23+
}
24+
return copy;
25+
}
26+
27+
function getMixins(code, file) {
28+
try {
29+
const requiresFromComponent = getRequires(code);
30+
let output = [];
31+
Object.keys(requiresFromComponent).forEach((reqFromComponent) =>{
32+
const tempRequire = reqFromComponent.split('/');
33+
if (tempRequire[0] === '.' || tempRequire[0] === '..') {
34+
const folderFile = path.dirname(file);
35+
const pathRequire = path.join(path.normalize(folderFile), reqFromComponent) + '.js'
36+
if (fs.existsSync(pathRequire)) {
37+
const source = fs.readFileSync(pathRequire, { encoding: 'utf-8' });
38+
stateDoc.saveMixin(source, pathRequire);
39+
if (stateDoc.isMixin()){
40+
const babelifycode = babelifyCode(source);
41+
const mixin = evalComponentCode(babelifycode.code);
42+
if (Object.keys(mixin.exports).length === 0 ) {
43+
mixin.exports.default = mixin.module.exports;
44+
}
45+
if (mixin.exports.default) {
46+
output.push(mixin.exports.default);
47+
}
48+
}
49+
}
50+
}
51+
});
52+
return output;
53+
} catch (err) {
54+
throw err
55+
}
56+
}
57+
58+
const evalComponentCode = (code) => {
59+
try {
60+
const script = new vm.Script(code, {});
61+
const sandbox = {
62+
exports: {},
63+
Vue: {
64+
component: () => {},
65+
extended: () => {},
66+
},
67+
module: {
68+
exports: {
69+
},
70+
},
71+
require:()=> {
72+
return function(){}
73+
},
74+
document: {},
75+
window: {
76+
location: {},
77+
},
78+
alert() {},
79+
confirm() {},
80+
console: {
81+
log() {},
82+
debug() {},
83+
},
84+
sessionStorage: {
85+
getItem() {},
86+
setItem() {},
87+
removeItem() {},
88+
},
89+
localStorage: {
90+
getItem() {},
91+
setItem() {},
92+
removeItem() {},
93+
},
94+
}
95+
const context = new vm.createContext(sandbox);
96+
script.runInContext(context);
97+
const output = sandbox;
98+
return clone(output);
99+
} catch (err) {
100+
throw err
101+
}
102+
};
103+
104+
module.exports = function getSandbox(jscodeReqest, file) {
105+
const babelifycode = babelifyCode(jscodeReqest);
106+
let component = evalComponentCode(babelifycode.code).exports;
107+
const mixins = getMixins(babelifycode.code, file).reverse();
108+
component.default.mixins = mixins;
109+
return component;
110+
};

src/utils/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export {default as getComponentModuleJSCode} from './getComponentModuleJSCode';
22
export {default as getComponent} from './getComponent';
33
export {default as getDocFile} from './getDocFile';
44
export {default as getVueDoc} from './getVueDoc';
5+
export {default as getSandbox} from './getSandbox';
56
export {default as parser} from './parser';

src/utils/stateDoc.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ class stateDoc {
77
this.docComponent = {};
88
this.sourceComponent = '';
99
this.docMixins = [];
10+
this.jscodeReqest = '';
11+
this.docTemp = '';
1012
}
1113

1214
isMainComponent(file){
@@ -15,13 +17,19 @@ class stateDoc {
1517

1618
saveComponent(source, file){
1719
if (this.isMainComponent(file) && this.sourceComponent !== source) {
18-
const jscodeReqest = getComponentModuleJSCode(source, file);
19-
const doc = getDocFile(jscodeReqest, file);
20+
this.jscodeReqest = getComponentModuleJSCode(source, file);
21+
const doc = this.getDocFile(this.jscodeReqest, file);
2022
this.docComponent = doc;
2123
}
2224
}
2325

26+
getDocFile(source, file){
27+
this.docTemp = getDocFile(source, file)
28+
return this.docTemp;
29+
}
30+
2431
isMixin(doc) {
32+
doc = doc || this.docTemp;
2533
return doc.some(docPart => {
2634
return docPart.kind === 'mixin'
2735
});
@@ -36,9 +44,8 @@ class stateDoc {
3644
}
3745

3846
saveMixin(source, file) {
39-
let doc = getDocFile(source, file);
47+
let doc = this.getDocFile(source, file);
4048
if (this.isMixin(doc)) {
41-
4249
doc = doc.map(docPart =>{
4350
let longnameSplit = docPart.longname.split('.');
4451
if (longnameSplit[0] === 'default') {

tests/components/button/Button.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
</template>
66

77
<script>
8+
import anotherMixin from '../../mixins/anotherMixin';
9+
import model from '../../utils/model.json';
810
import genericMixin from './genericMixin';
911
import colorMixin from './colorMixin';
12+
import review from '../../utils/review.json';
1013
1114
/**
1215
* This is an example of creating a reusable grid component and using it with external data.

tests/mixins/anotherMixin.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @mixin
3+
*/
4+
module.exports = {
5+
props: {
6+
/**
7+
* Another Mixins Error
8+
*/
9+
color: {
10+
type: String,
11+
default: 'blue'
12+
},
13+
/**
14+
* Error
15+
*/
16+
size: {
17+
default: 'example'
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)