var $988mA$lodash = require("lodash");
var $988mA$uuid = require("uuid");
var $988mA$tscustomerror = require("ts-custom-error");
var $988mA$markdownit = require("markdown-it");
var $988mA$stringsimilarity = require("string-similarity");


function $parcel$exportWildcard(dest, source) {
  Object.keys(source).forEach(function(key) {
    if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) {
      return;
    }

    Object.defineProperty(dest, key, {
      enumerable: true,
      get: function get() {
        return source[key];
      }
    });
  });

  return dest;
}

function $parcel$export(e, n, v, s) {
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
}
var $d505444d61c0b9b9$exports = {};

$parcel$export($d505444d61c0b9b9$exports, "AddonProvider", () => $d505444d61c0b9b9$export$94a1fd3bcee9529a);
/* eslint-disable  @typescript-eslint/no-unused-vars */ class $d505444d61c0b9b9$export$94a1fd3bcee9529a {
    getAllBatch(installations, addonIds) {
        return Promise.resolve({
            errors: {},
            installationResults: {}
        });
    }
    getAll(installation, addonIds) {
        return Promise.resolve({
            errors: [],
            searchResults: []
        });
    }
    getFeaturedAddons(installation, channelType) {
        return Promise.resolve([]);
    }
    shouldMigrate(addon) {
        return false;
    }
    searchByQuery(query, installation, channelType) {
        return Promise.resolve([]);
    }
    searchByUrl(addonUri, installation) {
        return Promise.resolve(undefined);
    }
    searchProtocol(protocol) {
        return Promise.resolve(undefined);
    }
    getCategory(category, installation) {
        return Promise.resolve([]);
    }
    getById(addonId, installation) {
        return Promise.resolve(undefined);
    }
    isValidAddonUri(addonUri) {
        return false;
    }
    isValidAddonId(addonId) {
        return false;
    }
    isValidProtocol(protocol) {
        return false;
    }
    scan(installation, addonChannelType, addonFolders) {
        return Promise.resolve(undefined);
    }
    getChangelog(installation, externalId, externalReleaseId) {
        return Promise.resolve('');
    }
    async getDescription(installation, externalId, addon) {
        return Promise.resolve('');
    }
    getAdPageParams() {
        return undefined;
    }
    getDownloadAuth() {
        return Promise.resolve(undefined);
    }
    constructor(){
        this.name = 'Unknown';
        this.enabled = false;
        this.forceIgnore = true;
        this.allowReinstall = false;
        this.allowChannelChange = false;
        this.allowEdit = false;
        this.allowViewAtSource = true;
        this.allowReScan = true;
        this.canShowChangelog = true;
        this.canBatchFetch = false;
        this.authRequired = false;
        this.adRequired = false;
        this.providerNote = '';
    }
}


var $8c2094342e06e0ec$exports = {};
var $3bc810309d87ce1d$exports = {};

$parcel$export($3bc810309d87ce1d$exports, "WowUpAddonProvider", () => $3bc810309d87ce1d$export$ffcbd940f1cdeba3);



const $af8d31735c159a26$export$e304de36686f57ab = 'WowUpHub';
const $af8d31735c159a26$export$b479ece230133092 = 'WowInterface';
const $af8d31735c159a26$export$d3c2b53bc8889c55 = 'TukUI';


var $bca446977c7d12f1$exports = {};
var $90f8b46f95f714d5$exports = {};

$parcel$export($90f8b46f95f714d5$exports, "ErrorContainer", () => $90f8b46f95f714d5$export$97bdf39f6b82bb0);

class $90f8b46f95f714d5$export$97bdf39f6b82bb0 extends (0, $988mA$tscustomerror.CustomError) {
    constructor(innerError, message, warningType){
        super(message);
        this.innerError = innerError;
        this.warningType = warningType;
    }
}


var $77fe2d115ecd2e32$exports = {};

$parcel$export($77fe2d115ecd2e32$exports, "GenericProviderError", () => $77fe2d115ecd2e32$export$b2f2a8bf3da76ab8);

class $77fe2d115ecd2e32$export$b2f2a8bf3da76ab8 extends (0, $90f8b46f95f714d5$export$97bdf39f6b82bb0) {
}


var $30d4dd98b4843be1$exports = {};

$parcel$export($30d4dd98b4843be1$exports, "SourceRemovedAddonError", () => $30d4dd98b4843be1$export$76b02e36ee9dcc33);
var $faefaad95e5fcca0$exports = {};

$parcel$export($faefaad95e5fcca0$exports, "AddonChannelType", () => $faefaad95e5fcca0$export$d045354f167da29);
$parcel$export($faefaad95e5fcca0$exports, "AddonDependencyType", () => $faefaad95e5fcca0$export$fb18689ba4522794);
$parcel$export($faefaad95e5fcca0$exports, "AddonWarningType", () => $faefaad95e5fcca0$export$8f1fa068c05f9b65);
$parcel$export($faefaad95e5fcca0$exports, "AddonCategory", () => $faefaad95e5fcca0$export$fc24ddd65f8d3565);
$parcel$export($faefaad95e5fcca0$exports, "WowClientType", () => $faefaad95e5fcca0$export$a56ef7ad1ec687bf);
$parcel$export($faefaad95e5fcca0$exports, "WowClientGroup", () => $faefaad95e5fcca0$export$b4ac9946b7924ac7);
$parcel$export($faefaad95e5fcca0$exports, "WowGameType", () => $faefaad95e5fcca0$export$b5eb10e2ed949d71);
var $faefaad95e5fcca0$export$d045354f167da29 = /*#__PURE__*/ function(AddonChannelType) {
    AddonChannelType[AddonChannelType["Stable"] = 0] = "Stable";
    AddonChannelType[AddonChannelType["Beta"] = 1] = "Beta";
    AddonChannelType[AddonChannelType["Alpha"] = 2] = "Alpha";
    return AddonChannelType;
}({});
var $faefaad95e5fcca0$export$fb18689ba4522794 = /*#__PURE__*/ function(AddonDependencyType) {
    AddonDependencyType[AddonDependencyType["Embedded"] = 1] = "Embedded";
    AddonDependencyType[AddonDependencyType["Required"] = 2] = "Required";
    AddonDependencyType[AddonDependencyType["Optional"] = 3] = "Optional";
    AddonDependencyType[AddonDependencyType["Other"] = 4] = "Other";
    return AddonDependencyType;
}({});
var $faefaad95e5fcca0$export$8f1fa068c05f9b65 = /*#__PURE__*/ function(AddonWarningType) {
    AddonWarningType["GameVersionTocMissing"] = "game-version-toc-missing";
    AddonWarningType["MissingOnProvider"] = "missing-on-provider";
    AddonWarningType["NoProviderFiles"] = "no-provider-files";
    AddonWarningType["TocNameMismatch"] = "toc-name-mismatch";
    return AddonWarningType;
}({});
var $faefaad95e5fcca0$export$fc24ddd65f8d3565 = /*#__PURE__*/ function(AddonCategory) {
    AddonCategory[AddonCategory["Unknown"] = 0] = "Unknown";
    AddonCategory[AddonCategory["AllAddons"] = 1] = "AllAddons";
    AddonCategory[AddonCategory["Achievements"] = 2] = "Achievements";
    AddonCategory[AddonCategory["ActionBars"] = 3] = "ActionBars";
    AddonCategory[AddonCategory["AuctionEconomy"] = 4] = "AuctionEconomy";
    AddonCategory[AddonCategory["BagsInventory"] = 5] = "BagsInventory";
    AddonCategory[AddonCategory["BossEncounters"] = 6] = "BossEncounters";
    AddonCategory[AddonCategory["BuffsDebuffs"] = 7] = "BuffsDebuffs";
    AddonCategory[AddonCategory["Bundles"] = 8] = "Bundles";
    AddonCategory[AddonCategory["ChatCommunication"] = 9] = "ChatCommunication";
    AddonCategory[AddonCategory["Class"] = 10] = "Class";
    AddonCategory[AddonCategory["Combat"] = 11] = "Combat";
    AddonCategory[AddonCategory["Companions"] = 12] = "Companions";
    AddonCategory[AddonCategory["DataExport"] = 13] = "DataExport";
    AddonCategory[AddonCategory["DevelopmentTools"] = 14] = "DevelopmentTools";
    AddonCategory[AddonCategory["Guild"] = 15] = "Guild";
    AddonCategory[AddonCategory["Libraries"] = 16] = "Libraries";
    AddonCategory[AddonCategory["Mail"] = 17] = "Mail";
    AddonCategory[AddonCategory["MapMinimap"] = 18] = "MapMinimap";
    AddonCategory[AddonCategory["Miscellaneous"] = 19] = "Miscellaneous";
    AddonCategory[AddonCategory["Missions"] = 20] = "Missions";
    AddonCategory[AddonCategory["Plugins"] = 21] = "Plugins";
    AddonCategory[AddonCategory["Professions"] = 22] = "Professions";
    AddonCategory[AddonCategory["PVP"] = 23] = "PVP";
    AddonCategory[AddonCategory["QuestsLeveling"] = 24] = "QuestsLeveling";
    AddonCategory[AddonCategory["Roleplay"] = 25] = "Roleplay";
    AddonCategory[AddonCategory["Tooltips"] = 26] = "Tooltips";
    AddonCategory[AddonCategory["UnitFrames"] = 27] = "UnitFrames";
    return AddonCategory;
}({});
var $faefaad95e5fcca0$export$a56ef7ad1ec687bf = /*#__PURE__*/ function(WowClientType) {
    WowClientType[WowClientType["Retail"] = 0] = "Retail";
    WowClientType[WowClientType["Classic"] = 1] = "Classic";
    WowClientType[WowClientType["RetailPtr"] = 2] = "RetailPtr";
    WowClientType[WowClientType["ClassicPtr"] = 3] = "ClassicPtr";
    WowClientType[WowClientType["Beta"] = 4] = "Beta";
    WowClientType[WowClientType["ClassicBeta"] = 5] = "ClassicBeta";
    WowClientType[WowClientType["ClassicEra"] = 6] = "ClassicEra";
    WowClientType[WowClientType["ClassicEraPtr"] = 7] = "ClassicEraPtr";
    WowClientType[WowClientType["RetailXPtr"] = 8] = "RetailXPtr";
    WowClientType[WowClientType["Anniversary"] = 9] = "Anniversary";
    WowClientType[WowClientType["None"] = 10] = "None";
    return WowClientType;
}({});
var $faefaad95e5fcca0$export$b4ac9946b7924ac7 = /*#__PURE__*/ function(WowClientGroup) {
    WowClientGroup[WowClientGroup["Retail"] = 0] = "Retail";
    WowClientGroup[WowClientGroup["BurningCrusade"] = 1] = "BurningCrusade";
    WowClientGroup[WowClientGroup["Classic"] = 2] = "Classic";
    WowClientGroup[WowClientGroup["WOTLK"] = 3] = "WOTLK";
    WowClientGroup[WowClientGroup["Cata"] = 4] = "Cata";
    WowClientGroup[WowClientGroup["Mists"] = 5] = "Mists";
    return WowClientGroup;
}({});
var $faefaad95e5fcca0$export$b5eb10e2ed949d71 = /*#__PURE__*/ function(WowGameType) {
    WowGameType["Retail"] = "retail";
    WowGameType["Classic"] = "classic";
    WowGameType["BurningCrusade"] = "burningCrusade";
    WowGameType["WOTLK"] = "wotlk";
    WowGameType["Cata"] = "cata";
    WowGameType["Mists"] = "mists";
    return WowGameType;
}({});



class $30d4dd98b4843be1$export$76b02e36ee9dcc33 extends (0, $77fe2d115ecd2e32$export$b2f2a8bf3da76ab8) {
    constructor(addonId, innerError){
        super(innerError, '', (0, $faefaad95e5fcca0$export$8f1fa068c05f9b65).MissingOnProvider), this.addonId = addonId;
    }
}


$parcel$exportWildcard($bca446977c7d12f1$exports, $90f8b46f95f714d5$exports);
$parcel$exportWildcard($bca446977c7d12f1$exports, $77fe2d115ecd2e32$exports);
$parcel$exportWildcard($bca446977c7d12f1$exports, $30d4dd98b4843be1$exports);



var $d7167569386d0d4c$exports = {};
var $e1c908100ed65354$exports = {};

$parcel$export($e1c908100ed65354$exports, "getGameVersionList", () => $e1c908100ed65354$export$692f1cc36daf4e6b);
$parcel$export($e1c908100ed65354$exports, "getGameVersion", () => $e1c908100ed65354$export$6538dd8981ac38d0);
function $e1c908100ed65354$export$692f1cc36daf4e6b(interfaceStrs) {
    return interfaceStrs.map((x)=>$e1c908100ed65354$export$6538dd8981ac38d0(x));
}
function $e1c908100ed65354$export$6538dd8981ac38d0(interfaceStr) {
    if (typeof interfaceStr !== 'string' || interfaceStr.length === 0) return Array(3).fill('0').join('.');
    if (interfaceStr.toString().indexOf('.') !== -1) return interfaceStr;
    // split the long interface into 3 chunks, major minor patch
    const chunks = [
        interfaceStr.substring(0, interfaceStr.length - 4),
        interfaceStr.substring(interfaceStr.length - 4, interfaceStr.length - 2),
        interfaceStr.substring(interfaceStr.length - 2)
    ];
    return chunks.map((c)=>parseInt(c, 10)).join('.');
}


var $0d6cddfe4f838ada$exports = {};

$parcel$export($0d6cddfe4f838ada$exports, "convertBbcode", () => $0d6cddfe4f838ada$export$5219cb438f5def3);
const $ddd5042797a4d3c0$export$a07804094c3ecf2d = '\n';
const $ddd5042797a4d3c0$export$f1c9dd0f5207dd5e = '\t';
const $ddd5042797a4d3c0$export$d66501df72047452 = '\f';
const $ddd5042797a4d3c0$export$db202ddc8be9136 = '\r';
const $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18 = '=';
const $ddd5042797a4d3c0$export$ec02bebb3d587457 = '"';
const $ddd5042797a4d3c0$export$27b7b95a5fde2b31 = ' ';
const $ddd5042797a4d3c0$export$ca00c90a733986ad = '[';
const $ddd5042797a4d3c0$export$1c9e21dfacb095e = ']';
const $ddd5042797a4d3c0$export$98238152dfccf046 = '/';
const $ddd5042797a4d3c0$export$80ffa1da6354d2a3 = '\\';


