UNPKG

bengaliscript

Version:

🚀 BengaliScript — Code in pure বাংলা! Write, run, and see output entirely in Bengali. Break language barriers, bring code closer to culture. Crafted with ❤️ by Atikin Verse.

153 lines (133 loc) 4.72 kB
/* Created by Atikin Verse */ import fs from "fs"; import vm from "vm"; import path from "path"; import { fileURLToPath } from "url"; import { KEYWORDS, ALIASES } from "./bengaliKeywords.js"; import fetch from "node-fetch"; import { JSDOM } from "jsdom"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Build replacement map (include aliases that point to canonical keys) const MAP = { ...KEYWORDS }; for (const [alias, to] of Object.entries(ALIASES)) { if (MAP[alias] === undefined && MAP[to]) { MAP[alias] = MAP[to]; } } function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Replace Bengali tokens in code sections, skip strings/comments function replaceKeywordsPreservingStrings(source, map) { const parts = []; let i = 0; const len = source.length; while (i < len) { const ch = source[i]; // Strings if (ch === "'" || ch === '"' || ch === "`") { const quote = ch; let j = i + 1; while (j < len) { if (source[j] === "\\" && j + 1 < len) { j += 2; continue; } if (source[j] === quote) { j++; break; } j++; } parts.push({ type: "string", text: source.slice(i, j) }); i = j; continue; } // Line comment if (ch === "/" && i + 1 < len && source[i + 1] === "/") { let j = i + 2; while (j < len && source[j] !== "\n") j++; parts.push({ type: "comment", text: source.slice(i, j) }); i = j; continue; } // Block comment if (ch === "/" && i + 1 < len && source[i + 1] === "*") { let j = i + 2; while (j + 1 < len && !(source[j] === "*" && source[j + 1] === "/")) j++; j = Math.min(len, j + 2); parts.push({ type: "comment", text: source.slice(i, j) }); i = j; continue; } // Code chunk let j = i + 1; while (j < len) { const c = source[j]; if (c === "'" || c === '"' || c === "`") break; if (c === "/" && (source[j + 1] === "/" || source[j + 1] === "*")) break; j++; } parts.push({ type: "code", text: source.slice(i, j) }); i = j; } // Longest-first token replacement with unicode-aware boundaries const keys = Object.keys(map).sort((a, b) => b.length - a.length); const letter = "\\p{L}\\p{N}_"; // letters, numbers, underscore for (const part of parts) { if (part.type !== "code") continue; let chunk = part.text; for (const key of keys) { const val = map[key]; const pattern = new RegExp(`(?<![${letter}])${escapeRegExp(key)}(?![${letter}])`, "gu"); chunk = chunk.replace(pattern, val); } part.text = chunk; } return parts.map(p => p.text).join(""); } export async function runBS(filePath, { enableDOM = true } = {}) { const abs = path.isAbsolute(filePath) ? filePath : path.join(process.cwd(), filePath); if (!fs.existsSync(abs)) throw new Error(`File not found: ${abs}`); const src = fs.readFileSync(abs, "utf8"); const translated = replaceKeywordsPreservingStrings(src, MAP); // Sandbox with optional DOM and utilities const sandbox = { console, setTimeout, setInterval, clearTimeout, clearInterval, fetch, global: null }; if (enableDOM) { const dom = new JSDOM( `<!doctype html><html><head></head><body><div id="app"></div></body></html>`, { url: "https://example.org" } ); sandbox.window = dom.window; sandbox.document = dom.window.document; sandbox.navigator = dom.window.navigator; sandbox.location = dom.window.location; // Simple browser-like APIs sandbox.alert = (msg) => console.log(String(msg)); sandbox.prompt = (q) => { console.log(String(q)); return ""; }; sandbox.confirm = (q) => { console.log(String(q)); return true; }; // Storage shims sandbox.localStorage = { _m: new Map(), getItem(k){ return this._m.has(k) ? this._m.get(k) : null; }, setItem(k,v){ this._m.set(k, String(v)); }, removeItem(k){ this._m.delete(k); }, clear(){ this._m.clear(); } }; sandbox.sessionStorage = { _m: new Map(), getItem(k){ return this._m.has(k) ? this._m.get(k) : null; }, setItem(k,v){ this._m.set(k, String(v)); }, removeItem(k){ this._m.delete(k); }, clear(){ this._m.clear(); } }; } sandbox.global = sandbox; const script = new vm.Script(translated, { filename: path.basename(abs) }); const context = vm.createContext(sandbox); const result = await script.runInContext(context); return result; }