Files
wehub-resource-sync 0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:24:08 +08:00

195 lines
6.8 KiB
TypeScript

import React from 'react';
import { PLUGIN_CATEGORIES, PLUGINS } from './data/plugins';
import { getCategoryAnchor } from './utils/categoryUtils';
import type { Plugin, PluginCategory } from './data/plugins';
type GroupedPlugins = Record<PluginCategory, Plugin[]>;
interface PluginTableProps {
vulnerabilityType?: string;
shouldRenderCategory?: boolean;
shouldRenderDescription?: boolean;
shouldRenderPluginId?: boolean;
shouldGroupByCategory?: boolean;
showApplicationTypes?: boolean;
showRemoteStatus?: boolean;
}
const styles = {
table: {
width: '100%',
borderCollapse: 'collapse' as const,
tableLayout: 'fixed' as const,
},
th: {
padding: '12px 8px',
textAlign: 'left' as const,
whiteSpace: 'nowrap' as const,
borderBottom: '2px solid var(--ifm-table-border-color)',
overflow: 'hidden',
textOverflow: 'ellipsis',
},
td: {
padding: '8px',
borderBottom: '1px solid var(--ifm-table-border-color)',
verticalAlign: 'top' as const,
overflow: 'hidden',
textOverflow: 'ellipsis',
},
// Column-specific widths
columns: {
category: { width: '15%', fontWeight: 'bold' },
name: { width: '20%', fontWeight: 'bold' },
description: { width: '40%', whiteSpace: 'normal' as const },
pluginId: { width: '15%' },
indicator: { width: '5%', textAlign: 'center' as const },
},
code: {
whiteSpace: 'nowrap' as const,
fontSize: '0.9em',
},
link: {
display: 'block',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap' as const,
},
};
const PluginTable = ({
vulnerabilityType,
shouldRenderCategory = true,
shouldRenderDescription = true,
shouldRenderPluginId = true,
shouldGroupByCategory = false,
showApplicationTypes = false,
showRemoteStatus = false,
}: PluginTableProps) => {
let filteredPlugins = PLUGINS;
// Apply filters if specified
if (vulnerabilityType) {
filteredPlugins = filteredPlugins.filter(
(plugin) => plugin.vulnerabilityType === vulnerabilityType,
);
}
// Group plugins by category if needed
const groupedPlugins: GroupedPlugins = {} as GroupedPlugins;
if (shouldGroupByCategory) {
for (const category of PLUGIN_CATEGORIES) {
groupedPlugins[category] = filteredPlugins
.filter((plugin) => plugin.category === category)
.sort((a, b) => a.name.localeCompare(b.name));
}
}
return (
<table style={styles.table}>
<thead>
<tr>
{shouldRenderCategory && shouldGroupByCategory && (
<th style={{ ...styles.th, ...styles.columns.category }}>Category</th>
)}
<th style={{ ...styles.th, ...styles.columns.name }}>Plugin Name</th>
{shouldRenderDescription && (
<th style={{ ...styles.th, ...styles.columns.description }}>Description</th>
)}
{shouldRenderPluginId && (
<th style={{ ...styles.th, ...styles.columns.pluginId }}>Plugin ID</th>
)}
{showApplicationTypes && (
<>
<th style={{ ...styles.th, ...styles.columns.indicator }}>RAG</th>
<th style={{ ...styles.th, ...styles.columns.indicator }}>Agent</th>
<th style={{ ...styles.th, ...styles.columns.indicator }}>Chatbot</th>
</>
)}
</tr>
</thead>
<tbody>
{shouldGroupByCategory
? Object.entries(groupedPlugins).map(([category, categoryPlugins]) => (
<React.Fragment key={category}>
{categoryPlugins.map((plugin, index) => (
<tr key={plugin.pluginId}>
{index === 0 && shouldRenderCategory && (
<td
rowSpan={categoryPlugins.length}
style={{ ...styles.td, ...styles.columns.category }}
id={getCategoryAnchor(plugin.category).slice(1)}
>
{plugin.category}
</td>
)}
<td style={{ ...styles.td, ...styles.columns.name }}>
<a href={plugin.link} style={styles.link} title={plugin.name}>
{plugin.name}
</a>
</td>
{shouldRenderDescription && (
<td style={{ ...styles.td, ...styles.columns.description }}>
{plugin.description}
{showRemoteStatus && plugin.isRemote && (
<span title="Uses remote inference"> 🌐</span>
)}
</td>
)}
{shouldRenderPluginId && (
<td style={{ ...styles.td, ...styles.columns.pluginId }}>
<code style={styles.code}>{plugin.pluginId}</code>
</td>
)}
{showApplicationTypes && (
<>
<td style={{ ...styles.td, ...styles.columns.indicator }}>
{plugin.applicationTypes?.rag ? '🚨' : '✅'}
</td>
<td style={{ ...styles.td, ...styles.columns.indicator }}>
{plugin.applicationTypes?.agent ? '🚨' : '✅'}
</td>
<td style={{ ...styles.td, ...styles.columns.indicator }}>
{plugin.applicationTypes?.chat ? '🚨' : '✅'}
</td>
</>
)}
</tr>
))}
</React.Fragment>
))
: filteredPlugins.map((plugin) => (
<tr key={plugin.pluginId}>
<td style={styles.td}>
<a href={plugin.link}>{plugin.name}</a>
</td>
{shouldRenderDescription && (
<td style={styles.td}>
{plugin.description}
{showRemoteStatus && plugin.isRemote && (
<span title="Uses remote inference"> 🌐</span>
)}
</td>
)}
{shouldRenderPluginId && (
<td style={styles.td}>
<code style={styles.code}>{plugin.pluginId}</code>
</td>
)}
{showApplicationTypes && (
<>
<td style={styles.td}>{plugin.applicationTypes?.rag ? '🚨' : '✅'}</td>
<td style={styles.td}>{plugin.applicationTypes?.agent ? '🚨' : '✅'}</td>
<td style={styles.td}>{plugin.applicationTypes?.chat ? '🚨' : '✅'}</td>
</>
)}
</tr>
))}
</tbody>
</table>
);
};
export default PluginTable;