const $d69a264b7d00bcdd$export$acf5cbfef892896d = (el)=>typeof el === 'object' && !!el.tag;
const $d69a264b7d00bcdd$export$ab3acb3c52feae8e = (el)=>typeof el === 'string';
const $d69a264b7d00bcdd$export$d12fbd4c03fafcb9 = (el)=>el === (0, $ddd5042797a4d3c0$export$a07804094c3ecf2d);
const $d69a264b7d00bcdd$var$keysReduce = (obj, reduce, def)=>Object.keys(obj).reduce(reduce, def);
const $d69a264b7d00bcdd$export$764444cc90432ec4 = (node)=>{
    if ($d69a264b7d00bcdd$export$acf5cbfef892896d(node)) return node.content.reduce((count, contentNode)=>count + $d69a264b7d00bcdd$export$764444cc90432ec4(contentNode), 0);
    if ($d69a264b7d00bcdd$export$ab3acb3c52feae8e(node)) return node.length;
    return 0;
};
/**
 * Appends value to Tag Node
 * @param {TagNode} node
 * @param value
 */ const $d69a264b7d00bcdd$export$8cf9602f2d674b24 = (node, value)=>{
    node.content.push(value);
};
/**
 * Replaces " to &qquot;
 * @param {String} value
 */ const $d69a264b7d00bcdd$export$5dd27816c66fb702 = (value)=>value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;').replace(/(javascript|data|vbscript):/gi, '$1%3A');
/**
 * Acept name and value and return valid html5 attribute string
 * @param {String} name
 * @param {String} value
 * @return {string}
 */ const $d69a264b7d00bcdd$export$8b278404877d50e2 = (name, value)=>{
    const type = typeof value;
    const types = {
        boolean: ()=>value ? `${name}` : '',
        number: ()=>`${name}="${value}"`,
        string: ()=>`${name}="${$d69a264b7d00bcdd$export$5dd27816c66fb702(value)}"`,
        object: ()=>`${name}="${$d69a264b7d00bcdd$export$5dd27816c66fb702(JSON.stringify(value))}"`
    };
    return types[type] ? types[type]() : '';
};
/**
 * Transforms attrs to html params string
 * @param values
 */ const $d69a264b7d00bcdd$export$f12220bef2863039 = (values)=>{
    // To avoid some malformed attributes
    if (values == null) return '';
    return $d69a264b7d00bcdd$var$keysReduce(values, (arr, key)=>[
            ...arr,
            $d69a264b7d00bcdd$export$8b278404877d50e2(key, values[key])
        ], [
        ''
    ]).join(' ');
};
/**
 * Gets value from
 * @example
 * getUniqAttr({ 'foo': true, 'bar': bar' }) => 'bar'
 * @param attrs
 * @returns {string}
 */ const $d69a264b7d00bcdd$export$789d431171141ae4 = (attrs)=>$d69a264b7d00bcdd$var$keysReduce(attrs, (res, key)=>attrs[key] === key ? attrs[key] : null, null);





const $5bc751c3cdc57441$var$getTagAttrs = (tag, params)=>{
    const uniqAattr = (0, $d69a264b7d00bcdd$export$789d431171141ae4)(params);
    if (uniqAattr) {
        const tagAttr = (0, $d69a264b7d00bcdd$export$8b278404877d50e2)(tag, uniqAattr);
        const attrs = {
            ...params
        };
        delete attrs[uniqAattr];
        const attrsStr = (0, $d69a264b7d00bcdd$export$f12220bef2863039)(attrs);
        return `${tagAttr}${attrsStr}`;
    }
    return `${tag}${(0, $d69a264b7d00bcdd$export$f12220bef2863039)(params)}`;
};
class $5bc751c3cdc57441$export$e9f1532f37a263c7 {
    constructor(tag, attrs, content){
        this.tag = tag;
        this.attrs = attrs;
        this.content = Array.isArray(content) ? content : [
            content
        ];
    }
    attr(name, value) {
        if (typeof value !== 'undefined') this.attrs[name] = value;
        return this.attrs[name];
    }
    append(value) {
        return (0, $d69a264b7d00bcdd$export$8cf9602f2d674b24)(this, value);
    }
    get length() {
        return (0, $d69a264b7d00bcdd$export$764444cc90432ec4)(this);
    }
    toTagStart({ openTag: openTag = (0, $ddd5042797a4d3c0$export$ca00c90a733986ad), closeTag: closeTag = (0, $ddd5042797a4d3c0$export$1c9e21dfacb095e) } = {}) {
        const tagAttrs = $5bc751c3cdc57441$var$getTagAttrs(this.tag, this.attrs);
        return `${openTag}${tagAttrs}${closeTag}`;
    }
    toTagEnd({ openTag: openTag = (0, $ddd5042797a4d3c0$export$ca00c90a733986ad), closeTag: closeTag = (0, $ddd5042797a4d3c0$export$1c9e21dfacb095e) } = {}) {
        return `${openTag}${0, $ddd5042797a4d3c0$export$98238152dfccf046}${this.tag}${closeTag}`;
    }
    toTagNode() {
        return new $5bc751c3cdc57441$export$e9f1532f37a263c7(this.tag.toLowerCase(), this.attrs, this.content);
    }
    toString({ openTag: openTag = (0, $ddd5042797a4d3c0$export$ca00c90a733986ad), closeTag: closeTag = (0, $ddd5042797a4d3c0$export$1c9e21dfacb095e) } = {}) {
        const isEmpty = this.content.length === 0;
        const content = this.content.reduce((r, node)=>r + node.toString({
                openTag: openTag,
                closeTag: closeTag
            }), '');
        const tagStart = this.toTagStart({
            openTag: openTag,
            closeTag: closeTag
        });
        if (isEmpty) return tagStart;
        return `${tagStart}${content}${this.toTagEnd({
            openTag: openTag,
            closeTag: closeTag
        })}`;
    }
}
const $5bc751c3cdc57441$export$17618813e93d6bac = (tag, attrs = {}, content = [])=>new $5bc751c3cdc57441$export$e9f1532f37a263c7(tag, attrs, content);
const $5bc751c3cdc57441$export$abf651b00b1d366d = (node, type)=>node.tag === type;








// type, value, line, row,
const $ecd72734d645606d$var$TOKEN_TYPE_ID = 'type'; // 0;
const $ecd72734d645606d$var$TOKEN_VALUE_ID = 'value'; // 1;
const $ecd72734d645606d$var$TOKEN_COLUMN_ID = 'row'; // 2;
const $ecd72734d645606d$var$TOKEN_LINE_ID = 'line'; // 3;
const $ecd72734d645606d$var$TOKEN_TYPE_WORD = 1; // 'word';
const $ecd72734d645606d$var$TOKEN_TYPE_TAG = 2; // 'tag';
const $ecd72734d645606d$var$TOKEN_TYPE_ATTR_NAME = 3; // 'attr-name';
const $ecd72734d645606d$var$TOKEN_TYPE_ATTR_VALUE = 4; // 'attr-value';
const $ecd72734d645606d$var$TOKEN_TYPE_SPACE = 5; // 'space';
const $ecd72734d645606d$var$TOKEN_TYPE_NEW_LINE = 6; // 'new-line';
/**
 * @param {Token} token
 * @returns {string}
 */ const $ecd72734d645606d$var$getTokenValue = (token)=>{
    if (token && typeof token[$ecd72734d645606d$var$TOKEN_VALUE_ID] !== 'undefined') return token[$ecd72734d645606d$var$TOKEN_VALUE_ID];
    return '';
};
/**
 * @param {Token}token
 * @returns {number}
 */ const $ecd72734d645606d$var$getTokenLine = (token)=>token && token[$ecd72734d645606d$var$TOKEN_LINE_ID] || 0;
const $ecd72734d645606d$var$getTokenColumn = (token)=>token && token[$ecd72734d645606d$var$TOKEN_COLUMN_ID] || 0;
/**
 * @param {Token} token
 * @returns {boolean}
 */ const $ecd72734d645606d$var$isTextToken = (token)=>{
    if (token && typeof token[$ecd72734d645606d$var$TOKEN_TYPE_ID] !== 'undefined') return token[$ecd72734d645606d$var$TOKEN_TYPE_ID] === $ecd72734d645606d$var$TOKEN_TYPE_SPACE || token[$ecd72734d645606d$var$TOKEN_TYPE_ID] === $ecd72734d645606d$var$TOKEN_TYPE_NEW_LINE || token[$ecd72734d645606d$var$TOKEN_TYPE_ID] === $ecd72734d645606d$var$TOKEN_TYPE_WORD;
    return false;
};
/**
 * @param {Token} token
 * @returns {boolean}
 */ const $ecd72734d645606d$var$isTagToken = (token)=>{
    if (token && typeof token[$ecd72734d645606d$var$TOKEN_TYPE_ID] !== 'undefined') return token[$ecd72734d645606d$var$TOKEN_TYPE_ID] === $ecd72734d645606d$var$TOKEN_TYPE_TAG;
    return false;
};
const $ecd72734d645606d$var$isTagEnd = (token)=>$ecd72734d645606d$var$getTokenValue(token).charCodeAt(0) === (0, $ddd5042797a4d3c0$export$98238152dfccf046).charCodeAt(0);
const $ecd72734d645606d$var$isTagStart = (token)=>!$ecd72734d645606d$var$isTagEnd(token);
const $ecd72734d645606d$var$isAttrNameToken = (token)=>{
    if (token && typeof token[$ecd72734d645606d$var$TOKEN_TYPE_ID] !== 'undefined') return token[$ecd72734d645606d$var$TOKEN_TYPE_ID] === $ecd72734d645606d$var$TOKEN_TYPE_ATTR_NAME;
    return false;
};
/**
 * @param {Token} token
 * @returns {boolean}
 */ const $ecd72734d645606d$var$isAttrValueToken = (token)=>{
    if (token && typeof token[$ecd72734d645606d$var$TOKEN_TYPE_ID] !== 'undefined') return token[$ecd72734d645606d$var$TOKEN_TYPE_ID] === $ecd72734d645606d$var$TOKEN_TYPE_ATTR_VALUE;
    return false;
};
const $ecd72734d645606d$var$getTagName = (token)=>{
    const value = $ecd72734d645606d$var$getTokenValue(token);
    return $ecd72734d645606d$var$isTagEnd(token) ? value.slice(1) : value;
};
const $ecd72734d645606d$var$convertTagToText = (token)=>{
    let text = (0, $ddd5042797a4d3c0$export$ca00c90a733986ad);
    text += $ecd72734d645606d$var$getTokenValue(token);
    text += (0, $ddd5042797a4d3c0$export$1c9e21dfacb095e);
    return text;
};
class $ecd72734d645606d$export$50792b0e93539fde {
    /**
   * @param {String} type
   * @param {String} value
   * @param line
   * @param row
   */ constructor(type, value, line, row){
        this[$ecd72734d645606d$var$TOKEN_TYPE_ID] = Number(type);
        this[$ecd72734d645606d$var$TOKEN_VALUE_ID] = String(value);
        this[$ecd72734d645606d$var$TOKEN_LINE_ID] = Number(line);
        this[$ecd72734d645606d$var$TOKEN_COLUMN_ID] = Number(row);
    }
    isEmpty() {
        return isNaN(this[$ecd72734d645606d$var$TOKEN_TYPE_ID]);
    }
    isText() {
        return $ecd72734d645606d$var$isTextToken(this);
    }
    isTag() {
        return $ecd72734d645606d$var$isTagToken(this);
    }
    isAttrName() {
        return $ecd72734d645606d$var$isAttrNameToken(this);
    }
    isAttrValue() {
        return $ecd72734d645606d$var$isAttrValueToken(this);
    }
    isStart() {
        return $ecd72734d645606d$var$isTagStart(this);
    }
    isEnd() {
        return $ecd72734d645606d$var$isTagEnd(this);
    }
    getName() {
        return $ecd72734d645606d$var$getTagName(this);
    }
    getValue() {
        return $ecd72734d645606d$var$getTokenValue(this);
    }
    getLine() {
        return $ecd72734d645606d$var$getTokenLine(this);
    }
    getColumn() {
        return $ecd72734d645606d$var$getTokenColumn(this);
    }
    toString() {
        return $ecd72734d645606d$var$convertTagToText(this);
    }
}
const $ecd72734d645606d$export$7c51262a8e3622c5 = $ecd72734d645606d$var$TOKEN_TYPE_ID;
const $ecd72734d645606d$export$b852257387b58445 = $ecd72734d645606d$var$TOKEN_VALUE_ID;
const $ecd72734d645606d$export$8bfab114887fbd3f = $ecd72734d645606d$var$TOKEN_LINE_ID;
const $ecd72734d645606d$export$e92d3fe80bd1d657 = $ecd72734d645606d$var$TOKEN_COLUMN_ID;
const $ecd72734d645606d$export$8b4c01b7cd875b89 = $ecd72734d645606d$var$TOKEN_TYPE_WORD;
const $ecd72734d645606d$export$d5f00fab9fda576b = $ecd72734d645606d$var$TOKEN_TYPE_TAG;
const $ecd72734d645606d$export$af3a20cc8143022e = $ecd72734d645606d$var$TOKEN_TYPE_ATTR_NAME;
const $ecd72734d645606d$export$2fc145e106e65582 = $ecd72734d645606d$var$TOKEN_TYPE_ATTR_VALUE;
const $ecd72734d645606d$export$2cf6eaa8fcfe1d4d = $ecd72734d645606d$var$TOKEN_TYPE_SPACE;
const $ecd72734d645606d$export$87d97767ed6e106 = $ecd72734d645606d$var$TOKEN_TYPE_NEW_LINE;



