Skip to content

Instantly share code, notes, and snippets.

@baransu
Created July 27, 2018 22:17
Show Gist options
  • Save baransu/ba11c1edbeb3e48894abe109f3029b87 to your computer and use it in GitHub Desktop.
Save baransu/ba11c1edbeb3e48894abe109f3029b87 to your computer and use it in GitHub Desktop.
[WIP] Generate ReasonReact bindings
// @noflow
const { compile, format } = require("reasonably-typed");
const fs = require("fs");
const COMPONENTS = [
"Button",
"Card",
"Center",
"Checkbox",
"CloseIcon",
"DatePicker",
"DotIcon",
"Error",
"FormItem",
"H2",
"Icon",
"If",
"Input",
"KeyValue",
"Link",
"Notifications",
"Pagination",
"Popconfirm",
"Quote",
"RangeDatePicker",
"SmallText",
"Spinner",
"Switch",
"Table",
"Tabs",
"Text",
"Textarea",
"Tooltip"
];
COMPONENTS.forEach(module => {
const inputPath = `./src/components/${module}.js`;
const source = fs.readFileSync(inputPath).toString();
const CLASS_REGEX = /(class \w+ extends Component<\w+(, \w+)?>)/gm;
const TYPE_REGEX = /(type \w+ = (.|\s)+?;)/gm;
const FUNCTION_REGEX = /(function|const) [A-Z]\w+ = \(props: Props\)/gm;
function getTypes(source) {
return (source.match(TYPE_REGEX) || [])
.map(type => type.replace(/<\*>/g, "<any>"))
.map(type => `declare ${type}`)
.join("\n\n");
}
function getClasses(source) {
return (source.match(CLASS_REGEX) || [])
.map(c => c.replace(/Component/, "React$Component"))
.map(c => `declare export ${c} { }`)
.join("\n\n");
}
function getFunctions(source) {
return (source.match(FUNCTION_REGEX) || []).join("\n\n");
}
const input = `
const React = require('react');
declare module 'components' {
${getTypes(source)}
${getClasses(source)}
${getFunctions(source)}
}
`;
console.log(input);
const { bsCode } = compile(input, inputPath, true, true);
const clean = bsCode
.replace(/elementRef\('any\)/g, "ref(ReasonReact.reactElement)")
.replace(/react_Node/g, "ReasonReact.reactElement")
.replace(/syntheticEvent\('any\)/g, "ReactEventRe.Synthetic.t")
.replace(/unit_or_promise_any/g, "Js.Promise.t(unit)")
.replace(/Js\.boolean/g, "bool")
.replace(/"style": Js\.Nullable\.t\('any\)/g, `"style": Js.Nullable.t(ReactDOMRe.style)`)
.replace(/"type": _type/g, `"_type": _type`)
.replace(/Js\.Boolean\.to_js_boolean/g, "")
.replace(/Js\.Nullable\.from_opt/g, "Js.Nullable.fromOption");
const reason = format(clean);
const output = `./src/${module}.re`;
if (fs.existsSync(output)) {
console.error(`Output file: ${output} already exists.`);
} else {
fs.writeFileSync(output, reason, "utf-8");
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment