WTR Lab Term Replacer

A modular, Webpack-powered TypeScript version of the WTR Lab Term Replacer userscript.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name WTR Lab Term Replacer
// @description A modular, Webpack-powered TypeScript version of the WTR Lab Term Replacer userscript.
// @version 5.7.0
// @author MasuRii
// @homepage https://github.com/MasuRii/wtr-lab-term-replacer-webpack#readme
// @supportURL https://github.com/MasuRii/wtr-lab-term-replacer-webpack/issues
// @match https://wtr-lab.com/en/novel/*/*/*
// @connect fonts.googleapis.com
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @icon https://www.google.com/s2/favicons?sz=64&domain=wtr-lab.com
// @license MIT
// @namespace https://github.com/MasuRii/wtr-lab-term-replacer-webpack
// @run-at document-idle
// ==/UserScript==

/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ 387
(module, __unused_webpack_exports, __webpack_require__) {

// config/versions.js
// Centralized version management for WTR Lab Term Replacer

// Environment variable overrides with fallbacks
const envVersion = ({ env: {} }).env.WTR_VERSION || ({ env: {} }).env.APP_VERSION;
const buildEnv = ({ env: {} }).env.WTR_BUILD_ENV || ({ env: {} }).env.BUILD_ENV || "production";
const buildDate = ({ env: {} }).env.WTR_BUILD_DATE || ({ env: {} }).env.BUILD_DATE || new Date().toISOString().split("T")[0];

// Derive base version from package.json at runtime so only package.json is edited manually
const pkg = __webpack_require__(330);
const BASE_VERSION = pkg.version;

const VERSION_INFO = {
  SEMANTIC: envVersion || BASE_VERSION,           // Semantic version
  DISPLAY: `v${envVersion || BASE_VERSION}`,      // Display version
  BUILD_ENV: buildEnv || "production",            // Build environment
  BUILD_DATE: buildDate,                          // Build date
  GREASYFORK: envVersion || BASE_VERSION,         // GreasyFork version
  NPM: envVersion || BASE_VERSION,                // NPM version
  BADGE: envVersion || BASE_VERSION,              // Badge version
  CHANGELOG: envVersion || BASE_VERSION,          // Changelog version
};

// Export version info and utility functions
module.exports = {
  VERSION_INFO,
  
  // Utility functions
  getVersion: (type = "semantic") => {
    switch (type.toLowerCase()) {
      case "semantic":
      case "semver":
        return VERSION_INFO.SEMANTIC;
      case "display":
        return VERSION_INFO.DISPLAY;
      case "build":
        return `${VERSION_INFO.SEMANTIC}-${VERSION_INFO.BUILD_ENV}`;
      case "dev":
        return `${VERSION_INFO.SEMANTIC}-dev.${Date.now()}`;
      default:
        return VERSION_INFO.SEMANTIC;
    }
  },
  
  getBuildTime: () => new Date().toISOString(),
  getBuildDate: () => VERSION_INFO.BUILD_DATE,
  isProduction: () => VERSION_INFO.BUILD_ENV === "production",
  isDevelopment: () => VERSION_INFO.BUILD_ENV === "development",
  getDisplayVersion: () => VERSION_INFO.DISPLAY
};

/***/ },

/***/ 333
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Ft: () => (/* binding */ SETTINGS_STORAGE_KEY_PREFIX),
/* harmony export */   Qp: () => (/* binding */ CURRENT_LOCATION_KEY),
/* harmony export */   fW: () => (/* binding */ TERMS_STORAGE_KEY_PREFIX),
/* harmony export */   re: () => (/* binding */ ITEMS_PER_PAGE),
/* harmony export */   sI: () => (/* binding */ GLOBAL_SETTINGS_KEY),
/* harmony export */   tA: () => (/* binding */ CHAPTER_BODY_SELECTOR)
/* harmony export */ });
// Configuration constants and selectors
const CHAPTER_BODY_SELECTOR = ".chapter-body";
const TERMS_STORAGE_KEY_PREFIX = "wtr_lab_terms_";
const SETTINGS_STORAGE_KEY_PREFIX = "wtr_lab_settings_";
const GLOBAL_SETTINGS_KEY = "wtr_lab_global_settings";
const CURRENT_LOCATION_KEY = "wtr_lab_term_list_location";
const ITEMS_PER_PAGE = 100;


/***/ },

/***/ 201
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Cs: () => (/* binding */ updateDupModeAfterChange),
/* harmony export */   DP: () => (/* binding */ changeDupGroup),
/* harmony export */   bj: () => (/* binding */ exitDupMode),
/* harmony export */   r_: () => (/* binding */ computeDupGroups)
/* harmony export */ });
/* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(654);
/* harmony import */ var _ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(141);
// Duplicate detection logic for WTR Lab Term Replacer


/**
 * Normalizes a term's original text into an array of its core components.
 * @param {object} term - The term object.
 * @returns {string[]} An array of normalized string components.
 */
function getNormalizedTermComponents(term) {
    const components = [];
    const original = term.original;
    const isSimpleAlternation = term.isRegex && !/[\\^$.*+?()[\]{}()]/.test(original);
    if (isSimpleAlternation) {
        components.push(...original.split("|"));
    }
    else {
        components.push(original);
    }
    return components
        .map((comp) => {
        let normalized = comp.trim().replace(/\s+/g, " ");
        if (!term.caseSensitive) {
            normalized = normalized.toLowerCase();
        }
        return normalized;
    })
        .filter((comp) => comp.length > 0);
}
/**
 * Computes duplicate groups from a given array of terms.
 * @param {object[]} termsToScan - The array of terms to check for duplicates.
 */
function computeDupGroups(termsToScan) {
    const componentMap = new Map();
    const replacementDupGroups = new Map();
    const allDupGroups = new Map();
    termsToScan.forEach((term) => {
        const components = getNormalizedTermComponents(term);
        if (components.length > 1) {
            const uniqueComponents = new Set(components);
            if (uniqueComponents.size < components.length) {
                const originalTextSnippet = term.original.length > 50 ? term.original.substring(0, 47) + "..." : term.original;
                const key = `Internal duplicate in: "${originalTextSnippet}"`;
                allDupGroups.set(key, [term]);
            }
        }
        components.forEach((comp) => {
            if (!componentMap.has(comp)) {
                componentMap.set(comp, []);
            }
            const group = componentMap.get(comp);
            if (!group.some((t) => t.id === term.id)) {
                group.push(term);
            }
        });
        if (term.replacement) {
            const key = term.replacement;
            if (!replacementDupGroups.has(key)) {
                replacementDupGroups.set(key, []);
            }
            replacementDupGroups.get(key).push(term);
        }
    });
    for (const [component, group] of componentMap.entries()) {
        if (group.length > 1) {
            allDupGroups.set(`Original component: "${component}"`, group);
        }
    }
    for (const [key, group] of replacementDupGroups.entries()) {
        if (group.length > 1) {
            const displayKey = `Replacement: "${key}"`;
            if (allDupGroups.has(displayKey)) {
                const existingGroup = allDupGroups.get(displayKey);
                const newTerms = group.filter((t) => !existingGroup.some((et) => et.id === t.id));
                allDupGroups.set(displayKey, [...existingGroup, ...newTerms]);
            }
            else {
                allDupGroups.set(displayKey, group);
            }
        }
    }
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupGroups = allDupGroups;
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys = Array.from(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupGroups.keys()).sort();
}
function exitDupMode() {
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.isDupMode = false;
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex = 0;
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupGroups = new Map();
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys = [];
    (0,_ui__WEBPACK_IMPORTED_MODULE_1__/* .renderTermList */ .FP)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue);
}
function changeDupGroup(delta) {
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex = Math.max(0, Math.min(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.length - 1, _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex + delta));
    (0,_ui__WEBPACK_IMPORTED_MODULE_1__/* .renderTermList */ .FP)();
}
function updateDupModeAfterChange() {
    computeDupGroups(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms); // Use the current in-memory `state.terms` array which has just been updated
    if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.length === 0) {
        alert("All duplicates resolved.");
        exitDupMode();
        return;
    }
    const oldKey = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys[_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex];
    const newIndex = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.indexOf(oldKey);
    if (newIndex !== -1) {
        const group = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupGroups.get(oldKey);
        if (group && (group.length > 1 || oldKey.startsWith("Internal duplicate"))) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex = newIndex;
        }
        else {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex = Math.min(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex, _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.length - 1);
        }
    }
    else {
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex = Math.min(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex, _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.length - 1);
    }
    (0,_ui__WEBPACK_IMPORTED_MODULE_1__/* .renderTermList */ .FP)();
}


/***/ },

/***/ 9
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   performReplacements: () => (/* binding */ performReplacements),
/* harmony export */   revertAllReplacements: () => (/* binding */ revertAllReplacements)
/* harmony export */ });
/* unused harmony exports executeReplacementLogic, traverseAndRevert */
/* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(654);
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(158);
/* harmony import */ var _ui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(141);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(333);
// Core replacement engine for WTR Lab Term Replacer




async function performReplacements(targetElement) {
    if (!targetElement) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: performReplacements called with null target element");
        return;
    }
    (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Starting performReplacements");
    (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(true);
    await new Promise((resolve) => setTimeout(resolve, 10));
    if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings.isDisabled || _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.length === 0) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Skipping replacements - disabled: ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings.isDisabled}, terms: ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.length}`);
        (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(false);
        return;
    }
    try {
        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Found ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.length} terms to process, beginning replacement with retry mechanism`);
        // Enhanced replacement with error handling and retry
        await performReplacementsWithRetry(targetElement, 3);
    }
    catch (error) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Failed to perform replacements after retries:`, error);
        console.error("WTR Term Replacer: Replacement failed, but original content preserved");
    }
    finally {
        (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(false);
        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: performReplacements completed");
    }
}
async function performReplacementsWithRetry(targetElement, maxRetries) {
    let lastError = null;
    let elementStabilityCounter = 0;
    (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Starting replacement process with ${maxRetries} retries`);
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
            (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Replacement attempt ${attempt}/${maxRetries}`);
            // Enhanced element stability validation
            if (!validateElementStability(targetElement, elementStabilityCounter)) {
                (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Element stability check failed, attempt ${elementStabilityCounter}`);
                // Re-acquire element reference for better stability
                const chapterId = (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .getChapterIdFromUrl */ .Ug)(window.location.href);
                if (chapterId) {
                    const chapterSelector = `#${chapterId} ${_config__WEBPACK_IMPORTED_MODULE_3__/* .CHAPTER_BODY_SELECTOR */ .tA}`;
                    targetElement = document.querySelector(chapterSelector);
                    if (!targetElement) {
                        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Unable to re-acquire target element for chapter ${chapterId}`);
                        throw new Error("Unable to re-acquire target element");
                    }
                    (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Re-acquired target element for chapter ${chapterId}`);
                    elementStabilityCounter++;
                }
                else {
                    (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Cannot determine chapter ID for element recovery");
                    throw new Error("Cannot determine chapter ID for element recovery");
                }
            }
            // Additional DOM validation before proceeding
            if (!document.contains(targetElement) || !targetElement.parentNode) {
                (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Target element validation failed - not in stable DOM");
                throw new Error("Target element not in stable DOM");
            }
            (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Element validation passed, executing replacement logic");
            // Perform the actual replacement logic
            await executeReplacementLogic(targetElement);
            (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Replacement attempt ${attempt} successful`);
            return; // Success, exit retry loop
        }
        catch (error) {
            lastError = error;
            (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Replacement attempt ${attempt} failed:`, error.message);
            if (attempt < maxRetries) {
                // Progressive backoff with stability checks
                const delay = Math.min(100 * Math.pow(2, attempt - 1), 2000);
                (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Retrying in ${delay}ms...`);
                await new Promise((resolve) => setTimeout(resolve, delay));
                // Pre-retry stability check
                if (error.message && error.message.includes("DOM")) {
                    elementStabilityCounter++;
                }
            }
            else {
                (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: All ${maxRetries} attempts failed, giving up`);
            }
        }
    }
    // All retries failed
    (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: All replacement attempts failed, throwing error: ${lastError?.message || "Unknown error"}`);
    throw lastError || new Error("Unknown replacement error");
}
// Enhanced element stability validation
function validateElementStability(element, stabilityCounter) {
    if (!element || !document.contains(element)) {
        return false;
    }
    // Check if element is visible and attached to DOM
    const rect = element.getBoundingClientRect();
    if (rect.width === 0 || rect.height === 0) {
        return false;
    }
    // Check parent chain is stable
    let parent = element.parentNode;
    let stabilityCheckCount = 0;
    while (parent && stabilityCheckCount < 10) {
        if (!document.contains(parent)) {
            return false;
        }
        parent = parent.parentNode;
        stabilityCheckCount++;
    }
    // Allow limited DOM recreation (stabilityCounter < 3)
    return stabilityCounter < 3;
}
async function executeReplacementLogic(targetElement) {
    // Validate target element state before processing
    if (!targetElement || targetElement.nodeType !== Node.ELEMENT_NODE) {
        throw new Error("Invalid target element");
    }
    // Additional DOM stability validation
    if (!validateElementStability(targetElement, 0)) {
        throw new Error("Target element DOM stability check failed");
    }
    // Check if element has meaningful content to process
    const textContent = targetElement.textContent?.trim() || "";
    if (textContent.length === 0) {
        const chapterId = (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .getChapterIdFromUrl */ .Ug)(window.location.href) || "unknown";
        const contentLength = targetElement.textContent?.length || 0;
        (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Target element has no text content in chapter ${chapterId} (${contentLength} chars), skipping`);
        return;
    }
    // Collect all text nodes and aggregate into a single string.
    const walker = document.createTreeWalker(targetElement, NodeFilter.SHOW_TEXT);
    const textNodes = [];
    let node;
    while ((node = walker.nextNode())) {
        if (!node.parentElement.closest(".wtr-replacer-ui, script, style")) {
            textNodes.push(node);
        }
    }
    const nodeValues = new Map();
    const nodeMap = [];
    let fullText = "";
    let currentPos = 0;
    textNodes.forEach((n) => {
        if (!_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.originalTextNodes.has(n)) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.originalTextNodes.set(n, n.nodeValue);
        }
        const originalValue = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.originalTextNodes.get(n);
        nodeValues.set(n, originalValue);
        if (originalValue.length > 0) {
            nodeMap.push({ node: n, start: currentPos, end: currentPos + originalValue.length });
        }
        fullText += originalValue;
        currentPos += originalValue.length;
    });
    if (!fullText.trim()) {
        (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(false);
        return;
    }
    // Categorize terms
    const simple_cs_partial = new Map();
    const simple_cs_whole = new Map();
    const simple_ci_partial = new Map();
    const simple_ci_whole = new Map();
    const regex_terms = [];
    for (const term of _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms) {
        if (!term.original) {
            continue;
        }
        if (term.isRegex) {
            try {
                const flags = term.caseSensitive ? "g" : "gi";
                regex_terms.push({
                    pattern: new RegExp(term.original, flags),
                    replacement: term.replacement,
                });
            }
            catch (e) {
                console.error(`Skipping invalid regex for term "${term.original}":`, e);
            }
        }
        else {
            const key = term.caseSensitive ? term.original : term.original.toLowerCase();
            const value = term.replacement;
            if (term.caseSensitive) {
                if (term.wholeWord) {
                    simple_cs_whole.set(key, value);
                }
                else {
                    simple_cs_partial.set(key, value);
                }
            }
            else {
                if (term.wholeWord) {
                    simple_ci_whole.set(key, value);
                }
                else {
                    simple_ci_partial.set(key, value);
                }
            }
        }
    }
    // Compile categorized terms into combined patterns.
    const compiledTerms = [...regex_terms];
    const addSimpleGroup = (map, flags, wholeWord, caseSensitive) => {
        if (map.size > 0) {
            const sortedKeys = [...map.keys()].sort((a, b) => b.length - a.length);
            const patterns = sortedKeys.map((k) => {
                const escaped = (0,_utils__WEBPACK_IMPORTED_MODULE_1__/* .escapeRegExp */ .Nt)(k);
                return wholeWord ? `\\b${escaped}\\b` : escaped;
            });
            const combined = patterns.join("|");
            compiledTerms.push({
                pattern: new RegExp(combined, flags),
                replacement_map: map,
                is_simple: true,
                case_sensitive: caseSensitive,
            });
        }
    };
    addSimpleGroup(simple_cs_partial, "g", false, true);
    addSimpleGroup(simple_cs_whole, "g", true, true);
    addSimpleGroup(simple_ci_partial, "gi", false, false);
    addSimpleGroup(simple_ci_whole, "gi", true, false);
    // Find ALL possible matches from all compiled terms.
    const allMatches = [];
    for (const comp of compiledTerms) {
        for (const match of fullText.matchAll(comp.pattern)) {
            if (match.index === match.index + match[0].length) {
                continue;
            } // Skip zero-length matches
            let replacementText;
            if (comp.is_simple) {
                const key = comp.case_sensitive ? match[0] : match[0].toLowerCase();
                replacementText = comp.replacement_map.get(key);
            }
            else {
                replacementText = comp.replacement;
            }
            if (replacementText !== undefined) {
                allMatches.push({
                    start: match.index,
                    end: match.index + match[0].length,
                    replacement: replacementText,
                });
            }
        }
    }
    // Resolve overlaps: Sort by start index, then by end index descending (longest match wins).
    allMatches.sort((a, b) => {
        if (a.start !== b.start) {
            return a.start - b.start;
        }
        return b.end - a.end;
    });
    // Select the non-overlapping "winning" matches.
    const winningMatches = [];
    let lastEnd = -1;
    for (const match of allMatches) {
        if (match.start >= lastEnd) {
            winningMatches.push(match);
            lastEnd = match.end;
        }
    }
    // Apply winning matches to the nodeValues map, from last to first.
    for (const match of winningMatches.reverse()) {
        const { start: matchStart, end: matchEnd, replacement: replacementString } = match;
        const affectedNodesInfo = [];
        for (const info of nodeMap) {
            if (info.start < matchEnd && info.end > matchStart) {
                affectedNodesInfo.push(info);
            }
        }
        if (affectedNodesInfo.length === 0) {
            continue;
        }
        const firstNodeInfo = affectedNodesInfo[0];
        const lastNodeInfo = affectedNodesInfo[affectedNodesInfo.length - 1];
        const startNode = firstNodeInfo.node;
        const lastNode = lastNodeInfo.node;
        const startOffset = matchStart - firstNodeInfo.start;
        const endOffset = matchEnd - lastNodeInfo.start;
        if (startNode === lastNode) {
            const currentVal = nodeValues.get(startNode);
            nodeValues.set(startNode, currentVal.substring(0, startOffset) + replacementString + currentVal.substring(endOffset));
        }
        else {
            const lastVal = nodeValues.get(lastNode);
            nodeValues.set(lastNode, lastVal.substring(endOffset));
            for (let i = 1; i < affectedNodesInfo.length - 1; i++) {
                nodeValues.set(affectedNodesInfo[i].node, "");
            }
            const firstVal = nodeValues.get(startNode);
            nodeValues.set(startNode, firstVal.substring(0, startOffset) + replacementString);
        }
    }
    // After all processing, apply the final values to the DOM.
    for (const n of textNodes) {
        const finalValue = nodeValues.get(n);
        if (n.nodeValue !== finalValue) {
            n.nodeValue = finalValue;
        }
    }
    (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(false);
}
function traverseAndRevert(node) {
    if (node.nodeType === Node.TEXT_NODE) {
        if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.originalTextNodes.has(node)) {
            node.nodeValue = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.originalTextNodes.get(node);
        }
        return;
    }
    if (node.nodeType === Node.ELEMENT_NODE &&
        node.tagName.toLowerCase() !== "script" &&
        node.tagName.toLowerCase() !== "style") {
        if (node.classList.contains("wtr-replacer-ui")) {
            return;
        }
        for (const child of node.childNodes) {
            traverseAndRevert(child);
        }
    }
}
async function revertAllReplacements(targetElement) {
    if (!targetElement) {
        return;
    }
    (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(true);
    await new Promise((resolve) => setTimeout(resolve, 10));
    traverseAndRevert(targetElement);
    (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .showProcessingIndicator */ .gn)(false);
}


/***/ },

/***/ 359
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  IY: () => (/* binding */ addTermProgrammatically),
  nS: () => (/* binding */ clearDiscoveryFormState),
  mA: () => (/* binding */ enhanceWtrTermPopovers),
  az: () => (/* binding */ handleAddTermFromSelection),
  Jm: () => (/* binding */ handleDeleteSelected),
  ts: () => (/* binding */ handleDisableToggle),
  ym: () => (/* binding */ handleExportAll),
  ow: () => (/* binding */ handleExportCombined),
  b7: () => (/* binding */ handleExportNovel),
  kF: () => (/* binding */ handleFileImport),
  y$: () => (/* binding */ handleFindDuplicates),
  VM: () => (/* binding */ handleListInteraction),
  Zw: () => (/* binding */ handleRefreshSuggestionsClick),
  JB: () => (/* binding */ handleReplacementSuggestionClick),
  l9: () => (/* binding */ handleReplacementSuggestionInput),
  s7: () => (/* binding */ handleSaveTerm),
  RX: () => (/* binding */ handleSearch),
  U8: () => (/* binding */ handleSuggestionTargetFocus),
  Qk: () => (/* binding */ handleTabSwitch),
  Me: () => (/* binding */ handleTextSelection),
  cD: () => (/* binding */ handleWtrPopoverAddTermClick),
  Xq: () => (/* binding */ handleWtrTextPatchClick),
  X: () => (/* binding */ hideUIPanel),
  AO: () => (/* binding */ normalizeOriginalRegexField),
  s3: () => (/* binding */ restoreTermListLocation),
  R6: () => (/* reexport */ storage.saveTermListLocation),
  o6: () => (/* binding */ toggleLogging),
  fA: () => (/* binding */ validateRegexSilent)
});