function $8d178c2fe9a3df90$var$CharGrabber(source, options) {
    const cursor = {
        pos: 0,
        len: source.length
    };
    const substrUntilChar = (char)=>{
        const { pos: pos } = cursor;
        const idx = source.indexOf(char, pos);
        return idx >= 0 ? source.substring(pos, idx) : '';
    };
    const includes = (val)=>source.indexOf(val, cursor.pos) >= 0;
    const hasNext = ()=>cursor.len > cursor.pos;
    const isLast = ()=>cursor.pos === cursor.len;
    const skip = (num = 1, silent)=>{
        cursor.pos += num;
        if (options && options.onSkip && !silent) options.onSkip();
    };
    const rest = ()=>source.substring(cursor.pos);
    const grabN = (num = 0)=>source.substring(cursor.pos, cursor.pos + num);
    const curr = ()=>source[cursor.pos];
    const prev = ()=>{
        const prevPos = cursor.pos - 1;
        return typeof source[prevPos] !== 'undefined' ? source[prevPos] : null;
    };
    const next = ()=>{
        const nextPos = cursor.pos + 1;
        return nextPos <= source.length - 1 ? source[nextPos] : null;
    };
    const grabWhile = (cond, silent)=>{
        let start = 0;
        if (hasNext()) {
            start = cursor.pos;
            while(hasNext() && cond(curr()))skip(1, silent);
        }
        return source.substring(start, cursor.pos);
    };
    /**
   * @type {skip}
   */ this.skip = skip;
    /**
   * @returns {Boolean}
   */ this.hasNext = hasNext;
    /**
   * @returns {String}
   */ this.getCurr = curr;
    /**
   * @returns {String}
   */ this.getRest = rest;
    /**
   * @returns {String}
   */ this.getNext = next;
    /**
   * @returns {String}
   */ this.getPrev = prev;
    /**
   * @returns {Boolean}
   */ this.isLast = isLast;
    /**
   * @returns {Boolean}
   */ this.includes = includes;
    /**
   * @param {Function} cond
   * @param {Boolean} silent
   * @return {String}
   */ this.grabWhile = grabWhile;
    /**
   * @param {Number} num
   * @return {String}
   */ this.grabN = grabN;
    /**
   * Grabs rest of string until it find a char
   * @param {String} char
   * @return {String}
   */ this.substrUntilChar = substrUntilChar;
}
const $8d178c2fe9a3df90$export$70cbeeca25cb6f01 = (source, options)=>new $8d178c2fe9a3df90$var$CharGrabber(source, options);
const $8d178c2fe9a3df90$export$74daeb15908b8515 = (str, charToRemove)=>{
    while(str.charAt(0) === charToRemove)str = str.substring(1);
    while(str.charAt(str.length - 1) === charToRemove)str = str.substring(0, str.length - 1);
    return str;
};
const $8d178c2fe9a3df90$export$f0199846ca09d4f9 = (str)=>str.replace((0, $ddd5042797a4d3c0$export$80ffa1da6354d2a3) + (0, $ddd5042797a4d3c0$export$ec02bebb3d587457), (0, $ddd5042797a4d3c0$export$ec02bebb3d587457));
function $8d178c2fe9a3df90$var$NodeList(values = []) {
    const nodes = values;
    const getLast = ()=>Array.isArray(nodes) && nodes.length > 0 && typeof nodes[nodes.length - 1] !== 'undefined' ? nodes[nodes.length - 1] : null;
    const flushLast = ()=>nodes.length ? nodes.pop() : false;
    const push = (value)=>nodes.push(value);
    const toArray = ()=>nodes;
    this.push = push;
    this.toArray = toArray;
    this.getLast = getLast;
    this.flushLast = flushLast;
}
const $8d178c2fe9a3df90$export$5897d8d7c7a3d871 = (values = [])=>new $8d178c2fe9a3df90$var$NodeList(values);


// for cases <!-- -->
const $ca2798f2f1ba5cca$var$EM = '!';
/**
 * Creates a Token entity class
 * @param {Number} type
 * @param {String} value
 * @param {Number} r line number
 * @param {Number} cl char number in line
 */ const $ca2798f2f1ba5cca$var$createToken = (type, value, r = 0, cl = 0)=>new (0, $ecd72734d645606d$export$50792b0e93539fde)(type, value, r, cl);
/**
 * @typedef {Object} Lexer
 * @property {Function} tokenize
 * @property {Function} isTokenNested
 */ /**
 * @param {String} buffer
 * @param {Object} options
 * @param {Function} options.onToken
 * @param {String} options.openTag
 * @param {String} options.closeTag
 * @param {Boolean} options.enableEscapeTags
 * @return {Lexer}
 */ function $ca2798f2f1ba5cca$export$542413421c3f8a82(buffer, options = {}) {
    const STATE_WORD = 0;
    const STATE_TAG = 1;
    const STATE_TAG_ATTRS = 2;
    const TAG_STATE_NAME = 0;
    const TAG_STATE_ATTR = 1;
    const TAG_STATE_VALUE = 2;
    let row = 0;
    let col = 0;
    let tokenIndex = -1;
    let stateMode = STATE_WORD;
    let tagMode = TAG_STATE_NAME;
    let contextFreeTag = '';
    const tokens = new Array(Math.floor(buffer.length));
    const openTag = options.openTag || (0, $ddd5042797a4d3c0$export$ca00c90a733986ad);
    const closeTag = options.closeTag || (0, $ddd5042797a4d3c0$export$1c9e21dfacb095e);
    const escapeTags = !!options.enableEscapeTags;
    const contextFreeTags = options.contextFreeTags || [];
    const onToken = options.onToken || (()=>{});
    const RESERVED_CHARS = [
        closeTag,
        openTag,
        (0, $ddd5042797a4d3c0$export$ec02bebb3d587457),
        (0, $ddd5042797a4d3c0$export$80ffa1da6354d2a3),
        (0, $ddd5042797a4d3c0$export$27b7b95a5fde2b31),
        (0, $ddd5042797a4d3c0$export$f1c9dd0f5207dd5e),
        (0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18),
        (0, $ddd5042797a4d3c0$export$a07804094c3ecf2d),
        $ca2798f2f1ba5cca$var$EM
    ];
    const NOT_CHAR_TOKENS = [
        openTag,
        (0, $ddd5042797a4d3c0$export$27b7b95a5fde2b31),
        (0, $ddd5042797a4d3c0$export$f1c9dd0f5207dd5e),
        (0, $ddd5042797a4d3c0$export$a07804094c3ecf2d)
    ];
    const WHITESPACES = [
        (0, $ddd5042797a4d3c0$export$27b7b95a5fde2b31),
        (0, $ddd5042797a4d3c0$export$f1c9dd0f5207dd5e)
    ];
    const SPECIAL_CHARS = [
        (0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18),
        (0, $ddd5042797a4d3c0$export$27b7b95a5fde2b31),
        (0, $ddd5042797a4d3c0$export$f1c9dd0f5207dd5e)
    ];
    const isCharReserved = (char)=>RESERVED_CHARS.indexOf(char) >= 0;
    const isNewLine = (char)=>char === (0, $ddd5042797a4d3c0$export$a07804094c3ecf2d);
    const isWhiteSpace = (char)=>WHITESPACES.indexOf(char) >= 0;
    const isCharToken = (char)=>NOT_CHAR_TOKENS.indexOf(char) === -1;
    const isSpecialChar = (char)=>SPECIAL_CHARS.indexOf(char) >= 0;
    const isEscapableChar = (char)=>char === openTag || char === closeTag || char === (0, $ddd5042797a4d3c0$export$80ffa1da6354d2a3);
    const isEscapeChar = (char)=>char === (0, $ddd5042797a4d3c0$export$80ffa1da6354d2a3);
    const onSkip = ()=>{
        col++;
    };
    const unq = (val)=>(0, $8d178c2fe9a3df90$export$f0199846ca09d4f9)((0, $8d178c2fe9a3df90$export$74daeb15908b8515)(val, (0, $ddd5042797a4d3c0$export$ec02bebb3d587457)));
    const checkContextFreeMode = (name, isClosingTag)=>{
        if (contextFreeTag !== '' && isClosingTag) contextFreeTag = '';
        if (contextFreeTag === '' && contextFreeTags.includes(name)) contextFreeTag = name;
    };
    const chars = (0, $8d178c2fe9a3df90$export$70cbeeca25cb6f01)(buffer, {
        onSkip: onSkip
    });
    /**
   * Emits newly created token to subscriber
   * @param {Number} type
   * @param {String} value
   */ function emitToken(type, value) {
        const token = $ca2798f2f1ba5cca$var$createToken(type, value, row, col);
        onToken(token);
        tokenIndex += 1;
        tokens[tokenIndex] = token;
    }
    function nextTagState(tagChars, isSingleValueTag) {
        if (tagMode === TAG_STATE_ATTR) {
            const validAttrName = (char)=>!(char === (0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18) || isWhiteSpace(char));
            const name = tagChars.grabWhile(validAttrName);
            const isEnd = tagChars.isLast();
            const isValue = tagChars.getCurr() !== (0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18);
            tagChars.skip();
            if (isEnd || isValue) emitToken((0, $ecd72734d645606d$export$2fc145e106e65582), unq(name));
            else emitToken((0, $ecd72734d645606d$export$af3a20cc8143022e), name);
            if (isEnd) return TAG_STATE_NAME;
            if (isValue) return TAG_STATE_ATTR;
            return TAG_STATE_VALUE;
        }
        if (tagMode === TAG_STATE_VALUE) {
            let stateSpecial = false;
            const validAttrValue = (char)=>{
                // const isEQ = char === EQ;
                const isQM = char === (0, $ddd5042797a4d3c0$export$ec02bebb3d587457);
                const prevChar = tagChars.getPrev();
                const nextChar = tagChars.getNext();
                const isPrevSLASH = prevChar === (0, $ddd5042797a4d3c0$export$80ffa1da6354d2a3);
                const isNextEQ = nextChar === (0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18);
                const isWS = isWhiteSpace(char);
                // const isPrevWS = isWhiteSpace(prevChar);
                const isNextWS = isWhiteSpace(nextChar);
                if (stateSpecial && isSpecialChar(char)) return true;
                if (isQM && !isPrevSLASH) {
                    stateSpecial = !stateSpecial;
                    if (!stateSpecial && !(isNextEQ || isNextWS)) return false;
                }
                if (!isSingleValueTag) return isWS === false;
                return true;
            };
            const name = tagChars.grabWhile(validAttrValue);
            tagChars.skip();
            emitToken((0, $ecd72734d645606d$export$2fc145e106e65582), unq(name));
            if (tagChars.isLast()) return TAG_STATE_NAME;
            return TAG_STATE_ATTR;
        }
        const validName = (char)=>!(char === (0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18) || isWhiteSpace(char) || tagChars.isLast());
        const name = tagChars.grabWhile(validName);
        emitToken((0, $ecd72734d645606d$export$d5f00fab9fda576b), name);
        checkContextFreeMode(name);
        tagChars.skip();
        // in cases when we has [url=someval]GET[/url] and we dont need to parse all
        if (isSingleValueTag) return TAG_STATE_VALUE;
        const hasEQ = tagChars.includes((0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18));
        return hasEQ ? TAG_STATE_ATTR : TAG_STATE_VALUE;
    }
    function stateTag() {
        const currChar = chars.getCurr();
        const nextChar = chars.getNext();
        chars.skip();
        // detect case where we have '[My word [tag][/tag]' or we have '[My last line word'
        const substr = chars.substrUntilChar(closeTag);
        const hasInvalidChars = substr.length === 0 || substr.indexOf(openTag) >= 0;
        if (isCharReserved(nextChar) || hasInvalidChars || chars.isLast()) {
            emitToken((0, $ecd72734d645606d$export$8b4c01b7cd875b89), currChar);
            return STATE_WORD;
        }
        // [myTag   ]
        const isNoAttrsInTag = substr.indexOf((0, $ddd5042797a4d3c0$export$1c0a5d05eb3f6e18)) === -1;
        // [/myTag]
        const isClosingTag = substr[0] === (0, $ddd5042797a4d3c0$export$98238152dfccf046);
        if (isNoAttrsInTag || isClosingTag) {
            const name = chars.grabWhile((char)=>char !== closeTag);
            chars.skip(); // skip closeTag
            emitToken((0, $ecd72734d645606d$export$d5f00fab9fda576b), name);
            checkContextFreeMode(name, isClosingTag);
            return STATE_WORD;
        }
        return STATE_TAG_ATTRS;
    }
    function stateAttrs() {
        const silent = true;
        const tagStr = chars.grabWhile((char)=>char !== closeTag, silent);
        const tagGrabber = (0, $8d178c2fe9a3df90$export$70cbeeca25cb6f01)(tagStr, {
            onSkip: onSkip
        });
        const hasSpace = tagGrabber.includes((0, $ddd5042797a4d3c0$export$27b7b95a5fde2b31));
        tagMode = TAG_STATE_NAME;
        while(tagGrabber.hasNext())tagMode = nextTagState(tagGrabber, !hasSpace);
        chars.skip(); // skip closeTag
        return STATE_WORD;
    }
    function stateWord() {
        if (isNewLine(chars.getCurr())) {
            emitToken((0, $ecd72734d645606d$export$87d97767ed6e106), chars.getCurr());
            chars.skip();
            col = 0;
            row++;
            return STATE_WORD;
        }
        if (isWhiteSpace(chars.getCurr())) {
            const word = chars.grabWhile(isWhiteSpace);
            emitToken((0, $ecd72734d645606d$export$2cf6eaa8fcfe1d4d), word);
            return STATE_WORD;
        }
        if (chars.getCurr() === openTag) {
            if (contextFreeTag) {
                const fullTagLen = openTag.length + (0, $ddd5042797a4d3c0$export$98238152dfccf046).length + contextFreeTag.length;
                const fullTagName = `${openTag}${(0, $ddd5042797a4d3c0$export$98238152dfccf046)}${contextFreeTag}`;
                const foundTag = chars.grabN(fullTagLen);
                const isEndContextFreeMode = foundTag === fullTagName;
                if (isEndContextFreeMode) return STATE_TAG;
            } else if (chars.includes(closeTag)) return STATE_TAG;
            emitToken((0, $ecd72734d645606d$export$8b4c01b7cd875b89), chars.getCurr());
            chars.skip();
            return STATE_WORD;
        }
        if (escapeTags) {
            if (isEscapeChar(chars.getCurr())) {
                const currChar = chars.getCurr();
                const nextChar = chars.getNext();
                chars.skip(); // skip the \ without emitting anything
                if (isEscapableChar(nextChar)) {
                    chars.skip(); // skip past the [, ] or \ as well
                    emitToken((0, $ecd72734d645606d$export$8b4c01b7cd875b89), nextChar);
                    return STATE_WORD;
                }
                emitToken((0, $ecd72734d645606d$export$8b4c01b7cd875b89), currChar);
                return STATE_WORD;
            }
            const isChar = (char)=>isCharToken(char) && !isEscapeChar(char);
            const word = chars.grabWhile(isChar);
            emitToken((0, $ecd72734d645606d$export$8b4c01b7cd875b89), word);
            return STATE_WORD;
        }
        const word = chars.grabWhile(isCharToken);
        emitToken((0, $ecd72734d645606d$export$8b4c01b7cd875b89), word);
        return STATE_WORD;
    }
    function tokenize() {
        stateMode = STATE_WORD;
        while(chars.hasNext())switch(stateMode){
            case STATE_TAG:
                stateMode = stateTag();
                break;
            case STATE_TAG_ATTRS:
                stateMode = stateAttrs();
                break;
            case STATE_WORD:
            default:
                stateMode = stateWord();
                break;
        }
        tokens.length = tokenIndex + 1;
        return tokens;
    }
    function isTokenNested(token) {
        const value = openTag + (0, $ddd5042797a4d3c0$export$98238152dfccf046) + token.getValue();
        // potential bottleneck
        return buffer.indexOf(value) > -1;
    }
    return {
        tokenize: tokenize,
        isTokenNested: isTokenNested
    };
}
const $ca2798f2f1ba5cca$export$dc03caf4b5bfd0a0 = $ca2798f2f1ba5cca$var$createToken;



