Initial commit
This commit is contained in:
79
hooks/check-figma-api-key.sh
Executable file
79
hooks/check-figma-api-key.sh
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 获取插件根目录
|
||||
if [ -n "$CLAUDE_PLUGIN_ROOT" ]; then
|
||||
PLUGIN_ROOT="$CLAUDE_PLUGIN_ROOT"
|
||||
else
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PLUGIN_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
||||
fi
|
||||
|
||||
MCP_JSON="$PLUGIN_ROOT/.mcp.json"
|
||||
MCP_JSON_TEMPLATE="$PLUGIN_ROOT/.mcp.json.template"
|
||||
|
||||
# 检查 .mcp.json 是否存在,如果不存在则从模板复制
|
||||
if [ ! -f "$MCP_JSON" ]; then
|
||||
if [ -f "$MCP_JSON_TEMPLATE" ]; then
|
||||
echo "📝 首次运行,正在从模板创建 .mcp.json 文件..."
|
||||
cp "$MCP_JSON_TEMPLATE" "$MCP_JSON"
|
||||
else
|
||||
echo "❌ 错误:找不到 .mcp.json 和 .mcp.json.template 文件"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查 .mcp.json 中是否还包含未替换的 ${FIGMA_API_KEY} 占位符
|
||||
if grep -q '\${FIGMA_API_KEY}' "$MCP_JSON"; then
|
||||
# 包含占位符,说明还没配置
|
||||
echo ""
|
||||
echo "╔════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 🎨 切图仔 (Qietuzai) Plugin - 配置向导 ║"
|
||||
echo "╚════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "⚠️ 检测到您还未配置 Figma API Key"
|
||||
echo ""
|
||||
echo "🌐 正在启动图形化配置界面..."
|
||||
echo ""
|
||||
|
||||
# 获取脚本所在目录(使用 CLAUDE_PLUGIN_ROOT 如果可用)
|
||||
if [ -n "$CLAUDE_PLUGIN_ROOT" ]; then
|
||||
SCRIPT_DIR="$CLAUDE_PLUGIN_ROOT/hooks"
|
||||
else
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
fi
|
||||
|
||||
# 启动 Python HTTP 服务器(后台运行)
|
||||
python3 "$SCRIPT_DIR/setup-server.py" > /dev/null 2>&1 &
|
||||
SERVER_PID=$!
|
||||
|
||||
# 等待服务器启动
|
||||
sleep 2
|
||||
|
||||
# 打开浏览器到配置页面
|
||||
CONFIG_URL="http://localhost:3456"
|
||||
|
||||
echo "✨ 配置页面已在浏览器中打开: $CONFIG_URL"
|
||||
echo ""
|
||||
echo "📝 请在浏览器中完成以下步骤:"
|
||||
echo " 1. 访问 Figma 设置页面获取 API Key"
|
||||
echo " 2. 在表单中输入您的 API Key"
|
||||
echo " 3. 点击保存"
|
||||
echo " 4. 重启 Claude Code"
|
||||
echo ""
|
||||
echo "💡 如果浏览器没有自动打开,请手动访问: $CONFIG_URL"
|
||||
echo ""
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS
|
||||
open "$CONFIG_URL" 2>/dev/null
|
||||
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
# Linux
|
||||
xdg-open "$CONFIG_URL" 2>/dev/null
|
||||
elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
|
||||
# Windows
|
||||
start "$CONFIG_URL" 2>/dev/null
|
||||
fi
|
||||
else
|
||||
# API Key 已配置,静默通过
|
||||
exit 0
|
||||
fi
|
||||
14
hooks/hooks.json
Normal file
14
hooks/hooks.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/check-figma-api-key.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
597
hooks/setup-server.py
Executable file
597
hooks/setup-server.py
Executable file
@@ -0,0 +1,597 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Qietuzai Plugin Setup Server
|
||||
提供图形化界面配置 Figma API Key
|
||||
"""
|
||||
|
||||
import http.server
|
||||
import socketserver
|
||||
import urllib.parse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PORT = 3456
|
||||
|
||||
# HTML 页面
|
||||
HTML_FORM = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>切图仔 Plugin - 配置向导</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1a202c;
|
||||
font-size: 28px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #718096;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.step {
|
||||
background: #f7fafc;
|
||||
border-left: 4px solid #667eea;
|
||||
padding: 16px;
|
||||
margin-bottom: 24px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
color: #2d3748;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.step-content {
|
||||
color: #4a5568;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.step-content a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.step-content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
color: #2d3748;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
font-family: 'Monaco', 'Menlo', monospace;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: #718096;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
padding: 14px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: #5568d3;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #e2e8f0;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #cbd5e0;
|
||||
}
|
||||
|
||||
.error {
|
||||
background: #fed7d7;
|
||||
border: 1px solid #fc8181;
|
||||
color: #c53030;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: none;
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 3px solid #f3f3f3;
|
||||
border-top: 3px solid #667eea;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="icon">🎨</div>
|
||||
<h1>切图仔 Plugin</h1>
|
||||
<p class="subtitle">配置 Figma API Key</p>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-title">
|
||||
<span>📝</span>
|
||||
<span>第 1 步:获取 Figma API Key</span>
|
||||
</div>
|
||||
<div class="step-content">
|
||||
访问 <a href="https://www.figma.com/settings" target="_blank">Figma 设置页面</a>,
|
||||
在 "Personal access tokens" 部分创建一个新的 token。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-title">
|
||||
<span>🔑</span>
|
||||
<span>第 2 步:输入 API Key</span>
|
||||
</div>
|
||||
<div class="step-content">
|
||||
将刚才复制的 token 粘贴到下方输入框中。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="setupForm">
|
||||
<div class="form-group">
|
||||
<label for="apiKey">Figma API Key *</label>
|
||||
<input
|
||||
type="password"
|
||||
id="apiKey"
|
||||
name="apiKey"
|
||||
placeholder="figd_xxxxxxxxxxxx"
|
||||
required
|
||||
autocomplete="off"
|
||||
>
|
||||
<div class="hint">
|
||||
💡 您的 API Key 将被安全地存储在插件配置文件中
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button type="button" class="btn-secondary" onclick="window.close()">
|
||||
取消
|
||||
</button>
|
||||
<button type="submit" class="btn-primary">
|
||||
保存配置
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="loading">
|
||||
<div class="spinner"></div>
|
||||
<p style="margin-top: 12px; color: #718096;">正在保存配置...</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('setupForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const apiKey = document.getElementById('apiKey').value;
|
||||
const loading = document.getElementById('loading');
|
||||
const submitBtn = e.target.querySelector('button[type="submit"]');
|
||||
|
||||
// 显示加载状态
|
||||
submitBtn.disabled = true;
|
||||
loading.style.display = 'block';
|
||||
|
||||
try {
|
||||
const response = await fetch('/save', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ apiKey })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// 跳转到成功页面
|
||||
window.location.href = '/success?shell=' + encodeURIComponent(result.shell || 'bash');
|
||||
} else {
|
||||
alert('保存失败: ' + result.error);
|
||||
submitBtn.disabled = false;
|
||||
loading.style.display = 'none';
|
||||
}
|
||||
} catch (error) {
|
||||
alert('保存失败: ' + error.message);
|
||||
submitBtn.disabled = false;
|
||||
loading.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
SUCCESS_HTML = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>配置成功</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.success-icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1a202c;
|
||||
font-size: 28px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.message {
|
||||
color: #4a5568;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: #f7fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 24px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.info-box h3 {
|
||||
color: #2d3748;
|
||||
font-size: 14px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.info-box p {
|
||||
color: #718096;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.command {
|
||||
background: #2d3748;
|
||||
color: #48bb78;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
font-family: 'Monaco', 'Menlo', monospace;
|
||||
font-size: 13px;
|
||||
margin: 8px 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
padding: 14px 32px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #5568d3;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="success-icon">✅</div>
|
||||
<h1>配置成功!</h1>
|
||||
<p class="message">
|
||||
您的 Figma API Key 已成功保存到系统环境变量中。
|
||||
</p>
|
||||
|
||||
<div class="info-box">
|
||||
<h3>📋 配置详情</h3>
|
||||
<p>✅ API Key 已保存到插件配置文件 <strong>.mcp.json</strong></p>
|
||||
<p>✅ 备份已添加到: <strong>{shell_config}</strong></p>
|
||||
<div class="command">export FIGMA_API_KEY="****"</div>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<h3>🔄 下一步</h3>
|
||||
<p>请<strong>重启 Claude Code</strong> 使配置生效,然后即可开始使用切图仔 Plugin!</p>
|
||||
<p style="margin-top: 8px; font-size: 12px; color: #e53e3e;">⚠️ 注意:请勿将 <strong>.mcp.json</strong> 提交到 git,以保护您的 API Key 安全</p>
|
||||
</div>
|
||||
|
||||
<button onclick="window.close()">关闭此页面</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 10 秒后自动关闭
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 10000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
class SetupHandler(http.server.SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
if self.path == '/' or self.path == '/index.html':
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'text/html; charset=utf-8')
|
||||
self.end_headers()
|
||||
self.wfile.write(HTML_FORM.encode('utf-8'))
|
||||
elif self.path.startswith('/success'):
|
||||
# 解析查询参数
|
||||
query = urllib.parse.urlparse(self.path).query
|
||||
params = urllib.parse.parse_qs(query)
|
||||
shell = params.get('shell', ['bash'])[0]
|
||||
|
||||
# 确定配置文件路径
|
||||
shell_configs = {
|
||||
'zsh': '~/.zshrc',
|
||||
'bash': '~/.bashrc',
|
||||
'fish': '~/.config/fish/config.fish'
|
||||
}
|
||||
shell_config = shell_configs.get(shell, '~/.bashrc')
|
||||
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'text/html; charset=utf-8')
|
||||
self.end_headers()
|
||||
html = SUCCESS_HTML.replace('{shell_config}', shell_config)
|
||||
self.wfile.write(html.encode('utf-8'))
|
||||
else:
|
||||
self.send_error(404)
|
||||
|
||||
def do_POST(self):
|
||||
if self.path == '/save':
|
||||
content_length = int(self.headers['Content-Length'])
|
||||
post_data = self.rfile.read(content_length)
|
||||
data = json.loads(post_data.decode('utf-8'))
|
||||
|
||||
api_key = data.get('apiKey', '').strip()
|
||||
|
||||
if not api_key:
|
||||
self.send_json_response({'success': False, 'error': 'API Key 不能为空'})
|
||||
return
|
||||
|
||||
# 检测 shell 类型
|
||||
shell = os.environ.get('SHELL', '/bin/bash')
|
||||
if 'zsh' in shell:
|
||||
config_file = Path.home() / '.zshrc'
|
||||
shell_name = 'zsh'
|
||||
elif 'fish' in shell:
|
||||
config_file = Path.home() / '.config' / 'fish' / 'config.fish'
|
||||
shell_name = 'fish'
|
||||
else:
|
||||
config_file = Path.home() / '.bashrc'
|
||||
shell_name = 'bash'
|
||||
|
||||
try:
|
||||
# 1. 更新 .mcp.json 文件(替换占位符)
|
||||
# 获取插件根目录
|
||||
script_dir = Path(__file__).parent
|
||||
plugin_root = script_dir.parent
|
||||
mcp_json_path = plugin_root / '.mcp.json'
|
||||
|
||||
if not mcp_json_path.exists():
|
||||
raise FileNotFoundError(f'.mcp.json 文件不存在: {mcp_json_path}')
|
||||
|
||||
# 读取并替换占位符
|
||||
mcp_content = mcp_json_path.read_text()
|
||||
if '${FIGMA_API_KEY}' in mcp_content:
|
||||
mcp_content = mcp_content.replace('${FIGMA_API_KEY}', api_key)
|
||||
mcp_json_path.write_text(mcp_content)
|
||||
|
||||
# 2. 同时也保存到 shell 配置文件(作为备份)
|
||||
# 读取现有配置
|
||||
if config_file.exists():
|
||||
content = config_file.read_text()
|
||||
else:
|
||||
content = ''
|
||||
|
||||
# 检查是否已经存在 FIGMA_API_KEY
|
||||
if 'FIGMA_API_KEY' in content:
|
||||
# 更新现有的
|
||||
import re
|
||||
pattern = r'export FIGMA_API_KEY=.*'
|
||||
if re.search(pattern, content):
|
||||
content = re.sub(pattern, f'export FIGMA_API_KEY="{api_key}"', content)
|
||||
else:
|
||||
content += f'\nexport FIGMA_API_KEY="{api_key}"\n'
|
||||
else:
|
||||
# 添加新的
|
||||
content += f'\n# Qietuzai Plugin - Figma API Key\nexport FIGMA_API_KEY="{api_key}"\n'
|
||||
|
||||
# 写入配置文件
|
||||
config_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
config_file.write_text(content)
|
||||
|
||||
self.send_json_response({
|
||||
'success': True,
|
||||
'shell': shell_name,
|
||||
'config_file': str(config_file),
|
||||
'mcp_json': str(mcp_json_path)
|
||||
})
|
||||
|
||||
# 配置成功后,延迟关闭服务器
|
||||
import threading
|
||||
def shutdown_server():
|
||||
import time
|
||||
time.sleep(2)
|
||||
print('\n✅ 配置已保存,服务器即将关闭...')
|
||||
os._exit(0)
|
||||
|
||||
threading.Thread(target=shutdown_server, daemon=True).start()
|
||||
|
||||
except Exception as e:
|
||||
self.send_json_response({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
})
|
||||
else:
|
||||
self.send_error(404)
|
||||
|
||||
def send_json_response(self, data):
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(data).encode('utf-8'))
|
||||
|
||||
def log_message(self, format, *args):
|
||||
# 减少日志输出
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
with socketserver.TCPServer(("", PORT), SetupHandler) as httpd:
|
||||
print(f"✨ 配置服务器已启动: http://localhost:{PORT}")
|
||||
print(f"📝 请在浏览器中完成配置...")
|
||||
print(f"⏹ 完成后服务器会自动关闭\n")
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n👋 服务器已关闭")
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
if e.errno == 48: # Address already in use
|
||||
print(f"❌ 端口 {PORT} 已被占用,请检查是否有其他配置向导正在运行")
|
||||
sys.exit(1)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
26
hooks/test-setup.sh
Executable file
26
hooks/test-setup.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
# 测试配置向导
|
||||
# 用法: bash test-setup.sh
|
||||
|
||||
echo "🧪 测试切图仔 Plugin 配置向导"
|
||||
echo ""
|
||||
|
||||
# 临时清除环境变量(仅用于测试)
|
||||
unset FIGMA_API_KEY
|
||||
|
||||
# 设置 CLAUDE_PLUGIN_ROOT(模拟 Claude Code 环境)
|
||||
export CLAUDE_PLUGIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
echo "📁 Plugin 目录: $CLAUDE_PLUGIN_ROOT"
|
||||
echo ""
|
||||
|
||||
# 运行配置检查脚本
|
||||
bash "$CLAUDE_PLUGIN_ROOT/hooks/check-figma-api-key.sh"
|
||||
|
||||
echo ""
|
||||
echo "✅ 测试完成!"
|
||||
echo ""
|
||||
echo "💡 提示:"
|
||||
echo " - 如果浏览器打开了配置页面,说明脚本工作正常"
|
||||
echo " - 配置成功后会在 ~/.claude/qietuzai-setup-done 创建标记文件"
|
||||
echo " - 可以通过 'cat ~/.zshrc | grep FIGMA_API_KEY' 验证配置"
|
||||
Reference in New Issue
Block a user