UNPKG

bufan-hardhat-strip-comments

Version:

Hardhat plugin to strip comments from contracts during verification with custom Dubai ASCII art headers

246 lines (244 loc) 10.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const config_1 = require("hardhat/config"); const strip_comments_1 = __importDefault(require("strip-comments")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); // 默认作者信息 const DEFAULT_AUTHOR_INFO = { author: "VeloraChain", createdDate: "2025-05-11", purpose: "VeloraChain Blockchain Technology Token", description: "This is no ordinary code — it carries ambition, and marks a legend on-chain." }; // 设置默认配置 (0, config_1.extendConfig)((config, userConfig) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; // 处理 authorInfo const authorInfo = ((_a = userConfig.stripComments) === null || _a === void 0 ? void 0 : _a.authorInfo) || {}; config.stripComments = { enabled: (_c = (_b = userConfig.stripComments) === null || _b === void 0 ? void 0 : _b.enabled) !== null && _c !== void 0 ? _c : true, customHeader: (_e = (_d = userConfig.stripComments) === null || _d === void 0 ? void 0 : _d.customHeader) !== null && _e !== void 0 ? _e : "// SPDX-License-Identifier: MIT", excludedFiles: (_g = (_f = userConfig.stripComments) === null || _f === void 0 ? void 0 : _f.excludedFiles) !== null && _g !== void 0 ? _g : [], preserveLicense: (_j = (_h = userConfig.stripComments) === null || _h === void 0 ? void 0 : _h.preserveLicense) !== null && _j !== void 0 ? _j : true, authorInfo: { author: (_k = authorInfo.author) !== null && _k !== void 0 ? _k : DEFAULT_AUTHOR_INFO.author, createdDate: (_l = authorInfo.createdDate) !== null && _l !== void 0 ? _l : DEFAULT_AUTHOR_INFO.createdDate, purpose: (_m = authorInfo.purpose) !== null && _m !== void 0 ? _m : DEFAULT_AUTHOR_INFO.purpose, description: (_o = authorInfo.description) !== null && _o !== void 0 ? _o : DEFAULT_AUTHOR_INFO.description, }, headerStyle: (_q = (_p = userConfig.stripComments) === null || _p === void 0 ? void 0 : _p.headerStyle) !== null && _q !== void 0 ? _q : "dubai" }; }); // 创建一个新任务,用于处理合约文件并去除注释 (0, config_1.task)("strip-comments", "Strips comments from contract files") .addOptionalParam("input", "Input directory or file path", "contracts") .addOptionalParam("output", "Output directory", "stripped-contracts") .setAction(async (taskArgs, { config }) => { const { input, output } = taskArgs; const stripCommentsConfig = config.stripComments; if (!stripCommentsConfig.enabled) { console.log("Strip comments plugin is disabled. Skipping..."); return; } // 确保输出目录存在 const outputDir = path.resolve(process.cwd(), output); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const inputPath = path.resolve(process.cwd(), input); const stats = fs.statSync(inputPath); if (stats.isFile()) { // 处理单个文件 processFile(inputPath, outputDir, stripCommentsConfig); } else if (stats.isDirectory()) { // 处理目录 processDirectory(inputPath, outputDir, stripCommentsConfig); } else { console.error(`Invalid input path: ${inputPath}`); } console.log(`Processed files saved to ${outputDir}`); }); // 重写verify任务,使其在验证前去除注释 (0, config_1.task)("verify", "Verifies contract on the block explorer") .setAction(async (taskArgs, hre, runSuper) => { const config = hre.config.stripComments; if (config.enabled) { console.log("Stripping comments before verification..."); // 检查要验证的合约文件 let contractFile = ""; if (taskArgs.contract) { const parts = taskArgs.contract.split(":"); if (parts.length > 1) { contractFile = parts[1]; } } // 如果找到合约文件,处理它 if (contractFile) { const contractsDir = path.resolve(process.cwd(), "contracts"); const outputDir = path.resolve(process.cwd(), "stripped-contracts"); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const filePath = path.resolve(contractsDir, contractFile); if (fs.existsSync(filePath)) { const newFilePath = processFile(filePath, outputDir, config); // 修改任务参数以使用处理后的文件 if (newFilePath) { const relativePath = path.relative(process.cwd(), newFilePath); taskArgs.contract = taskArgs.contract.replace(contractFile, relativePath); } } } } // 继续执行原始的verify任务 return runSuper(taskArgs); }); // 提取合约名称 function extractContractName(source) { const contractMatch = source.match(/contract\s+([a-zA-Z0-9_]+)/); if (contractMatch && contractMatch[1]) { return contractMatch[1]; } return "Contract"; } // 生成迪拜风格的头部 function generateDubaiHeader(contractName, config) { return `// SPDX-License-Identifier: MIT /* 🌴🏜️ 𓆃 DUBAI SMART CONTRACT 𓆃 🏜️🌴 ──────────────────────────────── "Built beneath the sun, coded for fortune, destined for legend." Contract Name : ${contractName} Author : ${config.authorInfo.author} Created Date : ${config.authorInfo.createdDate} Purpose : ${config.authorInfo.purpose} Description : ${config.authorInfo.description} */`; } // 生成标准风格的头部 function generateStandardHeader(contractName, config) { return `// SPDX-License-Identifier: MIT /* ___ _ _ _ | _ \\__ _ _| |_ (_)_ _ __ _ ___ __| |___ | _/ _\` | | ' \\| | ' \\/ _\` / -_)/ _\` (_-< |_| \\__,_|_|_||_|_|_||_\\__, \\___|\\_\\_,/__/ |___/ Contract Name : ${contractName} Author : ${config.authorInfo.author} Created Date : ${config.authorInfo.createdDate} Purpose : ${config.authorInfo.purpose} Description : ${config.authorInfo.description} */`; } // 处理单个文件 function processFile(filePath, outputDir, config) { const filename = path.basename(filePath); // 检查是否在排除列表中 if (config.excludedFiles.includes(filename)) { console.log(`Skipping excluded file: ${filename}`); return null; } try { let content = fs.readFileSync(filePath, "utf8"); // 保存许可证注释 let licenseComment = ""; if (config.preserveLicense) { const licenseMatch = content.match(/\/\/\s*SPDX-License-Identifier:.*?\n/); if (licenseMatch) { licenseComment = licenseMatch[0]; } } // 提取合约名称 const contractName = extractContractName(content); // 去除所有注释 content = (0, strip_comments_1.default)(content); // 添加自定义头部 let result = ""; if (config.headerStyle === "dubai") { result = generateDubaiHeader(contractName, config) + "\n\n" + content; } else if (config.headerStyle === "standard") { result = generateStandardHeader(contractName, config) + "\n\n" + content; } else if (config.customHeader) { result = config.customHeader + "\n" + content; } else if (config.preserveLicense && licenseComment) { result = licenseComment + content; } else { result = content; } // 写入输出文件 const outputPath = path.join(outputDir, filename); fs.writeFileSync(outputPath, result); console.log(`Processed: ${filename}`); return outputPath; } catch (error) { console.error(`Error processing file ${filename}:`, error); return null; } } // 递归处理目录 function processDirectory(dirPath, outputDir, config) { const items = fs.readdirSync(dirPath); for (const item of items) { const itemPath = path.join(dirPath, item); const stats = fs.statSync(itemPath); if (stats.isFile() && item.endsWith(".sol")) { // 为输出目录创建相对路径结构 const relativePath = path.relative(process.cwd(), dirPath); const targetDir = path.join(outputDir, relativePath); if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } processFile(itemPath, targetDir, config); } else if (stats.isDirectory()) { processDirectory(itemPath, outputDir, config); } } } //# sourceMappingURL=index.js.map