/**
 * @public
 * @param {string} input
 * @param {Object} opts
 * @param {Function} opts.createTokenizer
 * @param {Array<string>} opts.onlyAllowTags
 * @param {Array<string>} opts.contextFreeTags
 * @param {Boolean} opts.enableEscapeTags
 * @param {string} opts.openTag
 * @param {string} opts.closeTag
 * @return {Array<string|TagNode>}
 */ const $b7d2fcb8d10105e2$export$98e6a39c04603d36 = (input, opts = {})=>{
    const options = opts;
    const openTag = options.openTag || (0, $ddd5042797a4d3c0$export$ca00c90a733986ad);
    const closeTag = options.closeTag || (0, $ddd5042797a4d3c0$export$1c9e21dfacb095e);
    let tokenizer = null;
    /**
   * Result AST of nodes
   * @private
   * @type {NodeList}
   */ const nodes = (0, $8d178c2fe9a3df90$export$5897d8d7c7a3d871)();
    /**
   * Temp buffer of nodes that's nested to another node
   * @private
   * @type {NodeList}
   */ const nestedNodes = (0, $8d178c2fe9a3df90$export$5897d8d7c7a3d871)();
    /**
   * Temp buffer of nodes [tag..]...[/tag]
   * @private
   * @type {NodeList}
   */ const tagNodes = (0, $8d178c2fe9a3df90$export$5897d8d7c7a3d871)();
    /**
   * Temp buffer of tag attributes
   * @private
   * @type {NodeList}
   */ const tagNodesAttrName = (0, $8d178c2fe9a3df90$export$5897d8d7c7a3d871)();
    /**
   * Cache for nested tags checks
   * @type Set<string>
   */ const nestedTagsMap = new Set();
    /**
   * @param {Token} token
   * @returns {boolean}
   */ const isTokenNested = (token)=>{
        const value = token.getValue();
        if (!nestedTagsMap.has(value) && tokenizer.isTokenNested && tokenizer.isTokenNested(token)) {
            nestedTagsMap.add(value);
            return true;
        }
        return nestedTagsMap.has(value);
    };
    /**
   * @private
   * @param {string} tagName
   * @returns {boolean}
   */ const isTagNested = (tagName)=>Boolean(nestedTagsMap.has(tagName));
    /**
   * @private
   * @param {string} value
   * @return {boolean}
   */ const isAllowedTag = (value)=>{
        if (options.onlyAllowTags && options.onlyAllowTags.length) return options.onlyAllowTags.indexOf(value) >= 0;
        return true;
    };
    /**
   * Flushes temp tag nodes and its attributes buffers
   * @private
   * @return {Array}
   */ const flushTagNodes = ()=>{
        if (tagNodes.flushLast()) tagNodesAttrName.flushLast();
    };
    /**
   * @private
   * @return {Array}
   */ const getNodes = ()=>{
        const lastNestedNode = nestedNodes.getLast();
        if (lastNestedNode && Array.isArray(lastNestedNode.content)) return lastNestedNode.content;
        return nodes.toArray();
    };
    /**
   * @private
   * @param {string|TagNode} node
   * @param {boolean} isNested
   */ const appendNodeAsString = (node, isNested = true)=>{
        const items = getNodes();
        if (Array.isArray(items)) {
            items.push(node.toTagStart({
                openTag: openTag,
                closeTag: closeTag
            }));
            if (node.content.length) {
                node.content.forEach((item)=>{
                    items.push(item);
                });
                if (isNested) items.push(node.toTagEnd({
                    openTag: openTag,
                    closeTag: closeTag
                }));
            }
        }
    };
    /**
   * @private
   * @param {string|TagNode} node
   */ const appendNodes = (node)=>{
        const items = getNodes();
        if (Array.isArray(items)) {
            if ((0, $d69a264b7d00bcdd$export$acf5cbfef892896d)(node)) {
                if (isAllowedTag(node.tag)) items.push(node.toTagNode());
                else appendNodeAsString(node);
            } else items.push(node);
        }
    };
    /**
   * @private
   * @param {Token} token
   */ const handleTagStart = (token)=>{
        flushTagNodes();
        const tagNode = (0, $5bc751c3cdc57441$export$17618813e93d6bac)(token.getValue());
        const isNested = isTokenNested(token);
        tagNodes.push(tagNode);
        if (isNested) nestedNodes.push(tagNode);
        else appendNodes(tagNode, token);
    };
    /**
   * @private
   * @param {Token} token
   */ const handleTagEnd = (token)=>{
        flushTagNodes();
        const lastNestedNode = nestedNodes.flushLast();
        if (lastNestedNode) appendNodes(lastNestedNode, token);
        else if (typeof options.onError === 'function') {
            const tag = token.getValue();
            const line = token.getLine();
            const column = token.getColumn();
            options.onError({
                message: `Inconsistent tag '${tag}' on line ${line} and column ${column}`,
                tagName: tag,
                lineNumber: line,
                columnNumber: column
            });
        }
    };
    /**
   * @private
   * @param {Token} token
   */ const handleTag = (token)=>{
        // [tag]
        if (token.isStart()) handleTagStart(token);
        // [/tag]
        if (token.isEnd()) handleTagEnd(token);
    };
    /**
   * @private
   * @param {Token} token
   */ const handleNode = (token)=>{
        /**
     * @type {TagNode}
     */ const lastTagNode = tagNodes.getLast();
        const tokenValue = token.getValue();
        const isNested = isTagNested(token);
        if (lastTagNode) {
            if (token.isAttrName()) {
                tagNodesAttrName.push(tokenValue);
                lastTagNode.attr(tagNodesAttrName.getLast(), '');
            } else if (token.isAttrValue()) {
                const attrName = tagNodesAttrName.getLast();
                if (attrName) {
                    lastTagNode.attr(attrName, tokenValue);
                    tagNodesAttrName.flushLast();
                } else lastTagNode.attr(tokenValue, tokenValue);
            } else if (token.isText()) {
                if (isNested) lastTagNode.append(tokenValue);
                else appendNodes(tokenValue);
            } else if (token.isTag()) // if tag is not allowed, just past it as is
            appendNodes(token.toString());
        } else if (token.isText()) appendNodes(tokenValue);
        else if (token.isTag()) // if tag is not allowed, just past it as is
        appendNodes(token.toString());
    };
    /**
   * @private
   * @param {Token} token
   */ const onToken = (token)=>{
        if (token.isTag()) handleTag(token);
        else handleNode(token);
    };
    tokenizer = (opts.createTokenizer ? opts.createTokenizer : (0, $ca2798f2f1ba5cca$export$542413421c3f8a82))(input, {
        onToken: onToken,
        openTag: openTag,
        closeTag: closeTag,
        onlyAllowTags: options.onlyAllowTags,
        contextFreeTags: options.contextFreeTags,
        enableEscapeTags: options.enableEscapeTags
    });
    tokenizer.tokenize();
    // handles situations where we open tag, but forgot close them
    // for ex [q]test[/q][u]some[/u][q]some [u]some[/u] // forgot to close [/q]
    // so we need to flush nested content to nodes array
    const lastNestedNode = nestedNodes.flushLast();
    if (lastNestedNode && isTagNested(lastNestedNode.tag)) appendNodeAsString(lastNestedNode, false);
    return nodes.toArray();
};
var $b7d2fcb8d10105e2$export$2e2bcd8739ae039 = $b7d2fcb8d10105e2$export$98e6a39c04603d36;




const $a50b253e78482713$var$isObj = (value)=>typeof value === 'object';
const $a50b253e78482713$var$isBool = (value)=>typeof value === 'boolean';
function $a50b253e78482713$export$c1a059043cc9c119(t, cb) {
    const tree = t;
    if (Array.isArray(tree)) for(let idx = 0; idx < tree.length; idx++)tree[idx] = $a50b253e78482713$export$c1a059043cc9c119(cb(tree[idx]), cb);
    else if (tree && $a50b253e78482713$var$isObj(tree) && tree.content) $a50b253e78482713$export$c1a059043cc9c119(tree.content, cb);
    return tree;
}
function $a50b253e78482713$export$58b7571322dc50e1(expected, actual) {
    if (typeof expected !== typeof actual) return false;
    if (!$a50b253e78482713$var$isObj(expected) || expected === null) return expected === actual;
    if (Array.isArray(expected)) return expected.every((exp)=>[].some.call(actual, (act)=>$a50b253e78482713$export$58b7571322dc50e1(exp, act)));
    return Object.keys(expected).every((key)=>{
        const ao = actual[key];
        const eo = expected[key];
        if ($a50b253e78482713$var$isObj(eo) && eo !== null && ao !== null) return $a50b253e78482713$export$58b7571322dc50e1(eo, ao);
        if ($a50b253e78482713$var$isBool(eo)) return eo !== (ao === null);
        return ao === eo;
    });
}
function $a50b253e78482713$export$4659b591c19bdf3d(expression, cb) {
    return Array.isArray(expression) ? $a50b253e78482713$export$c1a059043cc9c119(this, (node)=>{
        for(let idx = 0; idx < expression.length; idx++){
            if ($a50b253e78482713$export$58b7571322dc50e1(expression[idx], node)) return cb(node);
        }
        return node;
    }) : $a50b253e78482713$export$c1a059043cc9c119(this, (node)=>$a50b253e78482713$export$58b7571322dc50e1(expression, node) ? cb(node) : node);
}


function $94a73a472a98a5c3$var$walk(cb) {
    return (0, $a50b253e78482713$export$c1a059043cc9c119)(this, cb);
}
function $94a73a472a98a5c3$export$2e2bcd8739ae039(plugs) {
    const plugins = typeof plugs === 'function' ? [
        plugs
    ] : plugs || [];
    let options = {
        skipParse: false
    };
    return {
        process (input, opts) {
            options = opts || {};
            const parseFn = options.parser || (0, $b7d2fcb8d10105e2$export$98e6a39c04603d36);
            const renderFn = options.render;
            const data = options.data || null;
            if (typeof parseFn !== 'function') throw new Error('"parser" is not a function, please pass to "process(input, { parser })" right function');
            let tree = options.skipParse ? input || [] : parseFn(input, options);
            // raw tree before modification with plugins
            const raw = tree;
            tree.messages = [];
            tree.options = options;
            tree.walk = $94a73a472a98a5c3$var$walk;
            tree.match = (0, $a50b253e78482713$export$4659b591c19bdf3d);
            plugins.forEach((plugin)=>{
                tree = plugin(tree, {
                    parse: parseFn,
                    render: renderFn,
                    iterate: $a50b253e78482713$export$c1a059043cc9c119,
                    match: $a50b253e78482713$export$4659b591c19bdf3d,
                    data: data
                }) || tree;
            });
            return {
                get html () {
                    if (typeof renderFn !== 'function') throw new Error('"render" function not defined, please pass to "process(input, { render })"');
                    return renderFn(tree, tree.options);
                },
                tree: tree,
                raw: raw,
                messages: tree.messages
            };
        }
    };
}



const $ce77b5efbac02396$var$SELFCLOSE_END_TAG = '/>';
const $ce77b5efbac02396$var$CLOSE_START_TAG = '</';
const $ce77b5efbac02396$var$START_TAG = '<';
const $ce77b5efbac02396$var$END_TAG = '>';
const $ce77b5efbac02396$var$renderNode = (node, { stripTags: stripTags = false })=>{
    if (!node) return '';
    const type = typeof node;
    if (type === 'string' || type === 'number') return node;
    if (type === 'object') {
        if (stripTags === true) return $ce77b5efbac02396$var$renderNodes(node.content, {
            stripTags: stripTags
        });
        if (node.content === null) return [
            $ce77b5efbac02396$var$START_TAG,
            node.tag,
            (0, $d69a264b7d00bcdd$export$f12220bef2863039)(node.attrs),
            $ce77b5efbac02396$var$SELFCLOSE_END_TAG
        ].join('');
        return [
            $ce77b5efbac02396$var$START_TAG,
            node.tag,
            (0, $d69a264b7d00bcdd$export$f12220bef2863039)(node.attrs),
            $ce77b5efbac02396$var$END_TAG,
            $ce77b5efbac02396$var$renderNodes(node.content),
            $ce77b5efbac02396$var$CLOSE_START_TAG,
            node.tag,
            $ce77b5efbac02396$var$END_TAG
        ].join('');
    }
    if (Array.isArray(node)) return $ce77b5efbac02396$var$renderNodes(node, {
        stripTags: stripTags
    });
    return '';
};
const $ce77b5efbac02396$var$renderNodes = (nodes, { stripTags: stripTags = false } = {})=>[].concat(nodes).reduce((r, node)=>r + $ce77b5efbac02396$var$renderNode(node, {
            stripTags: stripTags
        }), '');
const $ce77b5efbac02396$var$toHTML = (source, plugins, options)=>(0, $94a73a472a98a5c3$export$2e2bcd8739ae039)(plugins).process(source, {
        ...options,
        render: $ce77b5efbac02396$var$renderNodes
    }).html;
const $ce77b5efbac02396$export$b3890eb0ae9dca99 = $ce77b5efbac02396$var$renderNodes;
var $ce77b5efbac02396$export$2e2bcd8739ae039 = $ce77b5efbac02396$var$toHTML;


const $9c4e24f10055abae$var$isTagNode = (el)=>typeof el === 'object' && !!el.tag;
function $9c4e24f10055abae$var$process(tags, tree, core, options) {
    tree.walk((node)=>$9c4e24f10055abae$var$isTagNode(node) && tags[node.tag] ? tags[node.tag](node, core, options) : node);
}
/**
 * Creates preset for @bbob/core
 * @param defTags {Object}
 * @param processor {Function} a processor function of tree
 * @returns {function(*=): function(*=, *=): void}
 */ function $9c4e24f10055abae$export$b956d067c5bcf6b(defTags, processor = $9c4e24f10055abae$var$process) {
    const presetFactory = (opts = {})=>{
        presetFactory.options = Object.assign(presetFactory.options || {}, opts);
        const presetExecutor = (tree, core)=>processor(defTags, tree, core, presetFactory.options);
        presetExecutor.options = presetFactory.options;
        return presetExecutor;
    };
    presetFactory.extend = (callback)=>$9c4e24f10055abae$export$b956d067c5bcf6b(callback(defTags, presetFactory.options), processor);
    return presetFactory;
}
var $9c4e24f10055abae$export$2e2bcd8739ae039 = $9c4e24f10055abae$export$b956d067c5bcf6b;


const $0d6cddfe4f838ada$var$renderUrl = (node, render)=>(0, $d69a264b7d00bcdd$export$789d431171141ae4)(node.attrs) ? (0, $d69a264b7d00bcdd$export$789d431171141ae4)(node.attrs) : render(node.content);
const $0d6cddfe4f838ada$var$toNode = (tag, attrs, content)=>({
        tag: tag,
        attrs: attrs,
        content: content
    });
