v0-rails
Version:
Convert React/JSX + Tailwind UI code from v0.dev to Rails ViewComponent classes and ERB templates with automatic slot detection, icon handling, and route generation
55 lines (51 loc) • 1.98 kB
JavaScript
const t = require('@babel/types');
/**
* Detect event handlers in JSX elements
* @param {Object} jsxElement - Babel JSX element node
* @returns {Array} - List of detected events
*/
function detectEvents(jsxElement) {
const events = [];
if (!jsxElement.openingElement || !jsxElement.openingElement.attributes) {
return events;
}
jsxElement.openingElement.attributes.forEach(attr => {
if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name.startsWith('on') && attr.name.name.length > 2 && attr.name.name[2] === attr.name.name[2].toUpperCase()) {
// Extract event name (e.g., 'onClick' -> 'click')
const eventName = attr.name.name.slice(2).toLowerCase();
// Extract handler information
let handler = '';
let params = [];
if (t.isJSXExpressionContainer(attr.value)) {
if (t.isIdentifier(attr.value.expression)) {
// Simple handler reference (e.g., onClick={handleClick})
handler = attr.value.expression.name;
} else if (t.isArrowFunctionExpression(attr.value.expression)) {
// Arrow function (e.g., onClick={(e) => handleClick(e, id)})
const arrowFunc = attr.value.expression;
// Extract parameters
if (arrowFunc.params.length > 0) {
params = arrowFunc.params.map(param => t.isIdentifier(param) ? param.name : 'param');
}
// Extract handler from body
if (t.isCallExpression(arrowFunc.body)) {
handler = t.isIdentifier(arrowFunc.body.callee) ? arrowFunc.body.callee.name : 'complexHandler';
} else if (t.isBlockStatement(arrowFunc.body)) {
handler = `${eventName}Handler`;
} else {
handler = `${eventName}Handler`;
}
}
}
events.push({
name: eventName,
handler: handler || `${eventName}Handler`,
params
});
}
});
return events;
}
module.exports = {
detectEvents
};