// UNUSED EXPORTS: downloadJSON, setSearchFieldValue, validateRegex

// EXTERNAL MODULE: ./src/modules/state.ts
var state = __webpack_require__(654);
// EXTERNAL MODULE: ./src/modules/storage.ts
var storage = __webpack_require__(694);
// EXTERNAL MODULE: ./src/modules/ui.ts
var ui = __webpack_require__(141);
// EXTERNAL MODULE: ./src/modules/observer.ts
var observer = __webpack_require__(405);
// EXTERNAL MODULE: ./src/modules/duplicates.ts
var duplicates = __webpack_require__(201);
// EXTERNAL MODULE: ./src/modules/utils.ts
var utils = __webpack_require__(158);
// EXTERNAL MODULE: ./src/modules/engine.ts
var engine = __webpack_require__(9);
;// ./src/modules/termDiscoveryHelpers.ts
const MAX_TERM_LENGTH = 80;
const MAX_REPLACEMENT_LENGTH = 120;
const MAX_RESULTS = 100;
const CONTROL_CHARS_PATTERN = /[\u0000-\u001f\u007f]/g;
const HTML_TAG_PATTERN = /<[^>]*>/g;
const HTML_ENTITY_PATTERN = /&(?:nbsp|amp|lt|gt|quot|#39);/gi;
const SAFE_IDENTIFIER_PATTERN = /^[A-Za-z0-9_.:-]{1,80}$/;
const WTR_SOURCE_ID_PREFIX = "id.";
const COMMON_WORDS = new Set([
    "A",
    "An",
    "And",
    "As",
    "At",
    "But",
    "By",
    "For",
    "From",
    "He",
    "Her",
    "His",
    "I",
    "In",
    "Into",
    "It",
    "Of",
    "On",
    "Or",
    "She",
    "The",
    "They",
    "This",
    "To",
    "Was",
    "With",
]);
function sanitizeApiText(value, maxLength = MAX_TERM_LENGTH) {
    if (typeof value !== "string" && typeof value !== "number") {
        return null;
    }
    const normalized = String(value)
        .replace(CONTROL_CHARS_PATTERN, " ")
        .replace(/\s+/g, " ")
        .trim();
    if (!normalized) {
        return null;
    }
    return normalized.slice(0, maxLength);
}
function stripHtml(value) {
    return value
        .replace(HTML_TAG_PATTERN, " ")
        .replace(HTML_ENTITY_PATTERN, (entity) => {
        const lower = entity.toLowerCase();
        if (lower === "&nbsp;") {
            return " ";
        }
        if (lower === "&amp;") {
            return "&";
        }
        if (lower === "&lt;") {
            return "<";
        }
        if (lower === "&gt;") {
            return ">";
        }
        if (lower === "&quot;") {
            return '"';
        }
        return "'";
    });
}
function sanitizeIdentifier(value) {
    const sanitized = sanitizeApiText(value, 80);
    if (!sanitized || !SAFE_IDENTIFIER_PATTERN.test(sanitized)) {
        return undefined;
    }
    return sanitized;
}
function sanitizePreferenceHash(value) {
    return sanitizeApiText(value, MAX_TERM_LENGTH) || undefined;
}
function sanitizeLang(value, fallback = "en") {
    const sanitized = sanitizeApiText(value, 12);
    if (sanitized && /^[a-z]{2}(?:-[A-Z]{2})?$/.test(sanitized)) {
        return sanitized;
    }
    return fallback;
}
function parsePositiveInteger(value, pattern = /^(\d+)$/) {
    const sanitized = sanitizeApiText(value, 80);
    const match = sanitized?.match(pattern);
    if (!match) {
        return null;
    }
    const parsed = Number(match[1]);
    return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
}
function sanitizeTranslateService(value) {
    const sanitized = sanitizeApiText(value, 20);
    return sanitized && /^[a-z][a-z0-9_-]{0,19}$/i.test(sanitized) ? sanitized : "ai";
}
function buildReaderGetPayload(context, translateService = "ai") {
    const rawId = parsePositiveInteger(context.rawId);
    const chapterNoSource = context.chapterNo ?? context.chapterSlug;
    const chapterNo = parsePositiveInteger(chapterNoSource, /^(?:chapter-)?(\d+)$/);
    if (!rawId || !chapterNo) {
        return null;
    }
    const payload = {
        translate: sanitizeTranslateService(translateService),
        language: sanitizeLang(context.lang),
        raw_id: rawId,
        chapter_no: chapterNo,
        retry: false,
        force_retry: false,
    };
    const chapterId = parsePositiveInteger(context.chapterId);
    if (chapterId) {
        payload.chapter_id = chapterId;
    }
    return payload;
}
function firstTextValue(entry, keys, maxLength = MAX_TERM_LENGTH) {
    for (const fieldName of keys) {
        const value = sanitizeApiText(entry[fieldName], maxLength);
        if (value) {
            return value;
        }
    }
    return null;
}
function firstNumberValue(entry, keys) {
    for (const fieldName of keys) {
        const value = entry[fieldName];
        if (typeof value === "number" && Number.isFinite(value)) {
            return Math.max(0, value);
        }
        if (typeof value === "string" && value.trim() && Number.isFinite(Number(value))) {
            return Math.max(0, Number(value));
        }
    }
    return 0;
}
function getArrayPayload(payload) {
    if (Array.isArray(payload)) {
        return payload;
    }
    if (!payload || typeof payload !== "object") {
        return [];
    }
    const objectPayload = payload;
    for (const fieldName of ["data", "terms", "items", "results", "preferences", "sources", "glossaries"]) {
        const value = objectPayload[fieldName];
        if (Array.isArray(value)) {
            return value;
        }
        if (value && typeof value === "object") {
            const nested = getArrayPayload(value);
            if (nested.length > 0) {
                return nested;
            }
        }
    }
    return [];
}
function isRecord(value) {
    return Boolean(value && typeof value === "object" && !Array.isArray(value));
}
function isWtrTermTuple(value) {
    return Array.isArray(value) && Array.isArray(value[0]) && (typeof value[1] === "string" || typeof value[1] === "number");
}
function getGlossarySourceId(entry) {
    const explicitSourceId = sanitizeIdentifier(entry.source_id ?? entry.sourceId);
    if (explicitSourceId) {
        return explicitSourceId;
    }
    const data = isRecord(entry.data) ? entry.data : null;
    const sourceType = sanitizeIdentifier(data?.type ?? entry.type);
    const sourceId = sanitizeIdentifier(data?.id ?? entry.id ?? entry.raw_id ?? entry.rawId);
    if (!sourceType || !sourceId) {
        return undefined;
    }
    return `${WTR_SOURCE_ID_PREFIX}${sourceType}.${sourceId}`;
}
function collectNovelTermEntries(payload, fallbackLang, sourceId) {
    if (isWtrTermTuple(payload)) {
        return [{ item: payload, sourceId, lang: fallbackLang }];
    }
    if (Array.isArray(payload)) {
        return payload.flatMap((item) => collectNovelTermEntries(item, fallbackLang, sourceId));
    }
    if (!isRecord(payload)) {
        return [];
    }
    const localSourceId = getGlossarySourceId(payload) || sourceId;
    const localLang = sanitizeLang(payload.lang ?? payload.language, fallbackLang);
    const directTerm = firstTextValue(payload, ["source", "original", "source_text", "sourceText", "from", "term", "raw", "name"]);
    if (directTerm) {
        return [{ item: payload, sourceId: localSourceId, lang: localLang }];
    }
    const nestedEntries = [];
    for (const fieldName of ["glossaries", "data", "terms", "items", "results", "sources"]) {
        const value = payload[fieldName];
        if (value && (Array.isArray(value) || typeof value === "object")) {
            nestedEntries.push(...collectNovelTermEntries(value, localLang, localSourceId));
        }
    }
    return nestedEntries;
}
function textValuesFromArray(values, maxLength = MAX_TERM_LENGTH) {
    const deduped = new Map();
    for (const value of values) {
        const text = sanitizeApiText(value, maxLength);
        if (text) {
            deduped.set(text, text);
        }
    }
    return Array.from(deduped.values());
}
function firstTextFromArray(values, maxLength = MAX_TERM_LENGTH) {
    return textValuesFromArray(values, maxLength)[0] || null;
}
function maxNumberValue(values) {
    return values.reduce((maxValue, value) => {
        if (typeof value === "number" && Number.isFinite(value)) {
            return Math.max(maxValue, value);
        }
        if (typeof value === "string" && value.trim() && Number.isFinite(Number(value))) {
            return Math.max(maxValue, Number(value));
        }
        return maxValue;
    }, 0);
}
function collectReaderText(payload, depth = 0) {
    if (depth > 6 || payload == null) {
        return [];
    }
    if (typeof payload === "string") {
        return payload.length > 40 ? [payload] : [];
    }
    if (Array.isArray(payload)) {
        return payload.flatMap((item) => collectReaderText(item, depth + 1));
    }
    if (typeof payload !== "object") {
        return [];
    }
    const objectPayload = payload;
    const textKeys = ["body", "content", "chapter", "chapter_body", "chapterBody", "html", "text"];
    const directText = textKeys.flatMap((fieldName) => collectReaderText(objectPayload[fieldName], depth + 1));
    if (directText.length > 0) {
        return directText;
    }
    return Object.values(objectPayload).flatMap((value) => collectReaderText(value, depth + 1));
}
function rankChapterTermCandidates(text, existingTerms = new Set(), limit = 50) {
    const strippedText = stripHtml(text);
    const counts = new Map();
    const addTerm = (rawTerm) => {
        const term = sanitizeApiText(rawTerm);
        if (!term || term.length < 2 || existingTerms.has(term) || COMMON_WORDS.has(term)) {
            return;
        }
        counts.set(term, (counts.get(term) || 0) + 1);
    };
    const latinMatches = strippedText.matchAll(/\b[A-Z][\p{L}\p{M}'-]*(?:\s+[A-Z][\p{L}\p{M}'-]*){0,3}\b/gu);
    for (const match of latinMatches) {
        addTerm(match[0]);
    }
    const cjkMatches = strippedText.matchAll(/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\uAC00-\uD7AF]{2,12}/gu);
    for (const match of cjkMatches) {
        addTerm(match[0]);
    }
    return Array.from(counts.entries())
        .map(([term, count]) => ({ term, count, source: "chapter" }))
        .sort((a, b) => b.count - a.count || a.term.localeCompare(b.term))
        .slice(0, limit);
}
function extractCurrentChapterCandidates(readerPayload, existingTerms = new Set(), limit = 50) {
    const text = collectReaderText(readerPayload).join(" ");
    if (!text) {
        return [];
    }
    return rankChapterTermCandidates(text, existingTerms, limit);
}
function parseNovelTermEntries(payload, lang = "en", limit = MAX_RESULTS) {
    const deduped = new Map();
    const entries = collectNovelTermEntries(payload, sanitizeLang(lang));
    for (const { item, sourceId: inheritedSourceId, lang: entryLang } of entries) {
        let term = null;
        let replacement = null;
        let replacementSuggestions = [];
        let count = 0;
        let sourceId = inheritedSourceId;
        let hash;
        let candidateLang = entryLang;
        if (Array.isArray(item)) {
            const replacements = Array.isArray(item[0]) ? item[0] : [];
            term = sanitizeApiText(item[1]);
            replacementSuggestions = textValuesFromArray(replacements, MAX_REPLACEMENT_LENGTH);
            replacement = replacementSuggestions[0] || null;
            count = maxNumberValue(item.slice(2));
            hash = sanitizePreferenceHash(item[1]);
        }
        else if (isRecord(item)) {
            term = firstTextValue(item, ["source", "original", "source_text", "sourceText", "from", "term", "raw", "name"]);
            replacement = firstTextValue(item, ["target", "replacement", "target_text", "targetText", "translation", "value", "to"], MAX_REPLACEMENT_LENGTH);
            count = firstNumberValue(item, [
                "popularity",
                "count",
                "uses",
                "usage",
                "frequency",
                "preference_count",
                "userCount",
                "user_count",
            ]);
            sourceId = sanitizeIdentifier(item.source_id ?? item.sourceId ?? item.id) || sourceId;
            hash = sanitizePreferenceHash(item.hash ?? item.source_hash ?? item.sourceHash ?? item.from ?? item.source ?? item.original ?? term);
            candidateLang = sanitizeLang(item.lang ?? item.language, candidateLang);
        }
        if (!term) {
            continue;
        }
        const candidate = {
            term,
            replacement: replacement || undefined,
            ...(replacementSuggestions.length > 1 ? { replacementSuggestions } : {}),
            source: "novel",
            count,
            sourceId,
            hash,
            lang: candidateLang,
        };
        const mapKey = term.toLocaleLowerCase();
        const previous = deduped.get(mapKey);
        if (!previous || candidate.count > previous.count || (!previous.hash && candidate.hash)) {
            deduped.set(mapKey, candidate);
        }
    }
    return Array.from(deduped.values())
        .sort((a, b) => b.count - a.count || a.term.localeCompare(b.term))
        .slice(0, limit);
}
function getDiscoveryCandidateKey(candidate) {
    if (!candidate) {
        return "";
    }
    return [candidate.term, candidate.replacement || "", candidate.source, candidate.sourceId || "", candidate.hash || "", candidate.lang || ""].join("\u001f");
}
function isReplacementSuggestionRequestCurrent(requestId, latestRequestId, candidateKey, selectedCandidateKey, inputValue, currentInputValue) {
    return requestId === latestRequestId && candidateKey === selectedCandidateKey && inputValue === currentInputValue;
}
function parseReplacementPreferences(payload, limit = 20) {
    const deduped = new Map();
    const entries = getArrayPayload(payload);
    for (const item of entries) {
        if (!item || typeof item !== "object") {
            continue;
        }
        const entry = item;
        const replacement = firstTextValue(entry, ["target", "replacement", "target_text", "targetText", "translation", "value", "to"], MAX_REPLACEMENT_LENGTH);
        if (!replacement) {
            continue;
        }
        const count = firstNumberValue(entry, [
            "count",
            "score",
            "votes",
            "uses",
            "usage",
            "preference_count",
            "users_count",
            "userCount",
            "user_count",
        ]);
        const mapKey = replacement.toLocaleLowerCase();
        const previous = deduped.get(mapKey);
        if (!previous || count > previous.count) {
            deduped.set(mapKey, { replacement, count });
        }
    }
    return Array.from(deduped.values())
        .sort((a, b) => b.count - a.count || a.replacement.localeCompare(b.replacement))
        .slice(0, limit);
}

;// ./src/modules/termDiscovery.ts


const TERM_SUGGESTION_CACHE_PREFIX = "wtr_lab_term_suggestion_cache_v1_";
const NOVEL_TERMS_CACHE_TTL_MS = 60 * 60 * 1000;
const PREFERENCES_CACHE_TTL_MS = 6 * 60 * 60 * 1000;
function getReaderContext() {
    return (0,utils/* getReaderContextFromPath */.o7)(window.location.pathname);
}
function getCsrfToken() {
    const meta = document.querySelector('meta[name="csrf-token"], meta[name="csrf_token"]');
    return meta?.getAttribute("content") || null;
}
function getCacheKey(type, identifiers) {
    return `${TERM_SUGGESTION_CACHE_PREFIX}${type}_${identifiers.filter(Boolean).join("_")}`;
}
async function readCache(key, ttlMs) {
    try {
        const entry = (await GM_getValue(key, null));
        if (!entry || typeof entry.fetchedAt !== "number" || Date.now() - entry.fetchedAt > ttlMs) {
            return null;
        }
        return entry.data;
    }
    catch (_error) {
        return null;
    }
}
async function writeCache(key, data) {
    try {
        await GM_setValue(key, { fetchedAt: Date.now(), data });
    }
    catch (_error) {
        // Suggestion cache is optional and must never block the main term workflow.
    }
}
async function fetchJson(url, init = {}) {
    const headers = new Headers(init.headers || {});
    headers.set("Accept", "application/json");
    const csrfToken = getCsrfToken();
    if (csrfToken) {
        headers.set("X-CSRF-TOKEN", csrfToken);
    }
    const response = await fetch(url, {
        ...init,
        credentials: "same-origin",
        headers,
    });
    if (!response.ok) {
        throw new Error(`WTR API returned ${response.status}`);
    }
    return response.json();
}
function hasPreferenceIdentifiers(candidate) {
    return Boolean(candidate?.sourceId && candidate?.hash && candidate?.lang);
}
async function loadNovelTermEntries(forceRefresh = false) {
    const context = getReaderContext();
    if (!context.rawId) {
        return [];
    }
    const cacheKey = getCacheKey("novel", [context.lang, context.rawId]);
    if (!forceRefresh) {
        const cached = await readCache(cacheKey, NOVEL_TERMS_CACHE_TTL_MS);
        if (cached) {
            return cached;
        }
    }
    const apiPayload = await fetchJson(`/api/v2/reader/terms/${encodeURIComponent(context.rawId)}.json`);
    const candidates = parseNovelTermEntries(apiPayload, context.lang, 200);
    await writeCache(cacheKey, candidates);
    return candidates;
}
async function loadReplacementSuggestions(candidate, forceRefresh = false) {
    if (!hasPreferenceIdentifiers(candidate)) {
        return [];
    }
    const sourceId = candidate.sourceId;
    const hash = candidate.hash;
    const lang = candidate.lang;
    const cacheKey = getCacheKey("preferences", [lang, sourceId, hash]);
    if (!forceRefresh) {
        const cached = await readCache(cacheKey, PREFERENCES_CACHE_TTL_MS);
        if (cached) {
            return cached;
        }
    }
    const params = new URLSearchParams({ source_id: sourceId, hash, lang });
    const apiPayload = await fetchJson(`/api/v2/term-preferences?${params.toString()}`);
    const suggestions = parseReplacementPreferences(apiPayload, 12);
    await writeCache(cacheKey, suggestions);
    return suggestions;
}

// EXTERNAL MODULE: ./config/versions.js
var versions = __webpack_require__(387);
;// ./src/modules/handlers.ts
// Event handler functions for WTR Lab Term Replacer


// Re-export saveTermListLocation for UI module








