UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

360 lines (358 loc) • 12.8 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__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(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var sourceInspectorPlugin_exports = {}; __export(sourceInspectorPlugin_exports, { getSourceInspectorPath: () => getSourceInspectorPath, injectSourceToJsx: () => injectSourceToJsx, resolveEditorFilePath: () => resolveEditorFilePath, sourceInspectorPlugin: () => sourceInspectorPlugin }); module.exports = __toCommonJS(sourceInspectorPlugin_exports); var import_child_process = require("child_process"); var import_fs = require("fs"); var import_path = __toESM(require("path"), 1); var import_oxc_parser = require("oxc-parser"); var import_vite = require("vite"); var DOM_TAGS = new Set("a abbr address area article aside audio b base bdi bdo blockquote body br button canvas caption cite code col colgroup data datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins kbd label legend li link main map mark menu meta meter nav noscript object ol optgroup option output p picture pre progress q rp rt ruby s samp script search section select slot small source span strong style sub summary sup table tbody td template textarea tfoot th thead time title tr track u ul var video wbr svg animate animateMotion animateTransform circle clipPath defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter foreignObject g image line linearGradient marker mask metadata mpath path pattern polygon polyline radialGradient rect set stop switch symbol text textPath tspan use view".split(" ")); function isHostTag(tagName) { var first = tagName.charCodeAt(0); return first >= 97 && first <= 122 && !tagName.includes("."); } async function findJsxElements(code2, filename) { var result = await (0, import_oxc_parser.parse)(filename, code2); if (result.errors.length > 0) { return []; } var locations = []; function getJsxName(node) { if (!node) return null; if (node.type === "JSXIdentifier") return node.name; if (node.type === "JSXMemberExpression") { var _node_property; var obj = getJsxName(node.object); return obj ? `${obj}.${(_node_property = node.property) === null || _node_property === void 0 ? void 0 : _node_property.name}` : null; } return null; } function getLocation(offset) { var before = code2.slice(0, offset); var lines = before.split("\n"); return { line: lines.length, column: lines[lines.length - 1].length + 1 }; } function walk(node) { if (!node || typeof node !== "object") return; if (node.type === "JSXOpeningElement" && node.name) { var tagName = getJsxName(node.name); if (tagName && tagName !== "Fragment" && !tagName.endsWith(".Fragment") && (!isHostTag(tagName) || DOM_TAGS.has(tagName))) { var _node_attributes; var hasSourceAttr = (_node_attributes = node.attributes) === null || _node_attributes === void 0 ? void 0 : _node_attributes.some(function(attr) { var _attr_name; return attr.type === "JSXAttribute" && ((_attr_name = attr.name) === null || _attr_name === void 0 ? void 0 : _attr_name.name) === "data-one-source"; }); if (!hasSourceAttr) { var nameEnd = node.name.end; var loc = getLocation(node.start); locations.push({ insertOffset: nameEnd, line: loc.line, column: loc.column }); } } } var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0; try { for (var _iterator = Object.keys(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var key = _step.value; if (key === "parent") continue; var value = node[key]; if (Array.isArray(value)) { var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0; try { for (var _iterator1 = value[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) { var child = _step1.value; walk(child); } } catch (err) { _didIteratorError1 = true; _iteratorError1 = err; } finally { try { if (!_iteratorNormalCompletion1 && _iterator1.return != null) { _iterator1.return(); } } finally { if (_didIteratorError1) { throw _iteratorError1; } } } } else if (value && typeof value === "object") { walk(value); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } walk(result.program); return locations.sort(function(a, b) { return b.insertOffset - a.insertOffset; }); } function getSourceInspectorPath(filePath) { var cwd = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : process.cwd(); var normalizedFilePath = (0, import_vite.normalizePath)(filePath); var normalizedCwd = (0, import_vite.normalizePath)(cwd); if (normalizedFilePath === normalizedCwd) { return "/"; } if (normalizedFilePath.startsWith(`${normalizedCwd}/`)) { return normalizedFilePath.slice(normalizedCwd.length); } return normalizedFilePath; } function resolveEditorFilePath(filePath) { var cwd = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : process.cwd(), fileExists = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : import_fs.existsSync; var projectPath = (0, import_vite.normalizePath)(import_path.default.join(cwd, filePath)); return fileExists(projectPath) ? projectPath : filePath; } async function injectSourceToJsx(code2, id) { var [filePath] = id.split("?"); if (!filePath) return; var location = getSourceInspectorPath(filePath); if (!code2.includes("<") || !code2.includes(">")) { return; } var jsxLocations = await findJsxElements(code2, filePath); if (jsxLocations.length === 0) { return; } var result = code2; var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0; try { for (var _iterator = jsxLocations[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var jsx = _step.value; var sourceAttr = ` data-one-source="${location}:${jsx.line}:${jsx.column}"`; result = result.slice(0, jsx.insertOffset) + sourceAttr + result.slice(jsx.insertOffset); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return { code: result, map: null }; } var editorWarned = false; var editorArgs = { code: function code(f, l, c) { return ["-g", `${f}:${l}:${c}`]; }, cursor: function cursor(f, l, c) { return ["-g", `${f}:${l}:${c}`]; }, codium: function codium(f, l, c) { return ["-g", `${f}:${l}:${c}`]; }, vscodium: function vscodium(f, l, c) { return ["-g", `${f}:${l}:${c}`]; }, zed: function zed(f, l, c) { return [`${f}:${l}:${c}`]; }, subl: function subl(f, l, c) { return [`${f}:${l}:${c}`]; }, webstorm: function webstorm(f, l, c) { return [ "--line", l, "--column", c, f ]; }, idea: function idea(f, l, c) { return [ "--line", l, "--column", c, f ]; }, vim: function vim(f, l) { return [`+${l}`, f]; }, nvim: function nvim(f, l) { return [`+${l}`, f]; }, emacs: function emacs(f, l, c) { return [`+${l}:${c}`, f]; } }; function openInEditor(editor, filePath, line, column) { var resolved = editor || process.env.LAUNCH_EDITOR || process.env.EDITOR; if (!resolved) { if (!editorWarned) { editorWarned = true; console.warn(`[one] Set devtools.editor in your one config or LAUNCH_EDITOR env var to open files from the inspector (e.g. 'cursor', 'code', 'zed')`); } return; } var fullPath = resolveEditorFilePath(filePath); var l = line || "1"; var c = column || "1"; var buildArgs = editorArgs[resolved]; var args = buildArgs ? buildArgs(fullPath, l, c) : [fullPath]; var child = (0, import_child_process.spawn)(resolved, args, { stdio: "ignore", detached: true }); child.unref(); child.on("error", function(err) { console.warn(`[one:source-inspector] Failed to open editor '${resolved}': ${err.message}`); }); } var vscodeClients = /* @__PURE__ */ new Set(); function sourceInspectorPlugin(opts) { var cache = /* @__PURE__ */ new Map(); return [{ name: "one:source-inspector-transform", enforce: "pre", apply: "serve", transform: { order: "pre", async handler(code2, id) { var _this_environment; var envName = (_this_environment = this.environment) === null || _this_environment === void 0 ? void 0 : _this_environment.name; if (envName === "ios" || envName === "android") return; if (id.includes("node_modules") || id.includes("?raw") || id.includes("dist") || id.includes("build")) { return; } if (!id.endsWith(".jsx") && !id.endsWith(".tsx")) return; if (cache.has(code2)) { return cache.get(code2); } var out = await injectSourceToJsx(code2, id); cache.set(code2, out); if (cache.size > 100) { cache.clear(); } return out; } } }, { name: "one:source-inspector-server", apply: "serve", configureServer(server) { var wss = null; import("ws").then(function(param) { var { WebSocketServer } = param; var _server_httpServer; wss = new WebSocketServer({ noServer: true }); (_server_httpServer = server.httpServer) === null || _server_httpServer === void 0 ? void 0 : _server_httpServer.on("upgrade", function(req, socket, head) { if (req.url !== "/__one/cursor") return; wss.handleUpgrade(req, socket, head, function(ws) { vscodeClients.add(ws); ws.on("message", function(data) { try { var message = JSON.parse(data.toString()); if (message.type === "cursor-position") { server.hot.send("one:cursor-highlight", { file: message.file, line: message.line, column: message.column }); } else if (message.type === "cursor-clear") { server.hot.send("one:cursor-highlight", { clear: true }); } } catch (unused) {} }); ws.on("close", function() { vscodeClients.delete(ws); server.hot.send("one:cursor-highlight", { clear: true }); }); }); }); }); server.middlewares.use(async function(req, res, next) { var _req_url; if (!((_req_url = req.url) === null || _req_url === void 0 ? void 0 : _req_url.startsWith("/__one/open-source"))) { return next(); } try { var url = new URL(req.url, "http://localhost"); var source = url.searchParams.get("source"); if (!source) { res.statusCode = 400; res.end("Missing source parameter"); return; } var parts = source.split(":"); var column = parts.pop(); var line = parts.pop(); var filePath = parts.join(":"); openInEditor(opts === null || opts === void 0 ? void 0 : opts.editor, filePath, line, column); res.statusCode = 200; res.end("OK"); } catch (err) { console.error("[one:source-inspector] Error:", err); res.statusCode = 500; res.end("Internal server error"); } }); } }]; }