#!/usr/bin/env node import { execFileSync } from 'node:child_process'; import { existsSync, readFileSync, writeFileSync } from 'node:fs'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import ts from 'typescript'; import { parse as parseVueSfc } from 'vue/compiler-sfc'; const CODE_FILE_PATTERN = /\.(?:cjs|js|mjs|ts|tsx|vue)$/u; const HAN_CHARACTER_PATTERN = /\p{Script=Han}/u; const JSDOC_PREFIX = '/**'; const LIFECYCLE_METHOD_NAMES = new Set([ 'activated', 'beforeCreate', 'beforeDestroy', 'beforeMount', 'beforeUnmount', 'beforeUpdate', 'componentDidCatch', 'componentDidMount', 'componentDidUpdate', 'componentWillMount', 'componentWillReceiveProps', 'componentWillUnmount', 'componentWillUpdate', 'created', 'deactivated', 'destroyed', 'errorCaptured', 'getSnapshotBeforeUpdate', 'mounted', 'renderTracked', 'renderTriggered', 'serverPrefetch', 'shouldComponentUpdate', 'unmounted', 'updated', ]); function getIsolatedGitEnvironment() { return Object.fromEntries( Object.entries(process.env).filter(([name]) => !name.startsWith('GIT_')), ); } function getLineStarts(source) { const starts = [0]; for (let index = 0; index < source.length; index += 1) { const character = source.codePointAt(index); if (character === 13) { if (source.codePointAt(index + 1) === 10) { index += 1; } starts.push(index + 1); } else if (character === 10) { starts.push(index + 1); } } return starts; } function getLineAndColumn(lineStarts, position) { let low = 0; let high = lineStarts.length - 1; while (low <= high) { const middle = Math.floor((low + high) / 2); if (lineStarts[middle] <= position) { low = middle + 1; } else { high = middle - 1; } } const lineIndex = Math.max(0, high); return { column: position - lineStarts[lineIndex] + 1, line: lineIndex + 1, }; } function getScriptKind(filePath, language) { const normalizedLanguage = language?.toLowerCase(); if (normalizedLanguage === 'tsx' || filePath.endsWith('.tsx')) { return ts.ScriptKind.TSX; } if (normalizedLanguage === 'jsx') { return ts.ScriptKind.JSX; } if ( normalizedLanguage === 'ts' || filePath.endsWith('.ts') || filePath.endsWith('.mts') || filePath.endsWith('.cts') ) { return ts.ScriptKind.TS; } return ts.ScriptKind.JS; } function getVueScriptBlocks(filePath, source) { const { descriptor, errors } = parseVueSfc(source, { filename: filePath, sourceMap: false, }); if (errors.length > 0) { const message = errors .map((error) => (error instanceof Error ? error.message : String(error))) .join('; '); throw new Error(`Vue SFC 解析失败:${message}`); } return [ descriptor.script ? { content: descriptor.script.content, label: '