const $0d6cddfe4f838ada$var$isStartsWith = (node, type)=>node[0] === type;
const $0d6cddfe4f838ada$var$asListItems = (content)=>{
    let listIdx = 0;
    const listItems = [];
    const createItemNode = ()=>(0, $5bc751c3cdc57441$export$17618813e93d6bac)('li');
    const ensureListItem = (val)=>{
        listItems[listIdx] = listItems[listIdx] || val;
    };
    const addItem = (val)=>{
        if (listItems[listIdx] && listItems[listIdx].content) listItems[listIdx].content = listItems[listIdx].content.concat(val);
        else listItems[listIdx] = listItems[listIdx].concat(val);
    };
    content.forEach((el)=>{
        if ((0, $d69a264b7d00bcdd$export$ab3acb3c52feae8e)(el) && $0d6cddfe4f838ada$var$isStartsWith(el, '*')) {
            if (listItems[listIdx]) listIdx++;
            ensureListItem(createItemNode());
            addItem(el.substr(1));
        } else if ((0, $d69a264b7d00bcdd$export$acf5cbfef892896d)(el) && (0, $5bc751c3cdc57441$export$abf651b00b1d366d)(el, '*')) {
            if (listItems[listIdx]) listIdx++;
            ensureListItem(createItemNode());
        } else if (!(0, $d69a264b7d00bcdd$export$acf5cbfef892896d)(listItems[listIdx])) {
            listIdx++;
            ensureListItem(el);
        } else if (listItems[listIdx]) addItem(el);
        else ensureListItem(el);
    });
    return [
        ...listItems
    ];
};
const $0d6cddfe4f838ada$var$bbpreset = (0, $9c4e24f10055abae$export$b956d067c5bcf6b)({
    size: (node)=>{
        const keys = Object.keys(node.attrs);
        const sizeKey = keys.map((key)=>parseInt(key, 10)).find((num)=>!isNaN(num) && isFinite(num));
        return {
            tag: 'font',
            attrs: {
                size: sizeKey
            },
            content: node.content
        };
    },
    list: (node)=>{
        const type = (0, $d69a264b7d00bcdd$export$789d431171141ae4)(node.attrs);
        return $0d6cddfe4f838ada$var$toNode(type ? 'ol' : 'ul', type ? {
            type: type
        } : {}, $0d6cddfe4f838ada$var$asListItems(node.content));
    },
    i: (node)=>({
            tag: 'i',
            attrs: node.attrs,
            content: node.content
        }),
    img: (node, opts)=>$0d6cddfe4f838ada$var$toNode('img', {
            src: opts.render(node.content)
        }, null),
    url: (node, opts)=>({
            tag: 'a',
            attrs: {
                target: '_blank',
                appExternalLink: 'true',
                href: $0d6cddfe4f838ada$var$renderUrl(node, opts.render)
            },
            content: node.content
        })
});
function $0d6cddfe4f838ada$export$5219cb438f5def3(str) {
    if (str.trim().length === 0) return '';
    let html = (0, $ce77b5efbac02396$export$2e2bcd8739ae039)(str, $0d6cddfe4f838ada$var$bbpreset());
    const lines = html.split('\n');
    lines.forEach((line, idx)=>{
        lines[idx] = line.trim().replace(/(^(\r\n|\n|\r)$)|(^(\r\n|\n|\r))|^\s*$/gm, '<br><br>');
    });
    html = lines.join('');
    return html;
}


var $5f2e0f1a47f9eb9e$exports = {};

$parcel$export($5f2e0f1a47f9eb9e$exports, "getEnumKeys", () => $5f2e0f1a47f9eb9e$export$53a940bc3fb087a5);
$parcel$export($5f2e0f1a47f9eb9e$exports, "getEnumList", () => $5f2e0f1a47f9eb9e$export$2a6a804d48813f44);
$parcel$export($5f2e0f1a47f9eb9e$exports, "getEnumName", () => $5f2e0f1a47f9eb9e$export$e1d90e20ad64402a);
function $5f2e0f1a47f9eb9e$export$53a940bc3fb087a5(enume) {
    return Object.keys(enume).filter((k)=>typeof enume[k] === 'number'); // ["A", "B"]
}
function $5f2e0f1a47f9eb9e$export$2a6a804d48813f44(enume) {
    const keys = $5f2e0f1a47f9eb9e$export$53a940bc3fb087a5(enume);
    return keys.map((k)=>enume[k]);
}
function $5f2e0f1a47f9eb9e$export$e1d90e20ad64402a(enume, value) {
    if (value === undefined) throw new TypeError('Invalid value type');
    return enume[value];
}


var $7093e60e0957f8d7$exports = {};


var $937ed433b1107fd8$exports = {};

$parcel$export($937ed433b1107fd8$exports, "removeExtension", () => $937ed433b1107fd8$export$366c74c25333cf63);
function $937ed433b1107fd8$export$366c74c25333cf63(str) {
    return str.replace(/\.[^/.]+$/, '');
}


var $3462c0e8d213dd02$exports = {};

$parcel$export($3462c0e8d213dd02$exports, "getTocForGameType", () => $3462c0e8d213dd02$export$95aa335225555036);
$parcel$export($3462c0e8d213dd02$exports, "getTocForGameType2", () => $3462c0e8d213dd02$export$159396dab9859321);


function $3462c0e8d213dd02$export$95aa335225555036(tocFileNames, clientType) {
    let matchedToc = '';
    switch(clientType){
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Beta:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Retail:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).RetailPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).RetailXPtr:
            matchedToc = tocFileNames.find((tfn)=>/.*[-_]mainline\.toc$/gi.test(tfn)) || '';
            break;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEra:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEraPtr:
            matchedToc = tocFileNames.find((tfn)=>/.*[-_](classic|vanilla)\.toc$/gi.test(tfn)) || '';
            break;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Classic:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicBeta:
            matchedToc = tocFileNames.find((tfn)=>/.*[-_](mists)\.toc$/gi.test(tfn)) || '';
            break;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Anniversary:
            matchedToc = tocFileNames.find((tfn)=>/.*[-_](tbc|bcc)\.toc$/gi.test(tfn)) || '';
            break;
        default:
            break;
    }
    return matchedToc || tocFileNames.find((tfn)=>/.*(?<![-_](classic|vanilla|bcc|tbc|mainline|wrath|wotlkc|cata|mists))\.toc$/gi.test(tfn)) || '';
}
function $3462c0e8d213dd02$export$159396dab9859321(addonFolder, clientType) {
    let matchedToc = '';
    const tocs = addonFolder.tocs;
    const tocFileNames = tocs.map((toc)=>toc.fileName);
    matchedToc = $3462c0e8d213dd02$export$95aa335225555036(tocFileNames, clientType);
    // If we still have no match, we need to return the toc that matches the folder name if it exists
    // Example: All the things for TBC (ATT-Classic)
    if (matchedToc === '') return tocs.find((toc)=>(0, $937ed433b1107fd8$export$366c74c25333cf63)(toc.fileName).toLowerCase() === addonFolder.name.toLowerCase());
    return tocs.find((toc)=>toc.fileName === matchedToc);
}


var $461daba29b243306$exports = {};

$parcel$export($461daba29b243306$exports, "convertMarkdown", () => $461daba29b243306$export$f31d32bd04711717);

function $461daba29b243306$export$f31d32bd04711717(markdown) {
    const md = new $988mA$markdownit({
        html: true,
        breaks: false
    });
    let html = md.render(markdown?.trim() ?? '');
    html = html.replace(/(?:\r\n|\r|\n)/g, '');
    return html;
}


var $dc2b828c2a5e0181$exports = {};

$parcel$export($dc2b828c2a5e0181$exports, "getWowClientGroup", () => $dc2b828c2a5e0181$export$546a767afbd33f12);
$parcel$export($dc2b828c2a5e0181$exports, "getWowClientGroupForType", () => $dc2b828c2a5e0181$export$e8eb81993251de60);
$parcel$export($dc2b828c2a5e0181$exports, "getWowGameType", () => $dc2b828c2a5e0181$export$759152ffc5522fc0);
$parcel$export($dc2b828c2a5e0181$exports, "getWowMajorVersion", () => $dc2b828c2a5e0181$export$adbedbac0235e83b);
var $240fbc3f3e30fba8$exports = {};

$parcel$export($240fbc3f3e30fba8$exports, "WowMajorVersion", () => $240fbc3f3e30fba8$export$3229ac97a18cafdb);
class $240fbc3f3e30fba8$export$3229ac97a18cafdb {
    static{
        this.RetailBeta = 12;
    }
    static{
        this.Retail = 11;
    }
    static{
        this.Mists = 5;
    }
    static{
        this.Cata = 4;
    }
    static{
        this.Wrath = 3;
    }
    static{
        this.BurningCrusade = 2;
    }
    static{
        this.Classic = 1;
    }
}



