@babel/types#JSXElement TypeScript Examples
The following examples show how to use
@babel/types#JSXElement.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: js.ts From css-to-js with MIT License | 6 votes |
export function parseJsx(input: string): [JSXElement, string] {
let rawLines: string;
if (input.trim().match(/^<.*>$/s)) {
rawLines = input;
} else {
rawLines = `<TempComponent ${input} />`;
}
let expression: Expression;
try {
expression = babelParser.parseExpression(rawLines, {
plugins: ["jsx"],
});
} catch (e) {
if (e instanceof SyntaxError) {
const location = getErrorLocation(e);
const codeFrame = codeFrameColumns(rawLines, { start: location });
throw new SyntaxError(`${e.message}\n\n${codeFrame}`);
}
throw e;
}
if (expression.type !== "JSXElement") {
throw new Error("Expression is not a JSX element");
}
return [expression, rawLines];
}
Example #2
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
parseChildren = (n: JSXFragment | JSXElement): PlasmicASTNode[] => {
const nodesList: PlasmicASTNode[] = [];
n.children.forEach((child) => {
if (child.type === "JSXText") {
const text = child.value;
if (text !== undefined) {
const trimmed = text.trim();
if (trimmed) {
nodesList.push({ type: "text", rawNode: child, value: trimmed });
}
}
} else {
nodesList.push(parseNode(child, n, true));
}
});
return nodesList;
}
Example #3
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
tryParseAsPlasmicJsxElement = (
jsx: JSXElement,
parent: Node | undefined
): PlasmicJsxElement | undefined => {
let nodeId: string | undefined = undefined;
for (const attr of jsx.openingElement.attributes) {
const curNodeId = tryGetNodeIdFromAttr(attr);
if (curNodeId) {
if (nodeId) {
// The id in className and spreador must match.
assert(nodeId === curNodeId);
}
nodeId = curNodeId;
}
}
return nodeId ? parseJsxElement(jsx, nodeId, parent) : undefined;
}
Example #4
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
parseJsxElement = (
n: JSXElement,
plasmicId: string,
parent: Node | undefined
): PlasmicJsxElement => {
const attrs: Array<[string, PlasmicASTNode | null] | PlasmicASTNode> =
n.openingElement.attributes.map((attr) => {
if (attr.type === "JSXAttribute") {
const name = getAttrName(attr);
assert(L.isString(name));
return [
name,
attr.value === null
? null
: parseNode(attr.value as any, attr, false),
];
} else {
// spreador
return parseNode(attr.argument, attr, false);
}
});
const children = parseChildren(n);
return {
attrs,
children,
rawNode: n,
rawParent: parent,
nameInId: plasmicId,
};
}
Example #5
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
hasShowFuncCall(node: PlasmicTagOrComponent) {
if (node.rawNode === node.jsxElement.rawNode) {
return false;
}
let found = false;
traverse(node.rawNode, {
noScope: true,
CallExpression: function (path) {
if (
memberExpressionMatch(
path.node.callee,
helperObject,
`show${node.jsxElement.nameInId}`
)
) {
found = true;
path.stop();
}
},
JSXElement: function (path) {
if (path.node === node.jsxElement.rawNode) {
path.skip();
}
},
});
return found;
}
Example #6
Source File: utils.ts From plasmic with MIT License | 6 votes |
tagName = (jsxElement: JSXElement) => {
// babel generator append ";" to the name. stirp it.
return code(jsxElement.openingElement.name).replace(";", "").trim();
}
Example #7
Source File: index.ts From plasmic with MIT License | 6 votes |
getRawNamedAttrs = (jsxElement: JSXElement) => {
const attrs = new Map<string, JSXAttribute>();
for (const attr of jsxElement.openingElement.attributes) {
if (attr.type !== "JSXAttribute") {
continue;
}
assert(L.isString(attr.name.name));
attrs.set(attr.name.name, attr);
}
return attrs;
}
Example #8
Source File: resolveJsxComponent.ts From react-optimized-image with MIT License | 6 votes |
resolveJsxComponent = (types: Babel['types'], path: NodePath<JSXElement>): string | undefined => {
// check if it is a possible react-optimized-image component before proceeding further
const srcAttribute = getAttribute(path, 'src');
if (!srcAttribute) {
return;
}
const requireName = getRelevantRequireString(types, srcAttribute);
// check if the imported src is not an image in case an extension is present
if ((!requireName || !requireName.match(/\.(jpe?g|png|svg|gif|webp)($|\?)/gi)) && requireName !== '') {
return;
}
// it is now likely to be a react-optimized-image component, so start resolving
// check for a normal opening element (<Img ...)
if (path.node.openingElement.name.type === 'JSXIdentifier') {
const binding = path.scope.getBinding(path.node.openingElement.name.name);
const component = getImportedJsxComponent(binding);
return component;
}
// check for an object opening element (<styles.Img ...)
if (path.node.openingElement.name.type === 'JSXMemberExpression') {
const objectBindings = resolveJsxMemberExpression(path.node.openingElement.name);
const resolvedBinding = resolveObject(types, path, objectBindings);
const component = getImportedJsxComponent(resolvedBinding);
return component;
}
}
Example #9
Source File: jsx.ts From react-optimized-image with MIT License | 6 votes |
getNumberedArrayAttribute = (path: NodePath<JSXElement>, attributeName: string): number[] | undefined => {
const attribute = getAttribute(path, attributeName);
if (attribute) {
if (
attribute.node.value &&
attribute.node.value.type === 'JSXExpressionContainer' &&
attribute.node.value.expression.type === 'ArrayExpression'
) {
const values: number[] = [];
attribute.node.value.expression.elements.forEach((element, i) => {
if (element && element.type === 'NumericLiteral') {
values.push(element.value);
} else if (element) {
// todo: better error message with link to docs when ready & create test for this error
throw (((attribute.get('value') as NodePath<JSXExpressionContainer>).get('expression') as NodePath<
ArrayExpression
>).get(`elements.${i}`) as NodePath).buildCodeFrameError('Only static number values are allowed');
}
});
return values;
}
// todo: better error message with link to docs when ready & create test for this error
throw attribute.get('value').buildCodeFrameError('Only static array with number values is allowed');
}
return undefined;
}
Example #10
Source File: jsx.ts From react-optimized-image with MIT License | 6 votes |
getTypeAttribute = (path: NodePath<JSXElement>, types: string[]): string | undefined => {
const attribute = getAttribute(path, 'type');
if (attribute && attribute.node.value && attribute.node.value.type === 'StringLiteral') {
const type = attribute.node.value.value;
if (types.indexOf(type) < 0) {
throw (attribute.get('value') as NodePath<JSXExpressionContainer>).buildCodeFrameError(
`Type ${type} not found in images.config.js`,
);
}
return type;
}
if (attribute && attribute.node) {
throw (attribute.get('value') as NodePath).buildCodeFrameError('Only static string values are allowed');
}
}
Example #11
Source File: jsx.ts From react-optimized-image with MIT License | 6 votes |
getBooleanAttribute = (path: NodePath<JSXElement>, attributeName: string): boolean | undefined => {
const attribute = getAttribute(path, attributeName);
if (attribute) {
if (attribute.node.value === null) {
return true;
}
if (
attribute.node.value.type === 'JSXExpressionContainer' &&
attribute.node.value.expression.type === 'BooleanLiteral'
) {
return attribute.node.value.expression.value;
}
// todo: better error message with link to docs when ready & create test for this error
throw attribute.get('value').buildCodeFrameError('Only static boolean values are allowed');
}
return undefined;
}
Example #12
Source File: jsx.ts From react-optimized-image with MIT License | 6 votes |
getAttribute = (path: NodePath<JSXElement>, attributeName: string): NodePath<JSXAttribute> | undefined => {
if (path.node.openingElement.attributes) {
let attribue;
path.get('openingElement').traverse({
JSXAttribute(attributePath) {
if (attributePath.node.name.name === attributeName) {
attribue = attributePath;
attributePath.stop();
}
},
});
return attribue;
}
return undefined;
}
Example #13
Source File: svg.ts From react-optimized-image with MIT License | 6 votes |
transformSvgComponent = (types: Babel['types'], path: NodePath<JSXElement>): void => {
// abort if it has already the rawSrc attribute
if (getAttribute(path, 'rawSrc')) {
return;
}
const src = getAttribute(path, 'src');
const requireArgs = src ? getRequireArguments(types, src) : undefined;
if (!src || !requireArgs) {
return;
}
const rawSrc = buildRawSrcAttribute(types, requireArgs);
(path.get('openingElement') as NodePath<JSXOpeningElement>).pushContainer('attributes', rawSrc);
src.remove();
}
Example #14
Source File: img.ts From react-optimized-image with MIT License | 6 votes |
transformImgComponent = (types: Babel['types'], path: NodePath<JSXElement>): void => {
// abort if it has already the rawSrc attribute
if (getAttribute(path, 'rawSrc')) {
return;
}
// get src attribute
const src = getAttribute(path, 'src');
const requireArgs = src ? getRequireArguments(types, src) : undefined;
if (!src || !requireArgs) {
return;
}
const config = buildConfig(types, path);
const query: Record<string, string> = {};
// add boolean queries
['inline', 'url', 'original'].forEach((attr) => {
if ((config as Record<string, unknown>)[attr] === true) {
query[attr] = '';
}
});
// transfer original src attribute if a new query param needs to be set
if (Object.keys(query).length > 0) {
(src.get('value') as NodePath).replaceWith(
types.jsxExpressionContainer(buildRequireStatement(types, clone(requireArgs), query)),
);
}
const rawSrc = buildRawSrcAttribute(types, requireArgs, config, query);
(path.get('openingElement') as NodePath<JSXOpeningElement>).pushContainer('attributes', rawSrc);
}
Example #15
Source File: jsxConverter.ts From react-native-decompiler with GNU Affero General Public License v3.0 | 5 votes |
private parseJsx(node: Expression): JSXText | JSXExpressionContainer | JSXSpreadChild | JSXElement | JSXFragment {
if (isStringLiteral(node)) {
return jsxText(node.value);
}
if (isCallExpression(node)) {
const args = node.arguments;
let name: JSXIdentifier | JSXMemberExpression | undefined;
if (isIdentifier(args[0]) || isStringLiteral(args[0])) {
name = jsxIdentifier(isIdentifier(args[0]) ? args[0].name : args[0].value);
} else if (isMemberExpression(args[0]) && isIdentifier(args[0].object) && isIdentifier(args[0].property)) {
name = jsxMemberExpression(jsxIdentifier(args[0].object.name), jsxIdentifier(args[0].property.name));
} else {
this.debugLog(`fail to parse component ${args[0].type} inside callExpression`);
return jsxExpressionContainer(node);
}
let props: JSXAttribute[] = [];
if (isObjectExpression(args[1])) {
props = args[1].properties.map((prop) => {
if (!isObjectProperty(prop) || !isIdentifier(prop.key)) return null;
if (isStringLiteral(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), prop.value);
}
if (isBooleanLiteral(prop.value) && prop.value.value) {
return jsxAttribute(jsxIdentifier(prop.key.name), null);
}
if (isExpression(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), jsxExpressionContainer(prop.value));
}
return null;
}).filter((e): e is JSXAttribute => e != null);
}
const children = args.slice(2).map((e) => (isExpression(e) ? this.parseJsx(e) : null)).filter((e): e is JSXElement => e != null);
if (children.length) {
return jsxElement(jsxOpeningElement(name, props), jsxClosingElement(name), children);
}
return jsxElement(jsxOpeningElement(name, props, true), null, []);
}
this.debugLog(`fail to parse component ${node.type}`);
return jsxExpressionContainer(node);
}
Example #16
Source File: jsxConverter.ts From react-native-decompiler with GNU Affero General Public License v3.0 | 5 votes |
private parseJsx(node: Expression): JSXText | JSXExpressionContainer | JSXSpreadChild | JSXElement | JSXFragment {
if (isStringLiteral(node)) {
return jsxText(node.value);
}
if (isCallExpression(node)) {
const args = node.arguments;
let name: JSXIdentifier | JSXMemberExpression | undefined;
if (isIdentifier(args[0]) || isStringLiteral(args[0])) {
name = jsxIdentifier(isIdentifier(args[0]) ? args[0].name : args[0].value);
} else if (isMemberExpression(args[0]) && isIdentifier(args[0].object) && isIdentifier(args[0].property)) {
name = jsxMemberExpression(jsxIdentifier(args[0].object.name), jsxIdentifier(args[0].property.name));
} else {
this.debugLog(`fail to parse component ${args[0].type} inside callExpression`);
return jsxExpressionContainer(node);
}
let props: JSXAttribute[] = [];
if (isObjectExpression(args[1])) {
props = args[1].properties.map((prop) => {
if (!isObjectProperty(prop) || !isIdentifier(prop.key)) return null;
if (isStringLiteral(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), prop.value);
}
if (isBooleanLiteral(prop.value) && prop.value.value) {
return jsxAttribute(jsxIdentifier(prop.key.name), null);
}
if (isExpression(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), jsxExpressionContainer(prop.value));
}
return null;
}).filter((e): e is JSXAttribute => e != null);
}
const children = args.slice(2).map((e) => (isExpression(e) ? this.parseJsx(e) : null)).filter((e): e is JSXElement => e != null);
if (children.length) {
return jsxElement(jsxOpeningElement(name, props), jsxClosingElement(name), children);
}
return jsxElement(jsxOpeningElement(name, props, true), null, []);
}
this.debugLog(`fail to parse component ${node.type}`);
return jsxExpressionContainer(node);
}
Example #17
Source File: jsxConverter.ts From react-native-decompiler with GNU Affero General Public License v3.0 | 5 votes |
private parseJsx(node: Expression): JSXText | JSXExpressionContainer | JSXSpreadChild | JSXElement | JSXFragment {
if (isStringLiteral(node)) {
return jsxText(node.value);
}
if (isCallExpression(node)) {
const args = node.arguments;
let name: JSXIdentifier | JSXMemberExpression | undefined;
if (isIdentifier(args[0]) || isStringLiteral(args[0])) {
name = jsxIdentifier(isIdentifier(args[0]) ? args[0].name : args[0].value);
} else if (isMemberExpression(args[0]) && isIdentifier(args[0].object) && isIdentifier(args[0].property)) {
name = jsxMemberExpression(jsxIdentifier(args[0].object.name), jsxIdentifier(args[0].property.name));
} else {
this.debugLog(`fail to parse component ${args[0].type} inside callExpression`);
return jsxExpressionContainer(node);
}
let props: JSXAttribute[] = [];
if (isObjectExpression(args[1])) {
props = args[1].properties.map((prop) => {
if (!isObjectProperty(prop) || !isIdentifier(prop.key)) return null;
if (isStringLiteral(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), prop.value);
}
if (isBooleanLiteral(prop.value) && prop.value.value) {
return jsxAttribute(jsxIdentifier(prop.key.name), null);
}
if (isExpression(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), jsxExpressionContainer(prop.value));
}
return null;
}).filter((e): e is JSXAttribute => e != null);
}
const children = args.slice(2).map((e) => (isExpression(e) ? this.parseJsx(e) : null)).filter((e): e is JSXElement => e != null);
if (children.length) {
return jsxElement(jsxOpeningElement(name, props), jsxClosingElement(name), children);
}
return jsxElement(jsxOpeningElement(name, props, true), null, []);
}
this.debugLog(`fail to parse component ${node.type}`);
return jsxExpressionContainer(node);
}
Example #18
Source File: plasmic-parser.ts From plasmic with MIT License | 5 votes |
parseAsOneNode = (
n: Expression | JSXEmptyExpression | JSXFragment,
parent: Node | undefined
): PlasmicASTNode => {
if (n.type === "JSXEmptyExpression") {
return {
type: "opaque",
rawNode: n,
};
}
if (n.type === "StringLiteral") {
return {
type: "string-lit",
value: n.value,
rawNode: n,
};
}
if (n.type === "CallExpression") {
const callee = tryExtractPropertyNameOfMemberExpression(
n.callee,
helperObject
);
const m = callee?.match(/^childStr(.+)$/);
if (m) {
return { type: "child-str-call", plasmicId: ensure(m[1]), rawNode: n };
}
}
// Need to handle this case specially since traverse doesn't visit n itself.
if (n.type === "JSXElement") {
const jsxElement = tryParseAsPlasmicJsxElement(n, parent);
if (jsxElement) {
return {
type: "tag-or-component",
jsxElement,
rawNode: n,
secondaryNodes: [],
};
}
}
const jsxElements: PlasmicJsxElement[] = [];
traverse(n, {
noScope: true,
JSXElement: function (path) {
const jsxElement = tryParseAsPlasmicJsxElement(path.node, path.parent);
if (jsxElement) {
jsxElements.push(jsxElement);
path.skip();
}
},
});
return jsxElements.length > 0
? {
type: "tag-or-component",
jsxElement: jsxElements[0],
rawNode: n,
secondaryNodes: jsxElements.slice(1).map((elt) => ({
type: "tag-or-component",
jsxElement: elt,
rawNode:
elt.rawParent && elt.rawParent.type === "LogicalExpression"
? elt.rawParent
: elt.rawNode,
secondaryNodes: [],
})),
}
: {
type: "opaque",
rawNode: n,
};
}
Example #19
Source File: index.ts From plasmic with MIT License | 5 votes |
makeJsxElementWithShowCall = (jsxElement: JSXElement, nodeId: string) =>
babel.types.logicalExpression(
"&&",
makeCallExpression(helperObject, `show${nodeId}`),
jsxElement
)
Example #20
Source File: jsxConverter.ts From react-native-decompiler with GNU Affero General Public License v3.0 | 5 votes |
private parseJsx(node: Expression): JSXText | JSXExpressionContainer | JSXSpreadChild | JSXElement | JSXFragment {
if (isStringLiteral(node)) {
return jsxText(node.value);
}
if (isCallExpression(node)) {
const args = node.arguments;
let name: JSXIdentifier | JSXMemberExpression | undefined;
if (isIdentifier(args[0]) || isStringLiteral(args[0])) {
name = jsxIdentifier(isIdentifier(args[0]) ? args[0].name : args[0].value);
} else if (isMemberExpression(args[0]) && isIdentifier(args[0].object) && isIdentifier(args[0].property)) {
name = jsxMemberExpression(jsxIdentifier(args[0].object.name), jsxIdentifier(args[0].property.name));
} else {
this.debugLog(`fail to parse component ${args[0].type} inside callExpression`);
return jsxExpressionContainer(node);
}
let props: JSXAttribute[] = [];
if (isObjectExpression(args[1])) {
props = args[1].properties.map((prop) => {
if (!isObjectProperty(prop) || !isIdentifier(prop.key)) return null;
if (isStringLiteral(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), prop.value);
}
if (isBooleanLiteral(prop.value) && prop.value.value) {
return jsxAttribute(jsxIdentifier(prop.key.name), null);
}
if (isExpression(prop.value)) {
return jsxAttribute(jsxIdentifier(prop.key.name), jsxExpressionContainer(prop.value));
}
return null;
}).filter((e): e is JSXAttribute => e != null);
}
const children = args.slice(2).map((e) => (isExpression(e) ? this.parseJsx(e) : null)).filter((e): e is JSXElement => e != null);
if (children.length) {
return jsxElement(jsxOpeningElement(name, props), jsxClosingElement(name), children);
}
return jsxElement(jsxOpeningElement(name, props, true), null, []);
}
this.debugLog(`fail to parse component ${node.type}`);
return jsxExpressionContainer(node);
}
Example #21
Source File: resolveJsxComponent.ts From react-optimized-image with MIT License | 5 votes |
resolveObject = (types: Babel['types'], path: NodePath<JSXElement>, bindings: string[]): Binding | undefined => {
if (bindings.length < 2) {
return;
}
const variableName = bindings[bindings.length - 1];
const object = path.scope.getBinding(bindings[0]);
if (!object) {
return;
}
const program = path.findParent((node) => node.isProgram());
let declarationPath: any = null; // eslint-disable-line
let initializer;
// search for object declaration
program.traverse({
// styles.StyledImg = ...
MemberExpression(exPath: NodePath<MemberExpression>) {
if (exPath.node.property && exPath.node.property.name === variableName) {
const exBindings = resolveMemberExpression(exPath.node);
if (arraysMatch(bindings, exBindings) && exPath.parent.type === 'AssignmentExpression') {
declarationPath = exPath;
initializer = exPath.parent.right;
exPath.stop();
}
}
},
// const styles = { StyledImg: ... }
ObjectProperty(opPath: NodePath<ObjectProperty>) {
if (opPath.node.key && opPath.node.key.type === 'Identifier' && opPath.node.key.name === variableName) {
const exBindings = resolveObjectProperty(
opPath.findParent(() => true) as NodePath<ObjectExpression>,
opPath.node,
);
if (arraysMatch(bindings, exBindings)) {
declarationPath = opPath;
initializer = opPath.node.value;
opPath.stop();
}
}
},
});
if (!declarationPath) {
return;
}
declarationPath = declarationPath as NodePath<MemberExpression>;
// mock a binding
const binding: Partial<Binding> = {
kind: 'const',
scope: declarationPath.scope,
identifier: types.identifier(variableName),
path: {
...(declarationPath as any), // eslint-disable-line
node: types.variableDeclarator(
types.objectPattern([types.objectProperty(types.identifier(variableName), types.identifier(variableName))]),
initializer,
),
},
};
return binding as Binding;
}
Example #22
Source File: img.ts From react-optimized-image with MIT License | 5 votes |
buildConfig = (types: Babel['types'], path: NodePath<JSXElement>): ImageConfig => {
// build config
let config: ImageConfig = { ...(globalImageConfig.default || {}) };
// check if a specific type is set
const type = getTypeAttribute(path, Object.keys(globalImageConfig.types || {}));
// add type configs
if (type && globalImageConfig.types && globalImageConfig.types[type]) {
config = { ...config, ...globalImageConfig.types[type] };
}
// check boolean attributes: webp, inline, url, original
['webp', 'inline', 'url', 'original'].forEach((attr) => {
const value = getBooleanAttribute(path, attr);
if (typeof value !== 'undefined') {
(config as Record<string, unknown>)[attr] = value;
} else if (typeof value === 'undefined' && (config as Record<string, unknown>)[attr] === true) {
// add attr from global image config
(path.get('openingElement') as NodePath<JSXOpeningElement>).pushContainer(
'attributes',
types.jsxAttribute(types.jsxIdentifier(attr), null),
);
}
});
// get sizes
const sizes = getNumberedArrayAttribute(path, 'sizes');
if (typeof sizes !== 'undefined') {
config.sizes = sizes;
} else if (config.sizes) {
// add sizes attr from global image config
(path.get('openingElement') as NodePath<JSXOpeningElement>).pushContainer(
'attributes',
types.jsxAttribute(
types.jsxIdentifier('sizes'),
types.jsxExpressionContainer(types.arrayExpression(config.sizes.map((size) => types.numericLiteral(size)))),
),
);
}
// get densities
const densities = getNumberedArrayAttribute(path, 'densities');
if (typeof densities !== 'undefined') {
config.densities = densities;
} else if (config.densities) {
// add densities attr from global image config
(path.get('openingElement') as NodePath<JSXOpeningElement>).pushContainer(
'attributes',
types.jsxAttribute(
types.jsxIdentifier('densities'),
types.jsxExpressionContainer(types.arrayExpression(config.densities.map((size) => types.numericLiteral(size)))),
),
);
}
// get breakpoints
const breakpoints = getNumberedArrayAttribute(path, 'breakpoints');
if (typeof breakpoints !== 'undefined') {
config.breakpoints = breakpoints;
} else if (config.breakpoints) {
// add breakpoints attr from global image config
(path.get('openingElement') as NodePath<JSXOpeningElement>).pushContainer(
'attributes',
types.jsxAttribute(
types.jsxIdentifier('breakpoints'),
types.jsxExpressionContainer(
types.arrayExpression(config.breakpoints.map((size) => types.numericLiteral(size))),
),
),
);
}
return config;
}