Files
gemini-banlancer/frontend/js/utils/utils.js
2025-11-20 12:24:05 +08:00

124 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file utils/utils.js
* @description Provides a collection of common, reusable helper functions.
*/
/**
* A debounce utility to delay function execution, now with a cancel method.
* @param {Function} func The function to debounce.
* @param {number} wait The delay in milliseconds.
* @returns {Function} The new debounced function with a `.cancel()` method attached.
*/
export function debounce(func, wait) {
let timeout;
// create a named function expression here instead of returning an anonymous one directly.
const debounced = function(...args) {
// Store the context of 'this' in case it's needed inside the debounced function.
const context = this;
// The core logic remains the same.
const later = () => {
clearTimeout(timeout);
// Use .apply() to preserve the original 'this' context.
func.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
// Attach a 'cancel' method to the debounced function.
// This allows us to abort a pending execution.
debounced.cancel = () => {
clearTimeout(timeout);
};
return debounced;
}
/**
* Asynchronously copies a given string of text to the user's clipboard.
* @param {string} text The text to be copied.
* @returns {Promise<void>} A promise that resolves on success, rejects on failure.
*/
export function copyToClipboard(text) {
// Use the modern Clipboard API if available
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text);
}
// Fallback for older browsers
return new Promise((resolve, reject) => {
const textArea = document.createElement("textarea");
textArea.value = text;
// Make the textarea invisible and prevent scrolling
textArea.style.position = "fixed";
textArea.style.top = "-9999px";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand("copy");
if (successful) {
resolve();
} else {
reject(new Error("Fallback: Unable to copy text to clipboard."));
}
} catch (err) {
reject(err);
} finally {
document.body.removeChild(textArea);
}
});
}
/**
* Validates a single API Key against a list of known formats.
* @param {string} key - The API key string to validate.
* @returns {boolean} - True if the key matches any of the known formats.
*/
export function isValidApiKeyFormat(key) {
// [核心] 这是一个正则表达式列表。未来支持新的Key格式只需在此处添加新的正则即可。
const patterns = [
// Google Gemini API Key: AIzaSy + 33 characters (alphanumeric, _, -)
/^AIzaSy[\w-]{33}$/,
// OpenAI API Key (新格式): sk- + 48 alphanumeric characters
/^sk-[\w]{48}$/,
// Google AI Studio Key: gsk_ + alphanumeric & hyphens
/^gsk_[\w-]{40,}$/,
// Anthropic API Key (示例): sk-ant-api03- + long string
/^sk-ant-api\d{2}-[\w-]{80,}$/,
// Fallback for other potential "sk-" keys with a reasonable length
/^sk-[\w-]{20,}$/
];
// 使用 .some() 方法只要key匹配列表中的任意一个模式就返回true。
return patterns.some(pattern => pattern.test(key));
}
/**
* [NEW] A simple utility to escape HTML special characters from a string.
* This is a critical security function to prevent XSS attacks when using .innerHTML.
* @param {any} str The input string to escape. If not a string, it's returned as is.
* @returns {string} The escaped, HTML-safe string.
*/
export function escapeHTML(str) {
if (typeof str !== 'string') {
return str;
}
return str.replace(/[&<>"']/g, function(match) {
return {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#039;'
}[match];
});
}
// ... 其他未来可能添加的工具函数 ...