function $dc2b828c2a5e0181$export$546a767afbd33f12(gameType) {
    switch(gameType){
        case (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).BurningCrusade:
            return (0, $faefaad95e5fcca0$export$b4ac9946b7924ac7).BurningCrusade;
        case (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Classic:
            return (0, $faefaad95e5fcca0$export$b4ac9946b7924ac7).Classic;
        case (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Retail:
            return (0, $faefaad95e5fcca0$export$b4ac9946b7924ac7).Retail;
        case (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).WOTLK:
            return (0, $faefaad95e5fcca0$export$b4ac9946b7924ac7).WOTLK;
        case (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Cata:
            return (0, $faefaad95e5fcca0$export$b4ac9946b7924ac7).Cata;
        case (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Mists:
            return (0, $faefaad95e5fcca0$export$b4ac9946b7924ac7).Mists;
    }
}
function $dc2b828c2a5e0181$export$e8eb81993251de60(clientType) {
    return $dc2b828c2a5e0181$export$546a767afbd33f12($dc2b828c2a5e0181$export$759152ffc5522fc0(clientType));
}
function $dc2b828c2a5e0181$export$759152ffc5522fc0(clientType) {
    switch(clientType){
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEra:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEraPtr:
            return (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Classic;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Classic:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicBeta:
            return (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Mists;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Anniversary:
            return (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).BurningCrusade;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Retail:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).RetailPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).RetailXPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Beta:
        default:
            return (0, $faefaad95e5fcca0$export$b5eb10e2ed949d71).Retail;
    }
}
function $dc2b828c2a5e0181$export$adbedbac0235e83b(clientType) {
    switch(clientType){
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEra:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEraPtr:
            return (0, $240fbc3f3e30fba8$export$3229ac97a18cafdb).Classic;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Classic:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicBeta:
            return (0, $240fbc3f3e30fba8$export$3229ac97a18cafdb).Mists;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Anniversary:
            return (0, $240fbc3f3e30fba8$export$3229ac97a18cafdb).BurningCrusade;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Beta:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).RetailPtr:
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).RetailXPtr:
            return (0, $240fbc3f3e30fba8$export$3229ac97a18cafdb).RetailBeta;
        case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Retail:
        default:
            return (0, $240fbc3f3e30fba8$export$3229ac97a18cafdb).Retail;
    }
}


$parcel$exportWildcard($d7167569386d0d4c$exports, $e1c908100ed65354$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $0d6cddfe4f838ada$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $5f2e0f1a47f9eb9e$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $7093e60e0957f8d7$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $937ed433b1107fd8$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $3462c0e8d213dd02$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $461daba29b243306$exports);
$parcel$exportWildcard($d7167569386d0d4c$exports, $dc2b828c2a5e0181$exports);



class $3bc810309d87ce1d$export$ffcbd940f1cdeba3 extends (0, $d505444d61c0b9b9$export$94a1fd3bcee9529a) {
    constructor(_baseUrl, _websiteUrl, _networkInterface){
        super(), this._baseUrl = _baseUrl, this._websiteUrl = _websiteUrl, this._networkInterface = _networkInterface, this.name = (0, $af8d31735c159a26$export$e304de36686f57ab), this.forceIgnore = false, this.allowReinstall = true, this.allowChannelChange = true, this.allowEdit = true, this.canBatchFetch = true, this.enabled = true;
    }
    async scan(installation, addonChannelType, addonFolders) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const scanResults = (0, $988mA$lodash.filter)(addonFolders, (af)=>af.wowUpScanResults !== undefined).map((af)=>{
            const wuSr = {
                scanResult: af.wowUpScanResults
            };
            return wuSr;
        });
        const fingerprints = (0, $988mA$lodash.map)(scanResults, (res)=>res.scanResult?.fingerprint).filter((fp)=>typeof fp === 'string');
        const fingerprintResponse = await this.getAddonsByFingerprints(fingerprints);
        for (const wuScanResult of scanResults){
            const fingerprintMatches = fingerprintResponse.exactMatches.filter((exactMatch)=>this.hasMatchingFingerprint(wuScanResult, exactMatch.matched_release));
            let clientMatch = fingerprintMatches.find((exactMatch)=>this.hasGameType(exactMatch.matched_release, gameType));
            if (!clientMatch && fingerprintMatches.length > 0) {
                console.warn(`No matching client type found for ${wuScanResult.scanResult?.folderName}, using fallback`);
                clientMatch = fingerprintMatches[0];
            }
            wuScanResult.exactMatch = clientMatch;
        }
        for (const addonFolder of addonFolders){
            const scanResult = scanResults.find((sr)=>sr.scanResult?.path === addonFolder.path);
            if (scanResult === undefined || scanResult.exactMatch === undefined) continue;
            try {
                const newAddon = this.getAddon(installation, addonChannelType, scanResult);
                addonFolder.matchingAddon = newAddon;
            } catch (err) {
                console.error(scanResult);
                console.error(err);
            }
        }
    }
    async getDescription(installation, externalId) {
        try {
            const response = await this.getAddonById(externalId);
            return response.addon?.description ?? '';
        } catch (e) {
            console.error('Failed to get description', e);
        }
        return '';
    }
    shouldMigrate(addon) {
        return !addon.installedExternalReleaseId;
    }
    isValidProtocol(protocol) {
        return protocol.toLowerCase().startsWith(`wowup://`);
    }
    async searchProtocol(protocol) {
        const protocolData = this.parseProtocol(protocol);
        if (!protocolData.addonId || !protocolData.releaseId) throw new Error('Invalid protocol data');
        const addonResult = await this.getAddonById(protocolData.addonId);
        if (!addonResult) throw new Error(`Failed to get addon data: ${protocolData.addonId}`);
        const addonFileResponse = await this.getReleaseById(protocolData.addonId, protocolData.releaseId);
        if (!addonFileResponse) throw new Error('Failed to get target file');
        const addonSearchResult = this.getSearchResultWithReleases(addonResult.addon, [
            addonFileResponse.release
        ]);
        if (!addonSearchResult) throw new Error('Addon search result not created');
        const searchResult = {
            protocol: protocol,
            protocolAddonId: protocolData.addonId.toString(),
            protocolReleaseId: protocolData.releaseId.toString(),
            validClientGroups: (0, $988mA$lodash.map)(addonFileResponse.release.game_versions, (gv)=>(0, $dc2b828c2a5e0181$export$546a767afbd33f12)(gv.game_type)),
            ...addonSearchResult
        };
        return searchResult;
    }
    async getAllBatch(installations, addonIds) {
        const batchResult = {
            errors: {},
            installationResults: {}
        };
        if (!addonIds.length) return batchResult;
        const url = new URL(`${this._baseUrl}/addons/batch`);
        const addonIdList = (0, $988mA$lodash.map)(addonIds, (id)=>parseInt(id, 10));
        const response = await this._networkInterface.postJson(url, {
            body: {
                addonIds: addonIdList
            },
            cache: true
        });
        for (const installation of installations){
            const addonResults = [];
            const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
            for (const result of response.addons){
                const latestFiles = this.getLatestFiles(result, gameType);
                if (!latestFiles.length) continue;
                const searchResult = this.getSearchResult(result, gameType);
                if (searchResult) addonResults.push(searchResult);
            }
            const missingAddonIds = (0, $988mA$lodash.filter)(addonIds, (addonId)=>(0, $988mA$lodash.find)(addonResults, (sr)=>sr.externalId === addonId) === undefined);
            batchResult.errors[installation.id] = (0, $988mA$lodash.map)(missingAddonIds, (addonId)=>new (0, $30d4dd98b4843be1$export$76b02e36ee9dcc33)(addonId, undefined));
            batchResult.installationResults[installation.id] = addonResults;
        }
        return batchResult;
    }
    async getAll(installation, addonIds) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const url = new URL(`${this._baseUrl}/addons/batch/${gameType}`);
        const addonIdList = (0, $988mA$lodash.map)(addonIds, (id)=>parseInt(id, 10));
        const response = await this._networkInterface.postJson(url, {
            body: {
                addonIds: addonIdList
            },
            cache: true
        });
        const searchResults = (0, $988mA$lodash.map)(response?.addons, (addon)=>this.getSearchResult(addon, gameType)).filter((sr)=>sr !== undefined);
        const missingAddonIds = (0, $988mA$lodash.filter)(addonIds, (addonId)=>(0, $988mA$lodash.find)(searchResults, (sr)=>sr?.externalId === addonId) === undefined);
        const deletedErrors = (0, $988mA$lodash.map)(missingAddonIds, (addonId)=>new (0, $30d4dd98b4843be1$export$76b02e36ee9dcc33)(addonId, undefined));
        return {
            errors: [
                ...deletedErrors
            ],
            searchResults: searchResults
        };
    }
    async getFeaturedAddons(installation) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const url = new window.URL(`${this._baseUrl}/addons/featured/${gameType}`);
        url.searchParams.set('count', '60');
        url.searchParams.set('recent', '30');
        const response = await this._networkInterface.getJson(url);
        // Remove duplicate addons that are already in the popular list from the recents list
        const uniqueRecent = (response.recent ?? []).filter((ru)=>!response.addons.some((p)=>p.id === ru.id));
        const addonResults = [
            ...response.addons,
            ...uniqueRecent
        ];
        const searchResults = (0, $988mA$lodash.map)(addonResults, (addon)=>this.getSearchResult(addon, gameType)).filter((sr)=>sr !== undefined);
        return searchResults;
    }
    async searchByQuery(query, installation) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const url = new URL(`${this._baseUrl}/addons/search/${gameType}?query=${query}&limit=10`);
        const addons = await this._networkInterface.getJson(url);
        const searchResults = (0, $988mA$lodash.map)(addons?.addons, (addon)=>this.getSearchResult(addon, gameType)).filter((sr)=>sr !== undefined);
        return searchResults;
    }
    isValidAddonId(addonId) {
        const idNumber = parseInt(addonId, 10);
        return !isNaN(idNumber) && isFinite(idNumber) && idNumber > 0;
    }
    async getCategory(category, installation) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const response = await this.getAddonsByCategory(gameType, category);
        const searchResults = (0, $988mA$lodash.map)(response?.addons, (addon)=>this.getSearchResult(addon, gameType)).filter((sr)=>sr !== undefined);
        return searchResults ?? [];
    }
    async getById(addonId, installation) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const url = new URL(`${this._baseUrl}/addons/${addonId}`);
        const result = await this._networkInterface.getJson(url);
        return this.getSearchResult(result.addon, gameType);
    }
    async getChangelog(installation, externalId, externalReleaseId) {
        try {
            const addon = await this.getReleaseById(externalId, externalReleaseId);
            return addon?.release?.body ?? '';
        } catch (e) {
            console.error('Failed to get changelog', e);
        }
        return '';
    }
    parseProtocol(protocol) {
        const url = new window.URL(protocol);
        return {
            addonId: url.searchParams.get('addonId') || '',
            releaseId: url.searchParams.get('releaseId') || ''
        };
    }
    getAddonReleaseChannel(file) {
        return file.prerelease ? (0, $faefaad95e5fcca0$export$d045354f167da29).Beta : (0, $faefaad95e5fcca0$export$d045354f167da29).Stable;
    }
    // Only 1 game version should match a given game type
    getMatchingVersion(release, gameType) {
        return release.game_versions.find((gv)=>gv.game_type === gameType);
    }
    filterReleases(representation, gameType) {
        return (0, $988mA$lodash.filter)(representation.releases, (release)=>release.game_versions.some((gv)=>gv.game_type === gameType));
    }
    getLatestFiles(result, gameType) {
        const filtered = (0, $988mA$lodash.filter)(result?.releases, (latestFile)=>!!this.getMatchingVersion(latestFile, gameType));
        return (0, $988mA$lodash.sortBy)(filtered, (latestFile)=>latestFile.id).reverse();
    }
    hasMatchingFingerprint(scanResult, release) {
        if (!release?.addonFolders) return false;
        return release.addonFolders.some((addonFolder)=>addonFolder.fingerprint === scanResult.scanResult?.fingerprint);
    }
    getSearchResultFile(release, gameType) {
        const matchingVersion = this.getMatchingVersion(release, gameType);
        if (!matchingVersion) return undefined;
        return this.getSearchResultFileWithVersion(release, matchingVersion);
    }
    hasGameType(release, clientType) {
        if (!release) return false;
        const matchingVersion = this.getMatchingVersion(release, clientType);
        return matchingVersion !== undefined;
    }
    getSearchResultFileWithVersion(release, matchingVersion) {
        const version = matchingVersion?.version || release.tag_name || '';
        return {
            channelType: this.getAddonReleaseChannel(release),
            downloadUrl: release.download_url,
            folders: [],
            gameVersion: (0, $e1c908100ed65354$export$6538dd8981ac38d0)(matchingVersion?.interface),
            releaseDate: release.published_at,
            version: version,
            dependencies: [],
            changelog: release.body,
            externalId: release.id.toString(),
            title: release.toc_title ?? matchingVersion?.title,
            authors: matchingVersion?.authors
        };
    }
    getAddon(installation, addonChannelType, scanResult) {
        const gameType = (0, $dc2b828c2a5e0181$export$759152ffc5522fc0)(installation.clientType);
        const matchedRelease = scanResult.exactMatch?.matched_release;
        if (!matchedRelease || !matchedRelease.addonFolders) throw new Error('No matched release');
        const folders = matchedRelease.addonFolders.map((af)=>af.folder_name);
        const folderList = folders.join(', ');
        const channelType = addonChannelType;
        let matchingVersion = this.getMatchingVersion(matchedRelease, gameType);
        if (!matchingVersion) {
            matchingVersion = matchedRelease.game_versions[0];
            console.warn(`No matching version found: ${scanResult.exactMatch?.repository_name ?? ''}, using fallback ${matchingVersion?.interface ?? ''}`);
        }
        const name = matchingVersion?.title || scanResult.exactMatch?.repository_name;
        const version = matchingVersion?.version || scanResult.exactMatch?.matched_release?.tag_name || '';
        const authors = matchingVersion?.authors || scanResult.exactMatch?.owner_name || '';
        const interfaceVer = [
            matchingVersion?.interface
        ];
        if (!name || !version || !interfaceVer) throw new Error(`Invalid matching version data: name ${name}, version ${version}, interfaceVer ${interfaceVer}`);
        const screenshotUrls = this.getScreenshotUrls([
            matchedRelease
        ]);
        const externalUrl = scanResult.exactMatch ? `${this._websiteUrl}/addons/${scanResult.exactMatch.id}` : 'unknown';
        return {
            id: (0, $988mA$uuid.v4)(),
            author: authors,
            name: name,
            channelType: channelType,
            autoUpdateEnabled: false,
            autoUpdateNotificationsEnabled: false,
            clientType: installation.clientType,
            downloadUrl: scanResult.exactMatch?.matched_release?.download_url ?? '',
            externalUrl: externalUrl,
            externalId: scanResult.exactMatch?.id.toString() ?? 'unknown',
            gameVersion: (0, $e1c908100ed65354$export$692f1cc36daf4e6b)(interfaceVer),
            installedAt: new Date(),
            installedFolders: folderList,
            installedFolderList: folders,
            installedVersion: version,
            installedExternalReleaseId: scanResult.exactMatch?.matched_release?.id.toString() ?? 'unknown',
            isIgnored: false,
            latestVersion: version,
            providerName: this.name,
            providerSource: scanResult.exactMatch?.source ?? 'unknown',
            thumbnailUrl: scanResult.exactMatch?.image_url ?? '',
            fundingLinks: [
                ...scanResult.exactMatch?.funding_links ?? []
            ],
            isLoadOnDemand: false,
            releasedAt: scanResult.exactMatch?.matched_release?.published_at,
            externalChannel: (0, $5f2e0f1a47f9eb9e$export$e1d90e20ad64402a)((0, $faefaad95e5fcca0$export$d045354f167da29), channelType),
            latestChangelog: scanResult.exactMatch?.matched_release?.body,
            externalLatestReleaseId: scanResult?.exactMatch?.matched_release?.id?.toString(),
            installationId: installation.id,
            screenshotUrls: screenshotUrls
        };
    }
    getSearchResult(representation, gameType) {
        const clientReleases = this.filterReleases(representation, gameType);
        const searchResultFiles = (0, $988mA$lodash.map)(clientReleases, (release)=>this.getSearchResultFile(release, gameType)).filter((sr)=>sr !== undefined);
        if (searchResultFiles.length === 0) return undefined;
        const name = (0, $988mA$lodash.first)(searchResultFiles)?.title ?? representation.repository_name;
        const authors = (0, $988mA$lodash.first)(searchResultFiles)?.authors ?? representation.owner_name ?? '';
        return {
            author: authors,
            externalId: representation.id.toString(),
            externalUrl: `${this._websiteUrl}/addons/${representation.id}`,
            name: name,
            providerName: this.name,
            thumbnailUrl: representation.image_url || representation.owner_image_url || '',
            downloadCount: representation.total_download_count,
            files: searchResultFiles,
            releasedAt: new Date(),
            summary: representation.description,
            fundingLinks: [
                ...representation?.funding_links ?? []
            ],
            screenshotUrls: this.getScreenshotUrls(clientReleases)
        };
    }
    getSearchResultWithReleases(representation, releases) {
        const searchResultFiles = (0, $988mA$lodash.flatMap)(releases, (release)=>(0, $988mA$lodash.map)(release.game_versions, (gv)=>this.getSearchResultFileWithVersion(release, gv)).filter((r)=>r !== undefined)).filter((sr)=>sr !== undefined);
        if (searchResultFiles.length === 0) return undefined;
        const name = (0, $988mA$lodash.first)(searchResultFiles)?.title ?? representation.repository_name;
        const authors = (0, $988mA$lodash.first)(searchResultFiles)?.authors ?? representation.owner_name ?? '';
        return {
            author: authors,
            externalId: representation.id.toString(),
            externalUrl: `${this._websiteUrl}/addons/${representation.id}`,
            name: name,
            providerName: this.name,
            thumbnailUrl: representation.image_url || representation.owner_image_url || '',
            downloadCount: representation.total_download_count,
            files: searchResultFiles,
            releasedAt: new Date(),
            summary: representation.description,
            fundingLinks: [
                ...representation?.funding_links ?? []
            ],
            screenshotUrls: this.getScreenshotUrls(releases)
        };
    }
    // Currently we only support images, so we filter for those
    getScreenshotUrls(releases) {
        const urls = (0, $988mA$lodash.flatten)(releases.map((release)=>release.previews?.filter((preview)=>preview.preview_type === 'image').map((preview)=>preview.url))).filter((url)=>typeof url === 'string');
        return (0, $988mA$lodash.uniq)(urls);
    }
    async getReleaseById(addonId, releaseId) {
        const url = new URL(`${this._baseUrl}/addons/${addonId}/releases/${releaseId}`);
        return await this._networkInterface.getJson(url);
    }
    async getAddonById(addonId) {
        const url = new URL(`${this._baseUrl}/addons/${addonId}`);
        return await this._networkInterface.getJson(url);
    }
    async getAddonsByCategory(gameType, category) {
        const url = new URL(`${this._baseUrl}/addons/category/${category}/${gameType}`);
        return await this._networkInterface.getJson(url);
    }
    getAddonsByFingerprints(fingerprints) {
        const url = `${this._baseUrl}/addons/fingerprint`;
        return this._networkInterface.postJson(url, {
            body: {
                fingerprints: fingerprints
            }
        });
    }
}


var $0d8c76c1b79330ea$exports = {};

$parcel$export($0d8c76c1b79330ea$exports, "WowInterfaceAddonProvider", () => $0d8c76c1b79330ea$export$7d478aa7e7b1bd7a);







