Skip to content

Commit faf9dd2

Browse files
committed
Allow for importing components in examples and having adjacent JSX
1 parent 2223500 commit faf9dd2

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

loaders/utils/getRequires.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,22 @@
77
const REQUIRE_ANYTHING_BASE = 'require\\s*\\(([^)]+)\\)';
88
const REQUIRE_ANYTHING_REGEX = new RegExp(REQUIRE_ANYTHING_BASE, 'g');
99

10+
const IMPORT_ANYTHING_BASE = 'import .+ from (.+)';
11+
const IMPORT_ANYTHING_REGEX = new RegExp(IMPORT_ANYTHING_BASE, 'g');
12+
1013
const SIMPLE_STRING_REGEX = /^"([^"]+)"$|^'([^']+)'$/;
1114

15+
function getRequiresWithRegex(code, regex, requires) {
16+
code.replace(regex, function(requireExprMatch, requiredExpr) {
17+
const requireStrMatch = SIMPLE_STRING_REGEX.exec(requiredExpr.trim());
18+
if (!requireStrMatch) {
19+
throw new Error(`Requires using expressions are not supported in examples. (Used: ${requireExprMatch})`);
20+
}
21+
const requiredString = requireStrMatch[1] ? requireStrMatch[1] : requireStrMatch[2];
22+
requires[requiredString] = true;
23+
});
24+
}
25+
1226
/**
1327
* Returns a list of all strings used in require(...) calls in the given source code.
1428
* If there is any other expression inside the require call, it throws an error.
@@ -18,14 +32,9 @@ const SIMPLE_STRING_REGEX = /^"([^"]+)"$|^'([^']+)'$/;
1832
*/
1933
module.exports = function getRequires(code) {
2034
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(`Requires using expressions are not supported in examples. (Used: ${requireExprMatch})`);
25-
}
26-
const requiredString = requireStrMatch[1] ? requireStrMatch[1] : requireStrMatch[2];
27-
requires[requiredString] = true;
28-
});
35+
getRequiresWithRegex(code, REQUIRE_ANYTHING_REGEX, requires);
36+
getRequiresWithRegex(code, IMPORT_ANYTHING_REGEX, requires);
37+
2938
return Object.keys(requires);
3039
};
3140

src/rsg-components/Preview/Preview.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,34 @@ const compileCode = code => transform(code, {
1010
objectAssign: 'Object.assign',
1111
}).code;
1212

13+
const IMPORT_REGEX = /(import )(.+)( from )(.+)/g;
14+
const TRANSPILED_CONST_DESTRUCTURE_REGEX = /(\w+) as (\w+)/g;
15+
const TRANSPILED_CONST_DESTRUCTURE_REPLACEMENT = '$1: $2';
16+
const JSX_REGEX = /(<(.|\s)+>)/m;
17+
const REACT_ELEMENT_REGEX = /(React.createElement\(.+\))/;
18+
19+
/*
20+
* Convert `import {foo as bar} from 'something'` to `const { foo: bar } = require('something')`
21+
*/
22+
const dumbImportTranspiler = code => code
23+
.replace(IMPORT_REGEX, (...matches) => {
24+
return `const ${matches[2]
25+
.replace(TRANSPILED_CONST_DESTRUCTURE_REGEX, TRANSPILED_CONST_DESTRUCTURE_REPLACEMENT)
26+
} = require(${matches[4]});`;
27+
});
28+
29+
/*
30+
* Enclose JSX/React.createElement in a div
31+
*/
32+
const encloseJSX = code => code
33+
.replace(JSX_REGEX, '<div>$1</div>');
34+
35+
/*
36+
* Make sure React.createElement is returned from enclosing function
37+
*/
38+
const returnReactElement = code => code
39+
.replace(REACT_ELEMENT_REGEX, 'return $1');
40+
1341
export default class Preview extends Component {
1442
static propTypes = {
1543
code: PropTypes.string.isRequired,
@@ -47,7 +75,15 @@ export default class Preview extends Component {
4775
}
4876

4977
try {
50-
const compiledCode = compileCode(this.props.code);
78+
const compiledCode = `(function() { ${
79+
returnReactElement(
80+
compileCode(
81+
encloseJSX(
82+
dumbImportTranspiler(this.props.code)
83+
)
84+
)
85+
)
86+
} })();`;
5187

5288
// Initiate state and set with the callback in the bottom component;
5389
// Workaround for https://github.com/styleguidist/react-styleguidist/issues/155 - missed props on first render

0 commit comments

Comments
 (0)