mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 02:22:26 +08:00
✨ 新增 AI 工作列表支援 markdown 顯示
This commit is contained in:
parent
d79b040162
commit
3ed1150642
@ -136,9 +136,72 @@ def test_web_ui_simple():
|
|||||||
|
|
||||||
print("🔧 創建測試會話...")
|
print("🔧 創建測試會話...")
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
created_session_id = manager.create_session(
|
markdown_test_content = """# Web UI 測試 - Markdown 渲染功能
|
||||||
temp_dir, "Web UI 測試 - 驗證基本功能"
|
|
||||||
)
|
## 🎯 測試目標
|
||||||
|
驗證 **combinedSummaryContent** 區域的 Markdown 語法顯示功能
|
||||||
|
|
||||||
|
### ✨ 支援的語法特性
|
||||||
|
|
||||||
|
#### 文字格式
|
||||||
|
- **粗體文字** 使用雙星號
|
||||||
|
- *斜體文字* 使用單星號
|
||||||
|
- ~~刪除線文字~~ 使用雙波浪號
|
||||||
|
- `行內程式碼` 使用反引號
|
||||||
|
|
||||||
|
#### 程式碼區塊
|
||||||
|
```javascript
|
||||||
|
// JavaScript 範例
|
||||||
|
function renderMarkdown(content) {
|
||||||
|
return marked.parse(content);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Python 範例
|
||||||
|
def process_feedback(data):
|
||||||
|
return {"status": "success", "data": data}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 列表功能
|
||||||
|
**無序列表:**
|
||||||
|
- 第一個項目
|
||||||
|
- 第二個項目
|
||||||
|
- 巢狀項目 1
|
||||||
|
- 巢狀項目 2
|
||||||
|
- 第三個項目
|
||||||
|
|
||||||
|
**有序列表:**
|
||||||
|
1. 初始化 Markdown 渲染器
|
||||||
|
2. 載入 marked.js 和 DOMPurify
|
||||||
|
3. 配置安全選項
|
||||||
|
4. 渲染內容
|
||||||
|
|
||||||
|
#### 連結和引用
|
||||||
|
- 專案連結:[MCP Feedback Enhanced](https://github.com/example/mcp-feedback-enhanced)
|
||||||
|
- 文檔連結:[Marked.js 官方文檔](https://marked.js.org/)
|
||||||
|
|
||||||
|
> **重要提示:** 所有 HTML 輸出都經過 DOMPurify 清理,確保安全性。
|
||||||
|
|
||||||
|
#### 表格範例
|
||||||
|
| 功能 | 狀態 | 說明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 標題渲染 | ✅ | 支援 H1-H6 |
|
||||||
|
| 程式碼高亮 | ✅ | 基本語法高亮 |
|
||||||
|
| 列表功能 | ✅ | 有序/無序列表 |
|
||||||
|
| 連結處理 | ✅ | 安全連結渲染 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔒 安全特性
|
||||||
|
- XSS 防護:使用 DOMPurify 清理
|
||||||
|
- 白名單標籤:僅允許安全的 HTML 標籤
|
||||||
|
- URL 驗證:限制允許的 URL 協議
|
||||||
|
|
||||||
|
### 📝 測試結果
|
||||||
|
如果您能看到上述內容以正確的格式顯示,表示 Markdown 渲染功能運作正常!"""
|
||||||
|
|
||||||
|
created_session_id = manager.create_session(temp_dir, markdown_test_content)
|
||||||
|
|
||||||
if created_session_id:
|
if created_session_id:
|
||||||
print("✅ 會話創建成功")
|
print("✅ 會話創建成功")
|
||||||
|
@ -1149,7 +1149,42 @@ if __name__ == "__main__":
|
|||||||
async def main():
|
async def main():
|
||||||
try:
|
try:
|
||||||
project_dir = os.getcwd()
|
project_dir = os.getcwd()
|
||||||
summary = "這是一個測試摘要,用於驗證 Web UI 功能。"
|
summary = """# Markdown 功能測試
|
||||||
|
|
||||||
|
## 🎯 任務完成摘要
|
||||||
|
|
||||||
|
我已成功為 **mcp-feedback-enhanced** 專案實現了 Markdown 語法顯示功能!
|
||||||
|
|
||||||
|
### ✅ 完成的功能
|
||||||
|
|
||||||
|
1. **標題支援** - 支援 H1 到 H6 標題
|
||||||
|
2. **文字格式化**
|
||||||
|
- **粗體文字** 使用雙星號
|
||||||
|
- *斜體文字* 使用單星號
|
||||||
|
- `行內程式碼` 使用反引號
|
||||||
|
3. **程式碼區塊**
|
||||||
|
4. **列表功能**
|
||||||
|
- 無序列表項目
|
||||||
|
- 有序列表項目
|
||||||
|
|
||||||
|
### 📋 技術實作
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 使用 marked.js 進行 Markdown 解析
|
||||||
|
const renderedContent = this.renderMarkdownSafely(summary);
|
||||||
|
element.innerHTML = renderedContent;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔗 相關連結
|
||||||
|
|
||||||
|
- [marked.js 官方文檔](https://marked.js.org/)
|
||||||
|
- [DOMPurify 安全清理](https://github.com/cure53/DOMPurify)
|
||||||
|
|
||||||
|
> **注意**: 此功能包含 XSS 防護,使用 DOMPurify 進行 HTML 清理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**測試狀態**: ✅ 功能正常運作"""
|
||||||
|
|
||||||
from ..debug import debug_log
|
from ..debug import debug_log
|
||||||
|
|
||||||
|
@ -1624,3 +1624,287 @@ textarea:-ms-input-placeholder,
|
|||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== Markdown 內容樣式 ===== */
|
||||||
|
|
||||||
|
/* AI 摘要區域的 Markdown 樣式 - 基於 marked.js 官方樣式 */
|
||||||
|
/* 移除舊的衝突樣式,使用下方的 VSCode 風格樣式 */
|
||||||
|
|
||||||
|
/* Markdown 強調樣式 */
|
||||||
|
#summaryContent strong, #combinedSummaryContent strong {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent em, #combinedSummaryContent em {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown 刪除線樣式 */
|
||||||
|
#summaryContent del, #summaryContent s,
|
||||||
|
#combinedSummaryContent del, #combinedSummaryContent s {
|
||||||
|
text-decoration: line-through;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown 程式碼樣式 - 基於 marked.js 官方樣式 */
|
||||||
|
#summaryContent code, #combinedSummaryContent code {
|
||||||
|
padding: 0.2em 0.4em !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
font-size: 85% !important;
|
||||||
|
background-color: rgba(175, 184, 193, 0.2) !important;
|
||||||
|
border-radius: 3px !important;
|
||||||
|
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace !important;
|
||||||
|
color: var(--text-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent pre, #combinedSummaryContent pre {
|
||||||
|
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace !important;
|
||||||
|
padding: 16px !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
font-size: 85% !important;
|
||||||
|
line-height: 1.45 !important;
|
||||||
|
background-color: rgba(175, 184, 193, 0.1) !important;
|
||||||
|
border-radius: 3px !important;
|
||||||
|
margin: 16px 0 !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent pre code, #combinedSummaryContent pre code {
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
font-size: 100% !important;
|
||||||
|
color: var(--text-primary) !important;
|
||||||
|
display: block !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移除舊的列表樣式,使用下方的 VSCode 風格樣式 */
|
||||||
|
|
||||||
|
/* Markdown 引用區塊樣式 */
|
||||||
|
#summaryContent blockquote, #combinedSummaryContent blockquote {
|
||||||
|
border-left: 4px solid var(--accent-color);
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
background: rgba(0, 122, 204, 0.05);
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown 連結樣式 - 基於 marked.js 官方樣式 */
|
||||||
|
#summaryContent a, #combinedSummaryContent a {
|
||||||
|
color: #0366d6;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent a:hover, #combinedSummaryContent a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown 水平線樣式 - 基於 marked.js 官方樣式 */
|
||||||
|
#summaryContent hr, #combinedSummaryContent hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
margin: 24px 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 確保第一個元素沒有上邊距 */
|
||||||
|
#summaryContent > *:first-child, #combinedSummaryContent > *:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 確保最後一個元素沒有下邊距 */
|
||||||
|
#summaryContent > *:last-child, #combinedSummaryContent > *:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown 內容樣式 - VSCode 風格極緊湊樣式 */
|
||||||
|
#summaryContent, #combinedSummaryContent {
|
||||||
|
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol" !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
word-wrap: break-word !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 強制覆蓋所有子元素的行高和間距 */
|
||||||
|
#summaryContent *, #combinedSummaryContent * {
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent p, #combinedSummaryContent p {
|
||||||
|
margin: 0 !important;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 標題樣式 - VSCode 風格含底線 */
|
||||||
|
#summaryContent h1, #summaryContent h2, #summaryContent h3,
|
||||||
|
#summaryContent h4, #summaryContent h5, #summaryContent h6,
|
||||||
|
#combinedSummaryContent h1, #combinedSummaryContent h2, #combinedSummaryContent h3,
|
||||||
|
#combinedSummaryContent h4, #combinedSummaryContent h5, #combinedSummaryContent h6 {
|
||||||
|
color: var(--text-primary) !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent h1, #combinedSummaryContent h1 {
|
||||||
|
margin: 0.3em 0 0.1em 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 1.8em !important;
|
||||||
|
border-bottom: 2px solid var(--border-color) !important;
|
||||||
|
padding-bottom: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent h2, #combinedSummaryContent h2 {
|
||||||
|
margin: 0.25em 0 0.08em 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 1.5em !important;
|
||||||
|
border-bottom: 1px solid var(--border-color) !important;
|
||||||
|
padding-bottom: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent h3, #combinedSummaryContent h3 {
|
||||||
|
margin: 0.2em 0 0.03em 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 1.3em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent h4, #combinedSummaryContent h4 {
|
||||||
|
margin: 0.15em 0 0.02em 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 1.1em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent h5, #combinedSummaryContent h5,
|
||||||
|
#summaryContent h6, #combinedSummaryContent h6 {
|
||||||
|
margin: 0.1em 0 0.02em 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 1em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表樣式 - VSCode 風格極緊湊 */
|
||||||
|
#summaryContent ul, #combinedSummaryContent ul,
|
||||||
|
#summaryContent ol, #combinedSummaryContent ol {
|
||||||
|
margin: 0 !important;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
padding-left: 1.2em !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent li, #combinedSummaryContent li {
|
||||||
|
margin: 0 !important;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent li > ul, #combinedSummaryContent li > ul,
|
||||||
|
#summaryContent li > ol, #combinedSummaryContent li > ol {
|
||||||
|
margin: 0 !important;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
padding-left: 1.0em !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 強制段落後的列表緊密貼合 */
|
||||||
|
#summaryContent p + ul, #combinedSummaryContent p + ul,
|
||||||
|
#summaryContent p + ol, #combinedSummaryContent p + ol,
|
||||||
|
#summaryContent h1 + ul, #combinedSummaryContent h1 + ul,
|
||||||
|
#summaryContent h2 + ul, #combinedSummaryContent h2 + ul,
|
||||||
|
#summaryContent h3 + ul, #combinedSummaryContent h3 + ul,
|
||||||
|
#summaryContent h4 + ul, #combinedSummaryContent h4 + ul,
|
||||||
|
#summaryContent h1 + ol, #combinedSummaryContent h1 + ol,
|
||||||
|
#summaryContent h2 + ol, #combinedSummaryContent h2 + ol,
|
||||||
|
#summaryContent h3 + ol, #combinedSummaryContent h3 + ol,
|
||||||
|
#summaryContent h4 + ol, #combinedSummaryContent h4 + ol {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent blockquote, #combinedSummaryContent blockquote {
|
||||||
|
margin: 0.05em 0 !important;
|
||||||
|
padding: 0.1em 0.5em !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent pre, #combinedSummaryContent pre {
|
||||||
|
margin: 0.05em 0 !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 13px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent code, #combinedSummaryContent code {
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
font-size: 13px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown 表格樣式 - 適應主題顏色 */
|
||||||
|
#summaryContent table, #combinedSummaryContent table {
|
||||||
|
border-spacing: 0 !important;
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
display: table !important;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 0.5em 0 !important;
|
||||||
|
font-variant: tabular-nums !important;
|
||||||
|
border: 1px solid var(--border-color) !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
background-color: var(--bg-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent thead, #combinedSummaryContent thead {
|
||||||
|
display: table-header-group !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent tbody, #combinedSummaryContent tbody {
|
||||||
|
display: table-row-group !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent tr, #combinedSummaryContent tr {
|
||||||
|
display: table-row !important;
|
||||||
|
background-color: var(--bg-primary) !important;
|
||||||
|
border-top: 1px solid var(--border-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent tr:nth-child(2n), #combinedSummaryContent tr:nth-child(2n) {
|
||||||
|
background-color: var(--bg-secondary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent td, #summaryContent th,
|
||||||
|
#combinedSummaryContent td, #combinedSummaryContent th {
|
||||||
|
display: table-cell !important;
|
||||||
|
padding: 4px 8px !important;
|
||||||
|
border: 1px solid var(--border-color) !important;
|
||||||
|
text-align: left !important;
|
||||||
|
vertical-align: top !important;
|
||||||
|
color: var(--text-color) !important;
|
||||||
|
line-height: 1.3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent th, #combinedSummaryContent th {
|
||||||
|
font-weight: 600 !important;
|
||||||
|
background-color: var(--bg-secondary) !important;
|
||||||
|
border-bottom: 2px solid var(--border-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summaryContent td > *:last-child, #combinedSummaryContent td > *:last-child {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1222,6 +1222,7 @@
|
|||||||
|
|
||||||
// 更新 AI 摘要內容
|
// 更新 AI 摘要內容
|
||||||
if (self.uiManager) {
|
if (self.uiManager) {
|
||||||
|
// console.log('🔧 準備更新 AI 摘要內容,summary 長度:', sessionData.summary ? sessionData.summary.length : 'undefined');
|
||||||
self.uiManager.updateAISummaryContent(sessionData.summary);
|
self.uiManager.updateAISummaryContent(sessionData.summary);
|
||||||
self.uiManager.resetFeedbackForm();
|
self.uiManager.resetFeedbackForm();
|
||||||
self.uiManager.updateStatusIndicator();
|
self.uiManager.updateStatusIndicator();
|
||||||
|
@ -418,22 +418,69 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全地渲染 Markdown 內容
|
||||||
|
*/
|
||||||
|
UIManager.prototype.renderMarkdownSafely = function(content) {
|
||||||
|
try {
|
||||||
|
// 檢查 marked 和 DOMPurify 是否可用
|
||||||
|
if (typeof window.marked === 'undefined' || typeof window.DOMPurify === 'undefined') {
|
||||||
|
console.warn('⚠️ Markdown 庫未載入,使用純文字顯示');
|
||||||
|
return this.escapeHtml(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 marked 解析 Markdown
|
||||||
|
const htmlContent = window.marked.parse(content);
|
||||||
|
|
||||||
|
// 使用 DOMPurify 清理 HTML
|
||||||
|
const cleanHtml = window.DOMPurify.sanitize(htmlContent, {
|
||||||
|
ALLOWED_TAGS: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'br', 'strong', 'em', 'code', 'pre', 'ul', 'ol', 'li', 'blockquote', 'a', 'hr', 'del', 's', 'table', 'thead', 'tbody', 'tr', 'td', 'th'],
|
||||||
|
ALLOWED_ATTR: ['href', 'title', 'class', 'align', 'style'],
|
||||||
|
ALLOW_DATA_ATTR: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return cleanHtml;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Markdown 渲染失敗:', error);
|
||||||
|
return this.escapeHtml(content);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML 轉義函數
|
||||||
|
*/
|
||||||
|
UIManager.prototype.escapeHtml = function(text) {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新 AI 摘要內容
|
* 更新 AI 摘要內容
|
||||||
*/
|
*/
|
||||||
UIManager.prototype.updateAISummaryContent = function(summary) {
|
UIManager.prototype.updateAISummaryContent = function(summary) {
|
||||||
console.log('📝 更新 AI 摘要內容...');
|
console.log('📝 更新 AI 摘要內容...', '內容長度:', summary ? summary.length : 'undefined');
|
||||||
|
console.log('📝 marked 可用:', typeof window.marked !== 'undefined');
|
||||||
|
console.log('📝 DOMPurify 可用:', typeof window.DOMPurify !== 'undefined');
|
||||||
|
|
||||||
|
// 渲染 Markdown 內容
|
||||||
|
const renderedContent = this.renderMarkdownSafely(summary);
|
||||||
|
console.log('📝 渲染後內容長度:', renderedContent ? renderedContent.length : 'undefined');
|
||||||
|
|
||||||
const summaryContent = Utils.safeQuerySelector('#summaryContent');
|
const summaryContent = Utils.safeQuerySelector('#summaryContent');
|
||||||
if (summaryContent) {
|
if (summaryContent) {
|
||||||
summaryContent.textContent = summary;
|
summaryContent.innerHTML = renderedContent;
|
||||||
console.log('✅ 已更新分頁模式摘要內容');
|
console.log('✅ 已更新分頁模式摘要內容(Markdown 渲染)');
|
||||||
|
} else {
|
||||||
|
console.warn('⚠️ 找不到 #summaryContent 元素');
|
||||||
}
|
}
|
||||||
|
|
||||||
const combinedSummaryContent = Utils.safeQuerySelector('#combinedSummaryContent');
|
const combinedSummaryContent = Utils.safeQuerySelector('#combinedSummaryContent');
|
||||||
if (combinedSummaryContent) {
|
if (combinedSummaryContent) {
|
||||||
combinedSummaryContent.textContent = summary;
|
combinedSummaryContent.innerHTML = renderedContent;
|
||||||
console.log('✅ 已更新合併模式摘要內容');
|
console.log('✅ 已更新合併模式摘要內容(Markdown 渲染)');
|
||||||
|
} else {
|
||||||
|
console.warn('⚠️ 找不到 #combinedSummaryContent 元素');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -563,7 +563,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div id="summaryContent" class="text-input" style="min-height: 300px; white-space: pre-wrap !important; cursor: text; padding: 12px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word;" data-dynamic-content="aiSummary">
|
<div id="summaryContent" class="text-input" style="min-height: 300px; cursor: text; padding: 12px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word;" data-dynamic-content="aiSummary">
|
||||||
{{ summary }}
|
{{ summary }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -607,7 +607,7 @@
|
|||||||
<h3 class="combined-section-title" data-i18n="combined.summaryTitle">📋 AI 工作摘要</h3>
|
<h3 class="combined-section-title" data-i18n="combined.summaryTitle">📋 AI 工作摘要</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="combined-summary">
|
<div class="combined-summary">
|
||||||
<div id="combinedSummaryContent" class="text-input" style="min-height: 200px; white-space: pre-wrap !important; cursor: text; padding: 12px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word;" data-dynamic-content="aiSummary">{{ summary }}</div>
|
<div id="combinedSummaryContent" class="text-input" style="min-height: 200px; cursor: text; padding: 12px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word;" data-dynamic-content="aiSummary">{{ summary }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1096,6 +1096,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- WebSocket 和 JavaScript -->
|
<!-- WebSocket 和 JavaScript -->
|
||||||
|
<!-- Markdown 支援庫 -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked@14.1.3/marked.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.2/dist/purify.min.js"></script>
|
||||||
<script src="/static/js/i18n.js?v=2025010510"></script>
|
<script src="/static/js/i18n.js?v=2025010510"></script>
|
||||||
<!-- 載入所有模組 -->
|
<!-- 載入所有模組 -->
|
||||||
<!-- 核心模組(最先載入) -->
|
<!-- 核心模組(最先載入) -->
|
||||||
@ -1140,6 +1143,14 @@
|
|||||||
async function initializeApp() {
|
async function initializeApp() {
|
||||||
const sessionId = '{{ session_id }}';
|
const sessionId = '{{ session_id }}';
|
||||||
|
|
||||||
|
// 檢查 Markdown 依賴庫
|
||||||
|
if (typeof window.marked === 'undefined' || typeof window.DOMPurify === 'undefined') {
|
||||||
|
const logger = window.MCPFeedback?.logger || console;
|
||||||
|
logger.warn('Markdown 依賴庫尚未載入,等待中...');
|
||||||
|
setTimeout(initializeApp, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 檢查核心依賴
|
// 檢查核心依賴
|
||||||
const requiredModules = [
|
const requiredModules = [
|
||||||
'MCPFeedback',
|
'MCPFeedback',
|
||||||
@ -1193,6 +1204,20 @@
|
|||||||
window.MCPFeedback.app = window.feedbackApp;
|
window.MCPFeedback.app = window.feedbackApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化完成後,立即渲染現有的 AI 摘要內容為 Markdown
|
||||||
|
setTimeout(function() {
|
||||||
|
if (window.feedbackApp && window.feedbackApp.uiManager) {
|
||||||
|
// 獲取當前的摘要內容
|
||||||
|
const summaryElement = document.querySelector('#combinedSummaryContent');
|
||||||
|
const summaryTabElement = document.querySelector('#summaryContent');
|
||||||
|
|
||||||
|
if (summaryElement && summaryElement.textContent) {
|
||||||
|
console.log('🔧 初始化時渲染 Markdown 內容...');
|
||||||
|
window.feedbackApp.uiManager.updateAISummaryContent(summaryElement.textContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
logger.info('應用程式初始化完成');
|
logger.info('應用程式初始化完成');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const logger = window.MCPFeedback?.logger || console;
|
const logger = window.MCPFeedback?.logger || console;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user