ArchTranslator

Useful tools for ArchWiki translators, now written in TypeScript.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        ArchTranslator
// @namespace   bb89542e-b358-4be0-8c01-3797d1f3a1e3
// @match       https://wiki.archlinux.org/*
// @grant       none
// @version     2.0.5
// @author      bonk-dev
// @description Useful tools for ArchWiki translators, now written in TypeScript.
// @icon        https://gitlab.archlinux.org/uploads/-/system/group/avatar/23/iconfinder_archlinux_386451.png
// @license     MIT
// @run-at      document-start
// ==/UserScript==
"use strict";
(() => {
  // src/Utilities/MediaWikiJsApi.ts
  function isMwApiReady() {
    return typeof mw !== "undefined";
  }
  function getMwApi() {
    return mw;
  }

  // src/Injection/InjectionAgents.ts
  var DocumentLoadAgent = class {
    start() {
      return new Promise((resolve) => {
        window.addEventListener("load", () => {
          resolve();
        });
      });
    }
  };
  var StartupLoadAgent = class {
    constructor() {
      this._observer = null;
    }
    start() {
      if (isMwApiReady()) {
        return Promise.resolve();
      }
      return new Promise((resolve, reject) => {
        const checkScriptElement = (scriptElement) => {
          const srcUrl = new URL(scriptElement.src);
          const modules = srcUrl.searchParams.get("modules");
          if (modules === "startup") {
            scriptElement.addEventListener("load", () => {
              this._observer?.disconnect();
              resolve();
            });
            scriptElement.addEventListener("error", (e) => {
              reject(e);
            });
          }
        };
        const scripts = document.querySelectorAll("script[src]");
        if (scripts.length > 0) {
          for (const script of scripts) {
            checkScriptElement(script);
          }
        }
        this._observer = new MutationObserver((mutations) => {
          for (const mutation of mutations) {
            if (mutation.type !== "childList" || mutation.addedNodes.length <= 0 || mutation.target.nodeName !== "HEAD" || mutation.addedNodes[0].nodeName !== "SCRIPT") continue;
            const scriptElement = mutation.addedNodes[0];
            if (scriptElement.src.length <= 0) continue;
            checkScriptElement(scriptElement);
          }
        });
        this._observer.observe(document.documentElement, {
          childList: true,
          subtree: true
        });
      });
    }
  };

  // src/Injection/InjectionManager.ts
  var mediaWikiHookFunction = null;
  var onHookReady = null;
  var InjectionManager = class {
    constructor() {
      this._callbacks = {
        [0 /* DocumentLoad */]: {
          callbacks: [],
          fired: false
        },
        [1 /* MediaWikiStartup */]: {
          callbacks: [],
          fired: false
        },
        [3 /* ExtCodeMirrorSwitch */]: {
          callbacks: [],
          fired: false
        },
        [2 /* JQueryEditForm */]: {
          callbacks: [],
          fired: false,
          jqueryElement: null
        }
      };
      this._agentsStarted = false;
    }
    startAgents() {
      onHookReady = () => {
        this.fire(1 /* MediaWikiStartup */);
        getMwApi().hook("ext.CodeMirror.switch").add(() => {
          this.fire(3 /* ExtCodeMirrorSwitch */);
        });
        getMwApi().hook("wikipage.editform").add((jQueryEditForm) => {
          this.fireEditForm(jQueryEditForm);
        });
      };
      if (this._agentsStarted) {
        throw new Error("Agents were already started");
      }
      this._agentsStarted = true;
      const loadAgent = new DocumentLoadAgent();
      loadAgent.start().then(() => {
        this.fire(0 /* DocumentLoad */);
      });
      const startupAgent = new StartupLoadAgent();
      startupAgent.start().then(() => {
        if (getMwApi().hook == null) {
          console.debug("hook is null. Hijacking mw.hook");
          Object.defineProperty(getMwApi(), "hook", {
            get() {
              return mediaWikiHookFunction;
            },
            set(v) {
              mediaWikiHookFunction = v;
              console.debug("mw.hook hijacked");
              if (onHookReady != null) {
                onHookReady();
              }
            }
          });
        } else {
          if (onHookReady != null) {
            onHookReady();
          }
        }
      });
    }
    on(step, callback) {
      if (this._callbacks[step].fired) {
        callback();
      } else {
        this._callbacks[step].callbacks.push(callback);
      }
    }
    /**
     * Fired exclusively on edit pages. The manager will pass the JQuery editForm object as the first parameter.
     */
    onEditForm(callback) {
      const info = this._callbacks[2 /* JQueryEditForm */];
      if (info.fired) {
        callback(info.jqueryElement);
      } else {
        info.callbacks.push(callback);
      }
    }
    fire(step) {
      const info = this._callbacks[step];
      for (const callback of info.callbacks) {
        callback();
      }
      info.fired = true;
    }
    fireEditForm(jqueryEditForm) {
      const info = this._callbacks[2 /* JQueryEditForm */];
      info.jqueryElement = jqueryEditForm;
      for (const callback of info.callbacks) {
        callback(jqueryEditForm);
      }
      info.fired = true;
    }
  };

  // src/Tools/Utils/CollapsibleFooter.ts
  function makeCollapsibleFooter($content, $toggler, storeKey) {
    const collapsedVal = "0";
    const expandedVal = "1";
    const isCollapsed = mw.storage.get(storeKey) !== expandedVal;
    $toggler.addClass("mw-editfooter-toggler").prop("tabIndex", 0).attr("role", "button");
    $content.makeCollapsible({
      $customTogglers: $toggler,
      linksPassthru: true,
      plainMode: true,
      collapsed: isCollapsed
    });
    $toggler.addClass(isCollapsed ? "mw-icon-arrow-collapsed" : "mw-icon-arrow-expanded");
    $content.on("beforeExpand.mw-collapsible", () => {
      $toggler.removeClass("mw-icon-arrow-collapsed").addClass("mw-icon-arrow-expanded");
      mw.storage.set(storeKey, expandedVal);
    });
    $content.on("beforeCollapse.mw-collapsible", () => {
      $toggler.removeClass("mw-icon-arrow-expanded").addClass("mw-icon-arrow-collapsed");
      mw.storage.set(storeKey, collapsedVal);
    });
  }

  // src/Tools/Utils/ToolManager.ts
  var toolInProgressClass = "at-tool-inProgress";
  function sideTool(toolInfo) {
    const element = document.createElement("a");
    element.innerHTML = toolInfo.displayText;
    element.addEventListener("click", (e) => {
      if (element.parentElement.classList.contains(toolInProgressClass)) {
        return;
      }
      const result = toolInfo.handler(e);
      if (result instanceof Promise) {
        element.parentElement.classList.add(toolInProgressClass);
        result.finally(() => {
          element.parentElement.classList.remove(toolInProgressClass);
        });
      }
    });
    return {
      name: toolInfo.name,
      toolElement: element,
      showCallback: toolInfo.showCallback
    };
  }
  var ToolManager = class _ToolManager {
    constructor() {
      this._sidebarToolSectionAddedToDom = false;
      this._footerTools = [];
      this._footerToolContainer = null;
      if (_ToolManager._instance != null) {
        throw new Error("ToolManager was initialized already");
      }
      _ToolManager._instance = this;
      this._sidebarToolSection = _ToolManager._createToolSectionElement();
    }
    static {
      this._instance = null;
    }
    /**
     * Adds the ArchTranslator tool section to the DOM
     * @param parent If not null, adds the tool section to the specified element (otherwise looks for #vector-page-tools)
     */
    addSidebarToPage(parent = null) {
      if (this._sidebarToolSectionAddedToDom) {
        throw new Error("The tool section was added to DOM already");
      }
      if (parent == null) {
        parent = document.getElementById("vector-page-tools");
        if (parent == null) {
          throw new Error("Could not find vector-page-tools");
        }
      }
      parent.appendChild(this._sidebarToolSection.rootElement);
      this._sidebarToolSectionAddedToDom = true;
    }
    /**
     * Adds the footer tools to the DOM
     * @param editForm The JQuery element from editForm hook
     */
    addFooterToPage(editForm) {
      if (this._footerToolContainer != null) {
        throw new Error("Footer tool container was already initialized");
      }
      this._footerToolContainer = editForm;
      for (const tool of this._footerTools) {
        this._addFooterToolToContainer(tool);
      }
    }
    /**
     * Adds a custom tool to the sidebar
     * @param tool
     * @param currentPageInfo Used to hide useless tools based on the info about the current page
     */
    addSidebarTool(tool, currentPageInfo) {
      if (tool.showCallback != null && !tool.showCallback(currentPageInfo)) {
        return;
      }
      const listItem = document.createElement("li");
      listItem.id = `t-at-${tool.name}`;
      listItem.classList.add("mw-list-item");
      listItem.appendChild(tool.toolElement);
      this._sidebarToolSection.list.appendChild(listItem);
    }
    /**
     * Adds a custom tool to the footer as a collapsible element
     * @param tool
     */
    addFooterTool(tool) {
      const registeredTool = this._registerFooterTool(tool);
      this._addFooterToolToContainer(registeredTool);
      makeCollapsibleFooter(
        $(registeredTool.tool),
        $(registeredTool.toggler),
        tool.storeKey
      );
    }
    _addFooterToolToContainer(tool) {
      if (this._footerToolContainer != null) {
        this._footerToolContainer.find(".templatesUsed").before(tool.container);
      }
    }
    _registerFooterTool(tool) {
      const parentElement = document.createElement("div");
      parentElement.className = tool.name;
      const togglerElement = document.createElement("div");
      togglerElement.className = `${tool.name}-toggler`;
      togglerElement.innerHTML = `<p>${tool.header}</p>`;
      parentElement.appendChild(togglerElement);
      parentElement.appendChild(tool.toolElement);
      if (tool.toolElement.tagName === "UL" || tool.toolElement.tagName === "OL" || tool.toolElement.tagName === "DL") {
        tool.toolElement.classList.add("mw-editfooter-list");
      }
      const registeredTool = {
        container: parentElement,
        tool: tool.toolElement,
        toggler: togglerElement
      };
      this._footerTools.push(registeredTool);
      return registeredTool;
    }
    /** Returns the singleton instance of ToolManager */
    static get instance() {
      if (this._instance == null) {
        return new _ToolManager();
      }
      return this._instance;
    }
    static _createToolSectionElement() {
      const toolContainer = document.createElement("div");
      toolContainer.id = "p-arch-translator";
      toolContainer.classList.add("vector-menu", "mw-portlet");
      const menuHeading = document.createElement("div");
      menuHeading.classList.add("vector-menu-heading");
      menuHeading.innerText = "Arch Translator";
      toolContainer.appendChild(menuHeading);
      const menuContent = document.createElement("div");
      menuContent.classList.add("vector-menu-content");
      toolContainer.appendChild(menuContent);
      const menuList = document.createElement("ul");
      menuList.classList.add("vector-menu-content-list");
      menuContent.appendChild(menuList);
      return {
        rootElement: toolContainer,
        list: menuList
      };
    }
  };

  // src/Internalization/I18nConstants.ts
  var LanguageInfo = class {
    constructor(subtag, englishName, localizedName, customKey) {
      this.subtag = subtag;
      this.englishName = englishName;
      this.localizedName = localizedName;
      this.key = customKey ?? this.englishName;
    }
  };
  var LanguagesInfo = {
    Arabic: new LanguageInfo("ar", "Arabic", "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"),
    Bangla: new LanguageInfo(null, "Bangla", "\u09AC\u09BE\u0982\u09B2\u09BE"),
    Bosnian: new LanguageInfo("bs", "Bosnian", "Bosanski"),
    Bulgarian: new LanguageInfo("bg", "Bulgarian", "\u0411\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438"),
    Cantonese: new LanguageInfo(null, "Cantonese", "\u7CB5\u8A9E"),
    Catalan: new LanguageInfo("ca", "Catalan", "Catal\xE0"),
    ChineseClassical: new LanguageInfo(null, "Chinese (Classical)", "\u6587\u8A00\u6587", "ChineseClassical"),
    ChineseSimplified: new LanguageInfo("zh-hans", "Chinese (Simplified)", "\u7B80\u4F53\u4E2D\u6587", "ChineseSimplified"),
    ChineseTraditional: new LanguageInfo("zh-hant", "Chinese (Traditional)", "\u6B63\u9AD4\u4E2D\u6587", "ChineseTraditional"),
    Croatian: new LanguageInfo("hr", "Croatian", "Hrvatski"),
    Czech: new LanguageInfo("cs", "Czech", "\u010Ce\u0161tina"),
    Danish: new LanguageInfo("da", "Danish", "Dansk"),
    Dutch: new LanguageInfo("nl", "Dutch", "Nederlands"),
    English: new LanguageInfo("en", "English", "English"),
    Esperanto: new LanguageInfo(null, "Esperanto", "Esperanto"),
    Finnish: new LanguageInfo("fi", "Finnish", "Suomi"),
    French: new LanguageInfo("fr", "French", "Fran\xE7ais"),
    German: new LanguageInfo("de", "German", "Deutsch"),
    Greek: new LanguageInfo("el", "Greek", "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"),
    Hebrew: new LanguageInfo("he", "Heberew", "\u05E2\u05D1\u05E8\u05D9\u05EA"),
    Hungarian: new LanguageInfo("hu", "Hungarian", "Magyar"),
    Indonesian: new LanguageInfo("id", "Indonesian", "Bahasa Indonesia"),
    Italian: new LanguageInfo("it", "Italian", "Italiano"),
    Japanese: new LanguageInfo("ja", "Japanese", "\u65E5\u672C\u8A9E"),
    Korean: new LanguageInfo("ko", "Korean", "\uD55C\uAD6D\uC5B4"),
    Lithuanian: new LanguageInfo("lt", "Lithuanian", "Lietuvi\u0173"),
    NorwegianBokmal: new LanguageInfo(null, "Norwegian (Bokm\xE5l)", "Norsk Bokm\xE5l", "NorwegianBokmal"),
    Polish: new LanguageInfo("pl", "Polish", "Polski"),
    Portuguese: new LanguageInfo("pt", "Portuguese", "Portugu\xEAs"),
    Romanian: new LanguageInfo(null, "Romanian", "Rom\xE2n\u0103"),
    Russian: new LanguageInfo("ru", "Russian", "\u0420\u0443\u0441\u0441\u043A\u0438\u0439"),
    Serbian: new LanguageInfo("sr", "Serbian", "\u0421\u0440\u043F\u0441\u043A\u0438 (Srpski)"),
    Slovak: new LanguageInfo("sk", "Slovak", "Sloven\u010Dina"),
    Spanish: new LanguageInfo("es", "Spanish", "Espa\xF1ol"),
    Swedish: new LanguageInfo("sv", "Swedish", "Svenska"),
    Thai: new LanguageInfo("th", "Thai", "\u0E44\u0E17\u0E22"),
    Turkish: new LanguageInfo("tr", "Turkish", "T\xFCrk\xE7e"),
    Ukrainian: new LanguageInfo("uk", "Ukrainian", "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"),
    Vietnamese: new LanguageInfo(null, "Vietnamese", "Ti\u1EBFng Vi\u1EC7t"),
    Quechua: new LanguageInfo(null, "Quechua", "Runa simi")
  };
  var validLangPostfixes = Object.values(LanguagesInfo).map((i) => "(" + i.localizedName + ")");
  var validLangSubtags = Object.values(LanguagesInfo).filter((i) => i.subtag != null).map((i) => i.subtag);
  function isTranslated(title) {
    for (const postfix of validLangPostfixes) {
      if (title.endsWith(postfix)) {
        return true;
      }
    }
    return false;
  }
  function removeLanguagePostfix(pageOrTitle) {
    const remove = (target, postfix) => {
      return target.substring(0, target.length - 1 - postfix.length);
    };
    for (const postfix of validLangPostfixes) {
      if (!pageOrTitle.endsWith(postfix)) {
        continue;
      }
      const split = pageOrTitle.split("/");
      if (split.length <= 1) {
        return remove(pageOrTitle, postfix);
      } else {
        return split.map((part) => remove(part, postfix)).join("/");
      }
    }
    return pageOrTitle;
  }
  function getLangInfoFor(key) {
    const info = LanguagesInfo[key];
    if (info == null) {
      throw new Error(`Invalid language key: ${key}`);
    }
    return info;
  }

  // src/Utilities/Api/MediaWikiApiClient.ts
  var MAX_PAGE_QUERY_LIMIT = 50;
  var getPageContent = async (pageName) => {
    pageName = titleToPageName(pageName);
    const response = await fetch(
      `/api.php?action=query&prop=revisions&titles=${pageName}&rvslots=*&rvprop=ids|content&format=json&formatversion=2`
    );
    const jsonObj = await response.json();
    const revision = jsonObj.query.pages[0].revisions[0];
    return {
      revisionId: revision.revid,
      content: revision.slots.main.content,
      title: jsonObj.query.pages[0].title
    };
  };
  var getPageInfos = async (titles) => {
    if (titles.length <= 0) {
      throw new Error("Titles array must be larger than 0");
    }
    const fetchInfo = async (titles2) => {
      const encodedTitles = encodeURIComponent(titles2.join("|"));
      const apiResponse = await fetch(`/api.php?action=query&prop=info&titles=${encodedTitles}&format=json`);
      if (!apiResponse.ok) {
        throw new Error("API request failed: " + apiResponse.statusText);
      }
      return await apiResponse.json();
    };
    const groupLimit = (bigArray, limit) => {
      if (limit <= 0) {
        throw new Error("groupLimit 'limit' parameter must be larger than 0");
      }
      if (bigArray.length <= limit) {
        return [bigArray];
      }
      const parentArray = [];
      let addedTitles = 0;
      while (addedTitles < bigArray.length) {
        const childArray = [];
        const childSize = Math.min(bigArray.length - addedTitles, limit);
        const startingIndex = addedTitles;
        for (let i = 0; i < childSize; ++i) {
          childArray.push(bigArray[i + startingIndex]);
          addedTitles++;
        }
        parentArray.push(childArray);
      }
      return parentArray;
    };
    const groups = groupLimit(titles, MAX_PAGE_QUERY_LIMIT);
    const responses = [];
    for (const titleGroup of groups) {
      responses.push(await fetchInfo(titleGroup));
    }
    return Object.assign({}, ...responses);
  };
  var getPageLinks = async (titles) => {
    const titleConcat = encodeURIComponent(titles.join("|"));
    const response = await fetch(`/api.php?action=query&prop=links&titles=${titleConcat}&format=json`);
    if (!response.ok) {
      throw new Error("API request failed: " + response.statusText);
    }
    return await response.json();
  };

  // src/Storage/IndexedDbPromiseWrappers.ts
  var openDb = (name, version) => {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(name, version);
      request.onsuccess = (e) => {
        resolve({
          type: 0 /* Success */,
          // @ts-ignore
          database: e.target.result
        });
      };
      request.onblocked = (e) => {
        resolve({
          type: 1 /* Blocked */
        });
      };
      request.onupgradeneeded = (e) => {
        resolve({
          type: 2 /* UpgradeNeeded */,
          // @ts-ignore
          database: e.target.result,
          oldVer: e.oldVersion,
          newVer: e.newVersion
        });
      };
      request.onerror = (e) => {
        reject(e);
      };
    });
  };
  var wrapGenericRequest = (request) => {
    return new Promise((resolve, reject) => {
      request.onerror = () => {
        reject(request.error);
      };
      request.onsuccess = () => {
        resolve(request.result);
      };
    });
  };
  var get = async (store, key) => {
    const request = store.get(key);
    return await wrapGenericRequest(request);
  };
  var put = async (store, value, key) => {
    const request = store.put(value, key);
    return await wrapGenericRequest(request);
  };

  // src/Storage/ScriptDb.ts
  var ARCH_TRANSLATOR_DB_NAME = "ArchTranslator";
  var ARCH_TRANSLATOR_DB_VERSION = 1;
  var CACHED_PAGES_STORE = "cached_pages";
  var SETTINGS_STORE = "settings";
  var SETTINGS_LANG_KEY = "language";
  var DEFAULT_SETTINGS = {
    [SETTINGS_LANG_KEY]: "Polish"
  };
  var database = null;
  var getDb = () => {
    if (database == null) {
      throw new Error("Non-null database instance was requested, but the instance was null");
    }
    return database;
  };
  var upgradeDb = async (oldVersion, newVersion) => {
    console.debug(`upgradeDb: Upgrading from ${oldVersion} to ${newVersion}`);
    getDb().createObjectStore(CACHED_PAGES_STORE, {
      keyPath: "pageName"
    });
    getDb().createObjectStore(SETTINGS_STORE);
  };
  var setupDb = async () => {
    console.debug(`setupDb: ${ARCH_TRANSLATOR_DB_NAME} (${ARCH_TRANSLATOR_DB_VERSION})`);
    try {
      const dbResult = await openDb(ARCH_TRANSLATOR_DB_NAME, ARCH_TRANSLATOR_DB_VERSION);
      switch (dbResult.type) {
        case 0 /* Success */:
          database = dbResult.database;
          return true;
        case 2 /* UpgradeNeeded */:
          database = dbResult.database;
          await upgradeDb(dbResult.oldVer, dbResult.newVer);
          return true;
        default:
          console.error(dbResult);
          return false;
      }
    } catch (e) {
      console.error(e);
      return false;
    }
  };
  var getCachedPageInfo = async (pageName) => {
    const db = getDb();
    const tr = db.transaction([CACHED_PAGES_STORE]);
    const store = tr.objectStore(CACHED_PAGES_STORE);
    return await get(store, pageName);
  };
  var setCachedPageInfo = async (pageInfo) => {
    const db = getDb();
    const tr = db.transaction(CACHED_PAGES_STORE, "readwrite");
    const store = tr.objectStore(CACHED_PAGES_STORE);
    await put(store, pageInfo);
  };
  var getDefaultSettingValue = (key) => {
    return DEFAULT_SETTINGS[key];
  };
  var getCurrentLanguage = async () => {
    const db = getDb();
    const tr = db.transaction(SETTINGS_STORE);
    const store = tr.objectStore(SETTINGS_STORE);
    let languageKey = await get(store, SETTINGS_LANG_KEY);
    if (languageKey == null) {
      languageKey = getDefaultSettingValue(SETTINGS_LANG_KEY);
    }
    return getLangInfoFor(languageKey);
  };
  var setCurrentLanguage = async (info) => {
    const db = getDb();
    const tr = db.transaction(SETTINGS_STORE, "readwrite");
    const store = tr.objectStore(SETTINGS_STORE);
    await put(store, info.key, SETTINGS_LANG_KEY);
  };

  // src/Utilities/PageUtils.ts
  var cachedPageContent = null;
  var codeMirrorInstance = null;
  function getCurrentPageType() {
    const isArticle = getMwApi().config.values.wgIsArticle;
    const action = getMwApi().config.values.wgAction;
    switch (action) {
      case "edit":
        const isEditable = getMwApi().config.values.wgIsProbablyEditable;
        const editMessage = getMwApi().config.values.wgEditMessage;
        if (editMessage === "creating" /* Creating */) {
          return 3 /* CreateEditor */;
        }
        return isEditable ? 2 /* Editor */ : 4 /* ViewOnlyEditor */;
      case "view":
        const revisionId = getMwApi().config.values.wgCurRevisionId;
        if (revisionId === 0) {
          return 1 /* ReadNonExisting */;
        }
        return isArticle ? 0 /* Read */ : 5 /* Other */;
      default:
        return 5 /* Other */;
    }
  }
  function getCurrentPageInfo() {
    const title = getMwApi().config.values.wgTitle;
    const pageName = getMwApi().config.values.wgPageName;
    const isRedirect = getMwApi().config.values.wgIsRedirect;
    const revisionId = getMwApi().config.values.wgCurRevisionId;
    return {
      isRedirect,
      isTranslated: isTranslated(title),
      latestRevisionId: revisionId,
      pageName,
      pageType: getCurrentPageType(),
      title
    };
  }
  function cacheCurrentPageContent(content) {
    cachedPageContent = content;
  }
  function storeCodeMirrorInstance(cmEditor) {
    codeMirrorInstance = cmEditor;
  }
  async function getCurrentPageContent() {
    if (codeMirrorInstance == null && cachedPageContent != null) {
      console.debug(`getCurrentPageContent: cache hit`);
      return cachedPageContent;
    } else if (codeMirrorInstance != null) {
      return codeMirrorInstance.getValue();
    }
    const pageName = getMwApi().config.values.wgPageName;
    const type = getCurrentPageType();
    switch (type) {
      case 2 /* Editor */:
      case 3 /* CreateEditor */:
      case 4 /* ViewOnlyEditor */:
        console.warn("cachedPageContent was null on edit page. You might be requesting the page content too soon.");
        return (await getPageContent(pageName)).content;
      case 0 /* Read */:
        return (await getPageContent(pageName)).content;
      case 1 /* ReadNonExisting */:
        return "";
      case 5 /* Other */:
        throw new Error("Cannot return content for page of 'Other' type");
    }
  }
  async function getEnglishRevisionId() {
    const info = getCurrentPageInfo();
    if (!info.isTranslated) {
      throw new Error("The current page is not a translation");
    }
    const englishPageName = removeLanguagePostfix(info.pageName);
    if (englishPageName === info.pageName) {
      console.warn(`getEnglishRevisionId: Could not get the English for the ${info.pageName}`);
      return null;
    }
    const cachedInfo = await getCachedPageInfo(englishPageName);
    console.debug(`getEnglishRevisionId english name: ${englishPageName}`);
    if (cachedInfo != null) {
      console.debug("getEnglishRevisionId: cache hit");
      return cachedInfo.latestRevisionId;
    }
    return null;
  }
  function pageNameToTitle(pageName) {
    return pageName.replaceAll("_", "");
  }
  function titleToPageName(title) {
    return title.replaceAll(" ", "_");
  }

  // src/Utilities/WikiTextParser.ts
  var WikiLink = class {
    constructor(rawLink) {
      if (rawLink.startsWith("[[")) {
        rawLink = rawLink.substring(2);
      }
      if (rawLink.endsWith("]]")) {
        rawLink = rawLink.substring(0, rawLink.length - 2);
      }
      const split = rawLink.split("|");
      this._link = split[0];
      const headerSplit = this._link.split("#");
      if (headerSplit.length > 1) {
        this._link = headerSplit[0];
        this._linkedHeader = headerSplit[1];
      } else {
        this._linkedHeader = null;
      }
      this._alias = split.length > 1 ? split[1] : null;
      if (split[0].startsWith(":")) {
        this._linkType = "category" /* Category */;
      } else if (split[0].startsWith("#")) {
        this._linkType = "header" /* Header */;
      } else {
        this._linkType = "article" /* Article */;
      }
    }
    get link() {
      return this._link;
    }
    get alias() {
      return this._alias;
    }
    get linkType() {
      return this._linkType;
    }
    get header() {
      return this._linkedHeader;
    }
    get linkWithHeader() {
      const header = this.header != null ? `#${this.header}` : "";
      return this.link + header;
    }
  };
  var WikiTextParser = class {
    constructor() {
      this._redirects = [];
      this._magicWords = [];
      this._categories = [];
      this._interlanguageLinks = {};
      this._templates = [];
      this._relatedArticleElements = [];
      this._parsingContent = false;
      this._parseMagicWords = true;
      this._rawContentLines = [];
      this._links = [];
    }
    get headerText() {
      let sortedLinks = [];
      for (let langSubtag of Object.keys(this._interlanguageLinks).sort()) {
        sortedLinks.push(this._interlanguageLinks[langSubtag]);
      }
      const finalArray = [
        ...this._redirects,
        ...this._magicWords,
        ...this._categories,
        ...sortedLinks,
        ...this._templates,
        ...this._relatedArticleElements
      ];
      return finalArray.join("\n") + "\n";
    }
    get pageBodyText() {
      return this._rawContentLines.join("\n");
    }
    get pageContent() {
      return this.headerText + this.pageBodyText;
    }
    parse(wikiTextContent) {
      const lines = wikiTextContent.split("\n");
      for (let line of lines) {
        this.parseLine(line);
      }
    }
    parseLine(line) {
      if (!this._parsingContent) {
        const headerResult = this._parseHeaderLine(line);
        if (headerResult === 6 /* EndOfHeader */ || headerResult === 0 /* Redirect */) {
          this._parsingContent = true;
        }
        return headerResult;
      } else {
        return this._parseContentLine(line);
      }
    }
    get localizableLinks() {
      const firstCapitalLetter = (str) => {
        if (str.length < 2) {
          return str.toUpperCase();
        }
        return `${str[0].toUpperCase()}${str.substring(1)}`;
      };
      return [
        ...new Set(this._links.filter((l) => !isTranslated(l.link) && (l.linkType === "category" /* Category */ || l.linkType === "article" /* Article */)).map((l) => firstCapitalLetter(l.link)))
      ];
    }
    _parseHeaderLine(line) {
      const isBlank = (str) => {
        return !str || /^\s*$/.test(str);
      };
      if (isBlank(line)) {
        return 7 /* EmptyLine */;
      }
      if (line.startsWith("#REDIRECT")) {
        this._redirects.push(line);
        this._log("Found redirect: " + line);
        return 0 /* Redirect */;
      }
      for (let subtag of validLangSubtags) {
        if (line.startsWith(`[[${subtag}:`)) {
          this.addInterlanguageLink(line, subtag);
          this._parseMagicWords = false;
          return 3 /* InterlanguageLink */;
        }
      }
      if (line.startsWith("[[Category")) {
        this._addCategory(line);
        this._parseMagicWords = false;
        return 2 /* Category */;
      } else if (line.startsWith("{{Related")) {
        this._addRelatedArticleElement(line);
        return 5 /* RelatedArticle */;
      } else if (line.startsWith("{{") || line.startsWith("__")) {
        if (this._parseMagicWords) {
          this._addMagicWord(line);
          return 1 /* MagicWord */;
        } else {
          this.addTemplate(line);
          return 4 /* Template */;
        }
      } else {
        this._rawContentLines.push(line);
        return 6 /* EndOfHeader */;
      }
    }
    addInterlanguageLink(line, subtag) {
      this._interlanguageLinks[subtag] = line;
    }
    _addCategory(line) {
      this._categories.push(line);
    }
    _addMagicWord(line) {
      this._magicWords.push(line);
    }
    addTemplate(line) {
      this._templates.push(line);
    }
    _addRelatedArticleElement(line) {
      this._relatedArticleElements.push(line);
    }
    _parseContentLine(line) {
      this._rawContentLines.push(line);
      for (let match of line.matchAll(/\[\[(?!Wikipedia)(?!w)(?!mw)([^\[\]]*)]]/ig)) {
        const link = new WikiLink(match[1]);
        this._links.push(link);
      }
      return 8 /* ContentLine */;
    }
    _log(msg) {
      console.debug(`WikiTextParser: ${msg}`);
    }
  };
  var findRedirect = (wikiText) => {
    const prefix = "#REDIRECT ";
    if (wikiText.length < prefix.length) {
      return null;
    }
    const probablePrefix = wikiText.substring(0, prefix.length);
    if (probablePrefix.toUpperCase() != prefix) {
      return null;
    }
    const linkText = wikiText.substring(prefix.length).trim();
    return new WikiLink(linkText);
  };

  // src/Tools/Workers/TranslatedArticlesWorker.ts
  var localizeLink = (link, lang) => {
    const subPageSplit = link.split("/");
    const prefix = ` (${lang.localizedName})`;
    if (subPageSplit.length < 2) {
      return link + prefix;
    }
    return subPageSplit.map((s) => s + prefix).join("/");
  };
  var TranslatedArticlesWorker = class {
    constructor(pageInfo) {
      this._info = pageInfo;
    }
    willRun() {
      return (this._info.pageType === 3 /* CreateEditor */ || this._info.pageType === 2 /* Editor */) && this._info.isTranslated;
    }
    async run(parser) {
      if (!this.willRun()) {
        return {
          existing: [],
          notExisting: [],
          redirects: []
        };
      }
      const language = await getCurrentLanguage();
      const linksWithPostfixes = parser.localizableLinks.map((l) => localizeLink(l, language));
      if (linksWithPostfixes.length <= 0) {
        return {
          existing: [],
          notExisting: [],
          redirects: []
        };
      }
      const info = await this._getPageInfosFor(linksWithPostfixes);
      console.debug(info.filter((i) => i.exists));
      const possibleRedirects = info.filter((r) => !r.exists).map((r) => removeLanguagePostfix(r.link));
      const redirectsAndOther = await this._findRedirects(possibleRedirects);
      console.debug(redirectsAndOther.filter((r) => r.redirects));
      const actualRedirects = redirectsAndOther.filter((r) => r.redirects && !isTranslated(r.redirectsTo)).map((r) => localizeLink(r.redirectsTo, language));
      const redirectResults = actualRedirects.length > 0 ? await this._getPageInfosFor(actualRedirects) : [];
      console.debug(redirectResults);
      const findRedirectSource = (localizedLink) => {
        const englishLink = removeLanguagePostfix(localizedLink);
        if (englishLink.toLowerCase() === localizedLink.toLowerCase()) return localizedLink;
        const original = redirectsAndOther.find((r) => r.redirectsTo?.toLowerCase() === englishLink.toLowerCase());
        return original.link;
      };
      return {
        existing: info.filter((i) => i.exists).map((r) => r.link),
        redirects: redirectResults.map((r) => {
          return {
            link: findRedirectSource(r.link),
            redirectsTo: removeLanguagePostfix(r.link),
            localizedRedirectTarget: r.link,
            exists: r.exists
          };
        }),
        notExisting: redirectsAndOther.filter((r) => !r.redirects).map((r) => localizeLink(r.link, language))
      };
    }
    async _getPageInfosFor(links) {
      const apiData = await getPageInfos(links);
      if (Array.isArray(typeof apiData.query.pages)) {
        return apiData.query.pages.map((p) => {
          return {
            link: p.title,
            exists: "missing" in p
          };
        });
      }
      const data = [];
      const keyedApiData = apiData;
      if ("pages" in keyedApiData.query) {
        const pageValues = Object.values(keyedApiData.query.pages);
        data.push(...pageValues.map((pageInfo) => {
          return {
            link: pageInfo.title,
            exists: !("missing" in pageInfo)
          };
        }));
      }
      if ("interwiki" in keyedApiData.query) {
        const interwikiValues = Object.values(keyedApiData.query.interwiki);
        data.push(...interwikiValues.map((iwInfo) => {
          return {
            link: iwInfo.title,
            exists: false
            // Just assume it does not exist TODO: for now
          };
        }));
      }
      return data;
    }
    async _findRedirects(links) {
      const apiData = await getPageInfos(links);
      const redirects = [];
      if (Array.isArray(typeof apiData.query.pages)) {
        apiData.query.pages.forEach((p) => {
          if ("redirect" in p) {
            redirects.push(p.title);
          }
        });
      } else {
        const keyedApiData = apiData;
        Object.values(keyedApiData.query.pages).forEach((p) => {
          if ("redirect" in p) {
            redirects.push(p.title);
          }
        });
      }
      if (redirects.length <= 0) {
        return [];
      }
      const linksApiData = await getPageLinks(redirects);
      const redirectsInfo = Object.values(linksApiData.query.pages).map((l) => {
        return {
          link: l.title,
          redirects: true,
          redirectsTo: "links" in l ? l.links[0].title : null
        };
      });
      for (const info of redirectsInfo) {
        if (info.redirectsTo == null) {
          console.warn(`API returned no links for the redirect "${info.link}". Fixing...`);
          const content = await getPageContent(titleToPageName(info.link));
          console.debug(content);
          const redirectLink = findRedirect(content.content);
          if (redirectLink == null) {
            throw new Error(`Could not get redirect target for link ${info.link}`);
          }
          info.redirectsTo = redirectLink.link;
        }
      }
      const nonRedirectsInfo = links.filter((l) => !redirects.includes(l)).map((l) => {
        return {
          link: l,
          redirects: false
        };
      });
      return [...redirectsInfo, ...nonRedirectsInfo];
    }
  };

  // src/Tools/TranslatedArticlesUi.ts
  var LOCALIZED_LINKS_UI_STORE_KEY = "mwedit-state-arch-translator-translated-art";
  var editFormLocalizedArticlesTable = null;
  var tableBody = null;
  var addTranslatedArticlesUi = ($editForm) => {
    const localizedArticlesUiHtml = `<div class="localizedArticlesUi">
            <div class="localizedArticlesUi-toggler">
                <p>AT - Localized articles:</p>
            </div>
            <table class="wikitable mw-editfooter-list">
                <thead>
                    <tr>
                        <th>Localized name</th>
                        <th>Redirected from</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td colspan="2">Please wait</td>
                    </tr>
                </tbody>
            </table>
        </div>`;
    $editForm.find(".templatesUsed").before(localizedArticlesUiHtml);
    const linksTable = $editForm.find(".localizedArticlesUi table");
    editFormLocalizedArticlesTable = linksTable[0];
    tableBody = $editForm.find(".localizedArticlesUi table tbody")[0];
    makeCollapsibleFooter(
      linksTable,
      $editForm.find(".localizedArticlesUi-toggler"),
      LOCALIZED_LINKS_UI_STORE_KEY
    );
  };
  var addWorkerResultToUi = (result) => {
    const compareRedirects = (a, b) => {
      const aOrder = a.exists ? 0 : 1;
      const bOrder = b.exists ? 0 : 1;
      return aOrder - bOrder;
    };
    const linkify = (title, followRedirects = true) => {
      return followRedirects ? `/title/${titleToPageName(title)}` : `/index.php?title=${encodeURIComponent(titleToPageName(title))}&redirect=no`;
    };
    if (editFormLocalizedArticlesTable == null || tableBody == null) {
      throw new Error("editFormLocalizedArticlesTable was not created yet");
    }
    if (result.existing.length <= 0 && result.redirects.length <= 0 && result.notExisting.length <= 0) {
      tableBody.innerHTML = '<td class="muted-link" colspan="2">No links were found in the page content</td>';
      return;
    }
    tableBody.innerHTML = "";
    const existingRedirectCell = `<td class="muted-link" rowspan="${result.existing.length}">N/A</td>`;
    let existingRedirectCellAdded = false;
    for (const existing of result.existing) {
      const row = document.createElement("tr");
      const className = "green-link";
      row.classList.add(className);
      row.innerHTML = `<td class="${className}"><a href="${linkify(existing)}">${existing}</td></a>`;
      if (!existingRedirectCellAdded) {
        row.innerHTML += existingRedirectCell;
        existingRedirectCellAdded = true;
      }
      tableBody.appendChild(row);
    }
    for (const redirect of result.redirects.sort(compareRedirects)) {
      const row = document.createElement("tr");
      const className = "blue-link";
      row.classList.add(className);
      const nameCell = document.createElement("td");
      nameCell.className = redirect.exists ? "green-link" : "red-link";
      nameCell.innerHTML = redirect.exists ? `<a href="${linkify(redirect.localizedRedirectTarget)}">${redirect.localizedRedirectTarget}</a>` : redirect.localizedRedirectTarget;
      row.appendChild(nameCell);
      const redirectCell = document.createElement("td");
      redirectCell.className = className;
      const redirectSrc = `<a href="${linkify(redirect.link, false)}">${redirect.link}</a>`;
      const redirectTarget = `<a href="${linkify(redirect.redirectsTo)}">${redirect.redirectsTo}</a>`;
      redirectCell.innerHTML = `${redirectSrc} -&gt; ${redirectTarget}`;
      row.appendChild(redirectCell);
      tableBody.appendChild(row);
    }
    const notExistingRedirectCell = `<td class="muted-link" rowspan="${result.notExisting.length}">N/A</td>`;
    let notExistingRedirectCellAdded = false;
    for (const notExisting of result.notExisting) {
      const row = document.createElement("tr");
      const className = "red-link";
      row.classList.add(className);
      row.innerHTML = `<td class="${className}">${notExisting}</td>`;
      if (!notExistingRedirectCellAdded) {
        row.innerHTML += notExistingRedirectCell;
        notExistingRedirectCellAdded = true;
      }
      tableBody.appendChild(row);
    }
  };

  // src/Tools/SidebarTools.ts
  var copyCurrentRevisionIdTool = () => {
    const showCallback = (info) => {
      return info.pageType !== 3 /* CreateEditor */ && info.pageType !== 1 /* ReadNonExisting */;
    };
    const toolHandler = async () => {
      const revisionId = getMwApi().config.values.wgCurRevisionId;
      await window.navigator.clipboard.writeText(revisionId.toString());
    };
    return sideTool({
      name: "copy-current-revision-id",
      displayText: "Copy revision ID",
      handler: toolHandler,
      showCallback
    });
  };
  var copyEnglishRevisionIdTool = () => {
    const handler = async () => {
      const englishRevisionId = await getEnglishRevisionId();
      console.debug("English revision id: " + englishRevisionId);
      await window.navigator.clipboard.writeText(englishRevisionId?.toString() ?? "null");
    };
    const showCallback = (info) => {
      if (!info.isTranslated) {
        console.debug("Hiding copy English revision ID tool because current page is not a translation");
        return false;
      }
      return true;
    };
    return sideTool({
      name: "copy-english-revision-id",
      displayText: "Copy latest English revision ID",
      handler,
      showCallback
    });
  };
  var createTranslationTool = () => {
    const handler = async () => {
      const pageInfo = getCurrentPageInfo();
      const currentLang = await getCurrentLanguage();
      const translationPageName = `${pageInfo.pageName}_(${currentLang.localizedName})`;
      const target = `/index.php?title=${encodeURIComponent(translationPageName)}&action=edit`;
      console.debug(`createTranslationTool: navigating to ${target}`);
      window.location.assign(target);
    };
    const showCallback = (info) => {
      if (info.isTranslated) {
        console.debug("Hiding create translation tool because current page is already a translation");
        return false;
      }
      return true;
    };
    return sideTool({
      name: "create-translation",
      displayText: "Translate this page",
      handler,
      showCallback
    });
  };
  var changeActiveLanguageTool = () => {
    let anchorElement = null;
    let select = null;
    const saveLanguage = async () => {
      if (select == null) {
        throw new Error("Tried to save the language when the UI was not yet created");
      }
      const newLanguage = getLangInfoFor(select.value);
      await setCurrentLanguage(newLanguage);
      alert(`The Arch Translator active language was changed to ${newLanguage.localizedName}. Please refresh the page.`);
      select.parentElement.classList.add("hidden");
    };
    const createChangeUi = async () => {
      const parent = document.createElement("div");
      parent.classList.add("hidden");
      const selectElement = document.createElement("select");
      for (const [langKey, langInfo] of Object.entries(LanguagesInfo)) {
        const option = document.createElement("option");
        option.value = langKey;
        option.innerText = langInfo.localizedName;
        selectElement.appendChild(option);
      }
      selectElement.onchange = saveLanguage;
      const currentLang = await getCurrentLanguage();
      selectElement.value = currentLang.key;
      select = selectElement;
      parent.appendChild(selectElement);
      return parent;
    };
    const handler = async () => {
      if (anchorElement == null) {
        anchorElement = document.getElementById("t-at-change-language");
      }
      if (select == null) {
        const changeUi = await createChangeUi();
        anchorElement.after(changeUi);
      }
      select.parentElement.classList.toggle("hidden");
    };
    return sideTool({
      name: "change-language",
      displayText: "Change active language",
      handler
    });
  };
  var refreshTranslatedArticles = () => {
    const handler = async () => {
      console.debug("Rerunning translated articles worker");
      const pageInfo = getCurrentPageInfo();
      const contentToParse = await getCurrentPageContent();
      const parser = new WikiTextParser();
      parser.parse(contentToParse);
      const translatedArticleWorker = new TranslatedArticlesWorker(pageInfo);
      translatedArticleWorker.run(parser).then((r) => {
        console.debug(r);
        console.debug("Translated articles worker done");
        addWorkerResultToUi(r);
      });
    };
    return sideTool({
      name: "refresh-translated-articles",
      displayText: "Refresh translated articles",
      handler
    });
  };
  var allSidebarTools = [
    changeActiveLanguageTool(),
    copyCurrentRevisionIdTool(),
    copyEnglishRevisionIdTool(),
    createTranslationTool(),
    refreshTranslatedArticles()
  ];

  // src/Tools/CurrentPageDumper.ts
  var cacheCurrentPage = async () => {
    const info = getCurrentPageInfo();
    if (info.pageType !== 0 /* Read */) return;
    if (info.isRedirect) {
      const content = await getCurrentPageContent();
      const redirectTarget = findRedirect(content);
      if (redirectTarget == null) {
        throw new Error("The current page is a redirect but no redirect link was found");
      }
      await setCachedPageInfo({
        latestRevisionId: info.latestRevisionId,
        pageName: info.pageName,
        redirectsTo: redirectTarget.linkWithHeader,
        type: "redirect" /* Redirect */
      });
    } else {
      await setCachedPageInfo({
        latestRevisionId: info.latestRevisionId,
        pageName: info.pageName,
        type: info.isTranslated ? "translated" /* Translated */ : "english" /* English */
      });
    }
  };

  // src/Utilities/TemplateUtils.ts
  var translateTemplate = (template, language) => {
    return language == null ? template : `${template} (${language.localizedName})`;
  };
  var buildTranslationStatusTemplate = (englishName, date, englishRevisionId, language) => {
    const templateName = translateTemplate("TranslationStatus", language);
    const formattedDate = date.toISOString().split("T")[0];
    return `{{${templateName}|${englishName}|${formattedDate}|${englishRevisionId}}}`;
  };

  // src/Tools/Workers/NewArticleWorker.ts
  var NewArticleWorker = class {
    constructor(pageInfo, language, englishRevisionId) {
      this._info = pageInfo;
      this._language = language;
      this._englishRevisionId = englishRevisionId ?? 0;
    }
    willRun() {
      return this._info.pageType === 3 /* CreateEditor */ && this._info.isTranslated;
    }
    run(parser) {
      if (!this.willRun()) return;
      console.debug("NewArticleWorker: running");
      const englishName = removeLanguagePostfix(this._info.pageName);
      console.debug(`NewArticleWorker: fetching content of ${englishName}`);
      const englishTitle = pageNameToTitle(englishName);
      parser.addInterlanguageLink(`[[en:${englishTitle}]]`, "en");
      const translationStatus = buildTranslationStatusTemplate(
        englishName,
        /* @__PURE__ */ new Date(),
        this._englishRevisionId,
        this._language
      );
      parser.addTemplate(translationStatus);
    }
  };

  // src/Utilities/CssInjector.ts
  var injectCssCode = (cssCode) => {
    const styleElement = document.createElement("style");
    styleElement.innerHTML = cssCode;
    document.head.appendChild(styleElement);
  };

  // src/Styles/WikiTable.css
  var WikiTable_default = "/* Sadly, the Template:Yes and Template:No use inline styles and not CSS classes, so we need to include\n our own stylesheet. Besides, there is no Template:Blue */\n\n.wikitable {\n    .green-link {\n        background: #afa;\n    }\n    .blue-link {\n        background: #aaf;\n    }\n    .red-link {\n        background: #faa;\n    }\n    .muted-link {\n        background: #d6d6d6;\n        text-align: center;\n        vertical-align: center;\n        font-size: .7rem;\n    }\n}";

  // src/Styles/Common.css
  var Common_default = ".hidden {\n    display: none;\n}";

  // src/index.ts
  globalThis.getMwApi = getMwApi;
  globalThis.getId = getCachedPageInfo;
  globalThis.setId = setCachedPageInfo;
  globalThis.getContent = getCurrentPageContent;
  var runEditHook = true;
  var editFormJQuery = null;
  var codeMirrorFound = false;
  var initAfterCodeMirror = async (cmEditor) => {
    storeCodeMirrorInstance(cmEditor);
    codeMirrorFound = true;
    cacheCurrentPageContent(cmEditor.getValue());
    if (editFormJQuery == null) {
      throw new Error("editForm was null");
    }
    const pageInfo = getCurrentPageInfo();
    if (pageInfo.pageType === 3 /* CreateEditor */ || pageInfo.pageType === 2 /* Editor */) {
      const info = getCurrentPageInfo();
      if (!info.isTranslated) return;
      addTranslatedArticlesUi(editFormJQuery);
      const englishName = removeLanguagePostfix(info.pageName);
      const englishContent = await getPageContent(englishName);
      await setCachedPageInfo({
        pageName: englishName,
        type: "english" /* English */,
        latestRevisionId: englishContent.revisionId
      });
      const contentToParse = pageInfo.pageType === 3 /* CreateEditor */ ? englishContent.content : cmEditor.getValue();
      const parser = new WikiTextParser();
      parser.parse(contentToParse);
      const newTranslationWorker = new NewArticleWorker(
        pageInfo,
        await getCurrentLanguage(),
        englishContent.revisionId
      );
      const translatedArticleWorker = new TranslatedArticlesWorker(pageInfo);
      translatedArticleWorker.run(parser).then((r) => {
        console.debug(r);
        console.debug("Translated articles worker done");
        addWorkerResultToUi(r);
      });
      if (pageInfo.pageType === 3 /* CreateEditor */) {
        newTranslationWorker.run(parser);
        const newContent = parser.pageContent;
        cacheCurrentPageContent(newContent);
        cmEditor.setValue(newContent);
      }
    }
  };
  setupDb().then(() => {
    console.debug("ArchTranslator: setupDb successful");
    const manager = new InjectionManager();
    manager.on(0 /* DocumentLoad */, () => {
      console.debug("Document loaded");
      injectCssCode(Common_default);
      injectCssCode(WikiTable_default);
    });
    manager.on(1 /* MediaWikiStartup */, () => {
      const api = getMwApi();
      console.debug(api.config.values.wgTitle);
      cacheCurrentPage().then(() => {
        console.debug("index (MediaWikiStartup): cached current page");
      });
      const pageInfo = getCurrentPageInfo();
      for (const tool of allSidebarTools) {
        ToolManager.instance.addSidebarTool(tool, pageInfo);
      }
      ToolManager.instance.addSidebarToPage();
    });
    manager.on(3 /* ExtCodeMirrorSwitch */, async () => {
      if (codeMirrorFound) {
        return;
      }
      const cmElement = $(".CodeMirror");
      if (cmElement != null) {
        const cmEditor = cmElement.get()[0].CodeMirror;
        if (cmEditor == null) {
          console.error("Found .CodeMirror during the ExtCodeMirrorSwitch hook, but the JS editor instance was null");
        } else {
          console.debug("Found CodeMirror instance");
          await initAfterCodeMirror(cmEditor);
        }
      } else {
        console.error("Could not find .CodeMirror during the ExtCodeMirrorSwitch hook");
      }
    });
    manager.onEditForm(async (form) => {
      if (!runEditHook || codeMirrorFound) return;
      console.debug("editform hook");
      if (editFormJQuery == null) {
        console.debug("editForm found");
        editFormJQuery = form;
      }
      const codeMirrorElement = form.find(".CodeMirror");
      if (!codeMirrorFound && codeMirrorElement.length > 0) {
        console.debug("CodeMirror found (editForm hook)");
        runEditHook = false;
        const cmEditor = codeMirrorElement.get()[0].CodeMirror;
        await initAfterCodeMirror(cmEditor);
      }
    });
    manager.startAgents();
  }).catch((e) => {
    console.debug("ArchTranslator: an error has occurred while setting up the database");
    console.error(e);
  });
})();