UNPKG

@antv/dumi-theme-antv

Version:
230 lines (215 loc) 12.2 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } /** * 从代码字符串中提取依赖,并生成 package.json 的 dependencies 对象。 * * @param {string} codeString 包含代码的字符串。 * @returns {object} 一个符合 package.json dependencies 格式的对象。 */ export function generateDependencies() { var codeString = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var ext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'js'; // 1. 初始化固定的依赖 var dependencies = {}; // 2. 定义正则表达式来匹配 import 语句的来源 // 这个正则表达式可以处理以下情况: // - import defaultExport from 'package-name'; // - import { namedExport } from 'package-name'; // - import * as name from 'package-name'; // - import 'package-name'; (用于副作用) // - import defaultExport from '@scoped/package-name/sub-path'; // // 解析: // - `import(?:.*from)?` : 匹配 "import" 关键字,以及可选的 "... from" 部分。 // - `\s+` : 匹配一个或多个空格。 // - `['"]` : 匹配单引号或双引号。 // - `([^'"]+)` : 核心捕获组。匹配引号内的所有字符,这就是我们需要的包路径。 // - `['"]` : 匹配结束的引号。 // - `/g` : 全局匹配,查找所有符合条件的导入。 var importRegex = /import(?:.*from)?\s+['"]([^'"]+)['"]/g; // 使用 Set 来存储找到的包,可以自动去重 var foundPackages = new Set(); // 3. 遍历所有匹配项 var match; while ((match = importRegex.exec(codeString)) !== null) { // 捕获组 match[1] 包含了完整的导入路径,例如 '@antv/g2' 或 'react-dom/client' var importPath = match[1]; // 4. 过滤掉相对路径和绝对路径 if (importPath.startsWith('.') || importPath.startsWith('/')) { continue; } // 5. 提取根包名 // 这可以处理像 'react-dom/client' 这样的深层导入,我们只需要 'react-dom' // 或者像 '@antv/g2/es/chart',我们只需要 '@antv/g2' var rootPackage = void 0; var pathParts = importPath.split('/'); if (importPath.startsWith('@')) { // 对于作用域包 (scoped package),例如 @antv/g2,根包名是前两部分 rootPackage = "".concat(pathParts[0], "/").concat(pathParts[1]); } else { // 对于普通包,根包名是第一部分 rootPackage = pathParts[0]; } foundPackages.add(rootPackage); } // 6. 将找到的包添加到最终的依赖对象中 var _iterator = _createForOfIteratorHelper(foundPackages), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var pkg = _step.value; // 如果不是固定的依赖,就添加并设置为 'latest' if (!Object.prototype.hasOwnProperty.call(dependencies, pkg)) { dependencies[pkg] = "latest"; } } // VisionSnap限制只要是jsx就必须装React。 } catch (err) { _iterator.e(err); } finally { _iterator.f(); } if (ext === 'jsx' || ext === 'tsx') { dependencies["react"] = "^18"; dependencies["react-dom"] = "^18"; } if (ext === 'vue') { dependencies["vue"] = "^3"; } if (dependencies['@antv/s2'] || dependencies['@antv/s2-react'] || dependencies['@antv/s2-react-components']) { dependencies = _objectSpread(_objectSpread({}, dependencies), {}, { "@ant-design/icons": "^6.1.0", "@antv/s2": "^2.4.9", "@antv/s2-react": "^2.2.3", "@antv/s2-react-components": "^2.1.2", "antd": "^5.27.6", "insert-css": "^2.0.0", "react": "^18.3.1", "react-color": "^2.19.3", "react-dom": "^18.3.1", "@antv/g2": "^5.4.2" }); } return dependencies; } /** * 基于代码内容,启发式地判断其最合适的文件扩展名。 * @param {string} code - 要分析的前端代码字符串。 * @returns {'vue' | 'tsx' | 'jsx' | 'ts' | 'js'} - 推断出的文件扩展名(不含点)。 */ export function getLanguageExtension(code) { // --- 特征检测函数 --- /** * 检查代码是否包含 Vue 单文件组件 (SFC) 的特征。 * 这是最优先的检查,因为Vue的SFC结构非常独特。 */ var containsVue = function containsVue(text) { // 检查点 1: Vue 3 <script setup> 语法(最强信号) // 匹配 <script setup> 或 <script lang="ts" setup> var scriptSetupRegex = /<script\s+(?:lang="ts"\s+)?setup>/; if (scriptSetupRegex.test(text)) { return true; } // 检查点 2: 顶层 <template> 块(非常强的信号) // 使用 'm' (multiline) 标志,'^' 匹配每行的开头。 var templateRegex = /^\s*<template.*>/m; if (templateRegex.test(text)) { return true; } // 检查点 3: 导入 Vue 核心库(通用信号) // 匹配 import ... from 'vue' var vueImportRegex = /import\s+.*?\s+from\s*['"]vue['"]/; if (vueImportRegex.test(text)) { return true; } // 检查点 4: Vue 2 Options API 特征(辅助信号) // 匹配 export default { ... data|methods|computed ... } 结构 var optionsApiRegex = /\bexport\s+default\s*{[\s\S]*?\b(data|methods|computed|watch)\b/; if (optionsApiRegex.test(text)) { return true; } return false; }; var containsJsx = function containsJsx(text) { var jsxRegex = /<(?![\s!=])([a-zA-Z][a-zA-Z0-9-]*|\/|)/; return jsxRegex.test(text); }; var containsTypeScript = function containsTypeScript(text) { var typeDefinitionRegex = /\b(interface|type)\s+[A-Z][a-zA-Z0-9]*\b/; if (typeDefinitionRegex.test(text)) return true; var typeAnnotationRegex = /:\s*([A-Z][a-zA-Z0-9<>.]*|string|number|boolean|any\[?\]?)/; if (typeAnnotationRegex.test(text)) return true; var tsKeywordsRegex = /\b(as|implements|private|public|protected|readonly)\s+[a-zA-Z]/; if (tsKeywordsRegex.test(text)) return true; return false; }; // --- 决策逻辑(Vue优先) --- if (containsVue(code)) { return 'vue'; } // 如果不是Vue,则回退到原有的React/JS逻辑 if (containsJsx(code)) { if (containsTypeScript(code)) { return 'tsx'; } return 'jsx'; } else { if (containsTypeScript(code)) { return 'ts'; } return 'js'; } } export function wrap2VisionSnap() { var codeBlock = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var ext = getLanguageExtension(codeBlock); var mainFile = ext === 'vue' ? "/src/index.js" : "/src/index.".concat(ext); var appFile = "/src/App.".concat(ext); var dependencies = generateDependencies(codeBlock, ext); var rootElementType = dependencies['@antv/f2'] ? 'canvas' : 'div'; var dependenciesJSON = { "name": "AntV-adapted-project", "version": "1.0.0", "main": mainFile, "dependencies": dependencies }; var mainFileCode = ext === 'vue' ? "import { createApp } from 'vue';\nimport App from './App.vue';\n\nconst app = createApp(App);\napp.mount('#app');\n" : "\n// --- Adapter Script ---\n\n// 1. \u627E\u5230\u7F16\u8F91\u5668\u73AF\u5883\u63D0\u4F9B\u7684\u6839\u8282\u70B9 #root\nconst rootElement = document.getElementById('root');\n\nif (rootElement) {\n // 2. \u5728 #root \u5185\u90E8\u521B\u5EFA\u4E00\u4E2A ".concat(rootElementType, "\n const containerElement = document.createElement('").concat(rootElementType, "');\n\n // 3. \u5C06\u8FD9\u4E2A div \u7684 id \u8BBE\u7F6E\u4E3A 'container'\uFF0C\u4EE5\u6EE1\u8DB3\u7528\u6237\u4EE3\u7801\u7684\u9700\u6C42\n containerElement.id = 'container';\n\n // 4. \u5C06\u5B83\u6DFB\u52A0\u5230 #root \u4E2D\n rootElement.appendChild(containerElement);\n\n // 5. \u73B0\u5728 DOM \u4E2D\u5DF2\u7ECF\u5B58\u5728 #container\uFF0C\u5B89\u5168\u5730\u5BFC\u5165\u5E76\u6267\u884C\u7528\u6237\u7684\u4EE3\u7801\n import('./App.").concat(ext, "');\n\n}\n "); return { modules: _defineProperty(_defineProperty({ '/package.json': { fpath: '/package.json', code: JSON.stringify(dependenciesJSON, null, 2) } }, mainFile, { fpath: mainFile, code: mainFileCode }), appFile, { fpath: appFile, code: codeBlock }) }; } export function wrap2Sandpack() { var codeBlock = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; // const regex = /^```[\w-]*\n([\s\S]*?)\n?```$/m; // const match = codeBlock.match(regex); // if (match) { return { "/package.json": { code: "{\n \"name\": \"AntV-AI-Code\",\n \"version\": \"1.0.0\",\n \"main\": \"/index.tsx\",\n \"dependencies\": ".concat(JSON.stringify(generateDependencies(codeBlock), null, 2), "\n }") }, "/index.tsx": { code: codeBlock }, "/index.html": { code: "<!DOCTYPE html>\n<html>\n<head>\n <title>Vanilla JS Example</title>\n</head>\n<body>\n <div id=\"root\"></div>\n <div id=\"container\"></div>\n <script src=\"index.tsx\"></script>\n</body>\n</html>" } }; }