UNPKG

@react-lib-tech/react-text-extractor

Version:

A tiny React component library (JS)

1 lines 19.8 kB
{"version":3,"sources":["../src/utils/scanProject.jsx","../src/utils/extractTextFromAst.jsx"],"sourcesContent":["// scanProject.js\nimport fs from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport { JSDOM } from \"jsdom\";\nimport React from \"react\";\nimport { renderToString } from \"react-dom/server\";\nimport OpenAI from \"openai\";\nimport { extractTextFromAst } from \"./extractTextFromAst\"; // keep your AST fallback\n\n// ✅ Load .gitignore\nfunction loadGitignore(rootPath) {\n const gitignorePath = path.join(rootPath, \".gitignore\");\n if (!fs.existsSync(gitignorePath)) return [];\n const content = fs.readFileSync(gitignorePath, \"utf8\");\n return content\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith(\"#\"));\n}\n\n// ✅ Skip rules helper\nfunction shouldSkip(value, skipWord = []) {\n if (!value) return true;\n const cleaned = value.trim();\n const lower = cleaned.toLowerCase();\n\n const htmlTags = [\n \"html\",\"head\",\"body\",\"div\",\"span\",\"p\",\"a\",\"img\",\"br\",\"hr\",\"ul\",\"ol\",\"li\",\n \"table\",\"tr\",\"td\",\"th\",\"thead\",\"tbody\",\"tfoot\",\"form\",\"input\",\"button\",\n \"select\",\"option\",\"textarea\",\"label\",\"script\",\"link\",\"meta\",\"style\",\n \"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"nav\",\"header\",\"footer\",\"section\",\"article\",\n \"aside\",\"main\",\"figure\",\"figcaption\",\"iframe\",\"canvas\",\"video\",\"audio\",\n ...skipWord\n ];\n\n return (\n !cleaned ||\n htmlTags.includes(lower) ||\n /^\\d+$/.test(cleaned) || // pure numbers\n /^\\d+%$/.test(cleaned) || // percentages\n /^#[0-9a-f]{3,6}$/i.test(cleaned) || // hex colors\n /^[^a-zA-Z0-9]+$/.test(cleaned) // only special chars\n );\n}\n\n// ✅ Render a React component\nfunction extractTextJsdom(Component, file) {\n try {\n if (typeof Component !== \"function\") return null;\n\n const element = React.createElement(Component);\n const htmlString = renderToString(element);\n const dom = new JSDOM(htmlString);\n const document = dom.window.document;\n\n let texts = [];\n\n const bodyText = document.body.textContent.replace(/\\s+/g, \" \").trim();\n if (bodyText) texts.push(bodyText);\n\n const selectors = [\"placeholder\", \"title\", \"alt\", \"aria-label\"];\n const allElements = document.querySelectorAll(\"*\");\n allElements.forEach((el) => {\n selectors.forEach((attr) => {\n if (el.hasAttribute(attr)) {\n const val = el.getAttribute(attr).trim();\n if (val) texts.push(val);\n }\n });\n });\n\n return texts.length ? texts : null;\n } catch (err) {\n console.warn(`⚠️ Error rendering ${file}: ${err.message}`);\n return null;\n }\n}\n\n// ✅ Recursive walker\nasync function walkDir(folderPath, skipList = []) {\n const results = [];\n const entries = fs.readdirSync(folderPath);\n\n for (const entry of entries) {\n const fullPath = path.join(folderPath, entry);\n const stats = fs.statSync(fullPath);\n const tempPath = folderPath.replace(/\\\\/g, \"/\");\n\n if (skipList.some((pattern) => tempPath.includes(pattern))) continue;\n\n if (stats.isDirectory()) {\n results.push(...(await walkDir(fullPath, skipList)));\n } else if (stats.isFile() && (entry.endsWith(\".js\") || entry.endsWith(\".jsx\"))) {\n let textArr = null;\n try {\n const moduleUrl = pathToFileURL(fullPath).href;\n const imported = await import(moduleUrl);\n const Component = imported.default || imported;\n textArr = extractTextJsdom(Component, fullPath);\n } catch {\n textArr = extractTextFromAst(fullPath);\n }\n if (textArr) results.push({ file: fullPath, text: textArr });\n }\n }\n\n return results;\n}\n\n// ✅ OpenAI helper\nasync function applyOpenAI(texts, {\n userPrompt,\n model = \"gpt-4o-mini\",\n temperature = 0.3,\n systemPrompt = \"You are a text transformation assistant.\",\n apiKey\n}) {\n if (!userPrompt) return texts;\n\n const key = apiKey || process.env.OPENAI_API_KEY;\n if (!key) {\n console.error(\"❌ Missing OpenAI API key\");\n return texts;\n }\n\n try {\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${key}`\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: `${userPrompt}\\n\\nHere is the text:\\n${texts.join(\"\\n\")}` }\n ],\n temperature\n })\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`);\n }\n\n const json = await response.json();\n const out = json.choices[0]?.message?.content?.trim();\n return out ? out.split(\"\\n\").map(t => t.trim()).filter(Boolean) : texts;\n\n } catch (err) {\n console.error(\"⚠️ REST API error:\", err.message);\n return texts;\n }\n}\n\n\n// ✅ Main extractor\nexport async function ReactTextExtractor({\n rootPath,\n skipWord = [],\n returnBoth = true, // return raw + filtered\n applyFilter = true, // if false, returns raw only\n\n // AI options\n prompt = null,\n aiModel = \"gpt-4o-mini\",\n aiTemperature = 0.3,\n aiSystemPrompt = \"You are a text transformation assistant.\",\n openaiApiKey = null\n}) {\n const gitignorePatterns = loadGitignore(rootPath);\n const data = await walkDir(rootPath, gitignorePatterns);\n const allTexts = data?.map((item) => item?.text?.textContent).flat().filter(Boolean) || [];\n\n const rawUnique = [];\n const seenRaw = new Set();\n\n const filteredUnique = [];\n const seenFiltered = new Set();\n\n allTexts.forEach((item) => {\n let cleaned = item.trim();\n const key = cleaned.toLowerCase();\n\n // raw collection\n if (!seenRaw.has(key)) {\n seenRaw.add(key);\n rawUnique.push(cleaned);\n }\n\n // filtered collection\n if (!shouldSkip(cleaned, skipWord) && !seenFiltered.has(key)) {\n seenFiltered.add(key);\n filteredUnique.push(cleaned);\n }\n });\n\n let result = returnBoth ? { raw: rawUnique, filtered: filteredUnique }\n : applyFilter ? filteredUnique\n : rawUnique;\n\n // ✅ Apply OpenAI transformation if requested\n if (prompt) {\n const aiOptions = {\n userPrompt: prompt,\n model: aiModel,\n temperature: aiTemperature,\n systemPrompt: aiSystemPrompt,\n apiKey: openaiApiKey\n };\n\n if (returnBoth) {\n result = {\n raw: await applyOpenAI(rawUnique, aiOptions),\n filtered: await applyOpenAI(filteredUnique, aiOptions),\n };\n } else {\n result = await applyOpenAI(result, aiOptions);\n }\n }\n\n return result;\n}\n\n// ✅ CommonJS support\nif (typeof module !== \"undefined\" && module.exports) {\n module.exports = { ReactTextExtractor };\n}\n","import fs from \"fs\";\nimport { parse } from \"@babel/parser\";\nimport traverseModule from \"@babel/traverse\";\nconst traverse = traverseModule.default;\n\nexport function extractTextFromAst(filePath) {\n try {\n const code = fs.readFileSync(filePath, \"utf8\");\n const ast = parse(code, {\n sourceType: \"module\",\n plugins: [\"jsx\", \"typescript\"],\n });\n\n const result = {\n textContent: [], // everything plain text or string args\n placeholders: [],\n titles: [],\n labels: [],\n messages: [],\n buttons: [],\n functions: []\n };\n\n const getAttrValue = (valueNode) => {\n if (!valueNode) return null;\n\n if (valueNode.type === \"StringLiteral\") {\n return valueNode.value;\n }\n\n if (\n valueNode.type === \"JSXExpressionContainer\" &&\n valueNode.expression.type === \"StringLiteral\"\n ) {\n return valueNode.expression.value;\n }\n\n return null;\n };\n\n traverse(ast, {\n // <div>Hello</div>\n JSXText(path) {\n const text = path.node.value.trim();\n if (text) {\n result.textContent.push(text);\n }\n },\n\n // JSX attributes\n JSXAttribute(path) {\n const name = path.node.name?.name;\n const value = getAttrValue(path.node.value);\n if (value !== null) {\n if (name === \"placeholder\") result.placeholders.push(value);\n else if (name === \"title\") result.titles.push(value);\n else if (name === \"aria-label\" || name === \"label\")\n result.labels.push(value);\n else if (name === \"message\") result.messages.push(value);\n\n // also push into textContent\n result.textContent.push(value);\n }\n },\n\n // <label>Some Label</label>\n JSXElement(path) {\n const tagName = path.node.openingElement?.name?.name;\n\n if (tagName === \"label\") {\n path.node.children.forEach((child) => {\n if (child.type === \"JSXText\") {\n const text = child.value.trim();\n if (text) {\n result.labels.push(text);\n result.textContent.push(text);\n }\n }\n });\n }\n\n if (tagName === \"Button\") {\n path.node.children.forEach((child) => {\n if (child.type === \"JSXText\") {\n const text = child.value.trim();\n if (text) {\n result.buttons.push(text);\n result.textContent.push(text);\n }\n }\n if (\n child.type === \"JSXExpressionContainer\" &&\n child.expression.type === \"CallExpression\"\n ) {\n const callee =\n child.expression.callee.name ||\n child.expression.callee.property?.name;\n const args = child.expression.arguments\n .filter((a) => a.type === \"StringLiteral\")\n .map((a) => a.value);\n\n if (args.length) {\n result.buttons.push(...args);\n result.textContent.push(...args);\n result.functions.push({\n function: callee,\n args,\n from: \"child\",\n });\n }\n }\n });\n }\n },\n\n // any function call\n CallExpression(path) {\n const callee =\n path.node.callee.name ||\n path.node.callee.property?.name ||\n \"anonymousFn\";\n\n const args = path.node.arguments\n .filter((a) => a.type === \"StringLiteral\")\n .map((a) => a.value);\n\n if (args.length) {\n // store in function list\n result.functions.push({\n function: callee,\n args,\n from: \"code\",\n });\n\n // also push into textContent (even empty \"\")\n result.textContent.push(...args);\n }\n },\n });\n\n return result;\n } catch (err) {\n console.warn(`⚠️ AST parse failed for ${filePath}: ${err.message}`);\n return null;\n }\n}"],"mappings":"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","names":["fs","path","_a","fs"]}