@cifumo/scraper-node
Version:
Sebuah Module Scraper yang dibuat oleh Sxyz dan SuzakuTeam untuk memudahkan penggunaan scraper di project ESM maupun CJS.
161 lines (130 loc) • 4.39 kB
JavaScript
import * as acorn from "acorn";
function jsToCoffeeEsm(jsCode, options = {}) {
const ast = acorn.parse(jsCode, {
ecmaVersion: "latest",
sourceType: "module",
});
let output = "";
for (const node of ast.body) {
if (node.type === "FunctionDeclaration") {
output += convertFunctionDeclaration(node) + "\n\n";
}
if (node.type === "VariableDeclaration") {
output += convertVariableDeclaration(node) + "\n\n";
}
if (node.type === "ExpressionStatement") {
output += extractExpression(node.expression) + "\n";
}
}
return output.trim();
}
function jsToCoffee(jsCode, options = {}) {
const ast = acorn.parse(jsCode, {
ecmaVersion: "latest",
});
let output = "";
for (const node of ast.body) {
if (node.type === "FunctionDeclaration") {
output += convertFunctionDeclaration(node) + "\n\n";
}
if (node.type === "VariableDeclaration") {
output += convertVariableDeclaration(node) + "\n\n";
}
if (node.type === "ExpressionStatement") {
output += extractExpression(node.expression) + "\n";
}
}
return output.trim();
}
function convertFunctionDeclaration(node) {
const name = node.id.name;
const params = node.params.map((p) => p.name).join(", ");
const bodyLines = extractBodyStatements(node.body);
const indented = bodyLines.map((line) => " " + line).join("\n");
return `${name} = (${params}) ->\n${indented}`;
}
function convertVariableDeclaration(node) {
let out = "";
for (const decl of node.declarations) {
const name = decl.id.name;
const init = decl.init;
if (!init) continue;
if (init.type === "ArrowFunctionExpression") {
const params = init.params.map((p) => p.name).join(", ");
const bodyLines = extractBodyStatements(init.body);
const indented = bodyLines.map((line) => " " + line).join("\n");
out += `${name} = (${params}) ->\n${indented}\n`;
} else if (init.type === "ObjectExpression") {
const props = init.properties
.map((p) => {
const key = p.key.name || p.key.value;
if (p.value.type === "FunctionExpression") {
const args = p.value.params.map((a) => a.name).join(", ");
const body = extractBodyStatements(p.value.body)
.map((l) => " " + l)
.join("\n");
return ` ${key}: (${args}) ->\n${body}`;
} else {
return ` ${key}: ${extractExpression(p.value)}`;
}
})
.join("\n");
out += `${name} =\n${props}\n`;
} else {
out += `${name} = ${extractExpression(init)}\n`;
}
}
return out.trim();
}
function extractBodyStatements(bodyNode) {
if (bodyNode.type !== "BlockStatement") {
return ["return " + extractExpression(bodyNode)];
}
const lines = [];
for (const stmt of bodyNode.body) {
if (stmt.type === "ReturnStatement") {
lines.push("return " + extractExpression(stmt.argument));
} else if (stmt.type === "ExpressionStatement") {
lines.push(extractExpression(stmt.expression));
} else if (stmt.type === "VariableDeclaration") {
for (const d of stmt.declarations) {
const name = d.id.name;
const val = extractExpression(d.init);
lines.push(`${name} = ${val}`);
}
} else {
lines.push("# [unsupported statement]");
}
}
return lines;
}
function extractExpression(expr) {
switch (expr.type) {
case "Literal":
return JSON.stringify(expr.value);
case "Identifier":
return expr.name;
case "ThisExpression":
return "@";
case "BinaryExpression":
return `${extractExpression(expr.left)} ${expr.operator} ${extractExpression(expr.right)}`;
case "CallExpression": {
const callee = extractExpression(expr.callee);
const args = expr.arguments.map(extractExpression).join(", ");
return `${callee} ${args}`;
}
case "MemberExpression": {
const object =
expr.object.type === "ThisExpression"
? "@"
: extractExpression(expr.object);
const property = expr.computed
? `[${extractExpression(expr.property)}]`
: `.${extractExpression(expr.property)}`;
return `${object}${property}`;
}
default:
return "# [unsupported expression: " + expr.type + "]";
}
}
export { jsToCoffee, jsToCoffeeEsm };