const $0d8c76c1b79330ea$var$API_URL = 'https://api.mmoui.com/v4/game/WOW';
const $0d8c76c1b79330ea$var$API_URL_FALLBACK = 'https://api.mmoui.com/v3/game/WOW';
const $0d8c76c1b79330ea$var$ADDON_URL = 'https://www.wowinterface.com/downloads/info';
class $0d8c76c1b79330ea$export$7d478aa7e7b1bd7a extends (0, $d505444d61c0b9b9$export$94a1fd3bcee9529a) {
    constructor(_networkInterface){
        super(), this._networkInterface = _networkInterface, this.name = (0, $af8d31735c159a26$export$b479ece230133092), this.forceIgnore = false, this.allowReinstall = true, this.allowChannelChange = false, this.allowEdit = true, this.enabled = true, this.getAddonDetails = async (addonId)=>{
            if (typeof addonId !== 'string' || addonId.length === 0) return undefined;
            const url = new URL(`${$0d8c76c1b79330ea$var$API_URL}/filedetails/${addonId}.json`);
            let responses = [];
            try {
                responses = await this._networkInterface.getJson(url);
            } catch (e) {
                console.warn('[wowi] addon details failed, using fallback', e);
                try {
                    const fallbackUrl = new URL(`${$0d8c76c1b79330ea$var$API_URL_FALLBACK}/filedetails/${addonId}.json`);
                    const fallbackResponses = await this._networkInterface.getJson(fallbackUrl);
                    if (Array.isArray(fallbackResponses)) responses = (0, $988mA$lodash.map)(fallbackResponses, (fr)=>this.toV4(fr));
                } catch (e) {
                    console.error('[wowi] fallback request failed', e);
                }
            }
            return (0, $988mA$lodash.first)(responses);
        }, this.getAllAddonDetails = async (addonIds)=>{
            if (!Array.isArray(addonIds) || addonIds.length === 0) return [];
            let fallbackIds = [];
            let responses = [];
            try {
                const url = new URL(`${$0d8c76c1b79330ea$var$API_URL}/filedetails/${addonIds.join(',')}.json`);
                responses = await this._networkInterface.getJson(url);
                fallbackIds = addonIds.filter((aid)=>!responses.some((r)=>r.id.toString() === aid));
            } catch (e) {
                console.warn('[wowi] addon details failed, using fallback', e);
                fallbackIds = [
                    ...addonIds
                ];
            }
            if (fallbackIds.length > 0) try {
                const fallbackUrl = new URL(`${$0d8c76c1b79330ea$var$API_URL_FALLBACK}/filedetails/${fallbackIds.join(',')}.json`);
                const v3Responses = await this._networkInterface.getJson(fallbackUrl);
                responses.push(...v3Responses.map((r)=>this.toV4(r)));
            } catch (e) {
                console.warn('[wowi] addon details fallback failed', e);
            }
            return responses;
        };
    }
    async getDescription(installation, externalId) {
        try {
            const addonDetails = await this.getAddonDetails(externalId);
            return (0, $0d6cddfe4f838ada$export$5219cb438f5def3)(addonDetails?.description ?? '');
        } catch (error) {
            console.error(error);
            return '';
        }
    }
    async getAll(installation, addonIds) {
        const filteredIds = (0, $988mA$lodash.filter)(addonIds, (aid)=>this.isValidAddonId(aid));
        const errors = (0, $988mA$lodash.filter)(addonIds, (aid)=>!this.isValidAddonId(aid)).map((aid)=>new Error(`invalid addon id found: ${aid}`));
        let searchResults = await this.getAllById(filteredIds);
        searchResults = (0, $988mA$lodash.filter)(searchResults, (sr)=>filteredIds.includes(sr.externalId));
        if (searchResults.length !== filteredIds.length) {
            const missingIds = (0, $988mA$lodash.filter)(filteredIds, (aid)=>!searchResults.some((sr)=>sr.externalId === aid));
            errors.push(...(0, $988mA$lodash.map)(missingIds, (mid)=>new (0, $30d4dd98b4843be1$export$76b02e36ee9dcc33)(mid, new Error('addon not returned ' + mid))));
        }
        return {
            errors: errors,
            searchResults: searchResults
        };
    }
    async getChangelog(installation, externalId) {
        try {
            const addon = await this.getAddonDetails(externalId);
            return (0, $0d6cddfe4f838ada$export$5219cb438f5def3)(addon?.changeLog ?? '');
        } catch (error) {
            console.error(`Failed to get addon changelog`, error);
            return '';
        }
    }
    async searchByUrl(addonUri) {
        const addonId = this.getAddonId(addonUri);
        if (addonId.length === 0) throw new Error(`Addon ID not found ${addonUri.toString()}`);
        const addon = await this.getAddonDetails(addonId);
        if (addon === undefined) throw new Error(`Bad addon api response ${addonUri.toString()}`);
        const searchResult = this.toAddonSearchResult(addon);
        if (searchResult === undefined) throw new Error(`Failed to create search result  ${addonUri.toString()}`);
        return {
            errors: [],
            searchResult: searchResult
        };
    }
    async getById(addonId) {
        const result = await this.getAddonDetails(addonId);
        if (result !== undefined) return this.toAddonSearchResult(result, '');
    }
    isValidAddonUri(addonUri) {
        return typeof addonUri.host === 'string' && addonUri.host.length > 0 && addonUri.host.endsWith('wowinterface.com');
    }
    isValidAddonId(addonId) {
        return typeof addonId === 'string' && addonId.length > 0 && !isNaN(parseInt(addonId, 10));
    }
    async scan(installation, addonChannelType, addonFolders) {
        const wowiFolders = addonFolders.filter((folder)=>folder.tocs.some((toc)=>!!toc.wowInterfaceId && toc.loadOnDemand !== '1'));
        const addonIds = (0, $988mA$lodash.uniq)((0, $988mA$lodash.flatten)(wowiFolders.map((folder)=>folder.tocs.map((toc)=>toc.wowInterfaceId)))).filter((aid)=>aid !== undefined);
        const addonDetails = await this.getAllAddonDetails(addonIds);
        for (const addonFolder of wowiFolders){
            const targetToc = (0, $3462c0e8d213dd02$export$159396dab9859321)(addonFolder, installation.clientType);
            if (!targetToc?.wowInterfaceId) continue;
            const details = addonDetails.find((ad)=>ad.id.toString() === targetToc.wowInterfaceId);
            if (!details) {
                console.warn('Details not found');
                continue;
            }
            addonFolder.matchingAddon = this.toAddon(details, installation, addonChannelType, addonFolder);
        }
    }
    // https://www.wowinterface.com/downloads/download25538-Aardvark
    getAddonId(addonUri) {
        const downloadUrlregex = /\/download(\d+)/i;
        const downloadUrlMatch = downloadUrlregex.exec(addonUri.pathname);
        if (downloadUrlMatch) return downloadUrlMatch[1];
        const infoUrlRegex = /\/info(\d+)/i;
        const infoUrlMatch = infoUrlRegex.exec(addonUri.pathname);
        if (infoUrlMatch) return infoUrlMatch[1];
        throw new Error(`Unhandled URL: ${addonUri.toString()}`);
    }
    toV4(details) {
        return {
            author: details.UIAuthorName,
            categoryId: parseInt(details.UICATID, 10),
            changeLog: details.UIChangeLog,
            checksum: details.UIMD5,
            description: details.UIDescription,
            downloads: parseInt(details.UIHitCount, 10),
            downloadsMonthly: parseInt(details.UIHitCountMonthly, 10),
            downloadUri: details.UIDownload,
            favorites: parseInt(details.UIFavoriteTotal, 10),
            fileName: details.UIFileName,
            id: parseInt(details.UID, 10),
            images: [],
            lastUpdate: details.UIDate,
            pendingUpdate: details.UIPending,
            title: details.UIName,
            version: details.UIVersion
        };
    }
    async getAllById(addonIds) {
        const addonDetails = await this.getAllAddonDetails(addonIds);
        const mapped = addonDetails.map((ad)=>this.toAddonSearchResult(ad, ''));
        const filtered = (0, $988mA$lodash.filter)(mapped, (m)=>m !== undefined);
        return filtered;
    }
    getThumbnailUrl(response) {
        return (0, $988mA$lodash.first)(response.images)?.thumbUrl ?? '';
    }
    getAddonUrl(response) {
        return `${$0d8c76c1b79330ea$var$ADDON_URL}${response.id}`;
    }
    toAddon(response, installation, addonChannelType, addonFolder) {
        const targetToc = (0, $3462c0e8d213dd02$export$159396dab9859321)(addonFolder, installation.clientType);
        return {
            id: (0, $988mA$uuid.v4)(),
            author: response.author,
            autoUpdateEnabled: false,
            autoUpdateNotificationsEnabled: false,
            channelType: addonChannelType,
            clientType: installation.clientType,
            downloadUrl: response.downloadUri,
            externalId: response.id.toString(),
            externalUrl: this.getAddonUrl(response),
            gameVersion: (0, $e1c908100ed65354$export$692f1cc36daf4e6b)(targetToc?.interface ?? []),
            installedAt: new Date(),
            installedFolders: addonFolder.name,
            installedFolderList: [
                addonFolder.name
            ],
            installedVersion: targetToc?.version,
            isIgnored: false,
            latestVersion: response.version,
            name: response.title,
            providerName: this.name,
            thumbnailUrl: this.getThumbnailUrl(response),
            summary: (0, $0d6cddfe4f838ada$export$5219cb438f5def3)(response.description),
            screenshotUrls: response.images?.map((img)=>img.imageUrl),
            downloadCount: response.downloads,
            releasedAt: new Date(response.lastUpdate),
            isLoadOnDemand: false,
            latestChangelog: (0, $0d6cddfe4f838ada$export$5219cb438f5def3)(response.changeLog),
            externalChannel: (0, $5f2e0f1a47f9eb9e$export$e1d90e20ad64402a)((0, $faefaad95e5fcca0$export$d045354f167da29), (0, $faefaad95e5fcca0$export$d045354f167da29).Stable),
            installationId: installation.id
        };
    }
    toAddonSearchResult(response, folderName) {
        try {
            const searchResultFile = {
                channelType: (0, $faefaad95e5fcca0$export$d045354f167da29).Stable,
                version: response.version,
                downloadUrl: response.downloadUri,
                folders: folderName ? [
                    folderName
                ] : [],
                gameVersion: '',
                releaseDate: new Date(response.lastUpdate),
                changelog: (0, $0d6cddfe4f838ada$export$5219cb438f5def3)(response.changeLog)
            };
            return {
                author: response.author,
                externalId: response.id.toString(),
                name: response.title,
                thumbnailUrl: this.getThumbnailUrl(response),
                externalUrl: this.getAddonUrl(response),
                providerName: this.name,
                downloadCount: response.downloads,
                files: [
                    searchResultFile
                ],
                summary: (0, $0d6cddfe4f838ada$export$5219cb438f5def3)(response.description)
            };
        } catch (err) {
            console.error('Failed to create addon search result', err);
            return undefined;
        }
    }
}


var $6cda88f17193fdee$exports = {};

$parcel$export($6cda88f17193fdee$exports, "TukUiAddonProvider", () => $6cda88f17193fdee$export$98b14083777e0def);








