()
| 277 | |
| 278 | // --- Save Configuration --- |
| 279 | async function saveConfiguration() { |
| 280 | hideConfigError(); |
| 281 | let isValid = true; |
| 282 | const domain = domainInput.value |
| 283 | .trim() |
| 284 | .toLowerCase() |
| 285 | .replace(/^www\./, ""); // Normalize domain |
| 286 | const originalDomain = hiddenDomainInput.value |
| 287 | .trim() |
| 288 | .toLowerCase() |
| 289 | .replace(/^www\./, ""); |
| 290 | const baseUrl = baseUrlInput.value.trim(); |
| 291 | const linkSelectorsRaw = linkSelectorInput.value.trim(); |
| 292 | const nextPageSelectorsRaw = nextPageSelectorInput.value.trim(); |
| 293 | const dataType = dataTypeInput.value || "href"; |
| 294 | const defaultParams = defaultParamsInput.value.trim(); |
| 295 | const useInEngineSelect = useInSearchEngineCheckbox.checked; |
| 296 | const matchPatternsRaw = matchPatternsInput.value.trim(); |
| 297 | const captchaUrlPatternsRaw = captchaUrlPatternsInput?.value.trim() || ""; |
| 298 | const captchaTextPatternsRaw = captchaTextPatternsInput?.value.trim() || ""; |
| 299 | const captchaSelectorsRaw = captchaSelectorsInput?.value.trim() || ""; |
| 300 | |
| 301 | // --- Input Validations --- |
| 302 | if (!domain) { |
| 303 | isValid = false; |
| 304 | showConfigError("Domain cannot be empty."); |
| 305 | } else if ( |
| 306 | !/^[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})$/.test(domain) || |
| 307 | domain.startsWith(".") || |
| 308 | domain.endsWith(".") |
| 309 | ) { |
| 310 | isValid = false; |
| 311 | showConfigError("Invalid domain format (e.g., example.com)."); |
| 312 | } |
| 313 | if (baseUrl && !/^https?:\/\/.+/i.test(baseUrl)) { |
| 314 | isValid = false; |
| 315 | showConfigError( |
| 316 | "Invalid Base URL format (must start with http:// or https://)." |
| 317 | ); |
| 318 | } |
| 319 | if (useInEngineSelect && !baseUrl) { |
| 320 | isValid = false; |
| 321 | showConfigError( |
| 322 | "Base URL is required if 'Use as Search Engine' is checked." |
| 323 | ); |
| 324 | } |
| 325 | if (!linkSelectorsRaw) { |
| 326 | isValid = false; |
| 327 | showConfigError("Link Selector(s) cannot be empty."); |
| 328 | } |
| 329 | |
| 330 | const linkSelectorsArray = linkSelectorsRaw |
| 331 | .split(",") |
| 332 | .map((s) => s.trim()) |
| 333 | .filter(Boolean); |
| 334 | if (linkSelectorsArray.some((s) => !isValidSelector(s))) { |
| 335 | isValid = false; |
| 336 | showConfigError("One or more Link Selectors are invalid CSS."); |
nothing calls this directly
no test coverage detected