🚧 Modify toml,powershell prettier plugin(beta)

This commit is contained in:
2025-09-17 00:12:39 +08:00
parent a83c7139c9
commit 338ac358db
20 changed files with 4635 additions and 912 deletions

View File

@@ -43,7 +43,7 @@ import javaPrettierPlugin from "@/common/prettier/plugins/java"
import xmlPrettierPlugin from "@prettier/plugin-xml"
import * as rustPrettierPlugin from "@/common/prettier/plugins/rust";
import * as shellPrettierPlugin from "@/common/prettier/plugins/shell";
import tomlPrettierPlugin from "prettier-plugin-toml";
import tomlPrettierPlugin from "@/common/prettier/plugins/toml";
import clojurePrettierPlugin from "@cospaia/prettier-plugin-clojure";
import groovyPrettierPlugin from "@/common/prettier/plugins/groovy";
import powershellPrettierPlugin from "@/common/prettier/plugins/powershell";

View File

@@ -72,6 +72,66 @@
</div>
</SettingSection>
<!-- Go代码格式化测试区域 -->
<SettingSection title="Go Code Formatter Test">
<SettingItem title="Go Code Input">
<textarea
v-model="goCode"
placeholder="Enter Go code to format..."
class="select-input code-textarea"
rows="8"
></textarea>
</SettingItem>
<SettingItem title="Actions">
<div class="button-group">
<button @click="testGoFormatter" class="test-button primary" :disabled="isFormatting">
{{ isFormatting ? 'Formatting...' : 'Format Go Code' }}
</button>
<button @click="resetGoCode" class="test-button">
Reset to Sample
</button>
<button @click="loadComplexSample" class="test-button">
Load Complex Sample
</button>
<button @click="loadBrokenSample" class="test-button">
Load Broken Sample
</button>
<button @click="checkWasmStatus" class="test-button">
Check WASM Status
</button>
<button @click="initializeGoWasm" class="test-button" :disabled="isInitializing">
{{ isInitializing ? 'Initializing...' : 'Initialize Go WASM' }}
</button>
</div>
</SettingItem>
<!-- 加载状态和进度 -->
<div v-if="formatStatus" class="test-status detailed-status">
<div class="status-header" :class="formatStatus.type">
<strong>{{ formatStatus.type.toUpperCase() }}:</strong> {{ formatStatus.message }}
</div>
<div v-if="formatStatus.details" class="status-details">
<div v-for="(detail, index) in formatStatus.details" :key="index" class="status-detail">
<span class="detail-time">[{{ detail.time }}]</span>
<span class="detail-message">{{ detail.message }}</span>
</div>
</div>
<div v-if="formatStatus.duration" class="status-duration">
执行时间: {{ formatStatus.duration }}ms
</div>
</div>
<!-- 格式化结果 -->
<SettingItem v-if="formattedCode" title="Formatted Result">
<textarea
v-model="formattedCode"
readonly
class="select-input code-textarea result-textarea"
rows="8"
></textarea>
</SettingItem>
</SettingSection>
<!-- 清除所有测试状态 -->
<SettingSection title="Cleanup">
<SettingItem title="Clear All">
@@ -91,6 +151,8 @@ import { ref } from 'vue'
import * as TestService from '@/../bindings/voidraft/internal/services/testservice'
import SettingSection from '../components/SettingSection.vue'
import SettingItem from '../components/SettingItem.vue'
import { format } from 'prettier'
import goPrettierPlugin from '@/common/prettier/plugins/go/go.mjs'
// Badge测试状态
const badgeText = ref('')
@@ -105,6 +167,33 @@ const notificationStatus = ref<{ type: string; message: string } | null>(null)
// 清除状态
const clearStatus = ref<{ type: string; message: string } | null>(null)
// Go代码格式化测试状态
const goCode = ref(`package main
import(
"fmt"
"os"
)
func main(){
if len(os.Args)<2{
fmt.Println("Usage: program <name>")
return
}
name:=os.Args[1]
fmt.Printf("Hello, %s!\\n",name)
}`)
const formattedCode = ref('')
const isFormatting = ref(false)
const isInitializing = ref(false)
const formatStatus = ref<{
type: 'success' | 'error' | 'info' | 'warning';
message: string;
details?: Array<{ time: string; message: string }>;
duration?: number;
} | null>(null)
// 显示状态消息的辅助函数
const showStatus = (statusRef: any, type: 'success' | 'error', message: string) => {
statusRef.value = { type, message }
@@ -158,6 +247,382 @@ const testUpdateNotification = async () => {
}
}
// Go代码格式化相关函数
const addFormatDetail = (message: string) => {
const time = new Date().toLocaleTimeString()
if (!formatStatus.value) {
formatStatus.value = {
type: 'info',
message: '正在执行...',
details: []
}
}
if (!formatStatus.value.details) {
formatStatus.value.details = []
}
formatStatus.value.details.push({ time, message })
}
// 检查WASM状态
const checkWasmStatus = async () => {
formatStatus.value = {
type: 'info',
message: '检查WASM状态...',
details: []
}
addFormatDetail('开始检查环境...')
try {
// 检查浏览器环境
addFormatDetail('检查浏览器环境支持')
if (typeof WebAssembly === 'undefined') {
throw new Error('WebAssembly not supported in this browser')
}
addFormatDetail('✅ WebAssembly 支持正常')
// 检查Go运行时
addFormatDetail('检查Go运行时状态')
if (typeof globalThis.Go !== 'undefined') {
addFormatDetail('✅ Go运行时已加载')
} else {
addFormatDetail('❌ Go运行时未加载')
}
// 检查formatGo函数
addFormatDetail('检查formatGo函数')
if (typeof globalThis.formatGo === 'function') {
addFormatDetail('✅ formatGo函数可用')
} else {
addFormatDetail('❌ formatGo函数不可用')
}
// 检查WASM文件可访问性
addFormatDetail('检查WASM文件可访问性')
try {
const response = await fetch('/go.wasm', { method: 'HEAD' })
if (response.ok) {
addFormatDetail('✅ go.wasm文件可访问')
} else {
addFormatDetail(`❌ go.wasm文件不可访问: ${response.status}`)
}
} catch (error) {
addFormatDetail(`❌ go.wasm文件访问失败: ${error}`)
}
// 检查wasm_exec.js
addFormatDetail('检查wasm_exec.js文件')
try {
const response = await fetch('/wasm_exec.js', { method: 'HEAD' })
if (response.ok) {
addFormatDetail('✅ wasm_exec.js文件可访问')
} else {
addFormatDetail(`❌ wasm_exec.js文件不可访问: ${response.status}`)
}
} catch (error) {
addFormatDetail(`❌ wasm_exec.js文件访问失败: ${error}`)
}
formatStatus.value.type = 'success'
formatStatus.value.message = 'WASM状态检查完成'
} catch (error: any) {
addFormatDetail(`❌ 检查失败: ${error.message}`)
formatStatus.value.type = 'error'
formatStatus.value.message = `WASM状态检查失败: ${error.message}`
}
}
// 手动初始化 Go WASM
const initializeGoWasm = async () => {
if (isInitializing.value) return
isInitializing.value = true
formatStatus.value = {
type: 'info',
message: '正在初始化 Go WASM...',
details: []
}
try {
addFormatDetail('开始手动初始化 Go WASM')
// 直接调用插件的初始化函数
const { initialize } = await import('@/common/prettier/plugins/go/go.mjs')
addFormatDetail('调用插件初始化函数...')
await initialize()
addFormatDetail('检查 formatGo 函数是否可用...')
if (typeof globalThis.formatGo === 'function') {
addFormatDetail('✅ formatGo 函数初始化成功')
// 测试函数
addFormatDetail('测试 formatGo 函数...')
const testCode = 'package main\nfunc main(){}'
const result = globalThis.formatGo(testCode)
addFormatDetail(`✅ 测试成功,格式化后长度: ${result.length}`)
formatStatus.value = {
type: 'success',
message: 'Go WASM 初始化成功!',
details: formatStatus.value.details
}
} else {
throw new Error('formatGo 函数仍然不可用')
}
} catch (error: any) {
addFormatDetail(`❌ 初始化失败: ${error.message}`)
formatStatus.value = {
type: 'error',
message: `Go WASM 初始化失败: ${error.message}`,
details: formatStatus.value.details
}
} finally {
isInitializing.value = false
}
}
// 测试Go代码格式化
const testGoFormatter = async () => {
if (isFormatting.value) return
isFormatting.value = true
formattedCode.value = ''
const startTime = Date.now()
formatStatus.value = {
type: 'info',
message: '正在格式化Go代码...',
details: []
}
try {
addFormatDetail('开始格式化流程')
addFormatDetail(`输入代码长度: ${goCode.value.length} 字符`)
// 设置超时检测
const timeoutId = setTimeout(() => {
addFormatDetail('⚠️ 格式化超时 (10秒),可能存在阻塞')
}, 10000)
addFormatDetail('调用prettier格式化...')
const result = await format(goCode.value, {
parser: 'go-format',
plugins: [goPrettierPlugin]
})
clearTimeout(timeoutId)
const duration = Date.now() - startTime
addFormatDetail('✅ 格式化完成')
addFormatDetail(`输出代码长度: ${result.length} 字符`)
formattedCode.value = result
formatStatus.value = {
type: 'success',
message: '代码格式化成功!',
details: formatStatus.value.details,
duration
}
} catch (error: any) {
const duration = Date.now() - startTime
addFormatDetail(`❌ 格式化失败: ${error.message}`)
// 详细错误分析
if (error.message.includes('WASM')) {
addFormatDetail('可能原因: WASM模块加载或初始化问题')
} else if (error.message.includes('formatGo')) {
addFormatDetail('可能原因: Go函数未正确暴露到全局作用域')
} else if (error.message.includes('timeout')) {
addFormatDetail('可能原因: 代码执行超时或阻塞')
}
formatStatus.value = {
type: 'error',
message: `格式化失败: ${error.message}`,
details: formatStatus.value.details,
duration
}
} finally {
isFormatting.value = false
}
}
// 重置Go代码为示例
const resetGoCode = () => {
goCode.value = `package main
import(
"fmt"
"os"
)
func main(){
if len(os.Args)<2{
fmt.Println("Usage: program <name>")
return
}
name:=os.Args[1]
fmt.Printf("Hello, %s!\\n",name)
}`
formattedCode.value = ''
formatStatus.value = null
}
// 加载复杂示例
const loadComplexSample = () => {
goCode.value = `package main
import(
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strconv"
"strings"
"time"
)
type User struct{
ID int \`json:"id"\`
Name string \`json:"name"\`
Email string \`json:"email"\`
CreatedAt time.Time \`json:"created_at"\`
}
type UserService struct{
users []User
nextID int
}
func NewUserService()*UserService{
return &UserService{
users:make([]User,0),
nextID:1,
}
}
func(s *UserService)CreateUser(name,email string)*User{
user:=User{
ID:s.nextID,
Name:name,
Email:email,
CreatedAt:time.Now(),
}
s.users=append(s.users,user)
s.nextID++
return &user
}
func(s *UserService)GetUser(id int)*User{
for i:=range s.users{
if s.users[i].ID==id{
return &s.users[i]
}
}
return nil
}
func(s *UserService)ListUsers()[]User{
return s.users
}
func main(){
service:=NewUserService()
http.HandleFunc("/users",func(w http.ResponseWriter,r *http.Request){
switch r.Method{
case http.MethodGet:
users:=service.ListUsers()
w.Header().Set("Content-Type","application/json")
json.NewEncoder(w).Encode(users)
case http.MethodPost:
body,err:=ioutil.ReadAll(r.Body)
if err!=nil{
http.Error(w,"Bad request",http.StatusBadRequest)
return
}
var req struct{
Name string \`json:"name"\`
Email string \`json:"email"\`
}
if err:=json.Unmarshal(body,&req);err!=nil{
http.Error(w,"Invalid JSON",http.StatusBadRequest)
return
}
user:=service.CreateUser(req.Name,req.Email)
w.Header().Set("Content-Type","application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
default:
http.Error(w,"Method not allowed",http.StatusMethodNotAllowed)
}
})
http.HandleFunc("/users/",func(w http.ResponseWriter,r *http.Request){
if r.Method!=http.MethodGet{
http.Error(w,"Method not allowed",http.StatusMethodNotAllowed)
return
}
idStr:=strings.TrimPrefix(r.URL.Path,"/users/")
id,err:=strconv.Atoi(idStr)
if err!=nil{
http.Error(w,"Invalid user ID",http.StatusBadRequest)
return
}
user:=service.GetUser(id)
if user==nil{
http.Error(w,"User not found",http.StatusNotFound)
return
}
w.Header().Set("Content-Type","application/json")
json.NewEncoder(w).Encode(user)
})
port:=os.Getenv("PORT")
if port==""{
port="8080"
}
fmt.Printf("Server starting on port %s\\n",port)
log.Fatal(http.ListenAndServe(":"+port,nil))
}`
formattedCode.value = ''
formatStatus.value = null
}
// 加载有语法错误的示例
const loadBrokenSample = () => {
goCode.value = `package main
import(
"fmt"
"os
)
func main({
if len(os.Args<2{
fmt.Println("Usage: program <name>")
return
}
name:=os.Args[1
fmt.Printf("Hello, %s!\\n",name)
`
formattedCode.value = ''
formatStatus.value = null
}
// 清除所有测试状态
const clearAll = async () => {
try {
@@ -167,6 +632,10 @@ const clearAll = async () => {
notificationTitle.value = ''
notificationSubtitle.value = ''
notificationBody.value = ''
// 清空Go测试状态
formattedCode.value = ''
formatStatus.value = null
resetGoCode()
showStatus(clearStatus, 'success', 'All test states cleared successfully')
} catch (error: any) {
showStatus(clearStatus, 'error', `Failed to clear test states: ${error.message || error}`)
@@ -207,6 +676,25 @@ const clearAll = async () => {
font-family: inherit;
line-height: 1.4;
}
&.code-textarea {
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 11px;
line-height: 1.5;
width: 100%;
max-width: 600px;
min-height: 120px;
white-space: pre;
overflow-wrap: normal;
word-break: normal;
tab-size: 2;
&.result-textarea {
background-color: var(--settings-card-bg);
border-color: #22c55e;
color: var(--settings-text);
}
}
}
.button-group {
@@ -271,4 +759,47 @@ const clearAll = async () => {
border-color: rgba(239, 68, 68, 0.2);
}
}
.detailed-status {
.status-header {
margin-bottom: 8px;
font-weight: 600;
}
.status-details {
background-color: rgba(0, 0, 0, 0.05);
border-radius: 4px;
padding: 8px;
margin: 8px 0;
max-height: 200px;
overflow-y: auto;
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace;
font-size: 10px;
line-height: 1.4;
.status-detail {
margin-bottom: 2px;
display: flex;
gap: 8px;
.detail-time {
color: var(--settings-text-secondary);
flex-shrink: 0;
font-weight: 500;
}
.detail-message {
color: var(--settings-text);
word-break: break-word;
}
}
}
.status-duration {
margin-top: 8px;
font-size: 10px;
color: var(--settings-text-secondary);
font-weight: 500;
}
}
</style>