cnhkmcp 2.0.1__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.
Files changed (95) hide show
  1. cnhkmcp/__init__.py +125 -0
  2. cnhkmcp/untracked/APP/.gitignore +32 -0
  3. cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +112 -0
  4. cnhkmcp/untracked/APP/README.md +309 -0
  5. cnhkmcp/untracked/APP/Tranformer/Transformer.py +2192 -0
  6. cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
  7. cnhkmcp/untracked/APP/Tranformer/ace_lib.py +1489 -0
  8. cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +180 -0
  9. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +1786 -0
  10. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +654 -0
  11. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +261 -0
  12. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +170 -0
  13. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_/321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/277/321/207/320/253/342/224/244/321/206/320/236/320/265/321/210/342/225/234/342/225/234/321/205/320/225/320/265Machine_lib.json +22 -0
  14. cnhkmcp/untracked/APP/Tranformer/parsetab.py +60 -0
  15. cnhkmcp/untracked/APP/Tranformer/template_summary.txt +408 -0
  16. cnhkmcp/untracked/APP/Tranformer/transformer_config.json +7 -0
  17. cnhkmcp/untracked/APP/Tranformer/validator.py +889 -0
  18. cnhkmcp/untracked/APP/ace.log +65 -0
  19. cnhkmcp/untracked/APP/ace_lib.py +1489 -0
  20. cnhkmcp/untracked/APP/blueprints/__init__.py +6 -0
  21. cnhkmcp/untracked/APP/blueprints/feature_engineering.py +347 -0
  22. cnhkmcp/untracked/APP/blueprints/idea_house.py +221 -0
  23. cnhkmcp/untracked/APP/blueprints/inspiration_house.py +432 -0
  24. cnhkmcp/untracked/APP/blueprints/paper_analysis.py +570 -0
  25. cnhkmcp/untracked/APP/custom_templates/templates.json +1257 -0
  26. cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +400 -0
  27. cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +1489 -0
  28. cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +247 -0
  29. cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +180 -0
  30. cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +11 -0
  31. cnhkmcp/untracked/APP/helpful_functions.py +180 -0
  32. cnhkmcp/untracked/APP/hkSimulator/ace.log +0 -0
  33. cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +1476 -0
  34. cnhkmcp/untracked/APP/hkSimulator/autosim_20251205_145240.log +0 -0
  35. cnhkmcp/untracked/APP/hkSimulator/autosim_20251215_030103.log +0 -0
  36. cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +447 -0
  37. cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +180 -0
  38. cnhkmcp/untracked/APP/mirror_config.txt +20 -0
  39. cnhkmcp/untracked/APP/operaters.csv +129 -0
  40. cnhkmcp/untracked/APP/requirements.txt +53 -0
  41. cnhkmcp/untracked/APP/run_app.bat +28 -0
  42. cnhkmcp/untracked/APP/run_app.sh +34 -0
  43. cnhkmcp/untracked/APP/setup_tsinghua.bat +39 -0
  44. cnhkmcp/untracked/APP/setup_tsinghua.sh +43 -0
  45. cnhkmcp/untracked/APP/simulator/alpha_submitter.py +404 -0
  46. cnhkmcp/untracked/APP/simulator/simulator_wqb.py +618 -0
  47. cnhkmcp/untracked/APP/ssrn-3332513.pdf +109188 -19
  48. cnhkmcp/untracked/APP/static/brain.js +528 -0
  49. cnhkmcp/untracked/APP/static/decoder.js +1540 -0
  50. cnhkmcp/untracked/APP/static/feature_engineering.js +1729 -0
  51. cnhkmcp/untracked/APP/static/idea_house.js +937 -0
  52. cnhkmcp/untracked/APP/static/inspiration.js +465 -0
  53. cnhkmcp/untracked/APP/static/inspiration_house.js +868 -0
  54. cnhkmcp/untracked/APP/static/paper_analysis.js +390 -0
  55. cnhkmcp/untracked/APP/static/script.js +2942 -0
  56. cnhkmcp/untracked/APP/static/simulator.js +597 -0
  57. cnhkmcp/untracked/APP/static/styles.css +3127 -0
  58. cnhkmcp/untracked/APP/static/usage_widget.js +508 -0
  59. cnhkmcp/untracked/APP/templates/alpha_inspector.html +511 -0
  60. cnhkmcp/untracked/APP/templates/feature_engineering.html +960 -0
  61. cnhkmcp/untracked/APP/templates/idea_house.html +564 -0
  62. cnhkmcp/untracked/APP/templates/index.html +911 -0
  63. cnhkmcp/untracked/APP/templates/inspiration_house.html +861 -0
  64. cnhkmcp/untracked/APP/templates/paper_analysis.html +91 -0
  65. cnhkmcp/untracked/APP/templates/simulator.html +343 -0
  66. cnhkmcp/untracked/APP/templates/transformer_web.html +580 -0
  67. cnhkmcp/untracked/APP/usage.md +351 -0
  68. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/ace_lib.py +1489 -0
  69. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/brain_alpha_inspector.py +712 -0
  70. cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/helpful_functions.py +180 -0
  71. cnhkmcp/untracked/APP//321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +2393 -0
  72. cnhkmcp/untracked/arXiv_API_Tool_Manual.md +490 -0
  73. cnhkmcp/untracked/arxiv_api.py +229 -0
  74. cnhkmcp/untracked/forum_functions.py +998 -0
  75. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/forum_functions.py +407 -0
  76. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/platform_functions.py +2415 -0
  77. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/user_config.json +31 -0
  78. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/210/320/276/320/271AI/321/210/320/277/342/225/227/321/210/342/224/220/320/251/321/204/342/225/225/320/272/321/206/320/246/320/227/321/206/320/261/320/263/321/206/320/255/320/265/321/205/320/275/320/266/321/204/342/225/235/320/252/321/204/342/225/225/320/233/321/210/342/225/234/342/225/234/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270.md +101 -0
  79. cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +190 -0
  80. cnhkmcp/untracked/platform_functions.py +2886 -0
  81. cnhkmcp/untracked/sample_mcp_config.json +11 -0
  82. cnhkmcp/untracked/user_config.json +31 -0
  83. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/222/321/210/320/220/320/223/321/206/320/246/320/227/321/206/320/261/320/263_BRAIN_Alpha_Test_Requirements_and_Tips.md +202 -0
  84. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Alpha_explaination_workflow.md +56 -0
  85. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_6_Tips_Datafield_Exploration_Guide.md +194 -0
  86. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_Alpha_Improvement_Workflow.md +101 -0
  87. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Dataset_Exploration_Expert_Manual.md +436 -0
  88. cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_daily_report_workflow.md +128 -0
  89. cnhkmcp/untracked//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +190 -0
  90. cnhkmcp-2.0.1.dist-info/METADATA +187 -0
  91. cnhkmcp-2.0.1.dist-info/RECORD +95 -0
  92. cnhkmcp-2.0.1.dist-info/WHEEL +5 -0
  93. cnhkmcp-2.0.1.dist-info/entry_points.txt +2 -0
  94. cnhkmcp-2.0.1.dist-info/licenses/LICENSE +21 -0
  95. cnhkmcp-2.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,508 @@
