Files
OneOS1.2/scripts/ai-studio-converter.mjs
王冕 7ef8852919 Initial commit: OneOS prototype workspace baseline.
Include weekly report and other prototype sources with project tooling config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 15:36:52 +08:00

116 lines
3.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
function normalizeSlashes(input) {
return String(input || '').replace(/\\/g, '/');
}
function sanitizeName(rawName) {
return String(rawName || '')
.replace(/[^a-z0-9-]/gi, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
.toLowerCase();
}
function parseArgs(argv) {
const args = [...argv];
const projectDirArg = args.shift();
const outputNameArg = args.shift();
let targetType = 'prototypes';
let projectRoot = process.cwd();
let outputBaseDir = '';
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg === '--target-type') {
targetType = String(args[index + 1] || '').trim();
index += 1;
} else if (arg === '--project-root') {
projectRoot = path.resolve(args[index + 1] || projectRoot);
index += 1;
} else if (arg === '--output-base-dir') {
outputBaseDir = path.resolve(args[index + 1] || '');
index += 1;
}
}
if (!projectDirArg) throw new Error('Missing project directory');
const outputName = sanitizeName(outputNameArg || path.basename(projectDirArg));
if (!outputName) throw new Error('Missing valid output name');
return {
projectDir: path.resolve(projectRoot, projectDirArg),
outputName,
targetType,
projectRoot,
outputBaseDir: outputBaseDir || path.resolve(projectRoot, 'src', targetType),
};
}
function copyDirectory(src, dest) {
if (!fs.existsSync(src)) return 0;
fs.mkdirSync(dest, { recursive: true });
let count = 0;
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
if (entry.name === 'node_modules') continue;
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) count += copyDirectory(srcPath, destPath);
else if (entry.isFile()) {
fs.copyFileSync(srcPath, destPath);
count += 1;
}
}
return count;
}
function ensureIndex(outputDir) {
const indexPath = path.join(outputDir, 'index.tsx');
if (!fs.existsSync(indexPath)) {
fs.writeFileSync(indexPath, [
"import React from 'react';",
'',
'export default function ImportedAiStudioPrototype() {',
' return <div data-import-source="google_aistudio">AI Studio import requires AI conversion.</div>;',
'}',
'',
].join('\n'), 'utf8');
}
}
function main() {
const parsed = parseArgs(process.argv.slice(2));
if (!fs.existsSync(path.join(parsed.projectDir, 'App.tsx')) && !fs.existsSync(path.join(parsed.projectDir, 'index.html'))) {
throw new Error('这不是一个有效的 AI Studio 项目(缺少 App.tsx 或 index.html');
}
const outputDir = path.join(parsed.outputBaseDir, parsed.outputName);
fs.rmSync(outputDir, { recursive: true, force: true });
fs.mkdirSync(parsed.outputBaseDir, { recursive: true });
const fileCount = copyDirectory(parsed.projectDir, outputDir);
ensureIndex(outputDir);
const taskPath = path.join(outputDir, parsed.targetType === 'themes' ? '.ai-studio-theme-tasks.md' : '.ai-studio-tasks.md');
fs.writeFileSync(taskPath, [
'# AI Studio 项目转换任务清单',
'',
'> 请先阅读 `rules/ai-studio-project-converter.md` 和 `rules/development-guide.md`,再基于该目录完成原型转换。',
'',
`- 输出目录:\`${normalizeSlashes(path.relative(parsed.projectRoot, outputDir))}/\``,
`- 已复制文件数:${fileCount}`,
'',
].join('\n'), 'utf8');
console.log(JSON.stringify({
success: true,
outputDir,
tasksFile: normalizeSlashes(path.relative(parsed.projectRoot, taskPath)),
}));
}
try {
main();
} catch (error) {
console.error(error?.message || String(error));
process.exit(1);
}