@react-lib-tech/react-tsx-to-jsx
Version:
A tiny React component library (JS) for converting TSX → JSX and extracting text
1 lines • 11.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils/restore-project.jsx","../src/utils/rename-js-to-jsx.jsx"],"sourcesContent":["import axios from \"axios\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport https from \"https\";\n\nconst httpsAgent = new https.Agent({ rejectUnauthorized: false });\nconst API_URL = \"https://lovable-api.com/projects/\";\n\n/**\n * LovableDownload options:\n * - API_URL: string (source URL)\n * - Authorization: string (auth header)\n * - outputDir: string (where to write files) - defaults to process.cwd()\n * - allowBinary: boolean - if true, will write binary files (assumed base64). Default false.\n */\nexport async function LovableDownload({\n PROJECT_Id = \"5b9f446c-d608-4948-aed1-7e5ba9ad04c0\",\n Authorization = \"\",\n outputDir = process.cwd(),\n allowBinary = false\n} = {}) {\n // resolve and normalize output directory\n const baseOut = path.resolve(outputDir);\n\n // helper to ensure destination stays inside outputDir\n function safeResolve(rel) {\n // normalize incoming path so ../ segments are collapsed\n const resolved = path.resolve(baseOut, rel);\n // allow exactly baseOut or anything under it\n if (resolved === baseOut || resolved.startsWith(baseOut + path.sep)) {\n return resolved;\n }\n throw new Error(`Unsafe path detected: ${rel}`);\n }\n\n try {\n // 1. Fetch JSON from API\n const res = await axios.get(API_URL+PROJECT_Id+\"/source-code\", {\n httpsAgent,\n headers: { Authorization: Authorization },\n });\n\n const data = res?.data;\n if (!data || !Array.isArray(data.files)) {\n console.log(\"No files returned by API\");\n return;\n }\n\n for (const file of data?.files) {\n try {\n // compute the destination path safely (prevents ../ traversal)\n const destPath = safeResolve(file.name);\n\n if (file.binary && !allowBinary) {\n console.log(`⚠️ Skipping binary file: ${file.name}`);\n continue;\n }\n\n // ensure parent folder exists\n fs.mkdirSync(path.dirname(destPath), { recursive: true });\n\n // write file\n if (file.binary) {\n // assume base64-encoded binary content\n const contents = file.contents ?? \"\";\n try {\n const buffer = Buffer.from(contents, \"base64\");\n fs.writeFileSync(destPath, buffer);\n } catch (e) {\n console.warn(`⚠️ Failed to write binary file ${file.name}: ${e.message}`);\n continue;\n }\n } else {\n // ensure we write string data\n const contents = typeof file.contents === \"string\" ? file.contents : JSON.stringify(file.contents ?? \"\", null, 2);\n fs.writeFileSync(destPath, contents, \"utf8\");\n }\n\n console.log(`✅ Created: ${destPath}`);\n } catch (innerErr) {\n console.warn(`⚠️ Skipped file ${file.name}: ${innerErr.message}`);\n }\n }\n\n console.log(\"🎉 Project restored with correct folder structure!\");\n console.log(`Files written to: ${baseOut}`);\n } catch (err) {\n console.error(\"❌ Error:\", err?.message ?? err);\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport babel from \"@babel/core\";\n\n// ✅ Load and parse .gitignore manually\nfunction loadGitignore(rootPath = \".\") {\n const gitignorePath = path.join(rootPath, \".gitignore\");\n if (!fs.existsSync(gitignorePath)) return [];\n\n return fs\n .readFileSync(gitignorePath, \"utf8\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith(\"#\"));\n}\n\n// ✅ Convert gitignore patterns → regex\nfunction patternToRegex(pattern) {\n let regexStr = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\") // escape regex special chars\n .replace(/\\*\\*/g, \".*\") // ** → deep any\n .replace(/\\*/g, \"[^/]*\"); // * → single folder/file\n\n if (pattern.endsWith(\"/\")) {\n regexStr = regexStr + \".*\"; // match everything under folder\n }\n\n return new RegExp(regexStr);\n}\n\nfunction createIgnoreMatcher(rootPath, userSkips = []) {\n const patterns = [\n ...loadGitignore(rootPath).map(patternToRegex),\n ...userSkips.map(patternToRegex),\n ];\n\n return function isIgnored(relPath) {\n // Normalize to forward-slashes\n const normalized = relPath.replace(/\\\\/g, \"/\");\n return patterns.some((regex) => regex.test(normalized));\n };\n}\n\n// ✅ Default Replacement Rules\nconst defaultReplacementRules = [\n { find: /@\\/components\\//g, replace: \"../components/\" },\n { find: /@\\/lib\\//g, replace: \"../../lib/\" },\n { find: /@\\/utils\\//g, replace: \"../utils/\" },\n { find: /@\\/assets\\//g, replace: \"../public/assets/\" },\n];\n\n// ✅ Convert single file\nexport async function tsxToJsx(\n tsPath,\n outPath,\n isTsx,\n InputreplacementRules = []\n) {\n try {\n const code = fs.readFileSync(tsPath, \"utf-8\");\n\n const result = await babel.transformAsync(code, {\n filename: tsPath,\n presets: [\"@babel/preset-typescript\"],\n });\n\n let output = result.code || \"\";\n\n const replacementRules = [\n ...defaultReplacementRules,\n ...InputreplacementRules,\n ];\n replacementRules.forEach((rule) => {\n output = output.replace(rule.find, rule.replace);\n });\n\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n fs.writeFileSync(outPath, output, \"utf-8\");\n\n console.log(`✅ Converted: ${tsPath} -> ${outPath}`);\n } catch (err) {\n console.error(`❌ Error converting ${tsPath}:`, err.message);\n }\n}\n\n// ✅ Walk folders recursively\nconst convertFolder = async ({\n srcFolder = \"src\",\n outFolder = \"dist\",\n InputreplacementRules = [],\n typeConvert = \".jsx\",\n skipFiles = [],\n}) => {\n if (!fs.existsSync(srcFolder)) {\n console.error(`❌ Source folder not found: ${srcFolder}`);\n return;\n }\n\n const isIgnored = createIgnoreMatcher(process.cwd(), skipFiles);\n const entries = fs.readdirSync(srcFolder, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(srcFolder, entry.name);\n const relPath = path.relative(process.cwd(), srcPath); // relative to root\n\n // 🔄 Skip gitignored OR user-specified\n if (isIgnored(relPath)) {\n console.log(`⏭️ Skipped: ${relPath}`);\n continue;\n }\n\n const outPath = path.join(outFolder, entry.name);\n\n if (entry.isDirectory()) {\n await convertFolder({\n srcFolder: srcPath,\n outFolder: outPath,\n InputreplacementRules,\n typeConvert,\n skipFiles,\n });\n } else if (entry.isFile()) {\n if (entry.name.endsWith(\".tsx\")) {\n const jsxPath = outPath.replace(/\\.tsx$/, typeConvert);\n await tsxToJsx(srcPath, jsxPath, true, InputreplacementRules);\n } else if (entry.name.endsWith(\".ts\")) {\n const jsPath = outPath.replace(/\\.ts$/, \".js\");\n await tsxToJsx(srcPath, jsPath, false, InputreplacementRules);\n }\n }\n }\n};\n\nexport default convertFolder;\n"],"mappings":"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","names":["fs","path"]}