UNPKG

ucbuilder

Version:

:Shree Ganeshay Namah: new way app design

182 lines (180 loc) 6.82 kB
import fs from 'fs'; import path from 'path'; import { cleanPath } from '../../common/ipc/enumAndMore.js'; import { ImportUserConfig } from './userConfigManage.js'; export function ensureHead() { let html = document.documentElement; if (!html) { html = document.createElement('html'); document.appendChild(html); } let head = html.querySelector('head'); if (!head) { head = document.createElement('head'); html.insertBefore(head, html.firstChild); } return head; } export async function scanAllProjects(mainRoot = process.cwd()) { //console.log(mainRoot); const result = []; async function readProject(projectRoot) { const ucconfigPath = path.join(projectRoot, 'ucconfig.js'); if (!fs.existsSync(ucconfigPath)) return; try { // const json = JSON.parse(fs.readFileSync(ucconfigPath, 'utf8')) const json = await ImportUserConfig(ucconfigPath); const relPath = path.relative(mainRoot, projectRoot) || '.'; result.push({ rootPath: relPath.replace(/\\/g, '/'), projectName: /*json.name ??*/ path.basename(projectRoot), browser: json.browser ?? {} }); } catch { /* ignore invalid */ } } // ✅ main project first await readProject(mainRoot); // ✅ recursive scan async function walk(dir) { let entries; try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; } for (const entry of entries) { if (!entry.isDirectory()) continue; const full = path.join(dir, entry.name); await readProject(full); await walk(full); } } await walk(path.join(mainRoot, 'node_modules')); return result; } export function createImportMap(htmlPath, projects, baseDir = process.cwd()) { /*const docUrl = new URL(window.location.href); const htmlDir = docUrl.pathname.replace(/\/[^/]+$/, '/'); const htmlPath = fileURLToPath(docUrl)*/ const htmlDirPath = path.dirname(htmlPath); const projectRoot = baseDir; const relFromHtml = '.'; /*path .relative(htmlDirPath, projectRoot) .replace(/\\/g, '/')*/ console.log([ projectRoot, htmlDirPath, relFromHtml ]); const importMap = { scopes: {} }; for (const project of projects) { const isMain = project.rootPath === '.'; const scopeKey = isMain ? `./` : `${relFromHtml}/${project.rootPath}/`; importMap.scopes[scopeKey] ??= {}; const scope = importMap.scopes[scopeKey]; // ✅ ALWAYS add project-name alias scope[`${project.projectName}/`] = isMain ? `${relFromHtml}/` : `${relFromHtml}/${project.rootPath}/`; // ✅ add browser.importmap aliases for (const [alias, value] of Object.entries(project.browser.importmap ?? {})) { const a = `${cleanPath(alias)}/`; const v = `${relFromHtml}/${cleanPath(value)}/`; //value.startsWith('./') ? value : `./${value}` scope[a] = v; } } console.log(importMap); return importMap; } export function injectImportMap(html, importMap) { const importMapScript = `<script type="importmap">${JSON.stringify(importMap)}</script>`; if (/<head>/i.test(html)) { return html.replace(/<head>/i, `<head>\n${importMapScript}`); } else if (/<html[^>]*>/i.test(html)) { return html.replace(/<html[^>]*>/i, `$&\n<head>${importMapScript}</head>`); } else { return `${importMapScript}\n${html}`; } } function findSubProjects(rootDir) { const nodeModules = path.join(rootDir, "node_modules"); if (!fs.existsSync(nodeModules)) return []; const dirs = fs.readdirSync(nodeModules).filter(d => fs.statSync(path.join(nodeModules, d)).isDirectory()); return dirs.map(d => path.join(nodeModules, d)); } async function getBrowserConfig(projectDir) { const configPath = path.join(projectDir, "ucconfig.js"); if (!fs.existsSync(configPath)) return null; const cfg = await ImportUserConfig(configPath); //JSON.parse(fs.readFileSync(configPath, "utf-8")); return cfg.browser || null; } function findSubProjectsRecursive(dir, seen = new Set()) { const projects = []; if (!fs.existsSync(dir)) return projects; const nodeModules = path.join(dir, "node_modules"); if (!fs.existsSync(nodeModules)) return projects; const dirs = fs.readdirSync(nodeModules).filter(d => fs.statSync(path.join(nodeModules, d)).isDirectory()); for (const d of dirs) { const fullPath = path.join(nodeModules, d); if (seen.has(fullPath)) continue; seen.add(fullPath); // Only include if it has ucconfig.json if (fs.existsSync(path.join(fullPath, "ucconfig.js"))) { projects.push(fullPath); } // Recursively check inside this sub-project const nested = findSubProjectsRecursive(fullPath, seen); projects.push(...nested); } return projects; } function toFileUrl(p) { const fullPath = path.resolve(p).replace(/\\/g, "/"); // forward slashes return `file:///${fullPath}/`; // note 3 slashes } export async function generateImportMap(mainProjectDir) { const importMap = { imports: {}, scopes: {} }; const mainBrowser = await getBrowserConfig(mainProjectDir); const mainScope = `${toFileUrl(path.resolve(mainProjectDir).replace(/\\/g, "/"))}`; importMap.scopes[mainScope] = {}; if (mainBrowser?.importmap) { for (const [k, v] of Object.entries(mainBrowser.importmap)) { importMap.scopes[mainScope][`${cleanPath(k)}/`] = `${toFileUrl(path.resolve(mainProjectDir, v).replace(/\\/g, "/"))}`; } } // Recursive sub-projects const subProjects = findSubProjectsRecursive(mainProjectDir); for (const sub of subProjects) { const subBrowser = await getBrowserConfig(sub); if (!subBrowser) continue; const scopeKey = `${toFileUrl(sub.replace(/\\/g, "/"))}`; importMap.scopes[scopeKey] = {}; if (subBrowser.importmap) { for (const [k, v] of Object.entries(subBrowser.importmap)) { importMap.scopes[scopeKey][`${cleanPath(k)}/`] = `${toFileUrl(path.resolve(sub, v).replace(/\\/g, "/"))}`; } } // Always map project name → project root const projName = path.basename(sub); importMap.scopes[scopeKey][projName + "/"] = scopeKey; } return importMap; } //# sourceMappingURL=importMapGenerator.js.map