const $6cda88f17193fdee$var$NEW_API_URL = 'https://api.tukui.org/v1/addons';
const $6cda88f17193fdee$var$DOWNLOAD_CT = 2147483647;
class $6cda88f17193fdee$export$98b14083777e0def extends (0, $d505444d61c0b9b9$export$94a1fd3bcee9529a) {
    constructor(_networkInterface){
        super(), this._networkInterface = _networkInterface, this.name = (0, $af8d31735c159a26$export$d3c2b53bc8889c55), this.forceIgnore = false, this.allowReinstall = true, this.allowChannelChange = false, this.allowEdit = true, this.enabled = true, this.fetchChangelogHtml = async (addon)=>{
            const markdown = await this._networkInterface.getText(addon.changelog_url);
            return (0, $461daba29b243306$export$f31d32bd04711717)(markdown);
        }, this.getAllAddons = async (clientType)=>{
            if (clientType === (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).None) return [];
            try {
                return this.fetchApiResults();
            } catch (err) {
                console.error(err);
                return [];
            }
        }, this.fetchApiResults = async ()=>{
            const url = new window.URL($6cda88f17193fdee$var$NEW_API_URL);
            const addons = await this._networkInterface.getJson(url);
            return addons;
        };
    }
    async getCategory(category, installation) {
        // TBD categories are no longer available
        const allAddons = await this.getAllAddons(installation.clientType);
        const searchResults = [];
        for (const addon of allAddons){
            const searchResult = await this.toSearchResult(addon, installation);
            if (searchResult) searchResults.push(searchResult);
        }
        return searchResults;
    }
    async getDescription(installation, externalId) {
        const addons = await this.getAllAddons(installation.clientType);
        const addonMatch = (0, $988mA$lodash.find)(addons, (addon)=>addon.id.toString() === externalId.toString());
        return addonMatch?.small_desc ?? '';
    }
    async getChangelog(installation, externalId) {
        const addons = await this.getAllAddons(installation.clientType);
        const addon = (0, $988mA$lodash.find)(addons, (a)=>a.id.toString() === externalId.toString());
        if (!addon) {
            console.warn('Addon not found');
            return '';
        }
        return await this.formatChangelog(addon);
    }
    async getAll(installation, addonIds) {
        const validIds = (0, $988mA$lodash.filter)(addonIds, (aid)=>this.isValidAddonId(aid));
        const errors = (0, $988mA$lodash.filter)(addonIds, (aid)=>!this.isValidAddonId(aid)).map((aid)=>new Error('invalid addon id found: ' + aid));
        let results = [];
        try {
            const addons = await this.getAllAddons(installation.clientType);
            const filteredAddons = addons.filter((addon)=>(0, $988mA$lodash.some)(validIds, (aid)=>aid.toString() === addon.id.toString()));
            results = await this.mapAddonsToSearchResults(filteredAddons, installation);
        } catch (e) {
            console.error('Failed during getAll', e);
        }
        if (results.length !== validIds.length) {
            const missingIds = (0, $988mA$lodash.filter)(validIds, (aid)=>!(0, $988mA$lodash.some)(results, (r)=>r.externalId === aid));
            errors.push(...(0, $988mA$lodash.map)(missingIds, (mid)=>new (0, $30d4dd98b4843be1$export$76b02e36ee9dcc33)(mid, new Error('addon not found ' + mid))));
        }
        return {
            errors: errors,
            searchResults: results
        };
    }
    async getFeaturedAddons(installation) {
        const tukUiAddons = await this.getAllAddons(installation.clientType);
        return await this.mapAddonsToSearchResults(tukUiAddons, installation);
    }
    async searchByQuery(query, installation) {
        const searchResults = await this.searchAddons(query, installation.clientType, true);
        const similarAddons = (0, $988mA$lodash.orderBy)(searchResults, [
            'downloads'
        ]);
        return await this.mapAddonsToSearchResults(similarAddons, installation);
    }
    async getById(addonId, installation) {
        const addons = await this.getAllAddons(installation.clientType);
        const match = (0, $988mA$lodash.find)(addons, (addon)=>addon.id.toString() === addonId);
        if (match !== undefined) return await this.toSearchResult(match, installation);
        return undefined;
    }
    isValidAddonId(addonId) {
        return typeof addonId === 'string' && !isNaN(parseInt(addonId, 10));
    }
    async scan(installation, addonChannelType, addonFolders) {
        const allAddons = await this.getAllAddons(installation.clientType);
        // Sort folders to prioritize ones with a toc id
        let tukProjectAddonFolders = (0, $988mA$lodash.sortBy)(addonFolders, (folder)=>folder.tocs.some((toc)=>!!toc.tukUiProjectId && toc.loadOnDemand !== '1')).reverse();
        // Remove all folders that do not have a matching game type
        tukProjectAddonFolders = (0, $988mA$lodash.filter)(tukProjectAddonFolders, (af)=>(0, $3462c0e8d213dd02$export$159396dab9859321)(af, installation.clientType) !== undefined);
        // Go thru all the folders, see if they have an ID we can match.
        await this.scanAddonsWithIds(tukProjectAddonFolders, allAddons, installation, addonChannelType);
        // Go thru all the folders and see if any of the non-matched belong to the folder list of any matched ones
        await this.matchAddonSubfolders(tukProjectAddonFolders, installation);
        // Go thru all the folders and see if the names match anything that did not have a match
        await this.scanAddonsWithNames(tukProjectAddonFolders, installation, addonChannelType);
        // repeat step 2 for remaining non-matched folders
        await this.matchAddonSubfolders(tukProjectAddonFolders, installation);
    }
    async mapAddonsToSearchResults(addons, installation) {
        const results = [];
        for (const addon of addons){
            const searchResult = await this.toSearchResult(addon, installation);
            if (searchResult) results.push(searchResult);
        }
        return results;
    }
    async formatChangelog(addon) {
        try {
            return await this.fetchChangelogHtml(addon);
        } catch (e) {
            console.error('Failed to get changelog', e);
            return '';
        }
    }
    async searchAddons(addonName, clientType, allowContain = false) {
        if (!addonName) return [];
        const canonAddonName = addonName.toLowerCase();
        const addons = await this.getAllAddons(clientType);
        const similarity = addons.map((addon)=>{
            const compSim = $988mA$stringsimilarity.compareTwoStrings(canonAddonName, addon.name.toLowerCase());
            return {
                addon: addon,
                similarity: compSim
            };
        }).filter((result)=>result.similarity > 0.7);
        let matches = (0, $988mA$lodash.orderBy)(similarity, (match)=>match.similarity, 'desc').map((result)=>result.addon);
        // If we didnt get any similarity matches
        if (allowContain && matches.length === 0) matches = addons.filter((addon)=>addon.name.toLowerCase().indexOf(canonAddonName) !== -1);
        return matches;
    }
    async toSearchResult(addon, installation) {
        if (!addon) return undefined;
        const latestFile = {
            channelType: (0, $faefaad95e5fcca0$export$d045354f167da29).Stable,
            folders: addon.directories,
            downloadUrl: addon.url,
            gameVersion: this.getPatchForInstall(addon, installation),
            version: addon.version,
            releaseDate: new Date(`${addon.last_update} UTC`),
            changelog: undefined
        };
        return {
            author: addon.author,
            externalId: addon.id.toString(),
            name: addon.name,
            thumbnailUrl: addon.screenshot_url,
            externalUrl: addon.web_url,
            providerName: this.name,
            downloadCount: $6cda88f17193fdee$var$DOWNLOAD_CT,
            files: [
                latestFile
            ],
            summary: addon.small_desc
        };
    }
    getPatchForInstall(addon, installation) {
        const classicToken = '1.';
        const burningCrusadeToken = '2.';
        const wrathToken = '3.';
        const cataToken = '4.';
        const mistsToken = '5.';
        switch(installation.clientType){
            case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Classic:
            case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicPtr:
            case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicBeta:
                return addon.patch.find((p)=>p.startsWith(mistsToken)) ?? '';
            case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEra:
            case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).ClassicEraPtr:
                return addon.patch.find((p)=>p.startsWith(classicToken)) ?? '';
            case (0, $faefaad95e5fcca0$export$a56ef7ad1ec687bf).Anniversary:
                return addon.patch.find((p)=>p.startsWith(burningCrusadeToken)) ?? '';
            default:
                return addon.patch.find((p)=>!p.startsWith(classicToken) && !p.startsWith(wrathToken) && !p.startsWith(cataToken) && !p.startsWith(mistsToken)) ?? '';
        }
    }
    /** Iterate the list of addon folders, attempting to find and match anything based on the ID inside the correct toc file */ async scanAddonsWithIds(addonFolders, allAddons, installation, addonChannelType) {
        for (const addonFolder of addonFolders){
            const targetToc = (0, $3462c0e8d213dd02$export$159396dab9859321)(addonFolder, installation.clientType);
            if (targetToc === undefined) {
                console.warn(`[TukUI]: target toc was undefined`, installation.clientType, addonFolder);
                continue;
            }
            console.log(`[TukUI]: target ${targetToc.fileName}, ${targetToc.title}, ${targetToc.tukUiProjectId}`);
            if (typeof targetToc.tukUiProjectId === 'string' && targetToc.tukUiProjectId.length > 0) {
                const match = (0, $988mA$lodash.find)(allAddons, (addon)=>addon.id.toString() === targetToc.tukUiProjectId);
                if (match === undefined) continue;
                addonFolder.matchingAddon = await this.createAddonFolderAddon(targetToc, addonFolder, match, installation, addonChannelType);
            }
        }
    }
    async scanAddonsWithNames(addonFolders, installation, addonChannelType) {
        const missingAddons = (0, $988mA$lodash.filter)(addonFolders, (af)=>af.matchingAddon === undefined);
        for (const addonFolder of missingAddons){
            const targetToc = (0, $3462c0e8d213dd02$export$159396dab9859321)(addonFolder, installation.clientType);
            if (targetToc === undefined) {
                console.warn(`[TukUI]: target toc was undefined`, installation.clientType, addonFolder);
                continue;
            }
            console.info(`[TukUI]: falling back to title search`, targetToc.title);
            const results = await this.searchAddons(targetToc.title, installation.clientType);
            const firstResult = (0, $988mA$lodash.first)(results);
            if (firstResult === undefined) continue;
            addonFolder.matchingAddon = await this.createAddonFolderAddon(targetToc, addonFolder, firstResult, installation, addonChannelType);
        }
    }
    /** Given a list of pre-processed addon folders, attempt to place any matching folders with their 'parent' addon that has a list containing it */ async matchAddonSubfolders(addonFolders, installation) {
        const matchedAddons = (0, $988mA$lodash.filter)(addonFolders, (af)=>af.matchingAddon !== undefined);
        const missingAddons = (0, $988mA$lodash.filter)(addonFolders, (af)=>af.matchingAddon === undefined);
        for (const addonFolder of missingAddons){
            const targetToc = (0, $3462c0e8d213dd02$export$159396dab9859321)(addonFolder, installation.clientType);
            if (targetToc === undefined) {
                console.warn(`[TukUI]: target toc was undefined`, installation.clientType, addonFolder);
                continue;
            }
            const parent = matchedAddons.find((ma)=>ma.matchingAddon?.installedFolderList?.includes(addonFolder.name));
            if (parent?.matchingAddon === undefined) continue;
            console.info(`[TukUI]: parent found ${parent.name} : ${targetToc.fileName}, ${targetToc.title}, ${targetToc.tukUiProjectId}`);
            // this match is just a copy of the parent since its a sub-addon
            addonFolder.matchingAddon = {
                ...parent.matchingAddon
            };
        }
    }
    /** Create an addon from the matched TukUi addon and correct toc file */ async createAddonFolderAddon(targetToc, addonFolder, tukUiAddon, installation, addonChannelType) {
        const installedFolders = targetToc.tukUiProjectFolders ? targetToc.tukUiProjectFolders : addonFolder.name;
        const installedFolderList = targetToc.tukUiProjectFolders ? targetToc.tukUiProjectFolders.split(',').map((f)=>f.trim()) : [
            addonFolder.name
        ];
        return {
            autoUpdateEnabled: false,
            autoUpdateNotificationsEnabled: false,
            channelType: addonChannelType,
            clientType: installation.clientType,
            id: (0, $988mA$uuid.v4)(),
            isIgnored: false,
            name: tukUiAddon.name,
            author: tukUiAddon.author,
            downloadUrl: tukUiAddon.url,
            externalId: tukUiAddon.id.toString(),
            externalUrl: tukUiAddon.web_url,
            gameVersion: targetToc.interface,
            installedAt: addonFolder.fileStats?.birthtime ?? new Date(0),
            installedFolders: installedFolders,
            installedFolderList: installedFolderList,
            installedVersion: targetToc.version,
            latestVersion: tukUiAddon.version,
            providerName: this.name,
            thumbnailUrl: tukUiAddon.screenshot_url,
            updatedAt: new Date(),
            summary: tukUiAddon.small_desc,
            downloadCount: $6cda88f17193fdee$var$DOWNLOAD_CT,
            screenshotUrls: [
                tukUiAddon.screenshot_url
            ],
            releasedAt: new Date(`${tukUiAddon.last_update} UTC`),
            isLoadOnDemand: false,
            latestChangelog: undefined,
            externalChannel: (0, $5f2e0f1a47f9eb9e$export$e1d90e20ad64402a)((0, $faefaad95e5fcca0$export$d045354f167da29), (0, $faefaad95e5fcca0$export$d045354f167da29).Stable),
            installationId: installation.id
        };
    }
}


$parcel$exportWildcard($8c2094342e06e0ec$exports, $3bc810309d87ce1d$exports);
$parcel$exportWildcard($8c2094342e06e0ec$exports, $0d8c76c1b79330ea$exports);
$parcel$exportWildcard($8c2094342e06e0ec$exports, $6cda88f17193fdee$exports);


var $762712d8f2726127$exports = {};


var $4f0046e728a1a92c$exports = {};

$parcel$export($4f0046e728a1a92c$exports, "TOC_AUTHOR", () => $4f0046e728a1a92c$export$9efb0d1b9b4d923b);
$parcel$export($4f0046e728a1a92c$exports, "TOC_DEPENDENCIES", () => $4f0046e728a1a92c$export$d989c7edd72fb160);
$parcel$export($4f0046e728a1a92c$exports, "TOC_INTERFACE", () => $4f0046e728a1a92c$export$df02ec075fdd36f3);
$parcel$export($4f0046e728a1a92c$exports, "TOC_NOTES", () => $4f0046e728a1a92c$export$e17f8b790f736455);
$parcel$export($4f0046e728a1a92c$exports, "TOC_REQUIRED_DEPS", () => $4f0046e728a1a92c$export$6e047e9e7f7da6a5);
$parcel$export($4f0046e728a1a92c$exports, "TOC_TITLE", () => $4f0046e728a1a92c$export$23cf79bfa1e2c92a);
$parcel$export($4f0046e728a1a92c$exports, "TOC_VERSION", () => $4f0046e728a1a92c$export$4016d8522ecdf92a);
$parcel$export($4f0046e728a1a92c$exports, "TOC_WEBSITE", () => $4f0046e728a1a92c$export$e04530d6a891f2e9);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_ADDON_PROVIDER", () => $4f0046e728a1a92c$export$6d541bc5c491dd66);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_CATEGORY", () => $4f0046e728a1a92c$export$e2845edcd3a340ad);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_CURSE_PROJECT_ID", () => $4f0046e728a1a92c$export$8f7efc5e0db11d27);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_LOADONDEMAND", () => $4f0046e728a1a92c$export$e30ccef561f5c153);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_LOCALIZATIONS", () => $4f0046e728a1a92c$export$1b7233347279abf0);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_PART_OF", () => $4f0046e728a1a92c$export$8bf3fb4642bd7ef0);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_TUKUI_PROJECTID", () => $4f0046e728a1a92c$export$3ddd3b81fb8f4844);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_TUKUI_PROJECTFOLDERS", () => $4f0046e728a1a92c$export$a5cc5b09488bb38f);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_WEBSITE", () => $4f0046e728a1a92c$export$b491745c0a78a0a);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_WOWI_ID", () => $4f0046e728a1a92c$export$797d70f23cf50847);
$parcel$export($4f0046e728a1a92c$exports, "TOC_X_WAGO_ID", () => $4f0046e728a1a92c$export$e993c7b9ff539285);
const $4f0046e728a1a92c$export$9efb0d1b9b4d923b = 'Author';
const $4f0046e728a1a92c$export$d989c7edd72fb160 = 'Dependencies';
const $4f0046e728a1a92c$export$df02ec075fdd36f3 = 'Interface';
const $4f0046e728a1a92c$export$e17f8b790f736455 = 'Notes';
const $4f0046e728a1a92c$export$6e047e9e7f7da6a5 = 'RequiredDeps';
const $4f0046e728a1a92c$export$23cf79bfa1e2c92a = 'Title';
const $4f0046e728a1a92c$export$4016d8522ecdf92a = 'Version';
const $4f0046e728a1a92c$export$e04530d6a891f2e9 = 'Website';
const $4f0046e728a1a92c$export$6d541bc5c491dd66 = 'X-AddonProvider'; // Raider.IO
const $4f0046e728a1a92c$export$e2845edcd3a340ad = 'X-Category';
const $4f0046e728a1a92c$export$8f7efc5e0db11d27 = 'X-Curse-Project-ID'; // CurseForge
const $4f0046e728a1a92c$export$e30ccef561f5c153 = 'LoadOnDemand';
const $4f0046e728a1a92c$export$1b7233347279abf0 = 'X-Localizations';
const $4f0046e728a1a92c$export$8bf3fb4642bd7ef0 = 'X-Part-Of';
const $4f0046e728a1a92c$export$3ddd3b81fb8f4844 = 'X-Tukui-ProjectID'; // WowInterface
const $4f0046e728a1a92c$export$a5cc5b09488bb38f = 'X-Tukui-ProjectFolders'; // WowInterface
const $4f0046e728a1a92c$export$b491745c0a78a0a = 'X-Website';
const $4f0046e728a1a92c$export$797d70f23cf50847 = 'X-WoWI-ID'; // WowInterface
const $4f0046e728a1a92c$export$e993c7b9ff539285 = 'X-Wago-ID';


var $c76e181040acfb03$exports = {};




var $b9c8418edb6cb5ed$exports = {};
var $9c8090fefda3541c$exports = {};


var $5a9b8acff9195766$exports = {};



var $61263fd50ff3d86e$exports = {};


var $cbc9c6e75df4bf27$exports = {};


$parcel$exportWildcard($b9c8418edb6cb5ed$exports, $9c8090fefda3541c$exports);
$parcel$exportWildcard($b9c8418edb6cb5ed$exports, $5a9b8acff9195766$exports);
$parcel$exportWildcard($b9c8418edb6cb5ed$exports, $240fbc3f3e30fba8$exports);
$parcel$exportWildcard($b9c8418edb6cb5ed$exports, $61263fd50ff3d86e$exports);
$parcel$exportWildcard($b9c8418edb6cb5ed$exports, $cbc9c6e75df4bf27$exports);



$parcel$exportWildcard(module.exports, $d505444d61c0b9b9$exports);
$parcel$exportWildcard(module.exports, $8c2094342e06e0ec$exports);
$parcel$exportWildcard(module.exports, $762712d8f2726127$exports);
$parcel$exportWildcard(module.exports, $4f0046e728a1a92c$exports);
$parcel$exportWildcard(module.exports, $c76e181040acfb03$exports);
$parcel$exportWildcard(module.exports, $faefaad95e5fcca0$exports);
$parcel$exportWildcard(module.exports, $d7167569386d0d4c$exports);
$parcel$exportWildcard(module.exports, $b9c8418edb6cb5ed$exports);
$parcel$exportWildcard(module.exports, $bca446977c7d12f1$exports);


//# sourceMappingURL=index.js.map