// Export hideUIPanel function that can be called from UI
function hideUIPanel() {
    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: UI panel hide requested");
    (0,ui/* hideUIPanel */.X)();
}
function validateRegex(pattern) {
    try {
        new RegExp(pattern);
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Valid regex pattern: ${pattern}`);
        return true;
    }
    catch (e) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Invalid regex pattern: ${pattern} - ${e.message}`);
        return false;
    }
}
// Silent validation for real-time visual feedback
function validateRegexSilent(pattern) {
    try {
        new RegExp(pattern);
        return { isValid: true, error: null };
    }
    catch (e) {
        return { isValid: false, error: e.message };
    }
}
function ensureDiscoveryState() {
    if (!state/* state */.wk.termDiscovery) {
        state/* state */.wk.termDiscovery = {
            novelTerms: [],
            replacementSuggestions: [],
            selectedCandidate: null,
        };
    }
    return state/* state */.wk.termDiscovery;
}
function getFieldSuggestionTokens(fieldId) {
    const field = document.getElementById(fieldId);
    return getExistingSuggestionTokens(field?.value || "");
}
function getSuggestionPresenceLabels(suggestion) {
    const labels = [];
    const originalTokens = getFieldSuggestionTokens("wtr-original");
    const replacementTokens = getFieldSuggestionTokens("wtr-replacement");
    if (originalTokens.has(suggestion)) {
        labels.push("Original");
    }
    if (replacementTokens.has(suggestion)) {
        labels.push("Replacement");
    }
    return labels;
}
function renderReplacementSuggestions(suggestions, message = "") {
    const container = document.getElementById("wtr-replacement-suggestions");
    if (!container) {
        return;
    }
    container.textContent = "";
    if (message) {
        const messageEl = document.createElement("small");
        messageEl.textContent = message;
        container.appendChild(messageEl);
        return;
    }
    if (suggestions.length === 0) {
        return;
    }
    const label = document.createElement("small");
    label.textContent = "Suggestions:";
    container.appendChild(label);
    const buttonWrap = document.createElement("div");
    buttonWrap.className = "wtr-replacement-suggestion-buttons";
    suggestions.forEach((suggestion) => {
        const presenceLabels = getSuggestionPresenceLabels(suggestion.replacement);
        const button = document.createElement("button");
        button.type = "button";
        button.className = `btn btn-secondary btn-sm wtr-replacement-suggestion-btn${presenceLabels.length ? " wtr-suggestion-existing" : ""}`;
        button.dataset.replacement = suggestion.replacement;
        const replacementLabel = document.createElement("span");
        replacementLabel.textContent = suggestion.replacement;
        button.appendChild(replacementLabel);
        const metaParts = [suggestion.sourceLabel, suggestion.count > 0 ? String(suggestion.count) : "", ...presenceLabels].filter(Boolean);
        if (metaParts.length > 0) {
            const sourceLabel = document.createElement("small");
            sourceLabel.className = "wtr-replacement-suggestion-source";
            sourceLabel.textContent = metaParts.join(" • ");
            button.appendChild(sourceLabel);
        }
        buttonWrap.appendChild(button);
    });
    container.appendChild(buttonWrap);
}
function normalizeReplacementSuggestion(replacement, count = 0, sourceLabel = "", sourceRank = 50) {
    const normalizedReplacement = replacement.replace(/\s+/g, " ").trim();
    if (!normalizedReplacement) {
        return null;
    }
    return { replacement: normalizedReplacement, count, sourceLabel, sourceRank };
}
function mergeSuggestionLabels(existingLabel = "", newLabel = "") {
    const labels = new Set([...existingLabel.split(" + "), ...newLabel.split(" + ")].map((label) => label.trim()).filter(Boolean));
    return Array.from(labels).join(" + ");
}
function dedupeReplacementSuggestions(suggestions) {
    const deduped = new Map();
    suggestions.forEach((suggestion) => {
        const normalized = normalizeReplacementSuggestion(suggestion.replacement, suggestion.count, suggestion.sourceLabel, suggestion.sourceRank);
        if (!normalized) {
            return;
        }
        const key = normalized.replacement;
        const existing = deduped.get(key);
        if (!existing) {
            deduped.set(key, normalized);
            return;
        }
        existing.count = Math.max(existing.count, normalized.count);
        existing.sourceRank = Math.min(existing.sourceRank ?? 50, normalized.sourceRank ?? 50);
        existing.sourceLabel = mergeSuggestionLabels(existing.sourceLabel, normalized.sourceLabel);
    });
    return Array.from(deduped.values()).sort((a, b) => (a.sourceRank ?? 50) - (b.sourceRank ?? 50) ||
        b.count - a.count ||
        a.replacement.localeCompare(b.replacement));
}
function replacementSuggestionsFromValues(values, sourceLabel = "WTR", sourceRank = 50) {
    return dedupeReplacementSuggestions(values
        .map((value) => normalizeReplacementSuggestion(value, 0, sourceLabel, sourceRank))
        .filter((suggestion) => Boolean(suggestion)));
}
function getOriginalInputOptions() {
    const originalInput = document.getElementById("wtr-original");
    const regexCheckbox = document.getElementById("wtr-is-regex");
    const caseSensitiveCheckbox = document.getElementById("wtr-case-sensitive");
    return {
        value: originalInput ? originalInput.value.trim() : "",
        isRegex: Boolean(regexCheckbox?.checked),
        caseSensitive: Boolean(caseSensitiveCheckbox?.checked),
    };
}
function stripRegexSyntax(fragment) {
    return fragment
        .replace(/\\[bBAZzG]/g, " ")
        .replace(/\\s[+*?]?/g, " ")
        .replace(/\\[dDwW][+*?]?/g, " ")
        .replace(/\[([^\]\\]+)\][+*?]?/g, (_match, chars) => chars.match(/[\p{L}\p{M}\p{N}'-]/u)?.[0] || " ")
        .replace(/\(\?[:=!<][^)]*\)/g, " ")
        .replace(/[()]/g, " ")
        .replace(/[{}+*?^$]/g, " ")
        .replace(/\\(.)/g, "$1")
        .replace(/\s+/g, " ")
        .trim();
}
function splitTopLevelAlternatives(value) {
    const parts = [];
    let current = "";
    let isEscaped = false;
    let characterClassDepth = 0;
    let groupDepth = 0;
    for (const char of value) {
        if (isEscaped) {
            current += char;
            isEscaped = false;
            continue;
        }
        if (char === "\\") {
            current += char;
            isEscaped = true;
            continue;
        }
        if (char === "[") {
            characterClassDepth++;
            current += char;
            continue;
        }
        if (char === "]" && characterClassDepth > 0) {
            characterClassDepth--;
            current += char;
            continue;
        }
        if (characterClassDepth === 0 && char === "(") {
            groupDepth++;
            current += char;
            continue;
        }
        if (characterClassDepth === 0 && char === ")" && groupDepth > 0) {
            groupDepth--;
            current += char;
            continue;
        }
        if (characterClassDepth === 0 && groupDepth === 0 && char === "|") {
            parts.push(current);
            current = "";
            continue;
        }
        current += char;
    }
    parts.push(current);
    return parts;
}
function getSuggestionLookupTerms(original, isRegex) {
    const terms = new Map();
    const addTerm = (value) => {
        const term = value.replace(/\s+/g, " ").trim();
        if (term.length >= 2) {
            terms.set(term.toLocaleLowerCase(), term);
        }
    };
    addTerm(original);
    const splitPattern = isRegex ? /[\n,;]+/ : /[\n,;|/]+/;
    original.split(splitPattern).forEach(addTerm);
    if (isRegex) {
        for (const fragment of splitTopLevelAlternatives(original)) {
            addTerm(stripRegexSyntax(fragment));
            stripRegexSyntax(fragment)
                .split(/[|,;\n]+/)
                .forEach(addTerm);
        }
        stripRegexSyntax(original)
            .split(/[|,;\n]+/)
            .forEach(addTerm);
    }
    return Array.from(terms.values());
}
function findNovelCandidatesByOriginalInput(original, isRegex, caseSensitive) {
    const discovery = ensureDiscoveryState();
    const novelTerms = discovery.novelTerms;
    const deduped = new Map();
    const lookupTerms = getSuggestionLookupTerms(original, isRegex);
    const lookupSet = new Set(lookupTerms.map((term) => (caseSensitive ? term : term.toLocaleLowerCase())));
    const addCandidate = (candidate) => {
        deduped.set(candidate.term.toLocaleLowerCase(), candidate);
    };
    const getCandidateLookupValues = (candidate) => [
        candidate.term,
        ...(candidate.replacement ? [candidate.replacement] : []),
        ...(candidate.replacementSuggestions || []),
    ];
    for (const candidate of novelTerms) {
        const candidateValues = getCandidateLookupValues(candidate).map((value) => (caseSensitive ? value : value.toLocaleLowerCase()));
        if (candidateValues.some((candidateValue) => lookupSet.has(candidateValue))) {
            addCandidate(candidate);
        }
    }
    if (isRegex) {
        try {
            const regex = new RegExp(original, caseSensitive ? "" : "i");
            for (const candidate of novelTerms) {
                if (getCandidateLookupValues(candidate).some((value) => regex.test(value))) {
                    addCandidate(candidate);
                }
            }
        }
        catch (_error) {
            // Invalid in-progress regex input still gets literal/variant suggestions from extracted terms.
        }
    }
    return Array.from(deduped.values()).slice(0, 10);
}
function mergeReplacementSuggestions(candidates, suggestions) {
    const mergedSuggestions = [];
    for (const candidate of candidates) {
        mergedSuggestions.push({
            replacement: candidate.term,
            count: candidate.count || 0,
            sourceLabel: "Source",
            sourceRank: -10,
        });
        const candidateReplacements = candidate.replacementSuggestions?.length
            ? candidate.replacementSuggestions
            : candidate.replacement
                ? [candidate.replacement]
                : [];
        candidateReplacements.forEach((replacement) => {
            mergedSuggestions.push({
                replacement,
                count: candidate.count || 0,
                sourceLabel: "WTR",
                sourceRank: 30,
            });
        });
    }
    mergedSuggestions.push(...suggestions.map((suggestion) => ({
        ...suggestion,
        sourceLabel: suggestion.sourceLabel || "API",
        sourceRank: suggestion.sourceRank ?? 40,
    })));
    return dedupeReplacementSuggestions(mergedSuggestions);
}
let replacementSuggestionRequestId = 0;
let replacementSuggestionTimeout = null;
let suppressNextReplacementSuggestionInput = false;
let activeSuggestionTarget = "replacement";
function isActiveReplacementSuggestionRequest(requestId, inputValue) {
    return requestId === replacementSuggestionRequestId && getOriginalInputOptions().value === inputValue;
}
function getOriginalInputFieldSuggestions(value, isRegex) {
    if (!isRegex) {
        return [];
    }
    return normalizeOriginalRegexPattern(value)
        .split("|")
        .map((part) => normalizeReplacementSuggestion(part, 0, "Field", 5))
        .filter((suggestion) => Boolean(suggestion));
}
async function updateReplacementSuggestionsForCandidates(candidates, inputValue, mergeExisting = false, seedSuggestions = []) {
    const discovery = ensureDiscoveryState();
    const existingSuggestions = mergeExisting ? [...(discovery.replacementSuggestions || [])] : [];
    discovery.selectedCandidate = candidates[0] || null;
    const requestId = ++replacementSuggestionRequestId;
    if (candidates.length === 0) {
        const mergedExistingSuggestions = dedupeReplacementSuggestions([...existingSuggestions, ...seedSuggestions]);
        discovery.replacementSuggestions = mergedExistingSuggestions;
        renderReplacementSuggestions(mergedExistingSuggestions);
        return;
    }
    const loadedSuggestions = await Promise.all(candidates.map(async (candidate) => {
        if (!hasPreferenceIdentifiers(candidate)) {
            return [];
        }
        try {
            return await loadReplacementSuggestions(candidate);
        }
        catch (error) {
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Replacement suggestions unavailable", error);
            return [];
        }
    }));
    if (!isActiveReplacementSuggestionRequest(requestId, inputValue)) {
        return;
    }
    const mergedSuggestions = dedupeReplacementSuggestions([
        ...existingSuggestions,
        ...seedSuggestions,
        ...mergeReplacementSuggestions(candidates, loadedSuggestions.flat()),
    ]);
    discovery.replacementSuggestions = mergedSuggestions;
    renderReplacementSuggestions(mergedSuggestions, mergedSuggestions.length ? "" : "No replacement suggestions found for this original text.");
}
function clearDiscoveryFormState() {
    if (replacementSuggestionTimeout) {
        clearTimeout(replacementSuggestionTimeout);
        replacementSuggestionTimeout = null;
    }
    const discovery = ensureDiscoveryState();
    discovery.replacementSuggestions = [];
    discovery.selectedCandidate = null;
    replacementSuggestionRequestId++;
    const suggestionsContainer = document.getElementById("wtr-replacement-suggestions");
    if (suggestionsContainer) {
        suggestionsContainer.textContent = "";
    }
}
function handleReplacementSuggestionInput(event) {
    if (suppressNextReplacementSuggestionInput) {
        suppressNextReplacementSuggestionInput = false;
        return;
    }
    if (replacementSuggestionTimeout) {
        clearTimeout(replacementSuggestionTimeout);
    }
    const mergeExisting = Boolean(event?.mergeExisting);
    replacementSuggestionTimeout = setTimeout(async () => {
        const sourceValue = event?.target?.value;
        const options = getOriginalInputOptions();
        const query = typeof sourceValue === "string" ? sourceValue.trim() : options.value;
        const discovery = ensureDiscoveryState();
        const fieldSuggestions = getOriginalInputFieldSuggestions(query, options.isRegex);
        if (!query) {
            updateReplacementSuggestionsForCandidates([], query, mergeExisting, fieldSuggestions);
            return;
        }
        if (discovery.novelTerms.length === 0) {
            try {
                discovery.novelTerms = await loadNovelTermEntries(false);
            }
            catch (error) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Replacement suggestions unavailable", error);
            }
        }
        updateReplacementSuggestionsForCandidates(findNovelCandidatesByOriginalInput(query, options.isRegex, options.caseSensitive), query, mergeExisting, fieldSuggestions);
    }, 250);
}
async function handleRefreshSuggestionsClick() {
    if (replacementSuggestionTimeout) {
        clearTimeout(replacementSuggestionTimeout);
        replacementSuggestionTimeout = null;
    }
    const options = getOriginalInputOptions();
    if (!options.value) {
        renderReplacementSuggestions([], "Enter Original Text first, then refresh suggestions.");
        return;
    }
    renderReplacementSuggestions([], "Refreshing suggestions...");
    try {
        const discovery = ensureDiscoveryState();
        discovery.novelTerms = await loadNovelTermEntries(true);
        await updateReplacementSuggestionsForCandidates(findNovelCandidatesByOriginalInput(options.value, options.isRegex, options.caseSensitive), options.value, true, getOriginalInputFieldSuggestions(options.value, options.isRegex));
    }
    catch (error) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Replacement suggestion refresh failed", error);
        renderReplacementSuggestions([], "Suggestions are unavailable right now.");
    }
}
function handleSuggestionTargetFocus(event) {
    const fieldId = event?.target?.id;
    if (fieldId === "wtr-original") {
        activeSuggestionTarget = "original";
    }
    else if (fieldId === "wtr-replacement") {
        activeSuggestionTarget = "replacement";
    }
}
function getExistingSuggestionTokens(value) {
    return new Set(value
        .split(/\s*(?:\||\/|,|;|\n)\s*/)
        .map((token) => token.trim())
        .filter(Boolean));
}
function getReplacementAppendSeparator(value, isRegex) {
    if (value.includes("\n")) {
        return "\n";
    }
    if (value.includes(" | ")) {
        return " | ";
    }
    if (value.includes("|")) {
        return "|";
    }
    if (value.includes(" / ") || value.includes("/")) {
        return " / ";
    }
    if (value.includes(";")) {
        return "; ";
    }
    if (value.includes(",")) {
        return ", ";
    }
    return "|";
}
function normalizeOriginalRegexPattern(value) {
    const deduped = new Map();
    value
        .trim()
        .replace(/\s*\|\s*/g, "|")
        .replace(/\s*\/\s*/g, "|")
        .split("|")
        .map((part) => part.trim())
        .filter(Boolean)
        .forEach((part) => deduped.set(part, part));
    return Array.from(deduped.values())
        .sort((a, b) => b.length - a.length || a.localeCompare(b))
        .join("|");
}
function normalizeOriginalRegexField() {
    const regexCheckbox = document.getElementById("wtr-is-regex");
    const originalInput = document.getElementById("wtr-original");
    if (!regexCheckbox?.checked || !originalInput) {
        return;
    }
    const normalized = normalizeOriginalRegexPattern(originalInput.value);
    if (normalized && normalized !== originalInput.value) {
        originalInput.value = normalized;
        suppressNextReplacementSuggestionInput = true;
        originalInput.dispatchEvent(new Event("input", { bubbles: true }));
    }
}
function getSuggestionAppendSeparator(value, isRegex, targetField) {
    if (targetField === "original") {
        return "|";
    }
    return getReplacementAppendSeparator(value, isRegex);
}
function mergeSuggestionInputValue(currentValue, suggestion, isRegex, selectionStart, selectionEnd, targetField) {
    const replacement = suggestion.trim();
    if (!replacement) {
        return currentValue;
    }
    if (selectionStart !== null && selectionEnd !== null && selectionEnd > selectionStart) {
        return `${currentValue.slice(0, selectionStart)}${replacement}${currentValue.slice(selectionEnd)}`;
    }
    const trimmedValue = currentValue.trim();
    if (!trimmedValue) {
        return replacement;
    }
    if (getExistingSuggestionTokens(trimmedValue).has(replacement)) {
        return currentValue;
    }
    return `${currentValue.trimEnd()}${getSuggestionAppendSeparator(trimmedValue, isRegex, targetField)}${replacement}`;
}
function normalizePopoverText(value) {
    return (value || "").replace(/\s+/g, " ").trim();
}
function getElementClassText(element) {
    if (!element) {
        return "";
    }
    return typeof element.className === "string" ? element.className : element.getAttribute("class") || "";
}
function getPopoverBadgeCount(badge) {
    const countText = normalizePopoverText(badge.closest(".user-term")?.querySelector(".badge-segment span:last-child")?.textContent);
    if (!countText) {
        return 0;
    }
    if (countText.endsWith("+")) {
        return Number.parseInt(countText, 10) || 0;
    }
    return Number(countText) || 0;
}
function getPopoverBadgeSuggestion(badge) {
    const label = badge.querySelector("span:last-child") || badge;
    const replacement = normalizePopoverText(label.textContent);
    if (!replacement) {
        return null;
    }
    const userTerm = badge.closest(".user-term");
    const iconHref = badge.querySelector("use")?.getAttribute("href") || "";
    const classSource = `${getElementClassText(badge)} ${getElementClassText(userTerm)} ${iconHref}`;
    if (/google|g_translate|bg-primary/i.test(classSource)) {
        return normalizeReplacementSuggestion(replacement, getPopoverBadgeCount(badge), "Google", 90);
    }
    if (/dictionary|bg-success/i.test(classSource)) {
        return normalizeReplacementSuggestion(replacement, getPopoverBadgeCount(badge), "WTR", 30);
    }
    if (userTerm) {
        return normalizeReplacementSuggestion(replacement, getPopoverBadgeCount(badge), "WTR", 40);
    }
    return normalizeReplacementSuggestion(replacement, getPopoverBadgeCount(badge), "WTR", 50);
}
function getWtrPopoverContextFromElement(element) {
    const sourceTerm = normalizePopoverText(element.querySelector(".text-underscore")?.textContent);
    const popoverSuggestions = Array.from(element.querySelectorAll(".user-term .badge, .badge.bg-success, .badge.bg-primary"))
        .map(getPopoverBadgeSuggestion)
        .filter((suggestion) => Boolean(suggestion));
    const recentContext = state/* state */.wk.wtrPopoverTermContext || {};
    const recentSuggestions = Array.isArray(recentContext.suggestions) ? recentContext.suggestions : [];
    const original = normalizePopoverText(recentContext.original) || popoverSuggestions[0]?.replacement || sourceTerm;
    const resolvedSourceTerm = sourceTerm || normalizePopoverText(recentContext.sourceTerm);
    const sourceSuggestion = normalizeReplacementSuggestion(resolvedSourceTerm, 0, "Source", -10);
    const currentSuggestion = normalizeReplacementSuggestion(original, 0, "Current", 0);
    const resolvedSuggestions = dedupeReplacementSuggestions([
        ...(sourceSuggestion ? [sourceSuggestion] : []),
        ...(currentSuggestion ? [currentSuggestion] : []),
        ...popoverSuggestions,
        ...recentSuggestions,
    ]);
    if (!original && !resolvedSourceTerm && resolvedSuggestions.length === 0) {
        return null;
    }
    return {
        original,
        sourceTerm: resolvedSourceTerm,
        suggestions: resolvedSuggestions,
    };
}
function encodePopoverContext(context) {
    return JSON.stringify(context);
}
function decodePopoverContext(value) {
    if (!value) {
        return null;
    }
    try {
        return JSON.parse(value);
    }
    catch (_error) {
        return null;
    }
}
function openWtrPopoverTermContext(context) {
    (0,ui/* showUIPanel */.E1)();
    suppressNextReplacementSuggestionInput = true;
    (0,ui/* showFormView */.BD)();
    const originalInput = document.getElementById("wtr-original");
    const replacementInput = document.getElementById("wtr-replacement");
    if (!originalInput || !replacementInput) {
        return;
    }
    originalInput.value = context.original || context.suggestions[0]?.replacement || context.sourceTerm || "";
    originalInput.rows = Math.max(1, Math.ceil(originalInput.value.length / 40));
    replacementInput.value = "";
    ensureDiscoveryState().replacementSuggestions = dedupeReplacementSuggestions(context.suggestions);
    renderReplacementSuggestions(ensureDiscoveryState().replacementSuggestions);
    activeSuggestionTarget = "replacement";
    replacementInput.focus();
}
function handleWtrTextPatchClick(event) {
    const patch = event.target?.closest?.(".text-patch[data-hash]");
    if (!patch) {
        return;
    }
    const visibleText = normalizePopoverText(patch.textContent);
    const sourceTerm = normalizePopoverText(patch.getAttribute("data-hash"));
    const sourceSuggestion = normalizeReplacementSuggestion(sourceTerm, 0, "Source", -10);
    const currentSuggestion = normalizeReplacementSuggestion(visibleText, 0, "Current", 0);
    state/* state */.wk.wtrPopoverTermContext = {
        original: visibleText,
        sourceTerm,
        suggestions: [sourceSuggestion, currentSuggestion].filter((suggestion) => Boolean(suggestion)),
    };
}
function enhanceWtrTermPopovers(root = document) {
    const editors = [
        ...(root instanceof Element && root.matches(".mini-term-editor") ? [root] : []),
        ...Array.from(root.querySelectorAll(".mini-term-editor")),
    ];
    editors.forEach((editor) => {
        if (editor.querySelector(".wtr-replacer-popover-actions")) {
            return;
        }
        const popoverRoot = editor.closest(".popover-body") || editor;
        const context = getWtrPopoverContextFromElement(popoverRoot);
        if (!context) {
            return;
        }
        const encodedContext = encodePopoverContext(context);
        const actionColumn = editor.querySelector(".d-flex.flex-column.ms-2") || editor;
        const buttonGroup = document.createElement("div");
        buttonGroup.className = "wtr-replacer-popover-actions";
        const openButton = document.createElement("button");
        openButton.type = "button";
        openButton.className = "mt-1 btn btn-outline-primary btn-sm wtr-replacer-popover-add-btn";
        openButton.textContent = "+ Replacer Term";
        openButton.dataset.wtrContext = encodedContext;
        buttonGroup.appendChild(openButton);
        actionColumn.appendChild(buttonGroup);
    });
}
function handleWtrPopoverAddTermClick(event) {
    const button = event.target?.closest?.(".wtr-replacer-popover-add-btn");
    if (!button) {
        return;
    }
    event.preventDefault();
    event.stopPropagation();
    const context = decodePopoverContext(button.dataset.wtrContext) || getWtrPopoverContextFromElement(button.closest(".popover-body") || button);
    if (!context) {
        return;
    }
    openWtrPopoverTermContext(context);
}
function handleReplacementSuggestionClick(event) {
    const button = event.target.closest(".wtr-replacement-suggestion-btn");
    if (!button) {
        return;
    }
    const originalInput = document.getElementById("wtr-original");
    const replacementInput = document.getElementById("wtr-replacement");
    const regexCheckbox = document.getElementById("wtr-is-regex");
    const targetField = activeSuggestionTarget;
    const targetInput = targetField === "original" ? originalInput : replacementInput;
    if (targetInput) {
        targetInput.value = mergeSuggestionInputValue(targetInput.value, button.dataset.replacement || "", Boolean(regexCheckbox?.checked), targetInput.selectionStart, targetInput.selectionEnd, targetField);
        if (targetField === "original") {
            suppressNextReplacementSuggestionInput = true;
        }
        targetInput.dispatchEvent(new Event("input", { bubbles: true }));
        targetInput.focus();
    }
}
async function handleSaveTerm() {
    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Handle save term started");
    const id = document.getElementById("wtr-term-id").value;
    const originalInput = document.getElementById("wtr-original");
    const replacementInput = document.getElementById("wtr-replacement");
    const isRegex = document.getElementById("wtr-is-regex").checked;
    let original = originalInput.value.trim();
    if (isRegex) {
        original = normalizeOriginalRegexPattern(original);
        originalInput.value = original;
    }
    const wholeWord = document.getElementById("wtr-whole-word").checked;
    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Saving term - original: "${original}", replacement: "${replacementInput.value}", isRegex: ${isRegex}, wholeWord: ${wholeWord}, caseSensitive: ${document.getElementById("wtr-case-sensitive").checked}`);
    if (!original) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Save term failed - empty original text");
        return; // No error message shown, rely on disabled save button
    }
    if (isRegex && !validateRegex(original)) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Save term failed - invalid regex pattern");
        return; // No error message shown, rely on visual feedback
    }
    const newTerm = {
        id: id || `term_${Date.now()}`,
        original,
        replacement: replacementInput.value,
        caseSensitive: document.getElementById("wtr-case-sensitive").checked,
        isRegex,
        wholeWord: isRegex ? false : wholeWord,
    };
    const existingIndex = state/* state */.wk.terms.findIndex((t) => t.id === newTerm.id);
    if (existingIndex > -1) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Updating existing term ${newTerm.id}`);
        state/* state */.wk.terms[existingIndex] = newTerm;
    }
    else {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Adding new term ${newTerm.id}`);
        state/* state */.wk.terms.push(newTerm);
    }
    await (0,storage.saveTerms)(state/* state */.wk.terms);
    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Term saved successfully, total terms: ${state/* state */.wk.terms.length}`);
    (0,observer/* reprocessCurrentChapter */.J)();
    // Clear form fields
    originalInput.value = "";
    replacementInput.value = "";
    document.getElementById("wtr-term-id").value = "";
    document.getElementById("wtr-case-sensitive").checked = false;
    document.getElementById("wtr-is-regex").checked = false;
    document.getElementById("wtr-whole-word").checked = false;
    document.getElementById("wtr-save-btn").textContent = "Save Term";
    clearDiscoveryFormState();
    (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
    if (id) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Switching to terms tab after update");
        (0,ui/* switchTab */.OG)("terms");
    }
    else {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Focusing on original input for next term");
        originalInput.focus();
    }
    if (state/* state */.wk.isDupMode) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Updating duplicate mode after term change");
        (0,duplicates/* updateDupModeAfterChange */.Cs)();
    }
}
function handleListInteraction(e) {
    const termId = e.target.closest("li")?.dataset.id;
    if (!termId) {
        return;
    }
    if (e.target.classList.contains("wtr-edit-btn")) {
        const term = state/* state */.wk.terms.find((t) => t.id === termId);
        if (term) {
            (0,ui/* showFormView */.BD)(term);
        }
    }
}
async function handleDeleteSelected() {
    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Delete selected terms started");
    (0,ui/* showUILoader */.Xt)();
    try {
        const selectedIds = [...document.querySelectorAll(".wtr-replacer-term-select:checked")].map((cb) => cb.dataset.id);
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Found ${selectedIds.length} terms selected for deletion: ${selectedIds.join(", ")}`);
        if (selectedIds.length === 0) {
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Delete cancelled - no terms selected");
            alert("No terms selected.");
            return;
        }
        if (confirm(`Delete ${selectedIds.length} term(s)?`)) {
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: User confirmed deletion, proceeding...");
            const filteredTerms = state/* state */.wk.terms.filter((t) => !selectedIds.includes(t.id));
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Deleting ${state/* state */.wk.terms.length - filteredTerms.length} terms, ${filteredTerms.length} remaining`);
            await (0,storage.saveTerms)(filteredTerms);
            await (0,storage.loadData)();
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Terms deleted and data reloaded");
            (0,observer/* reprocessCurrentChapter */.J)();
            if (state/* state */.wk.isDupMode) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Updating duplicate mode after deletion");
                (0,duplicates/* updateDupModeAfterChange */.Cs)();
            }
            else {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Refreshing term list display");
                (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
            }
        }
        else {
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Delete cancelled by user");
        }
    }
    catch (error) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Error during term deletion: ${error.message}`);
        console.error("Error during term deletion:", error);
    }
    finally {
        (0,ui/* hideUILoader */.W4)();
    }
}
function handleTextSelection(e) {
    const CHAPTER_BODY_SELECTOR = ".chapter-body";
    if (!e.target.closest(CHAPTER_BODY_SELECTOR)) {
        return;
    }
    const selection = window.getSelection().toString().trim();
    const floatBtn = document.querySelector(".wtr-add-term-float-btn");
    if (selection && selection.length > 0 && selection.length < 100) {
        floatBtn.style.display = "block";
    }
    else {
        floatBtn.style.display = "none";
    }
}
function handleAddTermFromSelection() {
    const selection = window.getSelection().toString().trim();
    if (selection) {
        (0,ui/* showUIPanel */.E1)();
        (0,ui/* showFormView */.BD)();
        document.getElementById("wtr-original").value = selection;
        document.getElementById("wtr-replacement").focus();
    }
    document.querySelector(".wtr-add-term-float-btn").style.display = "none";
}
function handleSearch(e) {
    if (state/* state */.wk.isDupMode) {
        return;
    }
    state/* state */.wk.currentSearchValue = e.target.value;
    state/* state */.wk.currentPage = 1;
    (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
    // Immediately save the search field value for reactive behavior
    (0,storage.saveSearchFieldValue)();
}
async function handleDisableToggle(e) {
    state/* state */.wk.settings.isDisabled = e.target.checked;
    await (0,storage.saveSettings)(state/* state */.wk.settings);
    const getChapterIdFromUrl = (url) => {
        const match = url.match(/(chapter-\d+)/);
        return match ? match[1] : null;
    };
    const CHAPTER_BODY_SELECTOR = ".chapter-body";
    const chapterId = getChapterIdFromUrl(window.location.href);
    if (!chapterId) {
        return;
    }
    const chapterSelector = `#${chapterId} ${CHAPTER_BODY_SELECTOR}`;
    const chapterBody = document.querySelector(chapterSelector);
    if (chapterBody) {
        if (state/* state */.wk.settings.isDisabled) {
            (0,engine.revertAllReplacements)(chapterBody);
        }
        else {
            (0,engine.performReplacements)(chapterBody);
        }
    }
}
function downloadJSON(data, filename) {
    return new Promise((resolve) => {
        const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        resolve();
    });
}
// Enhanced Export Functions
async function handleExportNovel() {
    const exportData = {
        formatVersion: (0,versions.getVersion)(),
        settings: { [state/* state */.wk.novelSlug]: state/* state */.wk.settings },
        terms: { [state/* state */.wk.novelSlug]: state/* state */.wk.terms },
    };
    downloadJSON(exportData, `${state/* state */.wk.novelSlug}-terms.json`);
}
async function handleExportAll() {
    (0,ui/* showUILoader */.Xt)();
    try {
        const allKeys = await GM_listValues();
        const TERMS_STORAGE_KEY_PREFIX = "wtr_lab_terms_";
        const SETTINGS_STORAGE_KEY_PREFIX = "wtr_lab_settings_";
        const termKeys = allKeys.filter((k) => k.startsWith(TERMS_STORAGE_KEY_PREFIX));
        const settingKeys = allKeys.filter((k) => k.startsWith(SETTINGS_STORAGE_KEY_PREFIX));
        const exportData = { formatVersion: (0,versions.getVersion)(), settings: {}, terms: {} };
        for (const key of termKeys) {
            const slug = key.replace(TERMS_STORAGE_KEY_PREFIX, "");
            exportData.terms[slug] = await GM_getValue(key);
        }
        for (const key of settingKeys) {
            const slug = key.replace(SETTINGS_STORAGE_KEY_PREFIX, "");
            exportData.settings[slug] = await GM_getValue(key);
        }
        downloadJSON(exportData, "wtr-lab-all-terms-backup.json");
    }
    catch (e) {
        console.error("Error exporting all terms:", e);
        alert("Failed to export all terms.");
    }
    finally {
        (0,ui/* hideUILoader */.W4)();
    }
}
// Enhanced dual export functionality with sequential downloads
async function handleExportCombined() {
    (0,ui/* showUILoader */.Xt)();
    try {
        // Step 1: Export novel terms first
        const novelExportData = {
            formatVersion: (0,versions.getVersion)(),
            settings: { [state/* state */.wk.novelSlug]: state/* state */.wk.settings },
            terms: { [state/* state */.wk.novelSlug]: state/* state */.wk.terms },
        };
        await downloadJSON(novelExportData, `${state/* state */.wk.novelSlug}-terms.json`);
        // Step 2: Ask user for confirmation before proceeding to second download
        const userConfirmed = confirm('The first file (Novel Terms) has been downloaded. Please check if the download completed successfully. Click "OK" to proceed with the second download (All Terms backup), or "Cancel" to skip.');
        if (userConfirmed) {
            // Step 3: Export all terms only after user confirmation
            const allKeys = await GM_listValues();
            const TERMS_STORAGE_KEY_PREFIX = "wtr_lab_terms_";
            const SETTINGS_STORAGE_KEY_PREFIX = "wtr_lab_settings_";
            const termKeys = allKeys.filter((k) => k.startsWith(TERMS_STORAGE_KEY_PREFIX));
            const settingKeys = allKeys.filter((k) => k.startsWith(SETTINGS_STORAGE_KEY_PREFIX));
            const allExportData = { formatVersion: (0,versions.getVersion)(), settings: {}, terms: {} };
            for (const key of termKeys) {
                const slug = key.replace(TERMS_STORAGE_KEY_PREFIX, "");
                allExportData.terms[slug] = await GM_getValue(key);
            }
            for (const key of settingKeys) {
                const slug = key.replace(SETTINGS_STORAGE_KEY_PREFIX, "");
                allExportData.settings[slug] = await GM_getValue(key);
            }
            await downloadJSON(allExportData, "wtr-lab-all-terms-backup.json");
            alert("Both files have been successfully exported!");
        }
        else {
            alert("Second export cancelled. Only the novel terms file was downloaded.");
        }
    }
    catch (e) {
        console.error("Error exporting combined terms:", e);
        alert("Failed to export combined terms. Please try again.");
    }
    finally {
        (0,ui/* hideUILoader */.W4)();
    }
}
async function handleFileImport(event) {
    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: File import started, import type: ${state/* state */.wk.importType}`);
    (0,ui/* showUILoader */.Xt)();
    try {
        const file = event.target.files[0];
        if (!file) {
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: No file selected for import");
            return;
        }
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Importing file: ${file.name}, size: ${file.size} bytes, type: ${file.type}`);
        const reader = new FileReader();
        reader.onload = async (e) => {
            const content = String(e.target.result ?? "");
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: File content loaded, length: ${content.length} characters`);
            let importedData;
            try {
                importedData = JSON.parse(content);
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: JSON parsed successfully");
            }
            catch (err) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Import failed - invalid JSON: ${err.message}`);
                alert("Import failed. Invalid JSON data. Error: " + err.message);
                return;
            }
            const isNewFormat = Boolean(importedData.formatVersion);
            let termsData;
            let settingsData;
            const isArrayData = Array.isArray(importedData);
            const isOldGlobal = !isNewFormat && !isArrayData && typeof importedData === "object";
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Detected format - isNewFormat: ${isNewFormat}, isArrayData: ${isArrayData}, isOldGlobal: ${isOldGlobal}`);
            if (isArrayData) {
                termsData = { [state/* state */.wk.novelSlug]: importedData };
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Array format detected, mapping to current novel");
            }
            else if (isOldGlobal) {
                termsData = importedData;
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Old global format detected");
            }
            else if (isNewFormat) {
                termsData = importedData.terms || {};
                settingsData = importedData.settings || {};
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: New format detected - terms: ${Object.keys(termsData).length} slugs, settings: ${Object.keys(settingsData).length} slugs`);
            }
            else {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Import failed - unrecognized data format");
                alert("Import failed. Unrecognized data format.");
                return;
            }
            let slugs = Object.keys(termsData);
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Found data for ${slugs.length} slugs: ${slugs.join(", ")}`);
            if (state/* state */.wk.importType === "novel" && slugs.length > 1) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Novel import with multiple slugs - warning user");
                alert("Warning: File contains data for multiple novels, but importing to current novel only. Use Global Import for all.");
                termsData = { [state/* state */.wk.novelSlug]: termsData[Object.keys(termsData)[0]] || [] };
                if (settingsData) {
                    settingsData = { [state/* state */.wk.novelSlug]: settingsData[Object.keys(settingsData)[0]] || {} };
                }
                slugs = [state/* state */.wk.novelSlug];
            }
            let shouldImportSettings = false;
            if (settingsData && Object.keys(settingsData).length > 0) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Settings detected in import, asking user for confirmation");
                shouldImportSettings = confirm("This file contains settings. Would you like to import and overwrite your current settings?");
            }
            let totalAdded = 0, totalSkipped = 0, totalConflicts = 0, invalidCount = 0, validCount = 0;
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Starting term import process...");
            for (const slug of slugs) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Processing import for slug: ${slug}`);
                const existingTerms = await GM_getValue(`wtr_lab_terms_${slug}`, []);
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Existing terms for ${slug}: ${existingTerms.length}`);
                let overwrite = true;
                if (existingTerms.length > 0) {
                    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Existing terms found for ${slug}, asking user about merge vs overwrite`);
                    overwrite = !confirm(`An existing term list was found for ${slug}. Would you like to merge? (OK = Merge, Cancel = Overwrite)`);
                    if (!overwrite) {
                        if (!confirm("Are you sure you want to overwrite?")) {
                            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: User cancelled overwrite for ${slug}`);
                            continue;
                        }
                        overwrite = true;
                    }
                }
                const rawTerms = termsData[slug] || [];
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Raw terms for ${slug}: ${rawTerms.length}`);
                if (!Array.isArray(rawTerms)) {
                    (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Skipping ${slug} - not an array`);
                    continue;
                }
                const validatedTerms = rawTerms.filter((term) => {
                    term.wholeWord = term.wholeWord ?? false;
                    if (term.isRegex) {
                        try {
                            new RegExp(term.original);
                            validCount++;
                            return true;
                        }
                        catch (err) {
                            invalidCount++;
                            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Skipping invalid regex term: "${term.original}" - ${err.message}`);
                            console.warn(`Skipping invalid regex term on import: "${term.original}"`);
                            return false;
                        }
                    }
                    validCount++;
                    return true;
                });
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Validated terms for ${slug}: ${validatedTerms.length} valid, ${invalidCount} invalid`);
                const { added, skipped, conflicts } = await (0,storage.processAndSaveTerms)(slug, validatedTerms, overwrite);
                totalAdded += added;
                totalSkipped += skipped;
                totalConflicts += conflicts;
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Import results for ${slug} - added: ${added}, skipped: ${skipped}, conflicts: ${conflicts}`);
            }
            if (shouldImportSettings) {
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Importing settings data...");
                await (0,storage.processAndSaveSettings)(settingsData);
            }
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Reloading data and reprocessing chapters...");
            await (0,storage.loadData)();
            (0,observer/* reprocessCurrentChapter */.J)();
            (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
            if (state/* state */.wk.isDupMode) {
                (0,duplicates/* updateDupModeAfterChange */.Cs)();
            }
            let summary = "Import successful!";
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Import completed - totalAdded: ${totalAdded}, totalSkipped: ${totalSkipped}, totalConflicts: ${totalConflicts}, invalidCount: ${invalidCount}, validCount: ${validCount}`);
            if (totalAdded > 0 || totalSkipped > 0 || totalConflicts > 0) {
                summary += `\n${totalAdded} new terms added. ${totalSkipped} duplicates skipped. ${totalConflicts} conflicts skipped.`;
            }
            if (invalidCount > 0) {
                summary += `\n${validCount} terms imported. ${invalidCount} terms skipped due to invalid regex.`;
            }
            alert(summary);
        };
        reader.readAsText(file);
        event.target.value = "";
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: File import process initiated");
    }
    catch (e) {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Import error: ${e.message}`);
        alert("An error occurred during import.");
        console.error(e);
    }
    finally {
        (0,ui/* hideUILoader */.W4)();
    }
}
function handleTabSwitch(e) {
    const targetTab = e.target.dataset.tab;
    // Save current state before switching (if on terms tab)
    const currentTab = document.querySelector(".wtr-replacer-tab-btn.active").dataset.tab;
    if (currentTab === "terms") {
        // Save the full scroll position when leaving terms tab
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Saving scroll position before switching from terms to ${targetTab}`);
        (0,storage.saveTermListLocation)();
    }
    document.querySelectorAll(".wtr-replacer-tab-btn").forEach((btn) => btn.classList.remove("active"));
    e.target.classList.add("active");
    document.querySelectorAll(".wtr-replacer-tab-content").forEach((content) => content.classList.remove("active"));
    document.getElementById(`wtr-tab-${targetTab}`).classList.add("active");
    if (targetTab === "terms") {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, "WTR Term Replacer: Restoring scroll position after switching to terms tab");
        restoreTermListLocation();
    }
    else {
        (0,ui/* clearTermList */.kH)();
    }
}
async function handleFindDuplicates() {
    (0,ui/* showUILoader */.Xt)();
    try {
        const TERMS_KEY = `wtr_lab_terms_${state/* state */.wk.novelSlug}`;
        const currentNovelTerms = await GM_getValue(TERMS_KEY, []);
        (0,duplicates/* computeDupGroups */.r_)(currentNovelTerms);
        if (state/* state */.wk.dupKeys.length === 0) {
            alert("No duplicates found.");
            return;
        }
        state/* state */.wk.isDupMode = true;
        state/* state */.wk.currentDupIndex = 0;
        state/* state */.wk.currentSearchValue = "";
        setSearchFieldValue("");
    }
    finally {
        (0,ui/* hideUILoader */.W4)();
    }
}
// Use duplicate functions from duplicates module (imported above)
// Helper function to set search field value programmatically with reactive save
function setSearchFieldValue(value) {
    const searchBar = document.getElementById("wtr-search-bar");
    if (searchBar) {
        searchBar.value = value;
        state/* state */.wk.currentSearchValue = value;
        state/* state */.wk.currentPage = 1;
        (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
        (0,storage.saveSearchFieldValue)();
    }
}
async function restoreTermListLocation() {
    try {
        const saved = await GM_getValue(`wtr_lab_term_list_location_${state/* state */.wk.novelSlug}`, null);
        if (saved) {
            state/* state */.wk.savedTermListLocation = saved;
            (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Restoring scroll position - top: ${saved.scrollTop}, page: ${saved.page}`);
        }
        state/* state */.wk.currentPage = state/* state */.wk.savedTermListLocation.page || 1;
        state/* state */.wk.currentSearchValue = state/* state */.wk.savedTermListLocation.searchValue || "";
        // Apply the saved state to the UI
        const searchBar = document.getElementById("wtr-search-bar");
        if (searchBar && state/* state */.wk.currentSearchValue) {
            searchBar.value = state/* state */.wk.currentSearchValue;
        }
        (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
        // Restore scroll position after a short delay to ensure rendering is complete
        setTimeout(() => {
            const termListContainer = document.querySelector(".wtr-replacer-content");
            if (termListContainer && state/* state */.wk.savedTermListLocation.scrollTop) {
                termListContainer.scrollTop = state/* state */.wk.savedTermListLocation.scrollTop;
                (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Scroll position restored to ${state/* state */.wk.savedTermListLocation.scrollTop}`);
            }
        }, 100);
    }
    catch (e) {
        console.error("Error restoring term list location:", e);
    }
}
function toggleLogging() {
    state/* state */.wk.globalSettings.isLoggingEnabled = !state/* state */.wk.globalSettings.isLoggingEnabled;
    (0,storage.saveGlobalSettings)();
    alert(`Logging ${state/* state */.wk.globalSettings.isLoggingEnabled ? "enabled" : "disabled"}.`);
}
// Additional functions needed for index.js integration
async function addTermProgrammatically(original, replacement, isRegex = false) {
    if (!original) {
        return;
    }
    const newTerm = {
        id: `term_${Date.now()}`,
        original: original.trim(),
        replacement: replacement.trim(),
        caseSensitive: false,
        isRegex: isRegex,
        wholeWord: isRegex ? false : false,
    };
    const isDuplicate = state/* state */.wk.terms.some((t) => t.original === newTerm.original && t.replacement === newTerm.replacement && t.isRegex === newTerm.isRegex);
    if (!isDuplicate) {
        state/* state */.wk.terms.push(newTerm);
        await (0,storage.saveTerms)(state/* state */.wk.terms);
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Programmatically added term (Regex: ${isRegex}): ${newTerm.original} -> ${newTerm.replacement}`);
        if (document.querySelector(".wtr-replacer-ui").style.display === "flex") {
            (0,ui/* renderTermList */.FP)(state/* state */.wk.currentSearchValue);
        }
    }
    else {
        (0,utils/* log */.Rm)(state/* state */.wk.globalSettings, `WTR Term Replacer: Skipped adding duplicate term: ${newTerm.original}`);
    }
}


/***/ },

/***/ 405
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   J: () => (/* binding */ reprocessCurrentChapter),
/* harmony export */   _: () => (/* binding */ waitForInitialContent),
/* harmony export */   processVisibleChapter: () => (/* binding */ processVisibleChapter)
/* harmony export */ });
/* unused harmony import specifier */ var state;
/* unused harmony import specifier */ var getChapterIdFromUrl;
/* unused harmony import specifier */ var log;
/* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(654);
/* harmony import */ var _engine__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9);
/* harmony import */ var _ui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(141);
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(158);
// MutationObserver and content handling for WTR Lab Term Replacer




