( tools: RenderableTool[] )
| 77 | } |
| 78 | |
| 79 | export function renderToolsHtml( |
| 80 | tools: RenderableTool[] |
| 81 | ): string { |
| 82 | if (tools.length === 0) { |
| 83 | return ` |
| 84 | <div class="empty-state"> |
| 85 | <h3>No tools found</h3> |
| 86 | <p>Try a different category or clear the current filters</p> |
| 87 | </div> |
| 88 | `; |
| 89 | } |
| 90 | |
| 91 | return tools |
| 92 | .map((tool) => { |
| 93 | const badges: string[] = []; |
| 94 | if (tool.featured) { |
| 95 | badges.push('<span class="tool-badge featured">Featured</span>'); |
| 96 | } |
| 97 | badges.push( |
| 98 | `<span class="tool-badge category">${escapeHtml(tool.category)}</span>` |
| 99 | ); |
| 100 | |
| 101 | const features = |
| 102 | tool.features && tool.features.length > 0 |
| 103 | ? `<div class="tool-section"> |
| 104 | <h3>Features</h3> |
| 105 | <ul>${tool.features |
| 106 | .map((feature) => `<li>${escapeHtml(feature)}</li>`) |
| 107 | .join("")}</ul> |
| 108 | </div>` |
| 109 | : ""; |
| 110 | |
| 111 | const requirements = |
| 112 | tool.requirements && tool.requirements.length > 0 |
| 113 | ? `<div class="tool-section"> |
| 114 | <h3>Requirements</h3> |
| 115 | <ul>${tool.requirements |
| 116 | .map((requirement) => `<li>${escapeHtml(requirement)}</li>`) |
| 117 | .join("")}</ul> |
| 118 | </div>` |
| 119 | : ""; |
| 120 | |
| 121 | const tags = |
| 122 | tool.tags && tool.tags.length > 0 |
| 123 | ? `<div class="tool-tags"> |
| 124 | ${tool.tags |
| 125 | .map((tag) => `<span class="tool-tag">${escapeHtml(tag)}</span>`) |
| 126 | .join("")} |
| 127 | </div>` |
| 128 | : ""; |
| 129 | |
| 130 | const config = tool.configuration |
| 131 | ? `<div class="tool-config"> |
| 132 | <h3>Configuration</h3> |
| 133 | <div class="tool-config-wrapper"> |
| 134 | <pre><code>${escapeHtml(tool.configuration.content)}</code></pre> |
| 135 | </div> |
| 136 | <button class="copy-config-btn" data-config="${encodeURIComponent( |
no test coverage detected