1
+ (function () {
2
+ 'use strict';
3
+
4
+ const WIDGET_STYLE_ID = 'usageWidgetStyles';
5
+ const ROOT_ID = 'usageWidgetRoot';
6
+
7
+ function escapeHtml(text) {
8
+ return String(text)
9
+ .replace(/&/g, '&')
10
+ .replace(/</g, '&lt;')
11
+ .replace(/>/g, '&gt;')
12
+ .replace(/"/g, '&quot;')
13
+ .replace(/'/g, '&#39;');
14
+ }
15
+
16
+ function slugify(text) {
17
+ return String(text)
18
+ .trim()
19
+ .toLowerCase()
20
+ .replace(/[\u4e00-\u9fa5]/g, (m) => m) // keep CJK
21
+ .replace(/[^\w\u4e00-\u9fa5\-\s]/g, '')
22
+ .replace(/\s+/g, '-')
23
+ .replace(/-+/g, '-')
24
+ .replace(/^\-+|\-+$/g, '');
25
+ }
26
+
27
+ function ensureStyles() {
28
+ if (document.getElementById(WIDGET_STYLE_ID)) return;
29
+
30
+ const style = document.createElement('style');
31
+ style.id = WIDGET_STYLE_ID;
32
+ style.textContent = `
33
+ #${ROOT_ID} { position: fixed; z-index: 9999; left: 16px; bottom: 16px; font-family: inherit; }
34
+ #${ROOT_ID} .uw-fab {
35
+ display: inline-flex; align-items: center; gap: 8px;
36
+ padding: 12px 18px; border-radius: 999px;
37
+ border: 1px solid rgba(0,0,0,0.10);
38
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
39
+ color: #ffffff;
40
+ font-weight: 800;
41
+ font-size: 14px;
42
+ box-shadow: 0 14px 34px rgba(0,0,0,0.26);
43
+ cursor: pointer;
44
+ user-select: none;
45
+ }
46
+ #${ROOT_ID} .uw-fab:hover { transform: translateY(-1px); }
47
+ #${ROOT_ID} .uw-fab:active { transform: translateY(0px); }
48
+ #${ROOT_ID} .uw-fab .uw-dot { width: 10px; height: 10px; border-radius: 999px; background: rgba(255,255,255,0.95); box-shadow: 0 0 0 3px rgba(255,255,255,0.18); }
49
+
50
+ #${ROOT_ID} .uw-overlay {
51
+ position: fixed; inset: 0; background: rgba(0,0,0,0.45);
52
+ z-index: 10000;
53
+ opacity: 0; pointer-events: none; transition: opacity 180ms ease;
54
+ }
55
+ #${ROOT_ID}.open .uw-overlay { opacity: 1; pointer-events: auto; }
56
+
57
+ #${ROOT_ID} .uw-drawer {
58
+ position: fixed; left: 50%; top: 50%;
59
+ z-index: 10001;
60
+ width: min(980px, calc(100vw - 48px));
61
+ height: min(86vh, 920px);
62
+ background: #ffffff;
63
+ border-radius: 14px;
64
+ border: 1px solid rgba(0,0,0,0.10);
65
+ box-shadow: 0 20px 60px rgba(0,0,0,0.25);
66
+ overflow: hidden;
67
+ transform: translate(-50%, -50%) translateY(12px) scale(0.98);
68
+ opacity: 0;
69
+ pointer-events: none;
70
+ transition: transform 220ms ease, opacity 220ms ease;
71
+ }
72
+ #${ROOT_ID}.open .uw-drawer { transform: translate(-50%, -50%) translateY(0px) scale(1); opacity: 1; pointer-events: auto; }
73
+
74
+ #${ROOT_ID} .uw-header {
75
+ display: flex; align-items: center; justify-content: space-between;
76
+ padding: 12px 14px;
77
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
78
+ color: #fff;
79
+ }
80
+ #${ROOT_ID} .uw-header .uw-title { font-size: 14px; font-weight: 700; letter-spacing: .2px; }
81
+ #${ROOT_ID} .uw-header .uw-actions { display: flex; gap: 8px; align-items: center; }
82
+ #${ROOT_ID} .uw-header button {
83
+ border: 1px solid rgba(255,255,255,0.35);
84
+ background: rgba(255,255,255,0.12);
85
+ color: #fff;
86
+ border-radius: 8px;
87
+ padding: 6px 10px;
88
+ cursor: pointer;
89
+ }
90
+ #${ROOT_ID} .uw-header button:hover { background: rgba(255,255,255,0.18); }
91
+
92
+ #${ROOT_ID} .uw-body { display: grid; grid-template-columns: 240px 1fr; height: calc(100% - 48px); }
93
+ #${ROOT_ID} .uw-sidebar {
94
+ border-right: 1px solid rgba(0,0,0,0.08);
95
+ background: #f5f7fa;
96
+ padding: 10px;
97
+ overflow: auto;
98
+ }
99
+ #${ROOT_ID} .uw-content {
100
+ padding: 12px 14px;
101
+ overflow: auto;
102
+ background: #fff;
103
+ }
104
+
105
+ #${ROOT_ID} .uw-search {
106
+ width: 100%;
107
+ padding: 8px 10px;
108
+ border-radius: 10px;
109
+ border: 1px solid rgba(0,0,0,0.14);
110
+ outline: none;
111
+ margin-bottom: 10px;
112
+ }
113
+ #${ROOT_ID} .uw-search:focus { border-color: rgba(102,126,234,0.6); box-shadow: 0 0 0 3px rgba(102,126,234,0.18); }
114
+
115
+ #${ROOT_ID} .uw-toc { display: flex; flex-direction: column; gap: 6px; }
116
+ #${ROOT_ID} .uw-toc a {
117
+ display: block;
118
+ text-decoration: none;
119
+ color: #2c3e50;
120
+ padding: 6px 8px;
121
+ border-radius: 10px;
122
+ border: 1px solid transparent;
123
+ font-size: 13px;
124
+ line-height: 1.2;
125
+ }
126
+ #${ROOT_ID} .uw-toc a:hover { background: #ffffff; border-color: rgba(0,0,0,0.08); }
127
+ #${ROOT_ID} .uw-toc .uw-toc-section { display: block; }
128
+ #${ROOT_ID} .uw-toc .uw-toc-h1 {
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: space-between;
132
+ font-weight: 800;
133
+ }
134
+ #${ROOT_ID} .uw-toc .uw-toc-h1::after { content: '▸'; color: rgba(102,126,234,0.95); font-size: 12px; margin-left: 8px; }
135
+ #${ROOT_ID} .uw-toc .uw-toc-section.expanded .uw-toc-h1::after { content: '▾'; }
136
+ #${ROOT_ID} .uw-toc .uw-toc-children { display: none; margin-top: 4px; }
137
+ #${ROOT_ID} .uw-toc .uw-toc-section.expanded .uw-toc-children { display: block; }
138
+ #${ROOT_ID} .uw-toc a.level-2 { padding-left: 16px; font-size: 12.5px; opacity: 0.95; }
139
+ #${ROOT_ID} .uw-toc a.level-3 { padding-left: 24px; font-size: 12px; opacity: 0.9; }
140
+
141
+ #${ROOT_ID} .uw-md h1 { font-size: 18px; margin: 14px 0 10px; color: #2c3e50; }
142
+ #${ROOT_ID} .uw-md h2 { font-size: 16px; margin: 14px 0 10px; color: #2c3e50; }
143
+ #${ROOT_ID} .uw-md h3 { font-size: 14px; margin: 12px 0 8px; color: #2c3e50; }
144
+ #${ROOT_ID} .uw-md p { margin: 8px 0; color: #333; }
145
+ #${ROOT_ID} .uw-md ul { margin: 8px 0 8px 20px; }
146
+ #${ROOT_ID} .uw-md li { margin: 4px 0; }
147
+ #${ROOT_ID} .uw-md code { background: #f0f0f0; padding: 2px 6px; border-radius: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
148
+ #${ROOT_ID} .uw-md pre { background: #1e1e1e; color: #f8f8f2; padding: 12px; border-radius: 12px; overflow: auto; margin: 10px 0; }
149
+ #${ROOT_ID} .uw-md pre code { background: transparent; padding: 0; color: inherit; }
150
+ #${ROOT_ID} .uw-muted { color: #6c757d; font-size: 13px; }
151
+ `;
152
+
153
+ document.head.appendChild(style);
154
+ }
155
+
156
+ function buildMarkdownHtml(markdown) {
157
+ // Minimal markdown rendering: headings (#..###), fenced code blocks, inline code, unordered lists, paragraphs.
158
+ // This is intentionally lightweight (no external deps).
159
+ const lines = String(markdown || '').replace(/\r\n/g, '\n').split('\n');
160
+
161
+ const toc = [];
162
+ const usedIds = new Map();
163
+
164
+ function uniqueId(base) {
165
+ const raw = base || 'section';
166
+ let id = raw;
167
+ let i = 2;
168
+ while (usedIds.has(id)) {
169
+ id = `${raw}-${i++}`;
170
+ }
171
+ usedIds.set(id, true);
172
+ return id;
173
+ }
174
+
175
+ let html = '';
176
+ let inCode = false;
177
+ let codeLang = '';
178
+ let codeBuf = [];
179
+ let inUl = false;
180
+
181
+ function closeUl() {
182
+ if (inUl) {
183
+ html += '</ul>';
184
+ inUl = false;
185
+ }
186
+ }
187
+
188
+ function flushParagraph(text) {
189
+ closeUl();
190
+ if (!text) return;
191
+ const withInline = escapeHtml(text).replace(/`([^`]+)`/g, '<code>$1</code>');
192
+ html += `<p>${withInline}</p>`;
193
+ }
194
+
195
+ for (const line of lines) {
196
+ const fence = line.match(/^```\s*(.*)\s*$/);
197
+ if (fence) {
198
+ if (!inCode) {
199
+ closeUl();
200
+ inCode = true;
201
+ codeLang = fence[1] || '';
202
+ codeBuf = [];
203
+ } else {
204
+ const code = codeBuf.join('\n');
205
+ html += `<pre><code${codeLang ? ` data-lang="${escapeHtml(codeLang)}"` : ''}>${escapeHtml(code)}</code></pre>`;
206
+ inCode = false;
207
+ codeLang = '';
208
+ codeBuf = [];
209
+ }
210
+ continue;
211
+ }
212
+
213
+ if (inCode) {
214
+ codeBuf.push(line);
215
+ continue;
216
+ }
217
+
218
+ const h = line.match(/^(#{1,3})\s+(.*)$/);
219
+ if (h) {
220
+ closeUl();
221
+ const level = h[1].length;
222
+ const text = h[2].trim();
223
+ const id = uniqueId(slugify(text) || `h${level}`);
224
+ toc.push({ level, text, id });
225
+ html += `<h${level} id="${escapeHtml(id)}">${escapeHtml(text)}</h${level}>`;
226
+ continue;
227
+ }
228
+
229
+ const ul = line.match(/^\s*[-*]\s+(.*)$/);
230
+ if (ul) {
231
+ if (!inUl) {
232
+ closeUl();
233
+ html += '<ul>';
234
+ inUl = true;
235
+ }
236
+ const item = escapeHtml(ul[1]).replace(/`([^`]+)`/g, '<code>$1</code>');
237
+ html += `<li>${item}</li>`;
238
+ continue;
239
+ }
240
+
241
+ if (!line.trim()) {
242
+ closeUl();
243
+ continue;
244
+ }
245
+
246
+ flushParagraph(line);
247
+ }
248
+
249
+ closeUl();
250
+
251
+ return { html, toc };
252
+ }
253
+
254
+ function ensureRoot() {
255
+ let root = document.getElementById(ROOT_ID);
256
+ if (root) return root;
257
+
258
+ root = document.createElement('div');
259
+ root.id = ROOT_ID;
260
+ root.innerHTML = `
261
+ <div class="uw-overlay" aria-hidden="true"></div>
262
+ <button type="button" class="uw-fab" aria-label="打开使用说明">
263
+ <span class="uw-dot" aria-hidden="true"></span>
264
+ <span>使用说明</span>
265
+ </button>
266
+ <div class="uw-drawer" role="dialog" aria-modal="true" aria-label="使用说明">
267
+ <div class="uw-header">
268
+ <div class="uw-title">使用说明</div>
269
+ <div class="uw-actions">
270
+ <button type="button" class="uw-reload" title="重新加载">刷新</button>
271
+ <button type="button" class="uw-close" title="关闭">关闭</button>
272
+ </div>
273
+ </div>
274
+ <div class="uw-body">
275
+ <div class="uw-sidebar">
276
+ <input class="uw-search" type="search" placeholder="搜索标题..." />
277
+ <div class="uw-toc" aria-label="目录"></div>
278
+ </div>
279
+ <div class="uw-content">
280
+ <div class="uw-muted" data-uw-status>正在加载 usage.md...</div>
281
+ <div class="uw-md" data-uw-md style="display:none;"></div>
282
+ </div>
283
+ </div>
284
+ </div>
285
+ `;
286
+
287
+ document.body.appendChild(root);
288
+ return root;
289
+ }
290
+
291
+ async function fetchUsageMarkdown() {
292
+ const resp = await fetch('/api/usage-doc', { method: 'GET' });
293
+ const data = await resp.json();
294
+ if (!resp.ok || !data || !data.success) {
295
+ const msg = (data && data.error) ? data.error : `HTTP ${resp.status}`;
296
+ throw new Error(msg);
297
+ }
298
+ return data.markdown || '';
299
+ }
300
+
301
+ function open(root) {
302
+ root.classList.add('open');
303
+ }
304
+
305
+ function close(root) {
306
+ root.classList.remove('open');
307
+ }
308
+
309
+ function wire(root) {
310
+ const overlay = root.querySelector('.uw-overlay');
311
+ const fab = root.querySelector('.uw-fab');
312
+ const btnClose = root.querySelector('.uw-close');
313
+ const btnReload = root.querySelector('.uw-reload');
314
+ const tocEl = root.querySelector('.uw-toc');
315
+ const searchEl = root.querySelector('.uw-search');
316
+ const statusEl = root.querySelector('[data-uw-status]');
317
+ const mdEl = root.querySelector('[data-uw-md]');
318
+
319
+ let cache = { markdown: null, built: null };
320
+ const expandedSections = new Set();
321
+
322
+ function groupToc(toc) {
323
+ const items = (toc || []).filter(x => x.level <= 3);
324
+ const level1Count = items.filter(x => x.level === 1).length;
325
+ const level2Count = items.filter(x => x.level === 2).length;
326
+
327
+ // Common doc layout: a single H1 is just the document title.
328
+ // In that case, use H2 as the TOC top-level (expand to show H3).
329
+ const useH2AsTop = level1Count <= 1 && level2Count > 0;
330
+
331
+ const sections = [];
332
+ let current = null;
333
+
334
+ for (const h of items) {
335
+ if (useH2AsTop) {
336
+ if (h.level === 1) continue;
337
+ if (h.level === 2) {
338
+ current = { top: h, children: [] };
339
+ sections.push(current);
340
+ continue;
341
+ }
342
+ // level === 3
343
+ if (!current) {
344
+ current = { top: { ...h, level: 2 }, children: [] };
345
+ sections.push(current);
346
+ continue;
347
+ }
348
+ current.children.push(h);
349
+ continue;
350
+ }
351
+
352
+ // Default: H1 is top-level, H2/H3 are children.
353
+ if (h.level === 1) {
354
+ current = { top: h, children: [] };
355
+ sections.push(current);
356
+ continue;
357
+ }
358
+ if (!current) {
359
+ current = { top: { ...h, level: 1 }, children: [] };
360
+ sections.push(current);
361
+ continue;
362
+ }
363
+ current.children.push(h);
364
+ }
365
+
366
+ return { sections, useH2AsTop };
367
+ }
368
+
369
+ function renderToc(query) {
370
+ const built = cache.built;
371
+ if (!built) {
372
+ tocEl.innerHTML = '';
373
+ return;
374
+ }
375
+
376
+ const q = String(query || '').trim().toLowerCase();
377
+ const searchMode = q.length > 0;
378
+
379
+ const grouped = groupToc(built.toc);
380
+ const sections = grouped.sections;
381
+ const useH2AsTop = grouped.useH2AsTop;
382
+ const parts = [];
383
+
384
+ for (const section of sections) {
385
+ const top = section.top;
386
+ const sectionId = top.id;
387
+ const topText = top.text || '';
388
+
389
+ const sectionMatch = !q || topText.toLowerCase().includes(q);
390
+ const matchedChildren = searchMode
391
+ ? section.children.filter(c => (c.text || '').toLowerCase().includes(q))
392
+ : section.children;
393
+
394
+ const visible = !searchMode || sectionMatch || matchedChildren.length > 0;
395
+ if (!visible) continue;
396
+
397
+ const expanded = searchMode ? (matchedChildren.length > 0) : expandedSections.has(sectionId);
398
+ const childLinks = expanded
399
+ ? matchedChildren.map(c => {
400
+ const cls = useH2AsTop ? 'level-3' : (c.level === 2 ? 'level-2' : 'level-3');
401
+ return `<a class="${cls}" href="#${escapeHtml(c.id)}" data-uw-target="${escapeHtml(c.id)}">${escapeHtml(c.text)}</a>`;
402
+ }).join('')
403
+ : '';
404
+
405
+ parts.push(
406
+ `<div class="uw-toc-section ${expanded ? 'expanded' : ''}" data-uw-section="${escapeHtml(sectionId)}">` +
407
+ `<a class="uw-toc-h1" href="#${escapeHtml(sectionId)}" data-uw-target="${escapeHtml(sectionId)}">${escapeHtml(topText)}</a>` +
408
+ `<div class="uw-toc-children">${childLinks}</div>` +
409
+ `</div>`
410
+ );
411
+ }
412
+
413
+ tocEl.innerHTML = parts.join('');
414
+ }
415
+
416
+ function renderFromMarkdown(markdown) {
417
+ const built = buildMarkdownHtml(markdown);
418
+ mdEl.innerHTML = built.html;
419
+ mdEl.style.display = '';
420
+ statusEl.style.display = 'none';
421
+ cache.built = built;
422
+
423
+ renderToc(searchEl.value);
424
+
425
+ // Scroll to top when re-render
426
+ mdEl.parentElement.scrollTop = 0;
427
+ }
428
+
429
+ async function ensureLoaded(force) {
430
+ if (!force && cache.markdown) return;
431
+ statusEl.textContent = '正在加载 usage.md...';
432
+ statusEl.style.display = '';
433
+ mdEl.style.display = 'none';
434
+
435
+ try {
436
+ const markdown = await fetchUsageMarkdown();
437
+ cache.markdown = markdown;
438
+ renderFromMarkdown(markdown);
439
+ } catch (e) {
440
+ statusEl.textContent = `加载失败:${e && e.message ? e.message : String(e)}`;
441
+ statusEl.style.display = '';
442
+ mdEl.style.display = 'none';
443
+ }
444
+ }
445
+
446
+ function applySearch() {
447
+ renderToc(searchEl.value);
448
+ }
449
+
450
+ fab.addEventListener('click', async () => {
451
+ open(root);
452
+ await ensureLoaded(false);
453
+ });
454
+
455
+ overlay.addEventListener('click', () => close(root));
456
+ btnClose.addEventListener('click', () => close(root));
457
+
458
+ btnReload.addEventListener('click', async () => {
459
+ cache.markdown = null;
460
+ cache.built = null;
461
+ await ensureLoaded(true);
462
+ });
463
+
464
+ document.addEventListener('keydown', (e) => {
465
+ if (e.key === 'Escape') close(root);
466
+ });
467
+
468
+ tocEl.addEventListener('click', (e) => {
469
+ const a = e.target.closest('a[data-uw-target]');
470
+ if (!a) return;
471
+ e.preventDefault();
472
+
473
+ const q = (searchEl.value || '').trim();
474
+ const id = a.getAttribute('data-uw-target');
475
+
476
+ // Toggle sub-headings only when clicking a top-level entry, and not in search mode.
477
+ if (!q && a.classList.contains('uw-toc-h1')) {
478
+ if (expandedSections.has(id)) expandedSections.delete(id);
479
+ else expandedSections.add(id);
480
+ renderToc(searchEl.value);
481
+ }
482
+
483
+ const target = mdEl.querySelector(`#${CSS.escape(id)}`);
484
+ if (target) {
485
+ target.scrollIntoView({ behavior: 'smooth', block: 'start' });
486
+ }
487
+ });
488
+
489
+ searchEl.addEventListener('input', applySearch);
490
+
491
+ // Preload lazily after page settles
492
+ window.setTimeout(() => {
493
+ ensureLoaded(false).catch(() => {});
494
+ }, 800);
495
+ }
496
+
497
+ function init() {
498
+ ensureStyles();
499
+ const root = ensureRoot();
500
+ wire(root);
501
+ }
502
+
503
+ if (document.readyState === 'loading') {
504
+ document.addEventListener('DOMContentLoaded', init);
505
+ } else {
506
+ init();
507
+ }
508
+ })();