function waitForInitialContent() {
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Starting robust content detection for slow-loading websites...");
    // Set up mutation observer for dynamic content loading
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Setting up content change observer");
    setupContentObserver();
    // Set up additional fallback mechanisms
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Setting up fallback detection mechanisms");
    setupFallbackDetection();
}
function _detectContentWithMultipleStrategies() {
    const detectionStrategies = [
        // Strategy 1: Standard chapter ID detection
        () => {
            const chapterId = getChapterIdFromUrl(window.location.href);
            const contentContainer = chapterId ? document.querySelector(`#${chapterId}`) : null;
            return contentContainer ? { container: contentContainer, strategy: "chapter-id" } : null;
        },
        // Strategy 2: Look for chapter body directly
        () => {
            const CHAPTER_BODY_SELECTOR = ".chapter-body";
            const chapterBody = document.querySelector(CHAPTER_BODY_SELECTOR);
            return chapterBody ? { container: chapterBody.closest('[id*="chapter"]'), strategy: "chapter-body" } : null;
        },
        // Strategy 3: Look for any container with substantial content
        () => {
            const contentAreas = document.querySelectorAll('main, article, .content, .chapter, [role="main"]');
            for (const area of contentAreas) {
                if (area.textContent?.trim().length > 200) {
                    return { container: area, strategy: "content-area" };
                }
            }
            return null;
        },
        // Strategy 4: Last resort - any substantial text content
        () => {
            const bodyText = document.body.textContent?.trim() || "";
            if (bodyText.length > 500 && !bodyText.includes("loading")) {
                return { container: document.body, strategy: "body-fallback" };
            }
            return null;
        },
    ];
    let currentStrategy = 0;
    const maxRetriesPerStrategy = 20;
    let retries = 0;
    const enhancedPoll = setInterval(async () => {
        const result = detectionStrategies[currentStrategy]();
        if (result && result.container) {
            clearInterval(enhancedPoll);
            console.log(`WTR Term Replacer: Content detected using strategy: ${result.strategy}`);
            // Progressive processing based on content readiness
            await progressiveContentProcessing(result.container, result.strategy);
            monitorURLChanges();
            return;
        }
        retries++;
        if (retries >= maxRetriesPerStrategy) {
            currentStrategy++;
            retries = 0;
            if (currentStrategy >= detectionStrategies.length) {
                clearInterval(enhancedPoll);
                console.warn("WTR Term Replacer: All detection strategies exhausted. Will retry on content changes.");
                // Keep fallback detection active
            }
            else {
                log(`WTR Term Replacer: Strategy ${currentStrategy} failed, trying next strategy...`);
            }
        }
    }, 500); // Increased interval for slower polling
}
async function progressiveContentProcessing(container, strategy) {
    log(`WTR Term Replacer: Starting progressive processing with strategy: ${strategy}`);
    // Give the page more time to fully load, especially for slow connections
    const settlingDelays = [200, 500, 1000, 2000]; // Progressive delays
    let currentDelayIndex = 0;
    const attemptProcessing = async () => {
        try {
            // Check content readiness with multiple criteria
            if (isContentReadyForProcessing(container)) {
                log("WTR Term Replacer: Content ready for processing, proceeding...");
                processVisibleChapter();
                return true;
            }
            else if (currentDelayIndex < settlingDelays.length - 1) {
                currentDelayIndex++;
                log(`WTR Term Replacer: Content not ready, waiting ${settlingDelays[currentDelayIndex]}ms more...`);
                setTimeout(attemptProcessing, settlingDelays[currentDelayIndex]);
                return false;
            }
            else {
                log("WTR Term Replacer: Final attempt with current content state");
                processVisibleChapter(); // Force processing
                return true;
            }
        }
        catch (error) {
            log("WTR Term Replacer: Error during progressive processing:", error);
            return false;
        }
    };
    await attemptProcessing();
}
function isContentReadyForProcessing(container) {
    // Multiple readiness criteria for robust detection
    const hasSubstantialContent = container.textContent?.trim().length > 100;
    const hasNoActiveLoaders = !container.querySelector('.loading, .spinner, [style*="loading"], .skeleton');
    const isVisible = container.offsetWidth > 0 && container.offsetHeight > 0;
    const CHAPTER_BODY_SELECTOR = ".chapter-body";
    const hasChapterContent = container.querySelector(CHAPTER_BODY_SELECTOR) || container.querySelector("p, h1, h2, h3, h4, h5, h6");
    return hasSubstantialContent && hasNoActiveLoaders && isVisible && hasChapterContent;
}
function setupContentObserver() {
    // Watch for dynamic content loading with enhanced coordination
    let observerTimeout;
    let lastCheckTime = 0;
    let isContentChangeInProgress = false;
    let potentialMultiScriptConflicts = 0;
    const observer = new MutationObserver((mutations) => {
        // Prevent excessive triggering with timing constraints
        const now = Date.now();
        if (now - lastCheckTime < 2000) {
            // Minimum 2 seconds between checks
            return;
        }
        let shouldCheckForContent = false;
        const detectedScriptChanges = [];
        for (const mutation of mutations) {
            if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
                // Check if substantial content was added
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        const textContent = node.textContent?.trim() || "";
                        // Detect multi-script data attributes being added
                        if (node.hasAttribute?.("data-smart-quotes-processed")) {
                            detectedScriptChanges.push("Smart Quotes");
                            shouldCheckForContent = true;
                        }
                        if (node.hasAttribute?.("data-uncensor-processed")) {
                            detectedScriptChanges.push("Uncensor");
                            shouldCheckForContent = true;
                        }
                        if (node.hasAttribute?.("data-auto-scroll") || node.hasAttribute?.("data-reader-enhanced")) {
                            detectedScriptChanges.push("Reader Enhancer");
                            shouldCheckForContent = true;
                        }
                        // More strict content validation to reduce false positives
                        if (textContent.length > 100 &&
                            !textContent.includes("loading") &&
                            !textContent.includes("...") &&
                            (node.id?.includes("chapter") ||
                                node.className?.includes("chapter") ||
                                node.querySelector(".chapter-body"))) {
                            shouldCheckForContent = true;
                            break;
                        }
                    }
                }
            }
        }
        if (shouldCheckForContent && !isContentChangeInProgress) {
            isContentChangeInProgress = true;
            lastCheckTime = now;
            if (detectedScriptChanges.length > 0) {
                potentialMultiScriptConflicts++;
                (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Multi-script activity detected from: ${detectedScriptChanges.join(", ")} (conflict ${potentialMultiScriptConflicts})`);
                // Update our detected scripts
                detectedScriptChanges.forEach((script) => _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.add(script));
            }
            else {
                (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)("WTR Term Replacer: Content changes detected, checking for chapter content...");
            }
            // Debounced check to avoid excessive processing with enhanced delay for multi-script
            const baseDelay = 1500;
            const multiScriptDelay = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size > 0 ? 2500 : baseDelay;
            clearTimeout(observerTimeout);
            observerTimeout = setTimeout(() => {
                const queuedForProcessing = document.querySelector("[data-wtr-processed]") || _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.size > 0;
                if (!queuedForProcessing) {
                    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Initiating content processing (${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size} other scripts active, ${multiScriptDelay}ms coordination delay)`);
                    processVisibleChapter();
                }
                else {
                    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Skipping content processing - already in progress or completed (queue: ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.size})`);
                }
                isContentChangeInProgress = false;
            }, multiScriptDelay); // Increased delay to coordinate with other processes
        }
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ["style", "class", "id"],
    });
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)("WTR Term Replacer: Enhanced content observer activated with multi-script coordination");
}
function setupFallbackDetection() {
    // Periodic fallback check for stubborn slow-loading pages
    let fallbackAttempts = 0;
    const maxFallbackAttempts = 10;
    const fallbackInterval = setInterval(() => {
        if (document.querySelector("[data-wtr-processed]")) {
            clearInterval(fallbackInterval);
            return;
        }
        fallbackAttempts++;
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Fallback attempt ${fallbackAttempts}/${maxFallbackAttempts}`);
        // Try processing if we have any chapter-like content
        const chapterId = (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .getChapterIdFromUrl */ .Ug)(window.location.href);
        if (chapterId) {
            const CHAPTER_BODY_SELECTOR = ".chapter-body";
            const chapterSelector = `#${chapterId} ${CHAPTER_BODY_SELECTOR}`;
            const chapterBody = document.querySelector(chapterSelector);
            if (chapterBody) {
                (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)("WTR Term Replacer: Fallback processing successful");
                processVisibleChapter();
                clearInterval(fallbackInterval);
                return;
            }
        }
        // Check for any substantial content that might be chapter content
        const potentialContent = document.querySelector("main, article, .content, .chapter");
        if (potentialContent && potentialContent.textContent?.trim().length > 200) {
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)("WTR Term Replacer: Fallback processing with detected content");
            processVisibleChapter();
            clearInterval(fallbackInterval);
        }
        if (fallbackAttempts >= maxFallbackAttempts) {
            clearInterval(fallbackInterval);
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)("WTR Term Replacer: Fallback detection exhausted");
        }
    }, 3000); // Check every 3 seconds
    // Clear fallback interval after 5 minutes to prevent infinite polling
    setTimeout(() => {
        clearInterval(fallbackInterval);
    }, 300000);
}
function processVisibleChapter() {
    const chapterId = (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .getChapterIdFromUrl */ .Ug)(window.location.href);
    if (!chapterId) {
        return;
    }
    const CHAPTER_BODY_SELECTOR = ".chapter-body";
    const chapterSelector = `#${chapterId} ${CHAPTER_BODY_SELECTOR}`;
    const chapterBody = document.querySelector(chapterSelector);
    if (!chapterBody) {
        return;
    }
    if (chapterBody.dataset.wtrProcessed === "true") {
        return;
    }
    // Use queue-based processing to avoid race conditions
    scheduleChapterProcessing(chapterId, chapterBody);
}
function scheduleChapterProcessing(chapterId, _chapterBody) {
    const processingKey = `${chapterId}_${Date.now()}`;
    // Enhanced queue management with proper synchronization
    if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.has(chapterId)) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Chapter ${chapterId} already queued for processing ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.size} queued`);
        return;
    }
    // Add with unique identifier to prevent race conditions
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.add(processingKey);
    // Progressive retry with exponential backoff for slow-loading content
    const retryAttempts = [
        { delay: 100, maxContentLoad: 0.3 }, // Fast retry for quick loads
        { delay: 500, maxContentLoad: 0.5 }, // Medium retry for normal loads
        { delay: 1000, maxContentLoad: 0.7 }, // Slower retry for slow loads
        { delay: 2000, maxContentLoad: 0.9 }, // Very slow retry for very slow loads
        { delay: 5000, maxContentLoad: 1.0 }, // Final attempt with any content
    ];
    executeProcessingWithRetry(chapterId, retryAttempts, 0, processingKey);
}
async function executeProcessingWithRetry(chapterId, retryAttempts, attemptIndex, processingKey) {
    const attempt = retryAttempts[attemptIndex];
    try {
        // Wait for the specified delay
        await new Promise((resolve) => setTimeout(resolve, attempt.delay));
        // Verify queue entry still exists (prevent race conditions)
        if (!_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.has(processingKey)) {
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Chapter ${chapterId} processing cancelled (no longer in queue)`);
            return;
        }
        // Re-acquire chapter body element dynamically to avoid stale references
        const CHAPTER_BODY_SELECTOR = ".chapter-body";
        const chapterSelector = `#${chapterId} ${CHAPTER_BODY_SELECTOR}`;
        const chapterBody = document.querySelector(chapterSelector);
        if (!chapterBody) {
            throw new Error("Chapter body element not found");
        }
        // Additional DOM stability validation
        if (!document.contains(chapterBody) || chapterBody.nodeType !== Node.ELEMENT_NODE) {
            throw new Error("Chapter body element no longer in DOM");
        }
        // Check if content is sufficiently loaded
        const contentLoadLevel = estimateContentLoadLevel(chapterBody);
        if (contentLoadLevel >= attempt.maxContentLoad) {
            // Proceed with processing
            await performRobustReplacements(chapterBody, chapterId);
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.delete(processingKey);
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Successfully processed chapter ${chapterId} on attempt ${attemptIndex + 1}`);
        }
        else if (attemptIndex < retryAttempts.length - 1) {
            // Retry with next attempt
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Chapter ${chapterId} content not ready (load level: ${contentLoadLevel.toFixed(2)}), retrying...`);
            executeProcessingWithRetry(chapterId, retryAttempts, attemptIndex + 1, processingKey);
        }
        else {
            // Final attempt with any available content
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Final attempt for chapter ${chapterId} with available content`);
            await performRobustReplacements(chapterBody, chapterId, true); // force processing
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.delete(processingKey);
        }
    }
    catch (error) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Error processing chapter ${chapterId} on attempt ${attemptIndex + 1}:`, error);
        if (attemptIndex < retryAttempts.length - 1) {
            executeProcessingWithRetry(chapterId, retryAttempts, attemptIndex + 1, processingKey);
        }
        else {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.delete(processingKey);
            console.error(`WTR Term Replacer: Failed to process chapter ${chapterId} after all retries`);
        }
    }
}
function estimateContentLoadLevel(chapterBody) {
    // Estimate how much content is loaded based on text density and structure
    const textNodes = chapterBody.querySelectorAll("p, h1, h2, h3, h4, h5, h6, div, span");
    const totalTextLength = Array.from(textNodes).reduce((total, node) => total + (node.textContent?.trim().length || 0), 0);
    // Check for loading indicators or placeholder content
    const hasLoadingIndicators = chapterBody.querySelector('.loading, .spinner, [style*="loading"], [class*="loading"]');
    const hasPlaceholderContent = chapterBody.textContent?.includes("Loading...") ||
        chapterBody.textContent?.includes("loading") ||
        chapterBody.textContent?.includes("...");
    // Calculate load level based on content density and absence of loading indicators
    let loadLevel = Math.min(totalTextLength / 1000, 1.0); // Normalize to 0-1 based on 1000 chars
    if (hasLoadingIndicators || hasPlaceholderContent) {
        loadLevel *= 0.3; // Reduce load level if loading indicators present
    }
    // Ensure minimum threshold for processing
    return Math.max(loadLevel, totalTextLength > 100 ? 0.5 : 0.1);
}
function detectOtherWTRScripts() {
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Scanning for other WTR Lab scripts...");
    // Detect other WTR Lab scripts by their data attributes or specific patterns
    const scripts = document.querySelectorAll("[data-smart-quotes-processed], [data-uncensor-processed], [data-auto-scroll], [data-reader-enhanced]");
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Found ${scripts.length} elements with WTR script attributes`);
    scripts.forEach((el) => {
        if (el.hasAttribute("data-smart-quotes-processed")) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.add("Smart Quotes");
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Detected Smart Quotes script");
        }
        if (el.hasAttribute("data-uncensor-processed")) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.add("Uncensor");
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Detected Uncensor script");
        }
        if (el.hasAttribute("data-auto-scroll") || el.hasAttribute("data-reader-enhanced")) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.add("Reader Enhancer");
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Detected Reader Enhancer script");
        }
    });
    if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size > 0) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Multi-script environment detected - Active scripts: ${Array.from(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts).join(", ")}`);
    }
    else {
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: No other WTR scripts detected, running in single-script mode");
    }
}
function startProcessingTimer(operation) {
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Starting processing timer for ${operation}`);
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingStartTime.set(operation, Date.now());
}
function endProcessingTimer(operation, chapterId) {
    const startTime = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingStartTime.get(operation);
    if (startTime) {
        const processingTime = Date.now() - startTime;
        const isMultiScript = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size > 0;
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Processing timer ended for ${operation}, took ${processingTime}ms`);
        logProcessingWithMultiScriptContext(chapterId, processingTime, isMultiScript);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingStartTime.delete(operation);
        return processingTime;
    }
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Warning - processing timer for ${operation} not found`);
    return 0;
}
function logProcessingWithMultiScriptContext(chapterId, processingTime, isMultiScript = false) {
    const context = {
        chapterId,
        processingTime: `${processingTime}ms`,
        multiScriptEnvironment: isMultiScript,
        activeScripts: _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size,
        queueSize: _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.size,
        timestamp: new Date().toISOString(),
    };
    if (isMultiScript && _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size > 0) {
        context.activeScripts = Array.from(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts);
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Multi-script enhanced processing completed`, context);
    }
    else {
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Standard processing completed`, context);
    }
}
async function performRobustReplacements(chapterBody, chapterId, forceProcess = false) {
    try {
        // Additional readiness checks before processing
        if (!forceProcess && !isElementReadyForProcessing(chapterBody)) {
            throw new Error("Element not ready for processing");
        }
        startProcessingTimer(`chapter_${chapterId}`);
        // Detect other WTR scripts if not already done
        if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size === 0) {
            detectOtherWTRScripts();
        }
        const isMultiScript = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts.size > 0;
        if (isMultiScript) {
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Multi-script processing starting for chapter ${chapterId} with active scripts: ${Array.from(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.otherWTRScripts).join(", ")}`);
        }
        else {
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Processing chapter ${chapterId} with robust method`);
        }
        (0,_engine__WEBPACK_IMPORTED_MODULE_1__.performReplacements)(chapterBody);
        chapterBody.dataset.wtrProcessed = "true";
        (0,_ui__WEBPACK_IMPORTED_MODULE_2__/* .addMenuButton */ .L_)();
        const processingTime = endProcessingTimer(`chapter_${chapterId}`, chapterId);
        if (isMultiScript) {
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Successfully completed multi-script processing for chapter ${chapterId} in ${processingTime}ms`);
        }
    }
    catch (error) {
        const processingTime = endProcessingTimer(`chapter_${chapterId}`, chapterId) || 0;
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(`WTR Term Replacer: Robust processing failed for chapter ${chapterId} after ${processingTime}ms:`, error);
        throw error;
    }
}
function isElementReadyForProcessing(element) {
    // Check if element is visible and has substantial content
    const rect = element.getBoundingClientRect();
    const isVisible = rect.width > 0 && rect.height > 0;
    const hasSubstantialContent = element.textContent?.trim().length > 50;
    const hasNoLoadingStates = !element.querySelector('.loading, .spinner, [style*="display: none"]');
    return isVisible && hasSubstantialContent && hasNoLoadingStates;
}
function reprocessCurrentChapter() {
    const chapterId = (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .getChapterIdFromUrl */ .Ug)(window.location.href);
    if (!chapterId) {
        return;
    }
    const CHAPTER_BODY_SELECTOR = ".chapter-body";
    const chapterSelector = `#${chapterId} ${CHAPTER_BODY_SELECTOR}`;
    const chapterBody = document.querySelector(chapterSelector);
    if (chapterBody) {
        // Reset processing state to allow reprocessing
        chapterBody.dataset.wtrProcessed = "false";
        // Clear any existing processing entries for this chapter
        const existingKeys = Array.from(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue).filter((key) => key.startsWith(chapterId));
        existingKeys.forEach((key) => _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.processingQueue.delete(key));
        // Use robust reprocessing with retry mechanism
        scheduleChapterProcessing(chapterId, chapterBody);
    }
}
function monitorURLChanges() {
    setInterval(() => {
        if (window.location.href !== state.currentURL) {
            log(`WTR Term Replacer: URL changed to ${window.location.href}.`);
            state.currentURL = window.location.href;
            setTimeout(processVisibleChapter, 250);
        }
    }, 500);
}


