1 | "use strict";
|
2 | var __rest = (this && this.__rest) || function (s, e) {
|
3 | var t = {};
|
4 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
5 | t[p] = s[p];
|
6 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
7 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
8 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
9 | t[p[i]] = s[p[i]];
|
10 | }
|
11 | return t;
|
12 | };
|
13 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
14 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
15 | };
|
16 | var __importStar = (this && this.__importStar) || function (mod) {
|
17 | if (mod && mod.__esModule) return mod;
|
18 | var result = {};
|
19 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
20 | result["default"] = mod;
|
21 | return result;
|
22 | };
|
23 | Object.defineProperty(exports, "__esModule", { value: true });
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | const template_1 = __importDefault(require("@babel/template"));
|
31 | const t = __importStar(require("@babel/types"));
|
32 | const utils_1 = require("./utils");
|
33 | const const_1 = require("./const");
|
34 | const ast_1 = require("./ast");
|
35 |
|
36 |
|
37 | const standalone_1 = __importDefault(require("@miksu/prettier/lib/standalone"));
|
38 |
|
39 | const parser_babylon_1 = __importDefault(require("@miksu/prettier/lib/language-js/parser-babylon"));
|
40 | const reactImport = template_1.default.ast(`import * as React from 'react';`);
|
41 | exports.getAstPropValue = (prop, name, customProps) => {
|
42 | const value = prop.value;
|
43 | switch (prop.type) {
|
44 | case const_1.PropTypes.String:
|
45 | return t.stringLiteral(String(value));
|
46 | case const_1.PropTypes.Boolean:
|
47 | return t.booleanLiteral(Boolean(value));
|
48 | case const_1.PropTypes.Enum:
|
49 | if (!value) {
|
50 | return t.identifier(String(value));
|
51 | }
|
52 | if (!prop.imports) {
|
53 | return t.stringLiteral(String(value));
|
54 | }
|
55 | const [object, property] = String(value).split('.');
|
56 | return t.memberExpression(t.identifier(object), property.includes('-')
|
57 | ? t.stringLiteral(property)
|
58 | : t.identifier(property), property.includes('-') ? true : false);
|
59 | case const_1.PropTypes.Date:
|
60 | return t.newExpression(t.identifier('Date'), value ? [t.stringLiteral(String(value))] : []);
|
61 | case const_1.PropTypes.Ref:
|
62 | return null;
|
63 | case const_1.PropTypes.Object:
|
64 |
|
65 | return template_1.default.ast(`a = ${value}`, { plugins: ['jsx'] })
|
66 | .expression.right;
|
67 | case const_1.PropTypes.Array:
|
68 | case const_1.PropTypes.Number:
|
69 | case const_1.PropTypes.Function:
|
70 | case const_1.PropTypes.ReactNode:
|
71 | const output = template_1.default.ast(String(value), { plugins: ['jsx'] })
|
72 | .expression;
|
73 |
|
74 |
|
75 | if (output.type === 'Identifier') {
|
76 | return t.stringLiteral(output.name);
|
77 | }
|
78 | return output;
|
79 | case const_1.PropTypes.Custom:
|
80 | if (!customProps[name] || !customProps[name].generate) {
|
81 | console.error(`Missing customProps.${name}.generate definition.`);
|
82 | }
|
83 | return customProps[name].generate(value);
|
84 | }
|
85 | };
|
86 | exports.getAstPropsArray = (props, customProps) => {
|
87 | return Object.entries(props).map(([name, prop]) => {
|
88 | const { value, stateful, defaultValue } = prop;
|
89 | if (stateful)
|
90 | return t.jsxAttribute(t.jsxIdentifier(name), t.jsxExpressionContainer(t.identifier(name)));
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | if ((typeof value !== 'boolean' && !value) ||
|
98 | value === defaultValue ||
|
99 | (typeof value === 'boolean' && !value && !defaultValue)) {
|
100 | return null;
|
101 | }
|
102 | const astValue = exports.getAstPropValue(prop, name, customProps);
|
103 | if (!astValue)
|
104 | return null;
|
105 |
|
106 | if (astValue.type === 'BooleanLiteral' && astValue.value === true) {
|
107 | return t.jsxAttribute(t.jsxIdentifier(name), null);
|
108 | }
|
109 | return t.jsxAttribute(t.jsxIdentifier(name), astValue.type === 'StringLiteral'
|
110 | ? astValue
|
111 | : t.jsxExpressionContainer(astValue));
|
112 | });
|
113 | };
|
114 | exports.getAstReactHooks = (props, customProps) => {
|
115 | const hooks = [];
|
116 | const buildReactHook = template_1.default(`const [%%name%%, %%setName%%] = React.useState(%%value%%);`);
|
117 | Object.keys(props).forEach(name => {
|
118 | if (props[name].stateful === true) {
|
119 | hooks.push(buildReactHook({
|
120 | name: t.identifier(name),
|
121 | setName: t.identifier(`set${name[0].toUpperCase() + name.slice(1)}`),
|
122 | value: exports.getAstPropValue(props[name], name, customProps),
|
123 | }));
|
124 | }
|
125 | });
|
126 | return hooks;
|
127 | };
|
128 | exports.getAstImport = (identifiers, source, defaultIdentifier) => {
|
129 | return t.importDeclaration([
|
130 | ...(defaultIdentifier
|
131 | ? [t.importDefaultSpecifier(t.identifier(defaultIdentifier))]
|
132 | : []),
|
133 | ...identifiers.map(identifier => t.importSpecifier(t.identifier(identifier), t.identifier(identifier))),
|
134 | ], t.stringLiteral(source));
|
135 | };
|
136 | exports.getAstJsxElement = (name, attrs, children) => {
|
137 | const isSelfClosing = children.length === 0;
|
138 | return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(name), attrs.filter(attr => !!attr), isSelfClosing), isSelfClosing ? null : t.jsxClosingElement(t.jsxIdentifier(name)), children, true);
|
139 | };
|
140 | exports.addToImportList = (importList, imports) => {
|
141 | for (const [importFrom, importNames] of Object.entries(imports)) {
|
142 | if (!importList.hasOwnProperty(importFrom)) {
|
143 | importList[importFrom] = {
|
144 | named: [],
|
145 | default: '',
|
146 | };
|
147 | }
|
148 | if (importNames.default) {
|
149 | importList[importFrom].default = importNames.default;
|
150 | }
|
151 | if (importNames.named && importNames.named.length > 0) {
|
152 | if (!importList[importFrom].hasOwnProperty('named')) {
|
153 | importList[importFrom]['named'] = [];
|
154 | }
|
155 | importList[importFrom].named = [
|
156 | ...new Set(importList[importFrom].named.concat(importNames.named)),
|
157 | ];
|
158 | }
|
159 | }
|
160 | };
|
161 | exports.getAstImports = (importsConfig, providerImports, props) => {
|
162 |
|
163 | const importList = utils_1.clone(importsConfig);
|
164 |
|
165 |
|
166 | Object.values(props).forEach(prop => {
|
167 | if (prop.imports &&
|
168 | prop.value &&
|
169 | prop.value !== '' &&
|
170 | prop.value !== prop.defaultValue) {
|
171 | exports.addToImportList(importList, prop.imports);
|
172 | }
|
173 | });
|
174 | exports.addToImportList(importList, providerImports);
|
175 | return Object.keys(importList).map(from => exports.getAstImport(importList[from].named || [], from, importList[from].default));
|
176 | };
|
177 | const getChildrenAst = (value) => {
|
178 | return template_1.default.ast(`<>${value}</>`, {
|
179 | plugins: ['jsx'],
|
180 | }).expression.children;
|
181 | };
|
182 | exports.getAst = (props, componentName, provider, providerValue, importsConfig, customProps) => {
|
183 | const { children } = props, restProps = __rest(props, ["children"]);
|
184 | const buildExport = template_1.default(`export default () => {%%body%%}`);
|
185 | return t.file(t.program([
|
186 | reactImport,
|
187 | ...exports.getAstImports(importsConfig, providerValue ? provider.imports : {}, props),
|
188 | buildExport({
|
189 | body: [
|
190 | ...exports.getAstReactHooks(restProps, customProps),
|
191 | t.returnStatement(provider.generate(providerValue, exports.getAstJsxElement(componentName, exports.getAstPropsArray(restProps, customProps), children && children.value
|
192 | ? getChildrenAst(String(children.value))
|
193 | : []))),
|
194 | ],
|
195 | }),
|
196 | ]), [], []);
|
197 | };
|
198 | exports.formatAstAndPrint = (ast, printWidth) => {
|
199 | const result = standalone_1.default.__debug.formatAST(ast, {
|
200 | originalText: '',
|
201 | parser: 'babel',
|
202 | printWidth: printWidth ? printWidth : 58,
|
203 | plugins: [parser_babylon_1.default],
|
204 | });
|
205 | return (result.formatted
|
206 |
|
207 | .replace('export default', `${result.formatted.startsWith('import ') ? '\n' : ''}export default`)
|
208 |
|
209 | .replace(/[\r\n]+$/, '')
|
210 |
|
211 | .replace(/[;]+$/, ''));
|
212 | };
|
213 | exports.formatCode = (code) => {
|
214 | return exports.formatAstAndPrint(ast_1.parse(code));
|
215 | };
|
216 | exports.getCode = ({ props, componentName, provider, providerValue, importsConfig, customProps, }) => {
|
217 | if (Object.keys(props).length === 0) {
|
218 | return '';
|
219 | }
|
220 | const ast = exports.getAst(props, componentName, provider, providerValue, importsConfig, customProps);
|
221 | return exports.formatAstAndPrint(ast);
|
222 | };
|
223 |
|
\ | No newline at end of file |