htmlgen-mcp 0.3.3__py3-none-any.whl → 0.3.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of htmlgen-mcp might be problematic. Click here for more details.
- htmlgen_mcp/agents/quick_generator.py +481 -63
- htmlgen_mcp/agents/smart_web_agent.py +707 -235
- htmlgen_mcp/agents/web_tools/__init__.py +41 -41
- htmlgen_mcp/agents/web_tools/css.py +148 -0
- htmlgen_mcp/agents/web_tools/js.py +12 -10
- htmlgen_mcp/agents/web_tools/navigation.py +2 -0
- htmlgen_mcp/agents/web_tools/project.py +0 -4
- htmlgen_mcp/config.py +9 -30
- htmlgen_mcp/improved_progress.py +392 -0
- htmlgen_mcp/nas_log_manager.py +308 -0
- htmlgen_mcp/nas_storage.py +356 -0
- htmlgen_mcp/progress_tools.py +194 -0
- htmlgen_mcp/progress_tracker.py +378 -0
- htmlgen_mcp/web_agent_server.py +35 -4
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.5.dist-info}/METADATA +1 -1
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.5.dist-info}/RECORD +19 -16
- htmlgen_mcp/agents/cluster_state.py +0 -414
- htmlgen_mcp/agents/cluster_storage.py +0 -341
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.5.dist-info}/WHEEL +0 -0
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.5.dist-info}/entry_points.txt +0 -0
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.5.dist-info}/top_level.txt +0 -0
|
@@ -25,30 +25,30 @@ from .js import create_js_file
|
|
|
25
25
|
from .navigation import create_responsive_navbar
|
|
26
26
|
from .project import create_project_structure
|
|
27
27
|
from .validation import check_mobile_friendly, validate_html
|
|
28
|
-
from .colors import generate_color_scheme
|
|
28
|
+
# from .colors import generate_color_scheme # 暂停导出:无需在主流程中使用
|
|
29
29
|
|
|
30
|
-
#
|
|
31
|
-
from .simple_templates import (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
from .simple_css import (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
from .simple_js import (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
from .simple_builder import (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
30
|
+
# 新增简单模板支持(暂时注释,备用组件无需默认加载)
|
|
31
|
+
# from .simple_templates import (
|
|
32
|
+
# create_simple_html_file,
|
|
33
|
+
# create_blank_html_file,
|
|
34
|
+
# create_landing_page,
|
|
35
|
+
# create_blog_page,
|
|
36
|
+
# )
|
|
37
|
+
# from .simple_css import (
|
|
38
|
+
# create_clean_css_file,
|
|
39
|
+
# create_landing_css_file,
|
|
40
|
+
# create_blog_css_file,
|
|
41
|
+
# create_minimal_css_file,
|
|
42
|
+
# )
|
|
43
|
+
# from .simple_js import (
|
|
44
|
+
# create_simple_js_file,
|
|
45
|
+
# create_minimal_js_file,
|
|
46
|
+
# create_interactive_js_file,
|
|
47
|
+
# )
|
|
48
|
+
# from .simple_builder import (
|
|
49
|
+
# create_simple_website,
|
|
50
|
+
# create_simple_page_set,
|
|
51
|
+
# )
|
|
52
52
|
from .edgeone_deploy import (
|
|
53
53
|
deploy_folder_or_zip_to_edgeone,
|
|
54
54
|
EdgeOneDeployer,
|
|
@@ -70,24 +70,24 @@ __all__ = [
|
|
|
70
70
|
"start_live_server",
|
|
71
71
|
"validate_html",
|
|
72
72
|
"check_mobile_friendly",
|
|
73
|
-
"generate_color_scheme",
|
|
74
|
-
# 简单模板
|
|
75
|
-
"create_simple_html_file",
|
|
76
|
-
"create_blank_html_file",
|
|
77
|
-
"create_landing_page",
|
|
78
|
-
"create_blog_page",
|
|
79
|
-
# 简单CSS
|
|
80
|
-
"create_clean_css_file",
|
|
81
|
-
"create_landing_css_file",
|
|
82
|
-
"create_blog_css_file",
|
|
83
|
-
"create_minimal_css_file",
|
|
84
|
-
# 简单JS
|
|
85
|
-
"create_simple_js_file",
|
|
86
|
-
"create_minimal_js_file",
|
|
87
|
-
"create_interactive_js_file",
|
|
88
|
-
# 简单网站构建器
|
|
89
|
-
"create_simple_website",
|
|
90
|
-
"create_simple_page_set",
|
|
73
|
+
# "generate_color_scheme",
|
|
74
|
+
# # 简单模板
|
|
75
|
+
# "create_simple_html_file",
|
|
76
|
+
# "create_blank_html_file",
|
|
77
|
+
# "create_landing_page",
|
|
78
|
+
# "create_blog_page",
|
|
79
|
+
# # 简单CSS
|
|
80
|
+
# "create_clean_css_file",
|
|
81
|
+
# "create_landing_css_file",
|
|
82
|
+
# "create_blog_css_file",
|
|
83
|
+
# "create_minimal_css_file",
|
|
84
|
+
# # 简单JS
|
|
85
|
+
# "create_simple_js_file",
|
|
86
|
+
# "create_minimal_js_file",
|
|
87
|
+
# "create_interactive_js_file",
|
|
88
|
+
# # 简单网站构建器
|
|
89
|
+
# "create_simple_website",
|
|
90
|
+
# "create_simple_page_set",
|
|
91
91
|
# EdgeOne部署工具
|
|
92
92
|
"deploy_folder_or_zip_to_edgeone",
|
|
93
93
|
"EdgeOneDeployer",
|
|
@@ -358,6 +358,25 @@ img[loading="lazy"] {{
|
|
|
358
358
|
animation: heroFloat 20s ease-in-out infinite;
|
|
359
359
|
}}
|
|
360
360
|
|
|
361
|
+
.hero-overlay {{
|
|
362
|
+
position: relative;
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
}}
|
|
365
|
+
|
|
366
|
+
.hero-overlay .overlay {{
|
|
367
|
+
position: absolute;
|
|
368
|
+
inset: 0;
|
|
369
|
+
background: linear-gradient(200deg, rgba(17, 24, 39, 0.65) 0%, rgba(17, 24, 39, 0.35) 55%, rgba(17, 24, 39, 0.08) 100%);
|
|
370
|
+
mix-blend-mode: multiply;
|
|
371
|
+
backdrop-filter: blur(6px);
|
|
372
|
+
z-index: 0;
|
|
373
|
+
}}
|
|
374
|
+
|
|
375
|
+
.hero-overlay .container {{
|
|
376
|
+
position: relative;
|
|
377
|
+
z-index: 1;
|
|
378
|
+
}}
|
|
379
|
+
|
|
361
380
|
@keyframes heroFloat {{
|
|
362
381
|
0%, 100% {{ transform: rotate(0deg) scale(1); }}
|
|
363
382
|
33% {{ transform: rotate(10deg) scale(1.1); }}
|
|
@@ -1110,6 +1129,85 @@ img[loading="lazy"] {{
|
|
|
1110
1129
|
line-height: var(--line-height-relaxed);
|
|
1111
1130
|
}}
|
|
1112
1131
|
|
|
1132
|
+
.shadow-soft {{
|
|
1133
|
+
background: var(--white);
|
|
1134
|
+
border-radius: var(--radius-xl);
|
|
1135
|
+
box-shadow: 0 22px 45px -28px rgba(17, 24, 39, 0.4);
|
|
1136
|
+
transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
|
|
1137
|
+
}}
|
|
1138
|
+
|
|
1139
|
+
.shadow-soft:hover {{
|
|
1140
|
+
transform: translateY(-6px);
|
|
1141
|
+
box-shadow: 0 30px 55px -26px rgba(17, 24, 39, 0.45);
|
|
1142
|
+
}}
|
|
1143
|
+
|
|
1144
|
+
.icon-badge {{
|
|
1145
|
+
display: inline-flex;
|
|
1146
|
+
width: 3rem;
|
|
1147
|
+
height: 3rem;
|
|
1148
|
+
align-items: center;
|
|
1149
|
+
justify-content: center;
|
|
1150
|
+
border-radius: var(--radius-full);
|
|
1151
|
+
color: var(--white);
|
|
1152
|
+
box-shadow: var(--shadow-md);
|
|
1153
|
+
font-size: 1.35rem;
|
|
1154
|
+
}}
|
|
1155
|
+
|
|
1156
|
+
.border-gradient {{
|
|
1157
|
+
border-radius: var(--radius-xl);
|
|
1158
|
+
border: 1px solid transparent;
|
|
1159
|
+
background:
|
|
1160
|
+
linear-gradient(var(--white), var(--white)) padding-box,
|
|
1161
|
+
linear-gradient(135deg, rgba(var(--primary-rgb), 0.28), rgba(255, 255, 255, 0.08)) border-box;
|
|
1162
|
+
}}
|
|
1163
|
+
|
|
1164
|
+
.membership-card {{
|
|
1165
|
+
background: rgba(255, 255, 255, 0.94);
|
|
1166
|
+
border-radius: var(--radius-xl);
|
|
1167
|
+
border: 1px solid rgba(148, 163, 184, 0.18);
|
|
1168
|
+
transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
|
|
1169
|
+
display: flex;
|
|
1170
|
+
flex-direction: column;
|
|
1171
|
+
gap: var(--space-sm);
|
|
1172
|
+
color: var(--gray-800);
|
|
1173
|
+
}}
|
|
1174
|
+
|
|
1175
|
+
.membership-card:hover {{
|
|
1176
|
+
transform: translateY(-6px);
|
|
1177
|
+
box-shadow: var(--shadow-2xl);
|
|
1178
|
+
}}
|
|
1179
|
+
|
|
1180
|
+
.membership-card.highlight {{
|
|
1181
|
+
background: linear-gradient(135deg, rgba(30, 58, 138, 0.95) 0%, rgba(67, 56, 202, 0.95) 35%, rgba(245, 158, 11, 0.95) 100%);
|
|
1182
|
+
color: var(--white);
|
|
1183
|
+
}}
|
|
1184
|
+
|
|
1185
|
+
.membership-card.highlight p,
|
|
1186
|
+
.membership-card.highlight li {{
|
|
1187
|
+
color: rgba(255, 255, 255, 0.86);
|
|
1188
|
+
}}
|
|
1189
|
+
|
|
1190
|
+
.testimonial-card {{
|
|
1191
|
+
border-radius: var(--radius-xl);
|
|
1192
|
+
border: 1px solid rgba(148, 163, 184, 0.25);
|
|
1193
|
+
backdrop-filter: blur(10px);
|
|
1194
|
+
-webkit-backdrop-filter: blur(10px);
|
|
1195
|
+
background: rgba(255, 255, 255, 0.9);
|
|
1196
|
+
box-shadow: var(--shadow-md);
|
|
1197
|
+
transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
|
|
1198
|
+
}}
|
|
1199
|
+
|
|
1200
|
+
.testimonial-card:hover {{
|
|
1201
|
+
transform: translateY(-4px);
|
|
1202
|
+
box-shadow: var(--shadow-2xl);
|
|
1203
|
+
}}
|
|
1204
|
+
|
|
1205
|
+
.avatar {{
|
|
1206
|
+
width: 64px;
|
|
1207
|
+
height: 64px;
|
|
1208
|
+
object-fit: cover;
|
|
1209
|
+
}}
|
|
1210
|
+
|
|
1113
1211
|
/* ==================== CTA 区域 ==================== */
|
|
1114
1212
|
.cta {{
|
|
1115
1213
|
background: var(--gradient-primary);
|
|
@@ -1380,6 +1478,56 @@ img[loading="lazy"] {{
|
|
|
1380
1478
|
border-radius: var(--radius-xl);
|
|
1381
1479
|
}}
|
|
1382
1480
|
|
|
1481
|
+
.btn-gradient {{
|
|
1482
|
+
background: var(--gradient-primary);
|
|
1483
|
+
color: var(--white);
|
|
1484
|
+
border: none;
|
|
1485
|
+
box-shadow: var(--shadow-lg);
|
|
1486
|
+
}}
|
|
1487
|
+
|
|
1488
|
+
.btn-gradient:hover {{
|
|
1489
|
+
transform: translateY(-2px);
|
|
1490
|
+
box-shadow: 0 18px 45px -12px rgba(var(--primary-rgb), 0.45);
|
|
1491
|
+
opacity: 0.95;
|
|
1492
|
+
}}
|
|
1493
|
+
|
|
1494
|
+
.btn-dark-gradient {{
|
|
1495
|
+
background: linear-gradient(135deg, rgba(17, 24, 39, 0.95) 0%, rgba(55, 65, 81, 0.95) 100%);
|
|
1496
|
+
color: var(--white);
|
|
1497
|
+
border: none;
|
|
1498
|
+
box-shadow: var(--shadow-lg);
|
|
1499
|
+
}}
|
|
1500
|
+
|
|
1501
|
+
.btn-dark-gradient:hover {{
|
|
1502
|
+
transform: translateY(-2px);
|
|
1503
|
+
box-shadow: 0 20px 50px -15px rgba(17, 24, 39, 0.55);
|
|
1504
|
+
}}
|
|
1505
|
+
|
|
1506
|
+
.btn-outline-primary {{
|
|
1507
|
+
color: var(--primary);
|
|
1508
|
+
border: 2px solid var(--primary);
|
|
1509
|
+
background: transparent;
|
|
1510
|
+
}}
|
|
1511
|
+
|
|
1512
|
+
.btn-outline-primary:hover {{
|
|
1513
|
+
background: var(--primary);
|
|
1514
|
+
color: var(--white);
|
|
1515
|
+
box-shadow: var(--shadow-md);
|
|
1516
|
+
}}
|
|
1517
|
+
|
|
1518
|
+
.btn-outline-light {{
|
|
1519
|
+
color: var(--white);
|
|
1520
|
+
border: 2px solid rgba(255, 255, 255, 0.6);
|
|
1521
|
+
background: transparent;
|
|
1522
|
+
}}
|
|
1523
|
+
|
|
1524
|
+
.btn-outline-light:hover {{
|
|
1525
|
+
background: rgba(255, 255, 255, 0.15);
|
|
1526
|
+
color: var(--white);
|
|
1527
|
+
border-color: rgba(255, 255, 255, 0.9);
|
|
1528
|
+
transform: translateY(-2px);
|
|
1529
|
+
}}
|
|
1530
|
+
|
|
1383
1531
|
/* 按钮涟漪效果 */
|
|
1384
1532
|
.btn::before {{
|
|
1385
1533
|
content: '';
|
|
@@ -9,16 +9,18 @@ def create_js_file(file_path: str, content: str = ""):
|
|
|
9
9
|
js_template = f"""// 页面加载完成后执行
|
|
10
10
|
document.addEventListener('DOMContentLoaded', function() {{
|
|
11
11
|
// Smooth scroll 由 CSS scroll-behavior 支持,这里补充导航折叠与激活态处理
|
|
12
|
-
const navLinks = document.querySelectorAll('.navbar a.nav-link[href^="#"]');
|
|
13
|
-
navLinks.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
const navLinks = Array.from(document.querySelectorAll('.navbar a.nav-link[href^="#"]'));
|
|
13
|
+
if (navLinks.length) {{
|
|
14
|
+
navLinks.forEach(link => {{
|
|
15
|
+
link.addEventListener('click', () => {{
|
|
16
|
+
const navbarCollapse = document.querySelector('.navbar .navbar-collapse');
|
|
17
|
+
if (navbarCollapse && navbarCollapse.classList.contains('show')) {{
|
|
18
|
+
const toggler = document.querySelector('.navbar .navbar-toggler');
|
|
19
|
+
toggler && toggler.click();
|
|
20
|
+
}}
|
|
21
|
+
}});
|
|
20
22
|
}});
|
|
21
|
-
}}
|
|
23
|
+
}}
|
|
22
24
|
|
|
23
25
|
// 简易 ScrollSpy
|
|
24
26
|
const sections = Array.from(document.querySelectorAll('section[id]'));
|
|
@@ -30,7 +32,7 @@ document.addEventListener('DOMContentLoaded', function() {{
|
|
|
30
32
|
const top = window.scrollY + rect.top;
|
|
31
33
|
if (scrollY >= top) activeId = sec.id;
|
|
32
34
|
}});
|
|
33
|
-
if (activeId) {{
|
|
35
|
+
if (activeId && navLinks.length) {{
|
|
34
36
|
navLinks.forEach(a => a.classList.toggle('active', a.getAttribute('href') === '#' + activeId));
|
|
35
37
|
}}
|
|
36
38
|
|
|
@@ -58,6 +58,8 @@ def create_responsive_navbar(file_path: str, brand_name: str = "公司名称", n
|
|
|
58
58
|
{"name": "服务", "href": "#services", "active": False},
|
|
59
59
|
{"name": "联系", "href": "#contact", "active": False}
|
|
60
60
|
]
|
|
61
|
+
elif not nav_items:
|
|
62
|
+
return "导航栏未生成:nav_items 为空,已跳过注入导航组件"
|
|
61
63
|
|
|
62
64
|
# 归一化单个导航项,避免 KeyError
|
|
63
65
|
def _normalize_item(raw: object, index: int) -> tuple[dict, bool]:
|
|
@@ -12,14 +12,10 @@ def create_project_structure(project_name: str, project_path: str) -> str:
|
|
|
12
12
|
base_path = Path(project_path) / project_name
|
|
13
13
|
|
|
14
14
|
dirs = [
|
|
15
|
-
"css",
|
|
16
|
-
"js",
|
|
17
|
-
"images",
|
|
18
15
|
"assets",
|
|
19
16
|
"assets/css",
|
|
20
17
|
"assets/js",
|
|
21
18
|
"assets/images",
|
|
22
|
-
"components",
|
|
23
19
|
]
|
|
24
20
|
|
|
25
21
|
try:
|
htmlgen_mcp/config.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""项目配置管理 -
|
|
1
|
+
"""项目配置管理 - 跨平台支持"""
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
4
|
import platform
|
|
@@ -8,7 +8,7 @@ from datetime import datetime
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class ProjectConfig:
|
|
11
|
-
"""项目配置管理器 - 支持 Windows/macOS/Linux
|
|
11
|
+
"""项目配置管理器 - 支持 Windows/macOS/Linux"""
|
|
12
12
|
|
|
13
13
|
@staticmethod
|
|
14
14
|
def get_system_info() -> dict:
|
|
@@ -22,37 +22,16 @@ class ProjectConfig:
|
|
|
22
22
|
|
|
23
23
|
@staticmethod
|
|
24
24
|
def get_default_output_dir() -> Path:
|
|
25
|
-
"""
|
|
25
|
+
"""获取默认的项目输出目录(跨平台)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
1. 环境变量
|
|
29
|
-
2.
|
|
30
|
-
3.
|
|
31
|
-
4.
|
|
32
|
-
5. 系统临时目录
|
|
33
|
-
|
|
34
|
-
集群部署说明:
|
|
35
|
-
- 在 SSE 集群中,建议配置 WEB_AGENT_PROJECT_ROOT 为 NAS 共享路径
|
|
36
|
-
- 示例:WEB_AGENT_PROJECT_ROOT=/app/mcp-servers/mcp-servers/html_agent/projects
|
|
27
|
+
优先级:
|
|
28
|
+
1. 环境变量 WEB_AGENT_OUTPUT_DIR
|
|
29
|
+
2. 系统特定的文档目录
|
|
30
|
+
3. 用户主目录下的隐藏目录
|
|
31
|
+
4. 系统临时目录
|
|
37
32
|
"""
|
|
38
33
|
|
|
39
|
-
#
|
|
40
|
-
project_root = os.environ.get('WEB_AGENT_PROJECT_ROOT')
|
|
41
|
-
if project_root:
|
|
42
|
-
output_dir = Path(project_root)
|
|
43
|
-
try:
|
|
44
|
-
output_dir.mkdir(parents=True, exist_ok=True)
|
|
45
|
-
# 验证目录可写
|
|
46
|
-
test_file = output_dir / '.write_test'
|
|
47
|
-
test_file.touch()
|
|
48
|
-
test_file.unlink()
|
|
49
|
-
print(f"✅ 使用集群共享存储: {output_dir}")
|
|
50
|
-
return output_dir
|
|
51
|
-
except Exception as e:
|
|
52
|
-
print(f"⚠️ 集群共享存储不可用 ({output_dir}): {e}")
|
|
53
|
-
print(f"💡 请检查 NAS 挂载状态和权限")
|
|
54
|
-
|
|
55
|
-
# 1b. 检查兼容性环境变量
|
|
34
|
+
# 1. 检查环境变量(所有平台通用)
|
|
56
35
|
env_dir = os.environ.get('WEB_AGENT_OUTPUT_DIR')
|
|
57
36
|
if env_dir:
|
|
58
37
|
output_dir = Path(env_dir)
|