/***/ },

/***/ 654
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   oP: () => (/* binding */ setNovelSlug),
/* harmony export */   wk: () => (/* binding */ state)
/* harmony export */ });
/* unused harmony export initializeState */
// State management for WTR Lab Term Replacer
const state = {
    novelSlug: null,
    terms: [],
    settings: { isDisabled: false },
    globalSettings: { isLoggingEnabled: false },
    importType: "novel",
    currentSearchValue: "",
    isDupMode: false,
    dupGroups: new Map(),
    dupKeys: [],
    currentDupIndex: 0,
    currentPage: 1,
    savedTermListLocation: { page: 1, scrollTop: 0, searchValue: "" },
    originalTextNodes: new WeakMap(),
    otherWTRScripts: new Set(),
    processingStartTime: new Map(),
    domConflictDetected: false,
    multiScriptPerformanceImpact: new Map(),
    currentURL: window.location.href,
    processingQueue: new Set(),
    isProcessingInProgress: false,
    observedMenuContainers: new WeakSet(),
    termDiscovery: {
        novelTerms: [],
        replacementSuggestions: [],
        selectedCandidate: null,
    },
};
// Function to initialize novel slug - should be called after utils is loaded
function initializeState() {
    if (!state.novelSlug) {
        // Import getNovelSlug function dynamically to avoid circular dependencies
        Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 158)).then(({ getNovelSlug }) => {
            state.novelSlug = getNovelSlug();
        });
    }
    return state.novelSlug;
}
// Set novel slug (for synchronous initialization)
function setNovelSlug(slug) {
    state.novelSlug = slug;
}


/***/ },

