Files
wehub-resource-sync 3cd11ababe
Check Markdown links / linkChecker (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:38:56 +08:00

188 lines
4.8 KiB
TypeScript

import {
HookEventType,
PluginContext,
PluginHandler,
PluginParameters,
} from '../types';
import { getText } from '../utils';
// Extract JSON from code blocks and general text
function extractJson(text: string): string[] {
const codeBlockRegex = /```+(?:json)?\s*([\s\S]*?)```+/g;
const jsonRegex = /{[\s\S]*?}/g;
const matches = [];
// Extract from code blocks
let match;
while ((match = codeBlockRegex.exec(text)) !== null) {
matches.push(match[1].trim());
}
// Extract JSON-like structures
while ((match = jsonRegex.exec(text)) !== null) {
matches.push(match[0]);
}
return matches;
}
export const handler: PluginHandler = async (
context: PluginContext,
parameters: PluginParameters,
eventType: HookEventType
) => {
let error = null;
let verdict = false;
let data: any = null;
try {
const keys = parameters.keys;
const operator = parameters.operator;
let text = getText(context, eventType);
if (!text) {
throw new Error('Missing text to analyze');
}
if (!Array.isArray(keys) || keys.length === 0) {
throw new Error('Missing or invalid keys array');
}
if (!operator || !['any', 'all', 'none'].includes(operator)) {
throw new Error(
'Invalid or missing operator (must be "any", "all", or "none")'
);
}
const jsonMatches = extractJson(text);
if (jsonMatches.length === 0) {
data = {
explanation: 'No valid JSON found in the text.',
requiredKeys: keys,
operator,
textExcerpt: text.length > 100 ? text.slice(0, 100) + '...' : text,
};
return { error, verdict, data };
}
interface BestMatch {
json: any;
presentKeys: string[];
missingKeys: string[];
verdict: boolean;
}
let bestMatch: BestMatch = {
json: null,
presentKeys: [],
missingKeys: keys,
verdict: false,
};
for (const jsonMatch of jsonMatches) {
let parsedJson: any;
try {
parsedJson = JSON.parse(jsonMatch);
} catch (e) {
continue;
}
const presentKeys = keys.filter((key) => parsedJson.hasOwnProperty(key));
const missingKeys = keys.filter((key) => !parsedJson.hasOwnProperty(key));
let currentVerdict = false;
switch (operator) {
case 'any':
currentVerdict = presentKeys.length > 0;
break;
case 'all':
currentVerdict = missingKeys.length === 0;
break;
case 'none':
currentVerdict = presentKeys.length === 0;
break;
}
// Update best match if this is a better result
if (currentVerdict || presentKeys.length > bestMatch.presentKeys.length) {
bestMatch = {
json: parsedJson,
presentKeys,
missingKeys,
verdict: currentVerdict,
};
}
if (currentVerdict) {
break; // Found a valid match, no need to continue
}
}
verdict = bestMatch.verdict;
data = {
matchedJson: bestMatch.json,
verdict,
explanation: getExplanation(
operator,
bestMatch.presentKeys,
bestMatch.missingKeys,
verdict
),
presentKeys: bestMatch.presentKeys,
missingKeys: bestMatch.missingKeys,
operator,
textExcerpt: text.length > 100 ? text.slice(0, 100) + '...' : text,
};
} catch (e: any) {
error = e;
let textExcerpt = getText(context, eventType);
textExcerpt =
textExcerpt?.length > 100
? textExcerpt.slice(0, 100) + '...'
: textExcerpt;
data = {
explanation: `An error occurred while processing JSON: ${e.message}`,
operator: parameters.operator,
requiredKeys: parameters.keys,
textExcerpt: textExcerpt || 'No text available',
};
}
return { error, verdict, data };
};
function getExplanation(
operator: string,
presentKeys: string[],
missingKeys: string[],
verdict: boolean
): string {
const presentKeysList =
presentKeys.length > 0
? `Found keys: [${presentKeys.join(', ')}]`
: 'No matching keys found';
const missingKeysList =
missingKeys.length > 0
? `Missing keys: [${missingKeys.join(', ')}]`
: 'No missing keys';
switch (operator) {
case 'any':
return verdict
? `Successfully found at least one required key. ${presentKeysList}.`
: `Failed to find any required keys. ${missingKeysList}.`;
case 'all':
return verdict
? `Successfully found all required keys. ${presentKeysList}.`
: `Failed to find all required keys. ${missingKeysList}.`;
case 'none':
return verdict
? `Successfully verified no required keys are present. ${missingKeysList}.`
: `Found some keys that should not be present. ${presentKeysList}.`;
default:
return 'Invalid operator specified.';
}
}