UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

155 lines 6.53 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: !0 }); }, __copyProps = (to, from, except, desc) => { if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target, mod)), __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod); var sourceInspectorPlugin_exports = {}; __export(sourceInspectorPlugin_exports, { sourceInspectorPlugin: () => sourceInspectorPlugin }); module.exports = __toCommonJS(sourceInspectorPlugin_exports); var import_node_path = __toESM(require("node:path"), 1), import_oxc_parser = require("oxc-parser"), import_vite = require("vite"); function findJsxElements(code, filename) { const result = (0, import_oxc_parser.parseSync)(filename, code); if (result.errors.length > 0) return []; const locations = []; let traversalIndex = 0; function getJsxName(node) { if (!node) return null; if (node.type === "JSXIdentifier") return node.name; if (node.type === "JSXMemberExpression") { const obj = getJsxName(node.object); return obj ? `${obj}.${node.property?.name}` : null; } return null; } function getLocation(offset) { const lines = code.slice(0, offset).split(` `); return { line: lines.length, column: lines[lines.length - 1].length + 1 }; } function walk(node) { if (!(!node || typeof node != "object")) { if (node.type === "JSXOpeningElement" && node.name) { const tagName = getJsxName(node.name); if (tagName && tagName !== "Fragment" && !node.attributes?.some(attr => attr.type === "JSXAttribute" && attr.name?.name === "data-one-source")) { const nameEnd = node.name.end, loc = getLocation(node.start); locations.push({ insertOffset: nameEnd, index: traversalIndex++, line: loc.line, column: loc.column }); } } for (const key of Object.keys(node)) { if (key === "parent") continue; const value = node[key]; if (Array.isArray(value)) for (const child of value) walk(child);else value && typeof value == "object" && walk(value); } } } return walk(result.program), locations.sort((a, b) => b.insertOffset - a.insertOffset); } function injectSourceToJsx(code, id) { const [filePath] = id.split("?"); if (!filePath) return; const location = filePath.replace((0, import_vite.normalizePath)(process.cwd()), ""); if (!code.includes("<") || !code.includes(">")) return; const jsxLocations = findJsxElements(code, filePath); if (jsxLocations.length === 0) return; const sourceInfoEntries = [...jsxLocations].sort((a, b) => a.index - b.index).map(jsx => `${jsx.index}:[${jsx.line},${jsx.column}]`).join(","), sourceInfoScript = `globalThis.__oneSourceInfo=globalThis.__oneSourceInfo||{};globalThis.__oneSourceInfo["${location}"]={${sourceInfoEntries}};`; let result = code; for (const jsx of jsxLocations) { const sourceAttr = ` data-one-source="${location}:${jsx.index}"`; result = result.slice(0, jsx.insertOffset) + sourceAttr + result.slice(jsx.insertOffset); } return result = sourceInfoScript + result, { code: result, map: null }; } async function openInEditor(filePath, line, column) { try { const launch = (await import("launch-editor")).default, location = `${import_node_path.default.join(process.cwd(), filePath)}${line ? `:${line}` : ""}${column ? `:${column}` : ""}`; launch(location, void 0, (filename, errorMessage) => { errorMessage && console.warn(`[one:source-inspector] Failed to open ${filename} in editor:`, errorMessage); }); } catch (err) { console.warn("[one:source-inspector] Failed to launch editor:", err); } } function sourceInspectorPlugin() { return [ // Transform plugin - injects data-one-source attributes { name: "one:source-inspector-transform", enforce: "pre", apply: "serve", transform(code, id) { const envName = this.environment?.name; if (!(envName === "ios" || envName === "android") && !(id.includes("node_modules") || id.includes("?raw") || id.includes("dist") || id.includes("build")) && !(!id.endsWith(".jsx") && !id.endsWith(".tsx"))) return injectSourceToJsx(code, id); } }, // Note: Inspector UI script is now injected via DevHead.tsx for SSR compatibility // Server plugin - handles open-source requests { name: "one:source-inspector-server", apply: "serve", configureServer(server) { server.middlewares.use(async (req, res, next) => { if (!req.url?.startsWith("/__one/open-source")) return next(); try { const url = new URL(req.url, "http://localhost"), source = url.searchParams.get("source"); if (!source) { res.statusCode = 400, res.end("Missing source parameter"); return; } const lastColon = source.lastIndexOf(":"), filePath = source.slice(0, lastColon), index = source.slice(lastColon + 1), line = url.searchParams.get("line"), column = url.searchParams.get("column"); await openInEditor(filePath, line || void 0, column || void 0), res.statusCode = 200, res.end("OK"); } catch (err) { console.error("[one:source-inspector] Error:", err), res.statusCode = 500, res.end("Internal server error"); } }); } }]; }