entari-plugin-hyw 3.5.0rc1__py3-none-any.whl → 3.5.0rc2__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 entari-plugin-hyw might be problematic. Click here for more details.
- entari_plugin_hyw/__init__.py +77 -82
- entari_plugin_hyw/assets/card-dist/index.html +360 -99
- entari_plugin_hyw/card-ui/src/App.vue +246 -52
- entari_plugin_hyw/card-ui/src/components/MarkdownContent.vue +122 -67
- entari_plugin_hyw/card-ui/src/components/StageCard.vue +46 -26
- entari_plugin_hyw/card-ui/src/test_regex.js +103 -0
- entari_plugin_hyw/card-ui/src/types.ts +1 -0
- entari_plugin_hyw/{core/history.py → history.py} +25 -1
- entari_plugin_hyw/image_cache.py +283 -0
- entari_plugin_hyw/{core/pipeline.py → pipeline.py} +102 -27
- entari_plugin_hyw/{utils/prompts.py → prompts.py} +7 -24
- entari_plugin_hyw/render_vue.py +314 -0
- entari_plugin_hyw/{utils/search.py → search.py} +227 -10
- {entari_plugin_hyw-3.5.0rc1.dist-info → entari_plugin_hyw-3.5.0rc2.dist-info}/METADATA +1 -1
- {entari_plugin_hyw-3.5.0rc1.dist-info → entari_plugin_hyw-3.5.0rc2.dist-info}/RECORD +18 -29
- entari_plugin_hyw/core/__init__.py +0 -0
- entari_plugin_hyw/core/config.py +0 -35
- entari_plugin_hyw/core/hyw.py +0 -48
- entari_plugin_hyw/core/render_vue.py +0 -255
- entari_plugin_hyw/test_output/render_0.jpg +0 -0
- entari_plugin_hyw/test_output/render_1.jpg +0 -0
- entari_plugin_hyw/test_output/render_2.jpg +0 -0
- entari_plugin_hyw/test_output/render_3.jpg +0 -0
- entari_plugin_hyw/test_output/render_4.jpg +0 -0
- entari_plugin_hyw/tests/ui_test_output.jpg +0 -0
- entari_plugin_hyw/tests/verify_ui.py +0 -139
- entari_plugin_hyw/utils/__init__.py +0 -2
- entari_plugin_hyw/utils/browser.py +0 -40
- entari_plugin_hyw/utils/playwright_tool.py +0 -36
- /entari_plugin_hyw/{utils/misc.py → misc.py} +0 -0
- {entari_plugin_hyw-3.5.0rc1.dist-info → entari_plugin_hyw-3.5.0rc2.dist-info}/WHEEL +0 -0
- {entari_plugin_hyw-3.5.0rc1.dist-info → entari_plugin_hyw-3.5.0rc2.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed, onMounted } from 'vue'
|
|
3
3
|
import { Icon } from '@iconify/vue'
|
|
4
|
+
|
|
4
5
|
import type { RenderData } from './types'
|
|
5
6
|
import StageCard from './components/StageCard.vue'
|
|
6
7
|
import MarkdownContent from './components/MarkdownContent.vue'
|
|
7
8
|
|
|
9
|
+
// Get icon for card type
|
|
10
|
+
const getCardIcon = (contentType?: string): string => {
|
|
11
|
+
switch (contentType) {
|
|
12
|
+
case 'summary': return 'mdi:file-document-outline'
|
|
13
|
+
case 'code': return 'mdi:code-braces'
|
|
14
|
+
case 'table': return 'mdi:table'
|
|
15
|
+
default: return 'mdi:card-outline'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Get display label for card
|
|
20
|
+
const getCardLabel = (contentType?: string, language?: string): string => {
|
|
21
|
+
switch (contentType) {
|
|
22
|
+
case 'summary': return 'Summary'
|
|
23
|
+
case 'code': return language ? language.charAt(0).toUpperCase() + language.slice(1) : 'Code'
|
|
24
|
+
case 'table': return 'Table'
|
|
25
|
+
default: return ''
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
8
29
|
declare global {
|
|
9
30
|
interface Window {
|
|
10
31
|
RENDER_DATA: RenderData
|
|
@@ -22,6 +43,19 @@ window.updateRenderData = (newData: RenderData) => {
|
|
|
22
43
|
const numSearchRefs = computed(() => data.value?.references?.length || 0)
|
|
23
44
|
const numPageRefs = computed(() => data.value?.page_references?.length || 0)
|
|
24
45
|
|
|
46
|
+
// Calculate the reference offset for each stage (for unified badge numbering)
|
|
47
|
+
const getRefOffset = (stageIndex: number): number => {
|
|
48
|
+
if (!data.value?.stages) return 0
|
|
49
|
+
let offset = 0
|
|
50
|
+
for (let i = 0; i < stageIndex; i++) {
|
|
51
|
+
const stage = data.value.stages[i]
|
|
52
|
+
if (stage) {
|
|
53
|
+
offset += (stage.references?.length || 0) + (stage.crawled_pages?.length || 0)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return offset
|
|
57
|
+
}
|
|
58
|
+
|
|
25
59
|
// Helper: Strips content before the first H1 heading (e.g., AI "thought" prefixes)
|
|
26
60
|
const stripPrefixBeforeH1 = (text: string): string => {
|
|
27
61
|
// Find the first line starting with "# " (H1)
|
|
@@ -40,12 +74,64 @@ const mainTitle = computed(() => {
|
|
|
40
74
|
const match = md.match(/^#\s+(.+)$/m)
|
|
41
75
|
return match && match[1] ? match[1].trim() : ''
|
|
42
76
|
})
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
77
|
+
|
|
78
|
+
// Process title to support <u> underline tags
|
|
79
|
+
const processedTitle = computed(() => {
|
|
80
|
+
return mainTitle.value.replace(/<u>([^<]*)<\/u>/g, (_, content) => {
|
|
81
|
+
return `<span class="underline decoration-[5px] underline-offset-8" style="text-decoration-color: var(--theme-color)">${content}</span>`
|
|
82
|
+
})
|
|
46
83
|
})
|
|
47
84
|
|
|
48
85
|
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
const dedent = (text: string) => {
|
|
89
|
+
const lines = text.split('\n')
|
|
90
|
+
// Find minimum indentation of non-empty lines
|
|
91
|
+
let minIndent = Infinity
|
|
92
|
+
for (const line of lines) {
|
|
93
|
+
if (line.trim().length === 0) continue
|
|
94
|
+
const leadingSpace = line.match(/^\s*/)?.[0].length || 0
|
|
95
|
+
if (leadingSpace < minIndent) minIndent = leadingSpace
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (minIndent === Infinity || minIndent === 0) return text
|
|
99
|
+
|
|
100
|
+
return lines.map(line => {
|
|
101
|
+
if (line.trim().length === 0) return ''
|
|
102
|
+
return line.substring(minIndent)
|
|
103
|
+
}).join('\n')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
const themeColor = computed(() => data.value?.theme_color || '#ef4444')
|
|
108
|
+
|
|
109
|
+
// Calculate relative luminance to determine if color is light or dark
|
|
110
|
+
const getLuminance = (hex: string): number => {
|
|
111
|
+
const match = hex.replace('#', '').match(/.{2}/g)
|
|
112
|
+
if (!match) return 0
|
|
113
|
+
const [r, g, b] = match.map(x => {
|
|
114
|
+
const c = parseInt(x, 16) / 255
|
|
115
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
|
|
116
|
+
})
|
|
117
|
+
return 0.2126 * (r ?? 0) + 0.7152 * (g ?? 0) + 0.0722 * (b ?? 0)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Auto text color: dark text on light bg, white text on dark bg
|
|
121
|
+
const headerTextColor = computed(() => {
|
|
122
|
+
const luminance = getLuminance(themeColor.value)
|
|
123
|
+
return luminance > 0.4 ? '#1f2937' : '#ffffff' // gray-800 or white
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const themeStyle = computed(() => ({
|
|
127
|
+
'--theme-color': themeColor.value,
|
|
128
|
+
'--header-text-color': headerTextColor.value,
|
|
129
|
+
'--text-muted': '#4b5563', // gray-600, higher contrast for mobile
|
|
130
|
+
'--border-color': '#e5e7eb', // gray-200, for borders
|
|
131
|
+
'--bg-subtle': '#f9fafb' // gray-50, for subtle backgrounds
|
|
132
|
+
}))
|
|
133
|
+
|
|
134
|
+
|
|
49
135
|
const parsedSections = computed(() => {
|
|
50
136
|
const rawMd = data.value?.markdown || ''
|
|
51
137
|
if (!rawMd) return []
|
|
@@ -58,11 +144,12 @@ const parsedSections = computed(() => {
|
|
|
58
144
|
content = content.replace(/(?:^|\n)\s*(?:#{1,3}|\*\*)\s*(?:References|Citations|Sources)[\s\S]*$/i, '')
|
|
59
145
|
content = content.trim()
|
|
60
146
|
|
|
61
|
-
const sections: Array<{ type: 'markdown' | 'card', content: string, title?: string, contentType?: 'table' | 'code', language?: string }> = []
|
|
147
|
+
const sections: Array<{ type: 'markdown' | 'card', content: string, title?: string, contentType?: 'table' | 'code' | 'summary', language?: string }> = []
|
|
62
148
|
|
|
63
149
|
// Combine regex involves complexity, so we'll use a tokenizer approach
|
|
64
150
|
// split tokens by Code Block or Table
|
|
65
|
-
|
|
151
|
+
// split tokens by Code Block or Table or Summary
|
|
152
|
+
const combinedRegex = /(```[\s\S]*?```|((?:^|\n)\|[^\n]*\|(?:\n\|[^\n]*\|)*)|<summary>[\s\S]*?<\/summary>)/
|
|
66
153
|
|
|
67
154
|
let remaining = content
|
|
68
155
|
|
|
@@ -85,20 +172,28 @@ const parsedSections = computed(() => {
|
|
|
85
172
|
|
|
86
173
|
// Determine type
|
|
87
174
|
const isCode = matchedStr.startsWith('```')
|
|
175
|
+
const isSummary = matchedStr.startsWith('<summary>')
|
|
88
176
|
// Tables might match with a leading newline, trim it for checking but render carefully
|
|
89
|
-
const isTable = !isCode && matchedStr.trim().startsWith('|')
|
|
177
|
+
const isTable = !isCode && !isSummary && matchedStr.trim().startsWith('|')
|
|
90
178
|
|
|
91
|
-
if (isCode || isTable) {
|
|
179
|
+
if (isCode || isTable || isSummary) {
|
|
92
180
|
let language = ''
|
|
181
|
+
let content = matchedStr.trim()
|
|
182
|
+
|
|
93
183
|
if (isCode) {
|
|
94
184
|
const match = matchedStr.match(/^```(\w+)/)
|
|
95
185
|
if (match && match[1]) language = match[1]
|
|
186
|
+
} else if (isSummary) {
|
|
187
|
+
// Strip tags
|
|
188
|
+
content = content.replace(/^<summary>/, '').replace(/<\/summary>$/, '')
|
|
189
|
+
content = dedent(content)
|
|
96
190
|
}
|
|
191
|
+
|
|
97
192
|
sections.push({
|
|
98
193
|
type: 'card',
|
|
99
|
-
title: isCode ? 'Code' : 'Table',
|
|
100
|
-
content:
|
|
101
|
-
contentType: isCode ? 'code' : 'table',
|
|
194
|
+
title: isCode ? 'Code' : (isSummary ? 'Summary' : 'Table'),
|
|
195
|
+
content: content,
|
|
196
|
+
contentType: isCode ? 'code' : (isSummary ? 'summary' : 'table'),
|
|
102
197
|
language: language
|
|
103
198
|
})
|
|
104
199
|
} else {
|
|
@@ -116,36 +211,131 @@ onMounted(() => {
|
|
|
116
211
|
if (window.RENDER_DATA && Object.keys(window.RENDER_DATA).length > 0) {
|
|
117
212
|
data.value = window.RENDER_DATA
|
|
118
213
|
} else {
|
|
214
|
+
// Demo data for development preview
|
|
119
215
|
data.value = {
|
|
120
|
-
markdown:
|
|
121
|
-
|
|
216
|
+
markdown: `# 终极硬核整合包格雷科技新视野
|
|
217
|
+
|
|
218
|
+
<summary>
|
|
219
|
+
《格雷科技:新视野》(GregTech: New Horizons,简称 GTNH)是一款基于 Minecraft 1.7.10 版本的深度硬核科技向整合包。它以 GregTech 5 Unofficial 为核心,通过超过 8 年的持续开发,将 300 多个模组深度集成,构建了极其严苛且逻辑严密的科技树,是公认的生存挑战巅峰之作。
|
|
220
|
+
</summary>
|
|
221
|
+
|
|
222
|
+
## 核心机制与游戏体验
|
|
223
|
+
GTNH 的核心在于"格雷化"改造,几乎所有模组的合成表都经过重新设计,以匹配其严苛的阶级制度 [4][8]。玩家需要从原始的石器时代开始,历经蒸汽时代、电力时代,最终向星际航行迈进。其游戏过程极其漫长,旨在让玩家在每一毫秒的进度中感受工业发展的成就感 [3][7]。
|
|
224
|
+
|
|
225
|
+

|
|
226
|
+
|
|
227
|
+
## 科技阶层与任务系统
|
|
228
|
+
整合包拥有 15 个清晰的科技等级(Tiers),最终目标是建造"星门"(Stargate)[2]。为了引导玩家不迷失在复杂的工业流程中,GTNH 内置了超过 3900 条任务的巨型任务书,涵盖了从基础生存到高阶多方块结构的详细指导 [4][7]。
|
|
229
|
+
|
|
230
|
+
- 15 个科技等级
|
|
231
|
+
- 任务数量:3900+
|
|
232
|
+
- 最终目标:建造"星门"
|
|
233
|
+
|
|
234
|
+
> 机动战士高达系列是日本动画史上最具影响力的动画作品之一,深受全球观众的喜爱。
|
|
235
|
+
|
|
236
|
+
| 特性 | 详细描述 |
|
|
237
|
+
| :--- | :--- |
|
|
238
|
+
| **基础版本** | Minecraft 1.7.10 (高度优化) |
|
|
239
|
+
| **任务数量** | 3900+ 任务引导 [7] |
|
|
240
|
+
| **科技阶层** | 15 个技术等级 [2] |
|
|
241
|
+
| **核心模组** | GregTech 5 Unofficial, Thaumcraft 等 [8] |
|
|
242
|
+
|
|
243
|
+
## 安装与运行建议
|
|
244
|
+
由于其高度集成的特性,官方强烈建议使用 **Prism Launcher** 进行安装和管理 [5]。在运行环境方面,虽然基于旧版 MC,但通过社区努力,目前推荐使用 **Java 17-25** 版本以获得最佳的内存管理和性能优化,确保大型自动化工厂运行流畅 [5]。
|
|
245
|
+
|
|
246
|
+
\`\`\`bash
|
|
247
|
+
curl -s https://raw.githubusercontent.com/GTNewHorizons/GT-New-Horizons-Modpack/master/README.md
|
|
248
|
+
java -version
|
|
249
|
+
java -Xmx1024M -Xms1024M -jar prism-launcher.jar
|
|
250
|
+
\`\`\``,
|
|
251
|
+
total_time: 8.5,
|
|
122
252
|
stages: [
|
|
123
|
-
{
|
|
253
|
+
{
|
|
254
|
+
name: 'instruct',
|
|
255
|
+
model: 'qwen/qwen3-235b-a22b-2507',
|
|
256
|
+
provider: 'Qwen',
|
|
257
|
+
time: 1.83,
|
|
258
|
+
cost: 0.0002,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: 'search',
|
|
262
|
+
model: '',
|
|
263
|
+
provider: '',
|
|
264
|
+
time: 0.5,
|
|
265
|
+
cost: 0.0,
|
|
266
|
+
references: [
|
|
267
|
+
{ title: 'GTNH 2025 Server Information', url: 'https://stonelegion.com/mc-gtnh-2026/' },
|
|
268
|
+
{ title: 'GT New Horizons Wiki', url: 'https://gtnh.miraheze.org/wiki/Main_Page' },
|
|
269
|
+
{ title: 'GT New Horizons - GitHub', url: 'https://github.com/GTNewHorizons/GT-New-Horizons-Modpack' },
|
|
270
|
+
{ title: 'GT New Horizons - CurseForge', url: 'https://www.curseforge.com/minecraft/modpacks/gt-new-horizons' },
|
|
271
|
+
{ title: 'Installing and Migrating - GTNH', url: 'https://gtnh.miraheze.org/wiki/Installing_and_Migrating' },
|
|
272
|
+
{ title: 'Modlist - GT New Horizons', url: 'https://wiki.gtnewhorizons.com/wiki/Modlist' },
|
|
273
|
+
{ title: 'GregTech: New Horizons - Home', url: 'https://www.gtnewhorizons.com/' },
|
|
274
|
+
{ title: 'GT New Horizons - FTB Wiki', url: 'https://ftb.fandom.com/wiki/GT_New_Horizons' }
|
|
275
|
+
],
|
|
276
|
+
image_references: [
|
|
277
|
+
{ title: 'GTNH Live Lets Play', url: 'https://i.ytimg.com/vi/5T-oSWAgaMM/maxresdefault.jpg', thumbnail: 'https://tse4.mm.bing.net/th/id/OIP.b_56VnY4nyrzeqp1JetmFQHaEK?pid=Api' },
|
|
278
|
+
{ title: 'GTNH Modpack Cover', url: 'https://i.mcmod.cn/modpack/cover/20240113/1705139595_29797_dSkE.jpg', thumbnail: 'https://tse1.mm.bing.net/th/id/OIP.KNKaZX1d_4Ueq6vpl1qJNAHaEo?pid=Api' },
|
|
279
|
+
{ title: 'GTNH Steam Age', url: 'https://i.ytimg.com/vi/8IPwXxqB71w/maxresdefault.jpg', thumbnail: 'https://tse4.mm.bing.net/th/id/OIP.P-KrnI4GBH21yPgwpNPSzAHaEK?pid=Api' },
|
|
280
|
+
{ title: 'GTNH MCMod Cover', url: 'https://i.mcmod.cn/post/cover/20230201/1675241030_2_VqDc.jpg', thumbnail: 'https://tse2.mm.bing.net/th/id/OIP.GvYz7YWrg-fnpAHjOiW3OAHaEo?pid=Api' },
|
|
281
|
+
{ title: 'GTNH Tectech Tutorial', url: 'http://i0.hdslb.com/bfs/archive/1ed1e53341fd44018138f2823b2fe6c499fb9c9c.jpg', thumbnail: 'https://tse4.mm.bing.net/th/id/OIP.0Wg7xFHTjhxIV9hKuUo4xwHaEo?pid=Api' }
|
|
282
|
+
]
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: 'crawler',
|
|
286
|
+
model: '',
|
|
287
|
+
provider: '',
|
|
288
|
+
time: 2.5,
|
|
289
|
+
cost: 0.0,
|
|
290
|
+
crawled_pages: [
|
|
291
|
+
{ title: 'GregTech: New Horizons Official Wiki', url: 'https://gtnh.miraheze.org/wiki/Main_Page' },
|
|
292
|
+
{ title: 'GT New Horizons Modpack Download', url: 'https://www.curseforge.com/minecraft/modpacks/gt-new-horizons' },
|
|
293
|
+
{ title: 'Installing and Migrating Guide', url: 'https://gtnh.miraheze.org/wiki/Installing_and_Migrating' }
|
|
294
|
+
]
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
name: 'agent',
|
|
298
|
+
model: 'google/gemini-3-flash-preview',
|
|
299
|
+
provider: 'Google',
|
|
300
|
+
time: 13.0,
|
|
301
|
+
cost: 0.0018,
|
|
302
|
+
}
|
|
303
|
+
],
|
|
304
|
+
references: [
|
|
305
|
+
{ title: 'GTNH 2025 Server Information', url: 'https://stonelegion.com/mc-gtnh-2026/' },
|
|
306
|
+
{ title: 'GT New Horizons Wiki', url: 'https://gtnh.miraheze.org/wiki/Main_Page' },
|
|
307
|
+
{ title: 'GT New Horizons - GitHub', url: 'https://github.com/GTNewHorizons/GT-New-Horizons-Modpack' },
|
|
308
|
+
{ title: 'GT New Horizons - CurseForge', url: 'https://www.curseforge.com/minecraft/modpacks/gt-new-horizons' },
|
|
309
|
+
{ title: 'Installing and Migrating - GTNH', url: 'https://gtnh.miraheze.org/wiki/Installing_and_Migrating' },
|
|
310
|
+
{ title: 'Modlist - GT New Horizons', url: 'https://wiki.gtnewhorizons.com/wiki/Modlist' },
|
|
311
|
+
{ title: 'GregTech: New Horizons - Home', url: 'https://www.gtnewhorizons.com/' },
|
|
312
|
+
{ title: 'GT New Horizons - FTB Wiki', url: 'https://ftb.fandom.com/wiki/GT_New_Horizons' }
|
|
124
313
|
],
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
314
|
+
page_references: [
|
|
315
|
+
{ title: 'GregTech: New Horizons Official Wiki', url: 'https://gtnh.miraheze.org/wiki/Main_Page' },
|
|
316
|
+
{ title: 'GT New Horizons Modpack Download', url: 'https://www.curseforge.com/minecraft/modpacks/gt-new-horizons' }
|
|
317
|
+
],
|
|
318
|
+
image_references: [
|
|
319
|
+
{ title: 'GTNH Live Lets Play', url: 'https://i.ytimg.com/vi/5T-oSWAgaMM/maxresdefault.jpg', thumbnail: 'https://tse4.mm.bing.net/th/id/OIP.b_56VnY4nyrzeqp1JetmFQHaEK?pid=Api' },
|
|
320
|
+
{ title: 'GTNH Modpack Cover', url: 'https://i.mcmod.cn/modpack/cover/20240113/1705139595_29797_dSkE.jpg', thumbnail: 'https://tse1.mm.bing.net/th/id/OIP.KNKaZX1d_4Ueq6vpl1qJNAHaEo?pid=Api' },
|
|
321
|
+
{ title: 'GTNH Steam Age', url: 'https://i.ytimg.com/vi/8IPwXxqB71w/maxresdefault.jpg', thumbnail: 'https://tse4.mm.bing.net/th/id/OIP.P-KrnI4GBH21yPgwpNPSzAHaEK?pid=Api' }
|
|
322
|
+
],
|
|
323
|
+
stats: { total_time: 8.5 },
|
|
324
|
+
theme_color: '#ef4444'
|
|
129
325
|
}
|
|
130
326
|
}
|
|
131
327
|
})
|
|
132
328
|
</script>
|
|
133
329
|
|
|
134
330
|
<template>
|
|
135
|
-
<div class="min-h-screen bg-[#f2f2f2] flex justify-center
|
|
331
|
+
<div class="min-h-screen bg-[#f2f2f2] flex justify-center" :style="themeStyle">
|
|
136
332
|
<!-- Main container with explicit background for screenshot capture -->
|
|
137
|
-
<div id="main-container" class="w-
|
|
333
|
+
<div id="main-container" class="w-[540px] pt-16 pb-28 space-y-8 !bg-[#f2f2f2]" data-theme="light">
|
|
138
334
|
|
|
139
335
|
<!-- Title -->
|
|
140
|
-
<header v-if="mainTitle" class="px-
|
|
141
|
-
|
|
142
|
-
<h1 class="text-
|
|
143
|
-
{{ mainTitle }}
|
|
144
|
-
</h1>
|
|
145
|
-
<div class="mt-2 text-[10px] font-mono text-gray-900 tracking-widest flex items-center justify-end gap-2">
|
|
146
|
-
Report by {{ agentModel }}
|
|
147
|
-
<span class="w-2 h-2 bg-red-500"></span>
|
|
148
|
-
</div>
|
|
336
|
+
<header v-if="mainTitle" class="px-6 mb-8">
|
|
337
|
+
<!-- Removed Time/Icon Badge as requested -->
|
|
338
|
+
<h1 class="text-4xl font-black text-gray-800 leading-tight tracking-tighter uppercase tabular-nums" v-html="processedTitle"></h1>
|
|
149
339
|
</header>
|
|
150
340
|
|
|
151
341
|
<!-- Content Sections -->
|
|
@@ -157,24 +347,28 @@ onMounted(() => {
|
|
|
157
347
|
:markdown="section.content"
|
|
158
348
|
:num-search-refs="numSearchRefs"
|
|
159
349
|
:num-page-refs="numPageRefs"
|
|
160
|
-
class="prose-h2:text-
|
|
350
|
+
class="prose-h2:text-[26px] prose-h2:font-black prose-h2:uppercase prose-h2:tracking-tight prose-h2:mb-4 prose-h2:text-gray-800"
|
|
161
351
|
/>
|
|
162
352
|
</div>
|
|
163
353
|
|
|
164
|
-
<!-- Special Card (Table/Code) -->
|
|
165
|
-
<div v-else-if="section.type === 'card'" class="mx-6">
|
|
166
|
-
<!--
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<div v-if="section.language" class="text-gray-600 text-[9px] font-mono tabular-nums tracking-tighter">
|
|
174
|
-
{{ section.language }}
|
|
175
|
-
</div>
|
|
354
|
+
<!-- Special Card (Table/Code/Summary) -->
|
|
355
|
+
<div v-else-if="section.type === 'card'" class="mx-6 relative">
|
|
356
|
+
<!-- Corner Rectangle Badge with Icon and Label -->
|
|
357
|
+
<div
|
|
358
|
+
class="absolute -top-2 -left-2 h-7 px-2.5 z-10 flex items-center gap-1.5"
|
|
359
|
+
:style="{ backgroundColor: themeColor, color: headerTextColor, boxShadow: '0 2px 4px 0 rgba(0,0,0,0.15)' }"
|
|
360
|
+
>
|
|
361
|
+
<Icon :icon="getCardIcon(section.contentType)" class="text-base" />
|
|
362
|
+
<span class="text-xs font-bold uppercase tracking-wide">{{ getCardLabel(section.contentType, section.language) }}</span>
|
|
176
363
|
</div>
|
|
177
|
-
<div
|
|
364
|
+
<div
|
|
365
|
+
class="shadow-sm shadow-black/10 bg-white"
|
|
366
|
+
:class="[
|
|
367
|
+
section.contentType === 'summary' ? 'pt-8 px-5 pb-3 text-base leading-relaxed' : '',
|
|
368
|
+
section.contentType === 'code' ? 'pt-7 pb-2' : '',
|
|
369
|
+
section.contentType === 'table' ? 'pt-5' : ''
|
|
370
|
+
]"
|
|
371
|
+
>
|
|
178
372
|
<MarkdownContent
|
|
179
373
|
:markdown="section.content"
|
|
180
374
|
:bare="true"
|
|
@@ -187,17 +381,16 @@ onMounted(() => {
|
|
|
187
381
|
</template>
|
|
188
382
|
|
|
189
383
|
<!-- Workflow -->
|
|
190
|
-
<div v-if="data?.stages?.length" class="mx-6">
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
<
|
|
197
|
-
|
|
198
|
-
</div>
|
|
384
|
+
<div v-if="data?.stages?.length" class="mx-6 relative">
|
|
385
|
+
<!-- Corner Rectangle Badge with Icon and Label -->
|
|
386
|
+
<div
|
|
387
|
+
class="absolute -top-2 -left-2 h-7 px-2.5 z-10 flex items-center gap-1.5"
|
|
388
|
+
:style="{ backgroundColor: themeColor, color: headerTextColor, boxShadow: '0 2px 4px 0 rgba(0,0,0,0.15)' }"
|
|
389
|
+
>
|
|
390
|
+
<Icon icon="mdi:link-variant" class="text-base" />
|
|
391
|
+
<span class="text-xs font-bold uppercase tracking-wide">Flow</span>
|
|
199
392
|
</div>
|
|
200
|
-
<div class="p-
|
|
393
|
+
<div class="p-2 pt-5 bg-white shadow-sm shadow-black/10">
|
|
201
394
|
<StageCard
|
|
202
395
|
v-for="(stage, index) in data.stages"
|
|
203
396
|
:key="index"
|
|
@@ -205,6 +398,7 @@ onMounted(() => {
|
|
|
205
398
|
:is-first="index === 0"
|
|
206
399
|
:is-last="index === data.stages.length - 1"
|
|
207
400
|
:prev-stage-name="index > 0 ? data.stages[index - 1]?.name : undefined"
|
|
401
|
+
:ref-offset="getRefOffset(index)"
|
|
208
402
|
/>
|
|
209
403
|
</div>
|
|
210
404
|
</div>
|