/***/ 694
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   getTermKey: () => (/* binding */ getTermKey),
/* harmony export */   getTermsForSlug: () => (/* binding */ getTermsForSlug),
/* harmony export */   loadData: () => (/* binding */ loadData),
/* harmony export */   loadGlobalSettings: () => (/* binding */ loadGlobalSettings),
/* harmony export */   loadTermListLocation: () => (/* binding */ loadTermListLocation),
/* harmony export */   processAndSaveSettings: () => (/* binding */ processAndSaveSettings),
/* harmony export */   processAndSaveTerms: () => (/* binding */ processAndSaveTerms),
/* harmony export */   saveGlobalSettings: () => (/* binding */ saveGlobalSettings),
/* harmony export */   saveSearchFieldValue: () => (/* binding */ saveSearchFieldValue),
/* harmony export */   saveSettings: () => (/* binding */ saveSettings),
/* harmony export */   saveTermListLocation: () => (/* binding */ saveTermListLocation),
/* harmony export */   saveTerms: () => (/* binding */ saveTerms)
/* harmony export */ });
/* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(654);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(333);
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(158);
// Storage functions using GM_* API for WTR Lab Term Replacer



async function loadGlobalSettings() {
    try {
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings = await GM_getValue(_config__WEBPACK_IMPORTED_MODULE_1__/* .GLOBAL_SETTINGS_KEY */ .sI, { isLoggingEnabled: false });
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Global settings loaded");
    }
    catch (e) {
        console.error("Error loading global settings:", e);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings = { isLoggingEnabled: false };
    }
}
async function saveGlobalSettings() {
    try {
        await GM_setValue(_config__WEBPACK_IMPORTED_MODULE_1__/* .GLOBAL_SETTINGS_KEY */ .sI, _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings);
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Global settings saved");
    }
    catch (e) {
        console.error("Error saving global settings:", e);
    }
}
async function loadTermListLocation() {
    try {
        const saved = await GM_getValue(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .CURRENT_LOCATION_KEY */ .Qp}_${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`, null);
        if (saved) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.savedTermListLocation = saved;
        }
    }
    catch (e) {
        console.error("Error loading term list location:", e);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.savedTermListLocation = { page: 1, scrollTop: 0, searchValue: "" };
    }
}
async function saveTermListLocation() {
    try {
        const termListContainer = document.querySelector(".wtr-replacer-content");
        if (termListContainer) {
            // Capture more detailed location information for better preservation
            const locationData = {
                page: _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage,
                scrollTop: termListContainer.scrollTop,
                scrollHeight: termListContainer.scrollHeight,
                clientHeight: termListContainer.clientHeight,
                searchValue: _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue,
                timestamp: Date.now(), // Add timestamp for better tracking
            };
            await GM_setValue(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .CURRENT_LOCATION_KEY */ .Qp}_${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`, locationData);
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.savedTermListLocation = locationData;
            (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Saved scroll position - top: ${locationData.scrollTop}, page: ${locationData.page}`);
        }
    }
    catch (e) {
        console.error("Error saving term list location:", e);
    }
}
// Helper function to save search field value immediately
async function saveSearchFieldValue() {
    try {
        const locationData = {
            page: _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage,
            scrollTop: 0,
            searchValue: _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue,
        };
        await GM_setValue(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .CURRENT_LOCATION_KEY */ .Qp}_${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`, locationData);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.savedTermListLocation = locationData;
    }
    catch (e) {
        console.error("Error saving search field value:", e);
    }
}
async function getTermsForSlug(slug) {
    if (!slug) {
        return [];
    }
    const terms = await GM_getValue(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .TERMS_STORAGE_KEY_PREFIX */ .fW}${slug}`, []);
    if (!Array.isArray(terms)) {
        return [];
    }
    return terms.map((term) => ({
        ...term,
        wholeWord: term.wholeWord ?? false,
    }));
}
async function loadData() {
    try {
        const SETTINGS_KEY = `${_config__WEBPACK_IMPORTED_MODULE_1__/* .SETTINGS_STORAGE_KEY_PREFIX */ .Ft}${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`;
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms = await getTermsForSlug(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug);
        const savedSettings = await GM_getValue(SETTINGS_KEY, {});
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings = { isDisabled: false, ...savedSettings };
    }
    catch (e) {
        console.error("Error loading data:", e);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms = [];
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings = { isDisabled: false };
    }
}
async function saveTerms(termsToSave) {
    try {
        const TERMS_KEY = `${_config__WEBPACK_IMPORTED_MODULE_1__/* .TERMS_STORAGE_KEY_PREFIX */ .fW}${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`;
        await GM_setValue(TERMS_KEY, termsToSave);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms = termsToSave;
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Saved ${termsToSave.length} terms for novel ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`);
    }
    catch (e) {
        console.error("Error saving terms:", e);
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Failed to save terms: ${e.message}`);
        alert("Failed to save terms. Storage might be full.");
    }
}
async function saveSettings(settingsToSave) {
    try {
        const SETTINGS_KEY = `${_config__WEBPACK_IMPORTED_MODULE_1__/* .SETTINGS_STORAGE_KEY_PREFIX */ .Ft}${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug}`;
        await GM_setValue(SETTINGS_KEY, settingsToSave);
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings = settingsToSave;
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Settings saved successfully");
    }
    catch (e) {
        console.error("Error saving settings:", e);
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Failed to save settings: ${e.message}`);
        alert("Failed to save settings. Storage might be full.");
    }
}
function getTermKey(term) {
    return `${term.original}|${term.caseSensitive}|${term.isRegex}`;
}
async function processAndSaveTerms(slug, importedTerms, overwrite = true) {
    (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Processing import for slug ${slug}, overwrite: ${overwrite}`);
    const TERMS_KEY = `${_config__WEBPACK_IMPORTED_MODULE_1__/* .TERMS_STORAGE_KEY_PREFIX */ .fW}${slug}`;
    const existingTerms = await GM_getValue(TERMS_KEY, []);
    existingTerms.forEach((t) => {
        t.wholeWord = t.wholeWord ?? false;
    });
    let newTerms = [];
    let added = 0;
    let skipped = 0;
    let conflicts = 0;
    if (overwrite) {
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Overwrite mode - importing ${importedTerms.length} terms`);
        newTerms = importedTerms;
    }
    else {
        const existingMap = new Map();
        existingTerms.forEach((t) => existingMap.set(getTermKey(t), t));
        importedTerms.forEach((imp) => {
            const key = getTermKey(imp);
            if (!existingMap.has(key)) {
                newTerms.push(imp);
                added++;
            }
            else {
                const ext = existingMap.get(key);
                if (ext.replacement !== imp.replacement || ext.wholeWord !== imp.wholeWord) {
                    conflicts++;
                }
                else {
                    skipped++;
                }
            }
        });
        newTerms = [...existingTerms, ...newTerms];
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Merge mode - added: ${added}, skipped: ${skipped}, conflicts: ${conflicts}`);
    }
    await GM_setValue(TERMS_KEY, newTerms);
    if (slug === _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug) {
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms = newTerms;
    }
    (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Import complete for ${slug} - total terms: ${newTerms.length}`);
    return { added, skipped, conflicts };
}
async function processAndSaveSettings(importedSettings) {
    (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Processing settings import for ${Object.keys(importedSettings).length} slugs`);
    for (const slug in importedSettings) {
        const SETTINGS_KEY = `${_config__WEBPACK_IMPORTED_MODULE_1__/* .SETTINGS_STORAGE_KEY_PREFIX */ .Ft}${slug}`;
        const existing = await GM_getValue(SETTINGS_KEY, { isDisabled: false });
        const newSettings = { ...existing, ...importedSettings[slug] };
        await GM_setValue(SETTINGS_KEY, newSettings);
        if (slug === _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.novelSlug) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings = newSettings;
        }
        (0,_utils__WEBPACK_IMPORTED_MODULE_2__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, `WTR Term Replacer: Settings updated for slug ${slug}`);
    }
}


/***/ },

/***/ 141
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   BD: () => (/* binding */ showFormView),
/* harmony export */   E1: () => (/* binding */ showUIPanel),
/* harmony export */   FP: () => (/* binding */ renderTermList),
/* harmony export */   L_: () => (/* binding */ addMenuButton),
/* harmony export */   OG: () => (/* binding */ switchTab),
/* harmony export */   RD: () => (/* binding */ createUI),
/* harmony export */   W4: () => (/* binding */ hideUILoader),
/* harmony export */   X: () => (/* binding */ hideUIPanel),
/* harmony export */   Xt: () => (/* binding */ showUILoader),
/* harmony export */   gn: () => (/* binding */ showProcessingIndicator),
/* harmony export */   kH: () => (/* binding */ clearTermList)
/* harmony export */ });
/* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(654);
/* harmony import */ var _handlers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(359);
/* harmony import */ var _duplicates__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(201);
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(158);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(333);
/* harmony import */ var _config_versions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(387);
/* harmony import */ var _config_versions__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_config_versions__WEBPACK_IMPORTED_MODULE_5__);






const UI_HTML = `
    <div class="wtr-replacer-header">
        <h2>Term Replacer ${(0,_config_versions__WEBPACK_IMPORTED_MODULE_5__.getDisplayVersion)()}</h2>
        <div class="wtr-replacer-header-controls">
            <div class="wtr-replacer-disable-toggle">
                <label><input type="checkbox" id="wtr-disable-all"> Disable All</label>
            </div>
            <button class="wtr-replacer-close-btn">&times;</button>
        </div>
    </div>
    <div class="wtr-replacer-tabs">
        <button class="wtr-replacer-tab-btn active" data-tab="terms">Terms List</button>
        <button class="wtr-replacer-tab-btn" data-tab="add">Add/Edit Term</button>
        <button class="wtr-replacer-tab-btn" data-tab="io">Import/Export</button>
    </div>
    <div class="wtr-replacer-content">
        <div class="wtr-ui-loader" id="wtr-ui-loader">Loading...</div>
        <div id="wtr-tab-terms" class="wtr-replacer-tab-content active">
            <div id="wtr-dup-message" class="wtr-dup-message" style="display:none;"></div>
            <div id="wtr-dup-controls" class="wtr-dup-controls" style="display:none;">
                <button id="wtr-prev-dup-btn" class="btn btn-secondary">Previous</button>
                <button id="wtr-next-dup-btn" class="btn btn-secondary">Next</button>
                <button id="wtr-exit-dup-btn" class="btn btn-secondary">Exit Duplicate Mode</button>
            </div>
            <div class="wtr-replacer-list-controls">
                <input type="text" id="wtr-search-bar" class="wtr-replacer-search-bar" placeholder="Search terms...">
                <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
                    <button id="wtr-find-duplicates-btn" class="btn btn-secondary">Find Duplicates</button>
                    <button id="wtr-delete-selected-btn" class="btn btn-secondary">Delete Selected</button>
                </div>
            </div>
            <ul class="wtr-replacer-term-list"></ul>
            <div class="wtr-pagination-controls">
                <button id="wtr-first-page-btn" class="btn btn-secondary" title="First Page">&laquo;&laquo;</button>
                <button id="wtr-prev-page-btn" class="btn btn-secondary" title="Previous Page">&laquo;</button>
                <span id="wtr-page-indicator"></span>
                <button id="wtr-next-page-btn" class="btn btn-secondary" title="Next Page">&raquo;</button>
                <button id="wtr-last-page-btn" class="btn btn-secondary" title="Last Page">&raquo;&raquo;</button>
            </div>
        </div>
        <div id="wtr-tab-add" class="wtr-replacer-tab-content">
            <input type="hidden" id="wtr-term-id">
            <div class="wtr-replacer-form-group">
                <label for="wtr-original">Original Text</label>
                <textarea id="wtr-original" rows="1"></textarea>
                <small id="wtr-regex-disabled-warning" class="wtr-regex-disabled-warning" style="display:none;">This looks like regex syntax, but Use Regex is off. It will be saved as plain text unless you enable Use Regex.</small>
                <button type="button" id="wtr-refresh-suggestions-btn" class="btn btn-secondary btn-sm wtr-refresh-suggestions-btn">Refresh Suggestions</button>
            </div>
            <div class="wtr-replacer-form-group">
                <label for="wtr-replacement">Replacement Text</label>
                <input type="text" id="wtr-replacement">
                <div id="wtr-replacement-suggestions" class="wtr-replacement-suggestions" aria-live="polite"></div>
            </div>
            <div class="wtr-replacer-form-group">
                <label><input type="checkbox" id="wtr-case-sensitive"> Case Sensitive</label>
                <label><input type="checkbox" id="wtr-is-regex"> Use Regex</label>
                <label><input type="checkbox" id="wtr-whole-word" disabled> Whole Word Only</label>
            </div>
            <button id="wtr-save-btn" class="btn btn-primary">Save Term</button>
        </div>
        <div id="wtr-tab-io" class="wtr-replacer-tab-content">
            <input type="file" id="wtr-file-input" accept=".json" style="display: none;">
            <div class="wtr-replacer-io-section">
                <h3>Export</h3>
                <div class="wtr-replacer-io-actions" style="display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap;">
                    <button id="wtr-export-novel-btn" class="btn btn-success">Export Novel Terms</button>
                    <button id="wtr-export-all-btn" class="btn btn-success">Export All Terms</button>
                    <button id="wtr-export-combined-btn" class="btn btn-info wtr-export-combined">Export Both (Novel + All)</button>
                </div>
            </div>
            <div class="wtr-replacer-io-section">
                <h3>Import</h3>
                <div class="wtr-replacer-io-actions" style="display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap;">
                    <button id="wtr-import-novel-btn" class="btn btn-warning">Import to This Novel</button>
                    <button id="wtr-import-all-btn" class="btn btn-warning">Import All (Global)</button>
                </div>
            </div>
        </div>
    </div>
`;
const UI_CSS = `
    /* --- Google Material Symbols --- */
    @import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,1,0');
    
    .material-symbols-outlined {
        font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
        font-size: 16px;
        vertical-align: middle;
    }

    /* --- Main UI Container --- */
    .wtr-replacer-ui {
        position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
        width: 90%; max-width: 650px; max-height: 80vh;
        background-color: var(--bs-body-bg); color: var(--bs-body-color);
        border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius-lg);
        box-shadow: var(--bs-box-shadow-lg); z-index: 99999;
        display: none; flex-direction: column; font-family: var(--bs-body-font-family);
    }
    .wtr-replacer-ui * { box-sizing: border-box; }

    /* --- Header --- */
    .wtr-replacer-header {
        padding: 0.75rem 1rem; background-color: var(--bs-tertiary-bg);
        border-bottom: 1px solid var(--bs-border-color);
        display: flex; justify-content: space-between; align-items: center;
        border-radius: var(--bs-border-radius-lg) var(--bs-border-radius-lg) 0 0;
    }
    .wtr-replacer-header h2 { margin: 0; font-size: 1.25rem; }
    .wtr-replacer-header-controls { display: flex; align-items: center; gap: 1rem; }
    .wtr-replacer-disable-toggle label { display: flex; align-items: center; cursor: pointer; font-size: 0.9rem; }
    .wtr-replacer-disable-toggle input { margin-right: 0.5rem; }
    .wtr-replacer-close-btn { background: none; border: none; font-size: 1.5rem; cursor: pointer; line-height: 1; color: inherit; padding: 0; }

    /* --- Tabs --- */
    .wtr-replacer-tabs { display: flex; padding: 0 0.5rem; border-bottom: 1px solid var(--bs-border-color); background-color: var(--bs-tertiary-bg); }
    .wtr-replacer-tab-btn {
        background: none; border: none; padding: 0.75rem 1rem; cursor: pointer;
        font-size: 0.9rem; color: var(--bs-secondary-color);
        border-bottom: 3px solid transparent; margin-bottom: -1px;
    }
    .wtr-replacer-tab-btn.active { color: var(--bs-primary); border-bottom-color: var(--bs-primary); font-weight: bold; }

    /* --- Content & Forms --- */
    .wtr-replacer-content { padding: 1rem; overflow-y: auto; flex-grow: 1; position: relative; }
    .wtr-replacer-tab-content { display: none; }
    .wtr-replacer-tab-content.active { display: block; }
    .wtr-replacer-form-group { margin-bottom: 1rem; }
    .wtr-replacer-form-group label { display: block; margin-bottom: 0.5rem; font-weight: bold; font-size: 0.9rem; }
    .wtr-replacer-form-group input[type="text"], .wtr-replacer-search-bar {
        width: 100%; padding: 0.5rem 0.75rem;
        background-color: var(--bs-body-bg); color: var(--bs-body-color);
        border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius);
    }
    .wtr-replacer-form-group textarea {
        width: 100%; padding: 0.5rem 0.75rem;
        background-color: var(--bs-body-bg); color: var(--bs-body-color);
        border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius);
        resize: none;
        min-height: 2.5rem; max-height: 10rem;
        line-height: 1.5; font-family: inherit;
        word-wrap: break-word; white-space: pre-wrap;
    }
    .wtr-replacer-form-group input[type="checkbox"] { margin-right: 0.5rem; }

    /* --- Visual Validation States --- */
    .wtr-replacer-form-group .wtr-field-invalid {
        border-color: var(--bs-danger) !important;
        background-color: rgba(var(--bs-danger-rgb), 0.1) !important;
        box-shadow: 0 0 0 0.2rem rgba(var(--bs-danger-rgb), 0.25);
    }
    
    .wtr-replacer-form-group .wtr-field-valid {
        border-color: var(--bs-success) !important;
        background-color: rgba(var(--bs-success-rgb), 0.1) !important;
    }

    .wtr-replacer-form-group .wtr-field-warning {
        border-color: var(--bs-warning) !important;
        background-color: rgba(var(--bs-warning-rgb), 0.12) !important;
        box-shadow: 0 0 0 0.2rem rgba(var(--bs-warning-rgb), 0.2);
    }

    .wtr-regex-disabled-warning {
        display: block;
        margin-top: 0.35rem;
        color: var(--bs-warning-text-emphasis, var(--bs-warning));
    }
    
    .wtr-save-btn:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        background-color: var(--bs-secondary);
        border-color: var(--bs-secondary);
    }

    /* --- Buttons (Scoped to UI) --- */
    .wtr-replacer-ui .btn {
        display: inline-block; font-weight: 400; line-height: 1.5; color: var(--bs-body-color);
        text-align: center; vertical-align: middle; cursor: pointer; user-select: none;
        background-color: transparent; border: 1px solid transparent;
        padding: 0.375rem 0.75rem; font-size: 1rem; border-radius: var(--bs-border-radius);
        transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
    }
    .wtr-replacer-ui .btn:disabled { opacity: 0.65; cursor: not-allowed; }
    .wtr-replacer-ui .btn-primary { color: #fff; background-color: var(--bs-primary); border-color: var(--bs-primary); }
    .wtr-replacer-ui .btn-secondary { color: #fff; background-color: var(--bs-secondary); border-color: var(--bs-secondary); }
    .wtr-replacer-ui .btn-success { color: #fff; background-color: var(--bs-success); border-color: var(--bs-success); }
    .wtr-replacer-ui .btn-warning { color: #000; background-color: var(--bs-warning); border-color: var(--bs-warning); }
    .wtr-replacer-ui .btn-info { color: #fff; background-color: var(--bs-info); border-color: var(--bs-info); }
    .wtr-replacer-ui .btn-sm { padding: 0.25rem 0.5rem; font-size: 0.875rem; }

    .wtr-refresh-suggestions-btn { margin-top: 0.35rem; }
    .wtr-replacement-suggestions { margin-top: 0.35rem; }
    .wtr-replacement-suggestion-buttons { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: 0.35rem; }
    .wtr-replacement-suggestion-btn { display: inline-flex !important; align-items: center; gap: 0.35rem; }
    .wtr-replacement-suggestion-btn.wtr-suggestion-existing {
        background-color: var(--bs-success) !important;
        border-color: var(--bs-success) !important;
        color: #fff !important;
    }
    .wtr-replacement-suggestion-source { opacity: 0.85; font-size: 0.72rem; }
    .wtr-replacer-popover-actions { display: flex; flex-direction: column; gap: 0.25rem; }
    .wtr-replacer-popover-add-btn { white-space: nowrap; }

    /* --- Term List --- */
    .wtr-replacer-list-controls {
        display: flex; justify-content: space-between; align-items: center;
        gap: 0.75rem; position: sticky; top: -1rem;
        background-color: var(--bs-body-bg); padding: 0.75rem 0; z-index: 10;
        flex-wrap: wrap;
    }
    .wtr-replacer-term-list { list-style: none; padding: 0; margin: 0; }
    .wtr-replacer-term-item {
        padding: 0.75rem; border: 1px solid var(--bs-border-color);
        border-radius: var(--bs-border-radius); margin-bottom: 0.5rem;
        display: flex; align-items: center; gap: 0.75rem;
        background-color: var(--bs-secondary-bg-subtle);
    }
    .wtr-replacer-term-details { flex-grow: 1; overflow: hidden; }
    .wtr-replacer-term-text { font-family: var(--bs-font-monospace); font-size: 0.9rem; word-wrap: break-word; }
    .wtr-term-original { color: var(--bs-danger) !important; font-weight: bold; }
    .wtr-term-replacement { color: var(--bs-success) !important; font-weight: bold; }

    /* --- Floating Button --- */
    .wtr-add-term-float-btn {
        position: fixed; bottom: 20px; right: 20px;
        background-color: var(--bs-primary); color: white;
        padding: 0.75rem 1.25rem; border-radius: 50rem; border: none;
        box-shadow: var(--bs-box-shadow); cursor: pointer; font-size: 1rem; z-index: 99998; display: none;
    }

    /* --- Overlays & Loaders --- */
    .wtr-processing-overlay {
        position: fixed; top: 0; left: 0; width: 100%; height: 100%;
        background: rgba(0,0,0,0.5); color: white;
        display: flex; justify-content: center; align-items: center;
        font-size: 1.5rem; z-index: 100000; display: none;
    }
    .wtr-ui-loader {
        display: none; position: absolute; top: 0; left: 0; width: 100%; height: 100%;
        background: rgba(var(--bs-body-bg-rgb), 0.7); color: var(--bs-body-color);
        justify-content: center; align-items: center; z-index: 20;
    }

    /* --- Duplicate Mode & Pagination --- */
    .wtr-dup-message { margin-bottom: 0.75rem; font-weight: bold; }
    .wtr-dup-controls { display: flex; gap: 0.5rem; margin-bottom: 0.75rem; flex-wrap: wrap; }
    .wtr-pagination-controls {
        display: flex; justify-content: center; align-items: center; margin-top: 1rem; gap: 0.25rem;
        flex-wrap: wrap; padding: 0.5rem 0;
    }
    .wtr-pagination-controls .btn {
        padding: 0.25rem 0.5rem; font-size: 0.875rem; min-width: 2.5rem;
    }
    #wtr-page-indicator {
        white-space: nowrap; margin: 0 0.5rem; font-size: 0.875rem;
        padding: 0.25rem 0.5rem; background-color: var(--bs-secondary-bg-subtle);
        border-radius: var(--bs-border-radius);
    }

    /* --- Enhanced Export Button Styling --- */
    .wtr-export-combined {
        background: linear-gradient(45deg, var(--bs-success), #28a745);
        border: none;
        color: white;
        font-weight: bold;
        position: relative;
        overflow: hidden;
    }

    .wtr-export-combined:hover {
        background: linear-gradient(45deg, #28a745, var(--bs-success));
        transform: translateY(-1px);
        box-shadow: 0 4px 8px rgba(0,0,0,0.2);
    }

    .wtr-export-combined:active {
        transform: translateY(0);
    }

    /* --- Global Menu Button Alignment Fix --- */
    /* Fix menu button alignment - remove margin-right from Term Settings for all devices */
    .bottom-reader-nav .menu-button.small > span {
        margin-right: 0 !important;
    }

    /* --- Responsive Design (Mobile First) --- */
    #wtr-tab-terms.active {
        display: flex;
        flex-direction: column;
    }
    .wtr-replacer-list-controls { order: 1; }
    .wtr-pagination-controls { order: 2; margin-top: 0.5rem; margin-bottom: 0.5rem; }
    .wtr-replacer-term-list { order: 3; }

    /* --- Mobile Specific Improvements --- */
    @media (max-width: 768px) {

        .wtr-replacer-ui {
            width: 95%; max-height: 85vh;
            top: 2.5%; left: 2.5%; transform: none;
        }

        .wtr-replacer-content {
            padding: 0.5rem;
        }

        .wtr-replacer-list-controls {
            flex-direction: column; align-items: stretch; gap: 0.5rem;
        }

        .wtr-replacer-list-controls input[type="text"] {
            order: 1;
        }

        .wtr-replacer-list-controls .btn {
            order: 2; margin: 0;
        }

        .wtr-dup-controls {
            justify-content: center;
        }


        .wtr-pagination-controls {
            justify-content: center;
            gap: 0.125rem;
        }

        .wtr-pagination-controls .btn {
            padding: 0.375rem 0.5rem;
            font-size: 0.8rem;
            min-width: 2rem;
        }

        #wtr-page-indicator {
            font-size: 0.8rem;
            margin: 0 0.25rem;
            padding: 0.25rem;
        }

        .wtr-replacer-term-item {
            padding: 0.5rem;
            gap: 0.5rem;
        }

        .wtr-replacer-term-text {
            font-size: 0.8rem;
        }
    }

    @media (min-width: 769px) {
        .wtr-replacer-list-controls { order: 1; }
        .wtr-replacer-term-list { order: 2; }
        .wtr-pagination-controls { order: 3; margin-top: 1rem; margin-bottom: 0; }
    }
`;
function createUI() {
    if (document.querySelector(".wtr-replacer-ui")) {
        return;
    }
    GM_addStyle(UI_CSS);
    const uiContainer = document.createElement("div");
    uiContainer.className = "wtr-replacer-ui";
    uiContainer.innerHTML = UI_HTML;
    document.body.appendChild(uiContainer);
    const processingOverlay = document.createElement("div");
    processingOverlay.className = "wtr-processing-overlay";
    processingOverlay.textContent = "Processing...";
    document.body.appendChild(processingOverlay);
    // Event Listeners
    uiContainer.querySelector(".wtr-replacer-close-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .hideUIPanel */ .X);
    uiContainer.querySelector("#wtr-disable-all").addEventListener("change", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleDisableToggle */ .ts);
    uiContainer.querySelector("#wtr-save-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleSaveTerm */ .s7);
    uiContainer.querySelector("#wtr-refresh-suggestions-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleRefreshSuggestionsClick */ .Zw);
    uiContainer.querySelector("#wtr-replacement-suggestions").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleReplacementSuggestionClick */ .JB);
    uiContainer.querySelector("#wtr-delete-selected-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleDeleteSelected */ .Jm);
    uiContainer.querySelector("#wtr-search-bar").addEventListener("input", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleSearch */ .RX);
    uiContainer.querySelector(".wtr-replacer-term-list").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleListInteraction */ .VM);
    uiContainer
        .querySelectorAll(".wtr-replacer-tab-btn")
        .forEach((btn) => btn.addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleTabSwitch */ .Qk));
    uiContainer.querySelector("#wtr-export-novel-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleExportNovel */ .b7);
    uiContainer.querySelector("#wtr-export-all-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleExportAll */ .ym);
    uiContainer.querySelector("#wtr-export-combined-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleExportCombined */ .ow);
    uiContainer.querySelector("#wtr-import-novel-btn").addEventListener("click", () => {
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.importType = "novel";
        document.getElementById("wtr-file-input").click();
    });
    uiContainer.querySelector("#wtr-import-all-btn").addEventListener("click", () => {
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.importType = "all";
        document.getElementById("wtr-file-input").click();
    });
    uiContainer.querySelector("#wtr-file-input").addEventListener("change", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleFileImport */ .kF);
    uiContainer.querySelector("#wtr-find-duplicates-btn").addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleFindDuplicates */ .y$);
    uiContainer.querySelector("#wtr-prev-dup-btn").addEventListener("click", () => (0,_duplicates__WEBPACK_IMPORTED_MODULE_2__/* .changeDupGroup */ .DP)(-1));
    uiContainer.querySelector("#wtr-next-dup-btn").addEventListener("click", () => (0,_duplicates__WEBPACK_IMPORTED_MODULE_2__/* .changeDupGroup */ .DP)(1));
    uiContainer.querySelector("#wtr-exit-dup-btn").addEventListener("click", _duplicates__WEBPACK_IMPORTED_MODULE_2__/* .exitDupMode */ .bj);
    document.addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleWtrTextPatchClick */ .Xq, true);
    document.addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleWtrPopoverAddTermClick */ .cD);
    const wtrPopoverObserver = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node instanceof Element) {
                    _handlers__WEBPACK_IMPORTED_MODULE_1__/* .enhanceWtrTermPopovers */ .mA(node);
                }
            });
        });
    });
    wtrPopoverObserver.observe(document.body, { childList: true, subtree: true });
    _handlers__WEBPACK_IMPORTED_MODULE_1__/* .enhanceWtrTermPopovers */ .mA(document);
    // Add scroll event listener to save term list location
    const contentArea = uiContainer.querySelector(".wtr-replacer-content");
    if (contentArea) {
        let scrollTimeout;
        contentArea.addEventListener("scroll", () => {
            clearTimeout(scrollTimeout);
            scrollTimeout = setTimeout(() => {
                if (document.querySelector(".wtr-replacer-tab-btn.active").dataset.tab === "terms") {
                    _handlers__WEBPACK_IMPORTED_MODULE_1__/* .saveTermListLocation */ .R6();
                }
            }, 1000); // Save after 1 second of inactivity
        });
    }
    // Character-based auto-resize for original text field
    const regexCheckbox = uiContainer.querySelector("#wtr-is-regex");
    const caseSensitiveCheckbox = uiContainer.querySelector("#wtr-case-sensitive");
    const wholeWordCheckbox = uiContainer.querySelector("#wtr-whole-word");
    regexCheckbox.addEventListener("change", (e) => {
        wholeWordCheckbox.disabled = e.target.checked;
        if (e.target.checked) {
            wholeWordCheckbox.checked = false;
            _handlers__WEBPACK_IMPORTED_MODULE_1__/* .normalizeOriginalRegexField */ .AO();
        }
    });
    const originalTextarea = uiContainer.querySelector("#wtr-original");
    function autoResizeTextarea() {
        if (!originalTextarea) {
            return;
        }
        const text = originalTextarea.value;
        const charCount = text.length;
        const lines = Math.ceil(charCount / 40);
        const maxLines = Infinity;
        const finalLines = Math.min(lines, maxLines);
        originalTextarea.rows = Math.max(1, finalLines);
    }
    originalTextarea.addEventListener("input", autoResizeTextarea);
    originalTextarea.addEventListener("input", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleReplacementSuggestionInput */ .l9);
    originalTextarea.addEventListener("focus", autoResizeTextarea);
    originalTextarea.addEventListener("focus", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleSuggestionTargetFocus */ .U8);
    regexCheckbox.addEventListener("change", () => _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleReplacementSuggestionInput */ .l9({ target: originalTextarea, mergeExisting: true }));
    caseSensitiveCheckbox.addEventListener("change", () => _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleReplacementSuggestionInput */ .l9({ target: originalTextarea, mergeExisting: true }));
    // Real-time regex validation system
    const saveButton = uiContainer.querySelector("#wtr-save-btn");
    const replacementInput = uiContainer.querySelector("#wtr-replacement");
    replacementInput.addEventListener("focus", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleSuggestionTargetFocus */ .U8);
    function updateValidationVisual(state) {
        // Remove all validation classes
        originalTextarea.classList.remove("wtr-field-invalid", "wtr-field-valid", "wtr-field-warning");
        if (state === "invalid") {
            originalTextarea.classList.add("wtr-field-invalid");
        }
        else if (state === "valid") {
            originalTextarea.classList.add("wtr-field-valid");
        }
        else if (state === "warning") {
            originalTextarea.classList.add("wtr-field-warning");
        }
    }
    function looksLikeRegexSyntax(value) {
        return /(^|[^\\])\|/.test(value) || /\\[bBdDsSwW]/.test(value) || /\[[^\]]+\]/.test(value) || /\([^)]*\|[^)]*\)/.test(value) || /\.\*/.test(value) || /[+*?{}^$]/.test(value);
    }
    function validateAndUpdateUI() {
        const isRegexEnabled = regexCheckbox.checked;
        const originalText = originalTextarea.value.trim();
        const replacementText = replacementInput.value.trim();
        const isValidInput = originalText.length > 0 && replacementText.length > 0;
        const regexWarning = document.getElementById("wtr-regex-disabled-warning");
        const shouldWarnRegexDisabled = !isRegexEnabled && originalText.length > 0 && looksLikeRegexSyntax(originalText);
        if (regexWarning) {
            regexWarning.style.display = shouldWarnRegexDisabled ? "block" : "none";
        }
        if (!isRegexEnabled || originalText.length === 0) {
            // Not a regex or empty field, clear validation state unless the text looks like regex syntax.
            updateValidationVisual(shouldWarnRegexDisabled ? "warning" : null);
            saveButton.disabled = !isValidInput;
            return;
        }
        // Validate regex pattern
        const validation = _handlers__WEBPACK_IMPORTED_MODULE_1__/* .validateRegexSilent */ .fA(originalText);
        if (validation.isValid) {
            updateValidationVisual("valid");
            saveButton.disabled = !isValidInput;
        }
        else {
            updateValidationVisual("invalid");
            saveButton.disabled = true;
        }
    }
    // Add real-time validation listeners
    originalTextarea.addEventListener("input", validateAndUpdateUI);
    replacementInput.addEventListener("input", validateAndUpdateUI);
    regexCheckbox.addEventListener("change", validateAndUpdateUI);
    // Initial validation state
    validateAndUpdateUI();
    // Create floating action button
    const addTermFloatBtn = document.createElement("button");
    addTermFloatBtn.className = "wtr-add-term-float-btn";
    addTermFloatBtn.textContent = "Add Term";
    document.body.appendChild(addTermFloatBtn);
    addTermFloatBtn.addEventListener("click", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleAddTermFromSelection */ .az);
    document.addEventListener("mouseup", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleTextSelection */ .Me);
    document.addEventListener("touchend", _handlers__WEBPACK_IMPORTED_MODULE_1__/* .handleTextSelection */ .Me);
    // Pagination Listeners
    uiContainer.querySelector("#wtr-first-page-btn").addEventListener("click", () => {
        if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage > 1) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage = 1;
            renderTermList(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue);
        }
    });
    uiContainer.querySelector("#wtr-prev-page-btn").addEventListener("click", () => {
        if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage > 1) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage--;
            renderTermList(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue);
        }
    });
    uiContainer.querySelector("#wtr-next-page-btn").addEventListener("click", () => {
        const filteredTerms = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.filter((t) => t.original.toLowerCase().includes(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue.toLowerCase()) ||
            t.replacement.toLowerCase().includes(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue.toLowerCase()));
        const totalPages = Math.ceil(filteredTerms.length / _config__WEBPACK_IMPORTED_MODULE_4__/* .ITEMS_PER_PAGE */ .re) || 1;
        if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage < totalPages) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage++;
            renderTermList(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue);
        }
    });
    uiContainer.querySelector("#wtr-last-page-btn").addEventListener("click", () => {
        const filteredTerms = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.filter((t) => t.original.toLowerCase().includes(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue.toLowerCase()) ||
            t.replacement.toLowerCase().includes(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue.toLowerCase()));
        const totalPages = Math.ceil(filteredTerms.length / _config__WEBPACK_IMPORTED_MODULE_4__/* .ITEMS_PER_PAGE */ .re) || 1;
        if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage < totalPages) {
            _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage = totalPages;
            renderTermList(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue);
        }
    });
    (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: UI created successfully");
}
function showProcessingIndicator(show) {
    const overlay = document.querySelector(".wtr-processing-overlay");
    if (overlay) {
        overlay.style.display = show ? "flex" : "none";
    }
}
function showUILoader() {
    const loader = document.getElementById("wtr-ui-loader");
    if (loader) {
        loader.style.display = "flex";
    }
    const content = document.querySelector(".wtr-replacer-content");
    if (content) {
        content.style.pointerEvents = "none";
    }
}
function hideUILoader() {
    const loader = document.getElementById("wtr-ui-loader");
    if (loader) {
        loader.style.display = "none";
    }
    const content = document.querySelector(".wtr-replacer-content");
    if (content) {
        content.style.pointerEvents = "auto";
    }
}
function renderTermList(filter = "") {
    const listEl = document.querySelector(".wtr-replacer-term-list");
    const paginationControls = document.querySelector(".wtr-pagination-controls");
    const pageIndicator = document.getElementById("wtr-page-indicator");
    const firstBtn = document.getElementById("wtr-first-page-btn");
    const prevBtn = document.getElementById("wtr-prev-page-btn");
    const nextBtn = document.getElementById("wtr-next-page-btn");
    const lastBtn = document.getElementById("wtr-last-page-btn");
    const contentArea = document.querySelector(".wtr-replacer-content");
    if (!listEl || !paginationControls || !pageIndicator || !prevBtn || !nextBtn || !firstBtn || !lastBtn) {
        return;
    }
    // Capture current scroll position before re-rendering
    const previousScrollTop = contentArea ? contentArea.scrollTop : 0;
    const shouldRestoreScroll = previousScrollTop > 0 && !_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.isDupMode && filter === _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentSearchValue;
    listEl.innerHTML = "";
    let filteredTerms;
    let termsToRender;
    if (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.isDupMode) {
        const currentKey = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys[_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex];
        filteredTerms = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupGroups.get(currentKey) || [];
        document.getElementById("wtr-dup-message").textContent = `Duplicate group ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex + 1} of ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.length} — ${currentKey}`;
        document.getElementById("wtr-dup-message").style.display = "block";
        document.getElementById("wtr-dup-controls").style.display = "flex";
        document.getElementById("wtr-prev-dup-btn").disabled = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex === 0;
        document.getElementById("wtr-next-dup-btn").disabled = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentDupIndex === _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.dupKeys.length - 1;
        document.getElementById("wtr-search-bar").disabled = true;
        paginationControls.style.display = "none";
        termsToRender = filteredTerms;
    }
    else {
        const filterLower = filter.toLowerCase();
        filteredTerms = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.filter((t) => t.original.toLowerCase().includes(filterLower) || t.replacement.toLowerCase().includes(filterLower));
        document.getElementById("wtr-dup-message").style.display = "none";
        document.getElementById("wtr-dup-controls").style.display = "none";
        document.getElementById("wtr-search-bar").disabled = false;
        const totalPages = Math.ceil(filteredTerms.length / _config__WEBPACK_IMPORTED_MODULE_4__/* .ITEMS_PER_PAGE */ .re) || 1;
        _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage = Math.max(1, Math.min(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage, totalPages));
        const start = (_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage - 1) * _config__WEBPACK_IMPORTED_MODULE_4__/* .ITEMS_PER_PAGE */ .re;
        const end = start + _config__WEBPACK_IMPORTED_MODULE_4__/* .ITEMS_PER_PAGE */ .re;
        termsToRender = filteredTerms.slice(start, end);
        if (totalPages > 1) {
            paginationControls.style.display = "flex";
            pageIndicator.textContent = `Page ${_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage} of ${totalPages}`;
            firstBtn.disabled = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage === 1;
            prevBtn.disabled = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage === 1;
            nextBtn.disabled = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage === totalPages;
            lastBtn.disabled = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.currentPage === totalPages;
        }
        else {
            paginationControls.style.display = "none";
        }
    }
    if (termsToRender.length === 0) {
        listEl.innerHTML = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.terms.length === 0 ? "<li>No terms defined.</li>" : "<li>No terms match search.</li>";
    }
    else {
        const fragment = document.createDocumentFragment();
        termsToRender.forEach((term) => {
            const li = document.createElement("li");
            li.className = "wtr-replacer-term-item";
            li.dataset.id = term.id;
            const checkbox = document.createElement("input");
            checkbox.type = "checkbox";
            checkbox.className = "wtr-replacer-term-select";
            checkbox.dataset.id = term.id;
            li.appendChild(checkbox);
            const details = document.createElement("div");
            details.className = "wtr-replacer-term-details";
            const termText = document.createElement("div");
            termText.className = "wtr-replacer-term-text";
            const originalSpan = document.createElement("span");
            originalSpan.className = "wtr-term-original";
            originalSpan.textContent = term.original;
            const replacementSpan = document.createElement("span");
            replacementSpan.className = "wtr-term-replacement";
            replacementSpan.textContent = term.replacement;
            termText.appendChild(originalSpan);
            termText.appendChild(document.createTextNode(" → "));
            termText.appendChild(replacementSpan);
            details.appendChild(termText);
            const flags = document.createElement("div");
            if (term.caseSensitive) {
                const badge = document.createElement("small");
                badge.textContent = "CS";
                flags.appendChild(badge);
                flags.appendChild(document.createTextNode(" "));
            }
            if (term.isRegex) {
                const badge = document.createElement("small");
                badge.textContent = "RX";
                flags.appendChild(badge);
                flags.appendChild(document.createTextNode(" "));
            }
            if (term.wholeWord) {
                const badge = document.createElement("small");
                badge.textContent = "WW";
                flags.appendChild(badge);
            }
            details.appendChild(flags);
            li.appendChild(details);
            const actionWrap = document.createElement("div");
            const editButton = document.createElement("button");
            editButton.type = "button";
            editButton.className = "btn btn-secondary btn-sm wtr-edit-btn";
            editButton.dataset.id = term.id;
            editButton.textContent = "Edit";
            actionWrap.appendChild(editButton);
            li.appendChild(actionWrap);
            fragment.appendChild(li);
        });
        listEl.appendChild(fragment);
    }
    // Restore scroll position after DOM update if it was captured
    if (shouldRestoreScroll && contentArea) {
        // Use requestAnimationFrame to ensure DOM has been updated
        requestAnimationFrame(() => {
            contentArea.scrollTop = previousScrollTop;
        });
    }
}
function showUIPanel() {
    const ui = document.querySelector(".wtr-replacer-ui");
    ui.style.display = "flex";
    document.getElementById("wtr-disable-all").checked = _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.settings.isDisabled;
    // Restore saved location when showing the terms tab
    if (document.querySelector(".wtr-replacer-tab-btn.active").dataset.tab === "terms") {
        _handlers__WEBPACK_IMPORTED_MODULE_1__/* .restoreTermListLocation */ .s3();
    }
    else {
        renderTermList();
    }
}
function hideUIPanel() {
    // Save current location before hiding
    _handlers__WEBPACK_IMPORTED_MODULE_1__/* .saveTermListLocation */ .R6();
    document.querySelector(".wtr-replacer-ui").style.display = "none";
    clearTermList();
}
function clearTermList() {
    const listEl = document.querySelector(".wtr-replacer-term-list");
    if (listEl) {
        listEl.innerHTML = "";
    }
}
function showFormView(term = null) {
    if (!term) {
        _handlers__WEBPACK_IMPORTED_MODULE_1__/* .clearDiscoveryFormState */ .nS();
    }
    document.getElementById("wtr-term-id").value = term ? term.id : "";
    document.getElementById("wtr-original").value = term ? term.original : "";
    document.getElementById("wtr-replacement").value = term ? term.replacement : "";
    document.getElementById("wtr-case-sensitive").checked = term ? term.caseSensitive : false;
    document.getElementById("wtr-is-regex").checked = term ? term.isRegex : false;
    document.getElementById("wtr-whole-word").checked = term ? term.wholeWord : false;
    document.getElementById("wtr-whole-word").disabled = term ? term.isRegex : false;
    document.getElementById("wtr-save-btn").textContent = term ? "Update Term" : "Save Term";
    switchTab("add");
    // Initialize auto-resize after form is populated
    setTimeout(() => {
        const originalTextarea = document.getElementById("wtr-original");
        if (originalTextarea) {
            const text = originalTextarea.value;
            const charCount = text.length;
            const lines = Math.ceil(charCount / 40);
            originalTextarea.rows = Math.max(1, lines);
        }
        // Re-initialize validation state for the form
        const regexCheckbox = document.getElementById("wtr-is-regex");
        if (regexCheckbox) {
            const validationEvent = new Event("input", { bubbles: true });
            originalTextarea.dispatchEvent(validationEvent);
        }
    }, 10);
}
function switchTab(tabName) {
    document.querySelector(`.wtr-replacer-tab-btn[data-tab="${tabName}"]`).click();
}
// Simple function to create menu buttons with inline SVG icons
function createSimpleMenuButton(options) {
    const { text = "Settings", onClick = null, className = "", tooltip = "" } = options;
    const button = document.createElement("button");
    button.className = `replacer-settings-btn ${className}`;
    if (tooltip) {
        button.title = tooltip;
    }
    // Create settings icon using the specified SVG
    const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
    svg.setAttribute("height", "24px");
    svg.setAttribute("viewBox", "0 -960 960 960");
    svg.setAttribute("width", "24px");
    svg.setAttribute("fill", "#1f1f1f");
    svg.style.marginRight = "4px";
    svg.style.verticalAlign = "middle";
    svg.innerHTML =
        '<path d="M700-120h40v-100h100v-40H740v-100h-40v100H600v40h100v100Zm20 80q-83 0-141.5-58.5T520-240q0-83 58.5-141.5T720-440q83 0 141.5 58.5T920-240q0 83-58.5 141.5T720-40ZM280-600h400v-80H280v80Zm187 480H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v268q-29-14-58.5-21t-61.5-7q-11 0-20.5.5T680-517v-3H280v80h245q-18 17-32.5 37T467-360H280v80h163q-2 10-2.5 19.5T440-240q0 33 6 61.5t21 58.5Z"/>';
    button.appendChild(svg);
    // Add text
    const textSpan = document.createElement("span");
    textSpan.textContent = text;
    button.appendChild(textSpan);
    // Add click handler
    if (onClick) {
        button.addEventListener("click", onClick);
    }
    return button;
}
function addMenuButton() {
    const container = document.querySelector("div.col-6:has(button.term-edit-btn)");
    if (!container || _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.observedMenuContainers.has(container)) {
        return;
    }
    const ensureButtonState = () => {
        let settingsButton = container.querySelector(".replacer-settings-btn");
        const originalButton = container.querySelector(".term-edit-btn:not(.replacer-settings-btn)");
        // 1. Create the button if it doesn't exist
        if (!settingsButton) {
            if (!originalButton) {
                return;
            } // Can't create if the original doesn't exist yet
            // Create button with simple inline SVG icon
            settingsButton = createSimpleMenuButton({
                text: "Term Settings",
                onClick: showUIPanel,
                className: originalButton.className, // Copy classes for styling
                tooltip: "Open WTR Term Settings",
            });
            container.appendChild(settingsButton);
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Settings button created with simple icon system.");
        }
        // 2. Enforce the correct order (our button should be last)
        if (container.lastChild !== settingsButton) {
            container.appendChild(settingsButton);
            (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Settings button order corrected.");
        }
        // 3. Apply consistent styling
        if (originalButton && settingsButton) {
            const desiredFlexStyle = "1 1 0%";
            container.style.display = "flex";
            container.style.gap = "5px";
            originalButton.style.flex = desiredFlexStyle;
            settingsButton.style.flex = desiredFlexStyle;
        }
    };
    // Run once immediately
    ensureButtonState();
    // Observe for any changes and re-run to correct the state
    const observer = new MutationObserver(() => {
        (0,_utils__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(_state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.globalSettings, "WTR Term Replacer: Detected change in menu container, ensuring button state.");
        ensureButtonState();
    });
    observer.observe(container, { childList: true });
    // Mark this container as observed to prevent re-attaching observers
    _state__WEBPACK_IMPORTED_MODULE_0__/* .state */ .wk.observedMenuContainers.add(container);
}


/***/ },

/***/ 158
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Nt: () => (/* binding */ escapeRegExp),
/* harmony export */   Rm: () => (/* binding */ log),
/* harmony export */   Ug: () => (/* binding */ getChapterIdFromUrl),
/* harmony export */   getNovelSlug: () => (/* binding */ getNovelSlug),
/* harmony export */   o7: () => (/* binding */ getReaderContextFromPath)
/* harmony export */ });
/* unused harmony exports debounce, detectOtherWTRScripts, logDOMConflict, logProcessingWithMultiScriptContext, startProcessingTimer, endProcessingTimer, isContentReadyForProcessing, isElementReadyForProcessing, estimateContentLoadLevel */
/* harmony import */ var _config_versions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(387);
/* harmony import */ var _config_versions__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_config_versions__WEBPACK_IMPORTED_MODULE_0__);
// Utility functions for WTR Lab Term Replacer

function getReaderContextFromPath(pathname = window.location.pathname) {
    const parts = pathname.split("/").filter(Boolean);
    const novelIndex = parts.indexOf("novel");
    if (novelIndex >= 0) {
        return {
            lang: novelIndex > 0 ? parts[0] || "en" : "en",
            rawId: parts[novelIndex + 1] || null,
            novelSlug: parts[novelIndex + 2] || null,
            chapterSlug: parts[novelIndex + 3] || null,
        };
    }
    const serieIndex = parts.findIndex((part) => /^serie-\d+$/.test(part));
    if (serieIndex >= 0) {
        const rawId = parts[serieIndex].replace(/^serie-/, "") || null;
        return {
            lang: serieIndex > 0 ? parts[0] || "en" : "en",
            rawId,
            novelSlug: parts[serieIndex + 1] || null,
            chapterSlug: parts[serieIndex + 2] || null,
        };
    }
    return {
        lang: parts[0] || "en",
        rawId: null,
        novelSlug: null,
        chapterSlug: null,
    };
}
function getNovelSlug() {
    return getReaderContextFromPath().novelSlug;
}
function escapeRegExp(str) {
    return str.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
}
function debounce(func, delay) {
    let timeout;
    return function (...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), delay);
    };
}
function getChapterIdFromUrl(url) {
    const match = url.match(/(chapter-\d+)/);
    return match ? match[1] : null;
}
function log(globalSettings, ...args) {
    if (globalSettings && globalSettings.isLoggingEnabled) {
        console.log(...args);
    }
}
const _CURRENT_VERSION = (0,_config_versions__WEBPACK_IMPORTED_MODULE_0__.getVersion)();
// --- [ENHANCED ${CURRENT_VERSION}] MULTI-SCRIPT COORDINATION FUNCTIONS ---
function detectOtherWTRScripts() {
    // Detect other WTR Lab scripts by their data attributes or specific patterns
    const scripts = document.querySelectorAll("[data-smart-quotes-processed], [data-uncensor-processed], [data-auto-scroll], [data-reader-enhanced]");
    const otherWTRScripts = new Set();
    scripts.forEach((el) => {
        if (el.hasAttribute("data-smart-quotes-processed")) {
            otherWTRScripts.add("Smart Quotes");
        }
        if (el.hasAttribute("data-uncensor-processed")) {
            otherWTRScripts.add("Uncensor");
        }
        if (el.hasAttribute("data-auto-scroll") || el.hasAttribute("data-reader-enhanced")) {
            otherWTRScripts.add("Reader Enhancer");
        }
    });
    if (otherWTRScripts.size > 0) {
        log(null, `WTR Term Replacer: Multi-script environment detected - Active scripts: ${Array.from(otherWTRScripts).join(", ")}`);
    }
    return otherWTRScripts;
}
function logDOMConflict(sourceScript, element, processingQueue, chapterId) {
    const timestamp = new Date().toISOString();
    const conflictInfo = {
        timestamp,
        sourceScript,
        element: element.tagName,
        elementId: element.id || "no-id",
        processingQueueSize: processingQueue ? processingQueue.size : 0,
        chapterId: chapterId,
    };
    log(null, `WTR Term Replacer: DOM conflict detected with ${sourceScript} script`, conflictInfo);
}
function logProcessingWithMultiScriptContext(chapterId, processingTime, isMultiScript = false, otherWTRScripts, processingQueue) {
    const context = {
        chapterId,
        processingTime: `${processingTime}ms`,
        multiScriptEnvironment: isMultiScript,
        activeScripts: otherWTRScripts ? otherWTRScripts.size : 0,
        queueSize: processingQueue ? processingQueue.size : 0,
        timestamp: new Date().toISOString(),
    };
    if (isMultiScript && otherWTRScripts && otherWTRScripts.size > 0) {
        context.activeScripts = Array.from(otherWTRScripts);
        log(null, `WTR Term Replacer: Multi-script enhanced processing completed`, context);
    }
    else {
        log(null, `WTR Term Replacer: Standard processing completed`, context);
    }
}
function startProcessingTimer(operation, processingStartTime) {
    processingStartTime.set(operation, Date.now());
}
function endProcessingTimer(operation, chapterId, processingStartTime, otherWTRScripts, processingQueue) {
    const startTime = processingStartTime.get(operation);
    if (startTime) {
        const processingTime = Date.now() - startTime;
        const isMultiScript = otherWTRScripts && otherWTRScripts.size > 0;
        log(null, `WTR Term Replacer: Processing timer ended for ${operation}, took ${processingTime}ms`);
        logProcessingWithMultiScriptContext(chapterId, processingTime, isMultiScript, otherWTRScripts, processingQueue);
        processingStartTime.delete(operation);
        return processingTime;
    }
    log(null, `WTR Term Replacer: Warning - processing timer for ${operation} not found`);
    return 0;
}
// Content readiness check for enhanced content processing
function isContentReadyForProcessing(container) {
    // Multiple readiness criteria for robust detection
    const hasSubstantialContent = container.textContent?.trim().length > 100;
    const hasNoActiveLoaders = !container.querySelector('.loading, .spinner, [style*="loading"], .skeleton');
    const isVisible = container.offsetWidth > 0 && container.offsetHeight > 0;
    const hasChapterContent = container.querySelector(".chapter-body") || container.querySelector("p, h1, h2, h3, h4, h5, h6");
    return hasSubstantialContent && hasNoActiveLoaders && isVisible && hasChapterContent;
}
// Element readiness check for robust processing
function isElementReadyForProcessing(element) {
    // Check if element is visible and has substantial content
    const rect = element.getBoundingClientRect();
    const isVisible = rect.width > 0 && rect.height > 0;
    const hasSubstantialContent = element.textContent?.trim().length > 50;
    const hasNoLoadingStates = !element.querySelector('.loading, .spinner, [style*="display: none"]');
    return isVisible && hasSubstantialContent && hasNoLoadingStates;
}
// Enhanced content load level estimation for retry mechanisms
function estimateContentLoadLevel(chapterBody) {
    // Estimate how much content is loaded based on text density and structure
    const textNodes = chapterBody.querySelectorAll("p, h1, h2, h3, h4, h5, h6, div, span");
    const totalTextLength = Array.from(textNodes).reduce((total, node) => total + (node.textContent?.trim().length || 0), 0);
    // Check for loading indicators or placeholder content
    const hasLoadingIndicators = chapterBody.querySelector('.loading, .spinner, [style*="loading"], [class*="loading"]');
    const hasPlaceholderContent = chapterBody.textContent?.includes("Loading...") ||
        chapterBody.textContent?.includes("loading") ||
        chapterBody.textContent?.includes("...");
    // Calculate load level based on content density and absence of loading indicators
    let loadLevel = Math.min(totalTextLength / 1000, 1.0); // Normalize to 0-1 based on 1000 chars
    if (hasLoadingIndicators || hasPlaceholderContent) {
        loadLevel *= 0.3; // Reduce load level if loading indicators present
    }
    // Ensure minimum threshold for processing
    return Math.max(loadLevel, totalTextLength > 100 ? 0.5 : 0.1);
}


/***/ },

/***/ 330
(module) {

"use strict";
module.exports = /*#__PURE__*/JSON.parse('{"name":"wtr-lab-term-replacer-webpack","version":"5.7.0","description":"A modular, Webpack-powered TypeScript version of the WTR Lab Term Replacer userscript.","author":"MasuRii","license":"MIT","private":true,"main":"dist/wtr-lab-term-replacer-webpack.user.js","repository":{"type":"git","url":"https://github.com/MasuRii/wtr-lab-term-replacer-webpack.git"},"bugs":{"url":"https://github.com/MasuRii/wtr-lab-term-replacer-webpack/issues"},"keywords":["term","replacement","wtr-lab","userscript","modular","webpack"],"files":["dist/","src/"],"scripts":{"build":"npm run version:update && npm run typecheck && webpack --mode=production","build:performance":"npm run typecheck && webpack --config webpack.config.js --config-name performance --mode=production","build:greasyfork":"npm run typecheck && webpack --config webpack.config.js --config-name greasyfork --mode=production","build:devbundle":"npm run typecheck && webpack --config webpack.config.js --config-name dev --mode=development","dev":"webpack serve --config webpack.config.js --config-name dev --mode=development","typecheck":"tsc --noEmit","test":"node scripts/run-tests.js","version:update":"node scripts/update-versions.js update","version:check":"node scripts/update-versions.js check"},"devDependencies":{"@types/tampermonkey":"^5.0.5","ts-loader":"^9.5.7","typescript":"^6.0.3","webpack":"^5.106.2","webpack-cli":"^7.0.2","webpack-dev-server":"^5.2.3","webpack-userscript":"^3.2.3"}}');

/***/ }

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
/* harmony import */ var _modules_ui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(141);
/* harmony import */ var _modules_storage__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(694);
/* harmony import */ var _modules_observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(405);
/* harmony import */ var _modules_state__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(654);
/* harmony import */ var _modules_handlers__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(359);
/* harmony import */ var _modules_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(158);
// Main entry point for WTR Lab Term Replacer




 // Import all handlers

// Function to get chapter ID from URL (for module compatibility)
function getChapterIdFromUrl(url) {
    const match = url.match(/(chapter-\d+)/);
    return match ? match[1] : null;
}
// Enhanced error handling setup
function setupEnhancedErrorHandling() {
    // Global error handler to catch and log any issues
    window.addEventListener("error", (event) => {
        if (event.error && event.error.message && event.error.message.includes("WTR")) {
            (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Caught error:", event.error);
        }
    });
    // Handle unhandled promise rejections
    window.addEventListener("unhandledrejection", (event) => {
        if (event.reason && event.reason.message && event.reason.message.includes("WTR")) {
            (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Unhandled promise rejection:", event.reason);
        }
    });
    // Cleanup function for when page unloads
    window.addEventListener("beforeunload", () => {
        _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.processingQueue.clear();
        (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Cleanup on page unload");
    });
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Enhanced error handling activated");
}
// Enhanced navigation handling setup
function setupEnhancedNavigationHandling() {
    // Enhanced URL change detection with proper debouncing and coordination
    let isNavigationInProgress = false;
    const processNavigationSafely = () => {
        if (isNavigationInProgress) {
            (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Navigation already in progress, skipping");
            return;
        }
        isNavigationInProgress = true;
        // Clear processing queue for new chapter
        _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.processingQueue.clear();
        // Wait for content to load with enhanced detection
        setTimeout(() => {
            Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 405)).then(({ processVisibleChapter }) => {
                processVisibleChapter();
            });
            isNavigationInProgress = false;
        }, 500); // Increased delay to allow DOM updates and prevent conflicts
    };
    // Set up navigation event listeners for SPA-style navigation
    window.addEventListener("popstate", () => {
        (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Popstate event detected");
        processNavigationSafely();
    });
    // Handle pushState/replaceState (SPA navigation)
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;
    history.pushState = function (...args) {
        const result = originalPushState.apply(this, args);
        processNavigationSafely();
        return result;
    };
    history.replaceState = function (...args) {
        const result = originalReplaceState.apply(this, args);
        processNavigationSafely();
        return result;
    };
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Enhanced navigation handling activated");
}
// Enhanced disable functionality that works reliably
function addDisableAllRobustness() {
    // Enhanced disable functionality with proper error handling
    const handleDisableToggleRobust = async function (e) {
        const wasDisabled = _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.settings.isDisabled;
        const shouldDisable = e.target.checked;
        // Update settings immediately
        _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.settings.isDisabled = shouldDisable;
        await (await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 694))).saveSettings(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.settings);
        // Perform robust disable/enable operation
        const chapterId = getChapterIdFromUrl(window.location.href);
        if (!chapterId) {
            return;
        }
        const chapterSelector = `#${chapterId} .chapter-body`;
        const chapterBody = document.querySelector(chapterSelector);
        if (chapterBody) {
            try {
                const { performReplacements, revertAllReplacements } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 9));
                if (shouldDisable) {
                    // Disable: revert all replacements
                    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Robust disable - reverting all replacements");
                    await revertAllReplacements(chapterBody);
                    chapterBody.dataset.wtrProcessed = "false";
                }
                else {
                    // Enable: perform replacements with retry
                    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Robust enable - performing replacements");
                    await performReplacements(chapterBody);
                    chapterBody.dataset.wtrProcessed = "true";
                }
            }
            catch (error) {
                (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, `WTR Term Replacer: Error during ${shouldDisable ? "disable" : "enable"} operation:`, error);
                // Reset checkbox on error
                e.target.checked = wasDisabled;
                _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.settings.isDisabled = wasDisabled;
            }
        }
    };
    // Replace the existing event listener with our robust version
    const uiContainer = document.querySelector(".wtr-replacer-ui");
    if (uiContainer) {
        const disableCheckbox = uiContainer.querySelector("#wtr-disable-all");
        if (disableCheckbox) {
            // Remove existing listener and add our enhanced one
            const newDisableCheckbox = disableCheckbox.cloneNode(true);
            disableCheckbox.parentNode.replaceChild(newDisableCheckbox, disableCheckbox);
            newDisableCheckbox.addEventListener("change", handleDisableToggleRobust);
        }
    }
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Enhanced disable functionality activated");
}
function registerExternalIntegrationBridge() {
    if (window.__WTR_TERM_REPLACER_BRIDGE_REGISTERED__) {
        const existingApi = window.WTR_LAB_TERM_REPLACER || {};
        window.WTR_LAB_TERM_REPLACER = {
            ...existingApi,
            ready: true,
            bridgeVersion: 1,
        };
        return;
    }
    window.__WTR_TERM_REPLACER_BRIDGE_REGISTERED__ = true;
    const existingApi = window.WTR_LAB_TERM_REPLACER || {};
    window.WTR_LAB_TERM_REPLACER = {
        ...existingApi,
        ready: true,
        bridgeVersion: 1,
    };
    window.addEventListener("wtr:addTerm", (event) => {
        const { original, replacement, isRegex } = event?.detail || {};
        _modules_handlers__WEBPACK_IMPORTED_MODULE_4__/* .addTermProgrammatically */ .IY(original, replacement, isRegex);
    });
    window.addEventListener("wtr:requestTerms", async (event) => {
        const requestId = event?.detail?.requestId;
        const requestedSlug = event?.detail?.novelSlug || _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.novelSlug || (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__.getNovelSlug)();
        if (!requestId) {
            return;
        }
        try {
            const terms = requestedSlug === _modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.novelSlug ? [..._modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.terms] : await (0,_modules_storage__WEBPACK_IMPORTED_MODULE_1__.getTermsForSlug)(requestedSlug);
            window.dispatchEvent(new CustomEvent("wtr:termsResponse", {
                detail: {
                    requestId,
                    novelSlug: requestedSlug,
                    terms,
                    source: "wtr-term-replacer",
                    success: true,
                },
            }));
        }
        catch (error) {
            (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Failed to provide terms to external requester", error);
            window.dispatchEvent(new CustomEvent("wtr:termsResponse", {
                detail: {
                    requestId,
                    novelSlug: requestedSlug,
                    terms: [],
                    source: "wtr-term-replacer",
                    success: false,
                    error: error instanceof Error ? error.message : String(error),
                },
            }));
        }
    });
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: External integration bridge registered");
}
async function main() {
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Main function starting initialization...");
    // Initialize state and validate novel slug
    const novelSlug = (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__.getNovelSlug)();
    if (!novelSlug) {
        (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Critical error - could not determine novel slug");
        console.error("WTR Term Replacer: Could not determine novel slug.");
        return;
    }
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, `WTR Term Replacer: Novel slug determined: ${novelSlug}`);
    (0,_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .setNovelSlug */ .oP)(novelSlug);
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Loading global settings and data...");
    await (0,_modules_storage__WEBPACK_IMPORTED_MODULE_1__.loadGlobalSettings)();
    await (0,_modules_storage__WEBPACK_IMPORTED_MODULE_1__.loadData)();
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, `WTR Term Replacer: Data loaded - terms: ${_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.terms.length}, settings disabled: ${_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.settings.isDisabled}`);
    // Enhanced initialization with robustness features
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Setting up error handling...");
    setupEnhancedErrorHandling();
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Setting up disable functionality...");
    addDisableAllRobustness();
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Setting up navigation handling...");
    setupEnhancedNavigationHandling();
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Creating UI and menu commands...");
    (0,_modules_ui__WEBPACK_IMPORTED_MODULE_0__/* .createUI */ .RD)(); // This will also set up the initial event listeners
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Registering menu commands...");
    GM_registerMenuCommand("Term Replacer Settings", _modules_ui__WEBPACK_IMPORTED_MODULE_0__/* .showUIPanel */ .E1);
    GM_registerMenuCommand("Toggle Logging", _modules_handlers__WEBPACK_IMPORTED_MODULE_4__/* .toggleLogging */ .o6);
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Starting initial content detection...");
    (0,_modules_observer__WEBPACK_IMPORTED_MODULE_2__/* .waitForInitialContent */ ._)();
    (0,_modules_utils__WEBPACK_IMPORTED_MODULE_5__/* .log */ .Rm)(_modules_state__WEBPACK_IMPORTED_MODULE_3__/* .state */ .wk.globalSettings, "WTR Term Replacer: Initialization completed successfully");
}
registerExternalIntegrationBridge();
// Start the script
main().catch((err) => console.error("WTR Term Replacer failed to start:", err));

})();

/******/ })()
;