29147 lines
		
	
	
		
			1.1 MiB
		
	
	
	
	
	
	
	
			
		
		
	
	
			29147 lines
		
	
	
		
			1.1 MiB
		
	
	
	
	
	
	
	
| var __create = Object.create;
 | |
| var __defProp = Object.defineProperty;
 | |
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
 | |
| var __getOwnPropNames = Object.getOwnPropertyNames;
 | |
| var __getProtoOf = Object.getPrototypeOf;
 | |
| var __hasOwnProp = Object.prototype.hasOwnProperty;
 | |
| var __typeError = (msg) => {
 | |
|   throw TypeError(msg);
 | |
| };
 | |
| var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
 | |
| var __commonJS = (cb, mod) => function __require() {
 | |
|   return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
 | |
| };
 | |
| var __export = (target, all) => {
 | |
|   for (var name in all)
 | |
|     __defProp(target, name, { get: all[name], enumerable: true });
 | |
| };
 | |
| var __copyProps = (to2, from2, except, desc) => {
 | |
|   if (from2 && typeof from2 === "object" || typeof from2 === "function") {
 | |
|     for (let key of __getOwnPropNames(from2))
 | |
|       if (!__hasOwnProp.call(to2, key) && key !== except)
 | |
|         __defProp(to2, key, { get: () => from2[key], enumerable: !(desc = __getOwnPropDesc(from2, key)) || desc.enumerable });
 | |
|   }
 | |
|   return to2;
 | |
| };
 | |
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
 | |
|   // If the importer is in node compatibility mode or this is not an ESM
 | |
|   // file that has been converted to a CommonJS file using a Babel-
 | |
|   // compatible transform (i.e. "__esModule" has not been set), then set
 | |
|   // "default" to the CommonJS "module.exports" for node compatibility.
 | |
|   isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
 | |
|   mod
 | |
| ));
 | |
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
 | |
| var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
 | |
| var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
 | |
| var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
 | |
| var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
 | |
| var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
 | |
| var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
 | |
| 
 | |
| // node_modules/.pnpm/moment@2.30.1/node_modules/moment/moment.js
 | |
| var require_moment = __commonJS({
 | |
|   "node_modules/.pnpm/moment@2.30.1/node_modules/moment/moment.js"(exports, module2) {
 | |
|     (function(global, factory) {
 | |
|       typeof exports === "object" && typeof module2 !== "undefined" ? module2.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.moment = factory();
 | |
|     })(exports, function() {
 | |
|       "use strict";
 | |
|       var hookCallback;
 | |
|       function hooks() {
 | |
|         return hookCallback.apply(null, arguments);
 | |
|       }
 | |
|       function setHookCallback(callback2) {
 | |
|         hookCallback = callback2;
 | |
|       }
 | |
|       function isArray2(input) {
 | |
|         return input instanceof Array || Object.prototype.toString.call(input) === "[object Array]";
 | |
|       }
 | |
|       function isObject2(input) {
 | |
|         return input != null && Object.prototype.toString.call(input) === "[object Object]";
 | |
|       }
 | |
|       function hasOwnProp(a2, b2) {
 | |
|         return Object.prototype.hasOwnProperty.call(a2, b2);
 | |
|       }
 | |
|       function isObjectEmpty(obj) {
 | |
|         if (Object.getOwnPropertyNames) {
 | |
|           return Object.getOwnPropertyNames(obj).length === 0;
 | |
|         } else {
 | |
|           var k;
 | |
|           for (k in obj) {
 | |
|             if (hasOwnProp(obj, k)) {
 | |
|               return false;
 | |
|             }
 | |
|           }
 | |
|           return true;
 | |
|         }
 | |
|       }
 | |
|       function isUndefined(input) {
 | |
|         return input === void 0;
 | |
|       }
 | |
|       function isNumber2(input) {
 | |
|         return typeof input === "number" || Object.prototype.toString.call(input) === "[object Number]";
 | |
|       }
 | |
|       function isDate(input) {
 | |
|         return input instanceof Date || Object.prototype.toString.call(input) === "[object Date]";
 | |
|       }
 | |
|       function map3(arr, fn2) {
 | |
|         var res = [], i2, arrLen = arr.length;
 | |
|         for (i2 = 0; i2 < arrLen; ++i2) {
 | |
|           res.push(fn2(arr[i2], i2));
 | |
|         }
 | |
|         return res;
 | |
|       }
 | |
|       function extend(a2, b2) {
 | |
|         for (var i2 in b2) {
 | |
|           if (hasOwnProp(b2, i2)) {
 | |
|             a2[i2] = b2[i2];
 | |
|           }
 | |
|         }
 | |
|         if (hasOwnProp(b2, "toString")) {
 | |
|           a2.toString = b2.toString;
 | |
|         }
 | |
|         if (hasOwnProp(b2, "valueOf")) {
 | |
|           a2.valueOf = b2.valueOf;
 | |
|         }
 | |
|         return a2;
 | |
|       }
 | |
|       function createUTC(input, format2, locale3, strict) {
 | |
|         return createLocalOrUTC(input, format2, locale3, strict, true).utc();
 | |
|       }
 | |
|       function defaultParsingFlags() {
 | |
|         return {
 | |
|           empty: false,
 | |
|           unusedTokens: [],
 | |
|           unusedInput: [],
 | |
|           overflow: -2,
 | |
|           charsLeftOver: 0,
 | |
|           nullInput: false,
 | |
|           invalidEra: null,
 | |
|           invalidMonth: null,
 | |
|           invalidFormat: false,
 | |
|           userInvalidated: false,
 | |
|           iso: false,
 | |
|           parsedDateParts: [],
 | |
|           era: null,
 | |
|           meridiem: null,
 | |
|           rfc2822: false,
 | |
|           weekdayMismatch: false
 | |
|         };
 | |
|       }
 | |
|       function getParsingFlags(m2) {
 | |
|         if (m2._pf == null) {
 | |
|           m2._pf = defaultParsingFlags();
 | |
|         }
 | |
|         return m2._pf;
 | |
|       }
 | |
|       var some;
 | |
|       if (Array.prototype.some) {
 | |
|         some = Array.prototype.some;
 | |
|       } else {
 | |
|         some = function(fun) {
 | |
|           var t3 = Object(this), len = t3.length >>> 0, i2;
 | |
|           for (i2 = 0; i2 < len; i2++) {
 | |
|             if (i2 in t3 && fun.call(this, t3[i2], i2, t3)) {
 | |
|               return true;
 | |
|             }
 | |
|           }
 | |
|           return false;
 | |
|         };
 | |
|       }
 | |
|       function isValid(m2) {
 | |
|         var flags = null, parsedParts = false, isNowValid = m2._d && !isNaN(m2._d.getTime());
 | |
|         if (isNowValid) {
 | |
|           flags = getParsingFlags(m2);
 | |
|           parsedParts = some.call(flags.parsedDateParts, function(i2) {
 | |
|             return i2 != null;
 | |
|           });
 | |
|           isNowValid = flags.overflow < 0 && !flags.empty && !flags.invalidEra && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || flags.meridiem && parsedParts);
 | |
|           if (m2._strict) {
 | |
|             isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === void 0;
 | |
|           }
 | |
|         }
 | |
|         if (Object.isFrozen == null || !Object.isFrozen(m2)) {
 | |
|           m2._isValid = isNowValid;
 | |
|         } else {
 | |
|           return isNowValid;
 | |
|         }
 | |
|         return m2._isValid;
 | |
|       }
 | |
|       function createInvalid(flags) {
 | |
|         var m2 = createUTC(NaN);
 | |
|         if (flags != null) {
 | |
|           extend(getParsingFlags(m2), flags);
 | |
|         } else {
 | |
|           getParsingFlags(m2).userInvalidated = true;
 | |
|         }
 | |
|         return m2;
 | |
|       }
 | |
|       var momentProperties = hooks.momentProperties = [], updateInProgress = false;
 | |
|       function copyConfig(to3, from3) {
 | |
|         var i2, prop, val, momentPropertiesLen = momentProperties.length;
 | |
|         if (!isUndefined(from3._isAMomentObject)) {
 | |
|           to3._isAMomentObject = from3._isAMomentObject;
 | |
|         }
 | |
|         if (!isUndefined(from3._i)) {
 | |
|           to3._i = from3._i;
 | |
|         }
 | |
|         if (!isUndefined(from3._f)) {
 | |
|           to3._f = from3._f;
 | |
|         }
 | |
|         if (!isUndefined(from3._l)) {
 | |
|           to3._l = from3._l;
 | |
|         }
 | |
|         if (!isUndefined(from3._strict)) {
 | |
|           to3._strict = from3._strict;
 | |
|         }
 | |
|         if (!isUndefined(from3._tzm)) {
 | |
|           to3._tzm = from3._tzm;
 | |
|         }
 | |
|         if (!isUndefined(from3._isUTC)) {
 | |
|           to3._isUTC = from3._isUTC;
 | |
|         }
 | |
|         if (!isUndefined(from3._offset)) {
 | |
|           to3._offset = from3._offset;
 | |
|         }
 | |
|         if (!isUndefined(from3._pf)) {
 | |
|           to3._pf = getParsingFlags(from3);
 | |
|         }
 | |
|         if (!isUndefined(from3._locale)) {
 | |
|           to3._locale = from3._locale;
 | |
|         }
 | |
|         if (momentPropertiesLen > 0) {
 | |
|           for (i2 = 0; i2 < momentPropertiesLen; i2++) {
 | |
|             prop = momentProperties[i2];
 | |
|             val = from3[prop];
 | |
|             if (!isUndefined(val)) {
 | |
|               to3[prop] = val;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         return to3;
 | |
|       }
 | |
|       function Moment3(config) {
 | |
|         copyConfig(this, config);
 | |
|         this._d = new Date(config._d != null ? config._d.getTime() : NaN);
 | |
|         if (!this.isValid()) {
 | |
|           this._d = /* @__PURE__ */ new Date(NaN);
 | |
|         }
 | |
|         if (updateInProgress === false) {
 | |
|           updateInProgress = true;
 | |
|           hooks.updateOffset(this);
 | |
|           updateInProgress = false;
 | |
|         }
 | |
|       }
 | |
|       function isMoment(obj) {
 | |
|         return obj instanceof Moment3 || obj != null && obj._isAMomentObject != null;
 | |
|       }
 | |
|       function warn(msg) {
 | |
|         if (hooks.suppressDeprecationWarnings === false && typeof console !== "undefined" && console.warn) {
 | |
|           console.warn("Deprecation warning: " + msg);
 | |
|         }
 | |
|       }
 | |
|       function deprecate(msg, fn2) {
 | |
|         var firstTime = true;
 | |
|         return extend(function() {
 | |
|           if (hooks.deprecationHandler != null) {
 | |
|             hooks.deprecationHandler(null, msg);
 | |
|           }
 | |
|           if (firstTime) {
 | |
|             var args = [], arg, i2, key, argLen = arguments.length;
 | |
|             for (i2 = 0; i2 < argLen; i2++) {
 | |
|               arg = "";
 | |
|               if (typeof arguments[i2] === "object") {
 | |
|                 arg += "\n[" + i2 + "] ";
 | |
|                 for (key in arguments[0]) {
 | |
|                   if (hasOwnProp(arguments[0], key)) {
 | |
|                     arg += key + ": " + arguments[0][key] + ", ";
 | |
|                   }
 | |
|                 }
 | |
|                 arg = arg.slice(0, -2);
 | |
|               } else {
 | |
|                 arg = arguments[i2];
 | |
|               }
 | |
|               args.push(arg);
 | |
|             }
 | |
|             warn(
 | |
|               msg + "\nArguments: " + Array.prototype.slice.call(args).join("") + "\n" + new Error().stack
 | |
|             );
 | |
|             firstTime = false;
 | |
|           }
 | |
|           return fn2.apply(this, arguments);
 | |
|         }, fn2);
 | |
|       }
 | |
|       var deprecations = {};
 | |
|       function deprecateSimple(name, msg) {
 | |
|         if (hooks.deprecationHandler != null) {
 | |
|           hooks.deprecationHandler(name, msg);
 | |
|         }
 | |
|         if (!deprecations[name]) {
 | |
|           warn(msg);
 | |
|           deprecations[name] = true;
 | |
|         }
 | |
|       }
 | |
|       hooks.suppressDeprecationWarnings = false;
 | |
|       hooks.deprecationHandler = null;
 | |
|       function isFunction2(input) {
 | |
|         return typeof Function !== "undefined" && input instanceof Function || Object.prototype.toString.call(input) === "[object Function]";
 | |
|       }
 | |
|       function set2(config) {
 | |
|         var prop, i2;
 | |
|         for (i2 in config) {
 | |
|           if (hasOwnProp(config, i2)) {
 | |
|             prop = config[i2];
 | |
|             if (isFunction2(prop)) {
 | |
|               this[i2] = prop;
 | |
|             } else {
 | |
|               this["_" + i2] = prop;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         this._config = config;
 | |
|         this._dayOfMonthOrdinalParseLenient = new RegExp(
 | |
|           (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + "|" + /\d{1,2}/.source
 | |
|         );
 | |
|       }
 | |
|       function mergeConfigs(parentConfig, childConfig) {
 | |
|         var res = extend({}, parentConfig), prop;
 | |
|         for (prop in childConfig) {
 | |
|           if (hasOwnProp(childConfig, prop)) {
 | |
|             if (isObject2(parentConfig[prop]) && isObject2(childConfig[prop])) {
 | |
|               res[prop] = {};
 | |
|               extend(res[prop], parentConfig[prop]);
 | |
|               extend(res[prop], childConfig[prop]);
 | |
|             } else if (childConfig[prop] != null) {
 | |
|               res[prop] = childConfig[prop];
 | |
|             } else {
 | |
|               delete res[prop];
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         for (prop in parentConfig) {
 | |
|           if (hasOwnProp(parentConfig, prop) && !hasOwnProp(childConfig, prop) && isObject2(parentConfig[prop])) {
 | |
|             res[prop] = extend({}, res[prop]);
 | |
|           }
 | |
|         }
 | |
|         return res;
 | |
|       }
 | |
|       function Locale(config) {
 | |
|         if (config != null) {
 | |
|           this.set(config);
 | |
|         }
 | |
|       }
 | |
|       var keys;
 | |
|       if (Object.keys) {
 | |
|         keys = Object.keys;
 | |
|       } else {
 | |
|         keys = function(obj) {
 | |
|           var i2, res = [];
 | |
|           for (i2 in obj) {
 | |
|             if (hasOwnProp(obj, i2)) {
 | |
|               res.push(i2);
 | |
|             }
 | |
|           }
 | |
|           return res;
 | |
|         };
 | |
|       }
 | |
|       var defaultCalendar = {
 | |
|         sameDay: "[Today at] LT",
 | |
|         nextDay: "[Tomorrow at] LT",
 | |
|         nextWeek: "dddd [at] LT",
 | |
|         lastDay: "[Yesterday at] LT",
 | |
|         lastWeek: "[Last] dddd [at] LT",
 | |
|         sameElse: "L"
 | |
|       };
 | |
|       function calendar(key, mom, now3) {
 | |
|         var output = this._calendar[key] || this._calendar["sameElse"];
 | |
|         return isFunction2(output) ? output.call(mom, now3) : output;
 | |
|       }
 | |
|       function zeroFill(number, targetLength, forceSign) {
 | |
|         var absNumber = "" + Math.abs(number), zerosToFill = targetLength - absNumber.length, sign3 = number >= 0;
 | |
|         return (sign3 ? forceSign ? "+" : "" : "-") + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
 | |
|       }
 | |
|       var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g, localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, formatFunctions = {}, formatTokenFunctions = {};
 | |
|       function addFormatToken(token2, padded, ordinal2, callback2) {
 | |
|         var func = callback2;
 | |
|         if (typeof callback2 === "string") {
 | |
|           func = function() {
 | |
|             return this[callback2]();
 | |
|           };
 | |
|         }
 | |
|         if (token2) {
 | |
|           formatTokenFunctions[token2] = func;
 | |
|         }
 | |
|         if (padded) {
 | |
|           formatTokenFunctions[padded[0]] = function() {
 | |
|             return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
 | |
|           };
 | |
|         }
 | |
|         if (ordinal2) {
 | |
|           formatTokenFunctions[ordinal2] = function() {
 | |
|             return this.localeData().ordinal(
 | |
|               func.apply(this, arguments),
 | |
|               token2
 | |
|             );
 | |
|           };
 | |
|         }
 | |
|       }
 | |
|       function removeFormattingTokens(input) {
 | |
|         if (input.match(/\[[\s\S]/)) {
 | |
|           return input.replace(/^\[|\]$/g, "");
 | |
|         }
 | |
|         return input.replace(/\\/g, "");
 | |
|       }
 | |
|       function makeFormatFunction(format2) {
 | |
|         var array = format2.match(formattingTokens), i2, length;
 | |
|         for (i2 = 0, length = array.length; i2 < length; i2++) {
 | |
|           if (formatTokenFunctions[array[i2]]) {
 | |
|             array[i2] = formatTokenFunctions[array[i2]];
 | |
|           } else {
 | |
|             array[i2] = removeFormattingTokens(array[i2]);
 | |
|           }
 | |
|         }
 | |
|         return function(mom) {
 | |
|           var output = "", i3;
 | |
|           for (i3 = 0; i3 < length; i3++) {
 | |
|             output += isFunction2(array[i3]) ? array[i3].call(mom, format2) : array[i3];
 | |
|           }
 | |
|           return output;
 | |
|         };
 | |
|       }
 | |
|       function formatMoment(m2, format2) {
 | |
|         if (!m2.isValid()) {
 | |
|           return m2.localeData().invalidDate();
 | |
|         }
 | |
|         format2 = expandFormat(format2, m2.localeData());
 | |
|         formatFunctions[format2] = formatFunctions[format2] || makeFormatFunction(format2);
 | |
|         return formatFunctions[format2](m2);
 | |
|       }
 | |
|       function expandFormat(format2, locale3) {
 | |
|         var i2 = 5;
 | |
|         function replaceLongDateFormatTokens(input) {
 | |
|           return locale3.longDateFormat(input) || input;
 | |
|         }
 | |
|         localFormattingTokens.lastIndex = 0;
 | |
|         while (i2 >= 0 && localFormattingTokens.test(format2)) {
 | |
|           format2 = format2.replace(
 | |
|             localFormattingTokens,
 | |
|             replaceLongDateFormatTokens
 | |
|           );
 | |
|           localFormattingTokens.lastIndex = 0;
 | |
|           i2 -= 1;
 | |
|         }
 | |
|         return format2;
 | |
|       }
 | |
|       var defaultLongDateFormat = {
 | |
|         LTS: "h:mm:ss A",
 | |
|         LT: "h:mm A",
 | |
|         L: "MM/DD/YYYY",
 | |
|         LL: "MMMM D, YYYY",
 | |
|         LLL: "MMMM D, YYYY h:mm A",
 | |
|         LLLL: "dddd, MMMM D, YYYY h:mm A"
 | |
|       };
 | |
|       function longDateFormat(key) {
 | |
|         var format2 = this._longDateFormat[key], formatUpper = this._longDateFormat[key.toUpperCase()];
 | |
|         if (format2 || !formatUpper) {
 | |
|           return format2;
 | |
|         }
 | |
|         this._longDateFormat[key] = formatUpper.match(formattingTokens).map(function(tok) {
 | |
|           if (tok === "MMMM" || tok === "MM" || tok === "DD" || tok === "dddd") {
 | |
|             return tok.slice(1);
 | |
|           }
 | |
|           return tok;
 | |
|         }).join("");
 | |
|         return this._longDateFormat[key];
 | |
|       }
 | |
|       var defaultInvalidDate = "Invalid date";
 | |
|       function invalidDate() {
 | |
|         return this._invalidDate;
 | |
|       }
 | |
|       var defaultOrdinal = "%d", defaultDayOfMonthOrdinalParse = /\d{1,2}/;
 | |
|       function ordinal(number) {
 | |
|         return this._ordinal.replace("%d", number);
 | |
|       }
 | |
|       var defaultRelativeTime = {
 | |
|         future: "in %s",
 | |
|         past: "%s ago",
 | |
|         s: "a few seconds",
 | |
|         ss: "%d seconds",
 | |
|         m: "a minute",
 | |
|         mm: "%d minutes",
 | |
|         h: "an hour",
 | |
|         hh: "%d hours",
 | |
|         d: "a day",
 | |
|         dd: "%d days",
 | |
|         w: "a week",
 | |
|         ww: "%d weeks",
 | |
|         M: "a month",
 | |
|         MM: "%d months",
 | |
|         y: "a year",
 | |
|         yy: "%d years"
 | |
|       };
 | |
|       function relativeTime(number, withoutSuffix, string, isFuture) {
 | |
|         var output = this._relativeTime[string];
 | |
|         return isFunction2(output) ? output(number, withoutSuffix, string, isFuture) : output.replace(/%d/i, number);
 | |
|       }
 | |
|       function pastFuture(diff2, output) {
 | |
|         var format2 = this._relativeTime[diff2 > 0 ? "future" : "past"];
 | |
|         return isFunction2(format2) ? format2(output) : format2.replace(/%s/i, output);
 | |
|       }
 | |
|       var aliases = {
 | |
|         D: "date",
 | |
|         dates: "date",
 | |
|         date: "date",
 | |
|         d: "day",
 | |
|         days: "day",
 | |
|         day: "day",
 | |
|         e: "weekday",
 | |
|         weekdays: "weekday",
 | |
|         weekday: "weekday",
 | |
|         E: "isoWeekday",
 | |
|         isoweekdays: "isoWeekday",
 | |
|         isoweekday: "isoWeekday",
 | |
|         DDD: "dayOfYear",
 | |
|         dayofyears: "dayOfYear",
 | |
|         dayofyear: "dayOfYear",
 | |
|         h: "hour",
 | |
|         hours: "hour",
 | |
|         hour: "hour",
 | |
|         ms: "millisecond",
 | |
|         milliseconds: "millisecond",
 | |
|         millisecond: "millisecond",
 | |
|         m: "minute",
 | |
|         minutes: "minute",
 | |
|         minute: "minute",
 | |
|         M: "month",
 | |
|         months: "month",
 | |
|         month: "month",
 | |
|         Q: "quarter",
 | |
|         quarters: "quarter",
 | |
|         quarter: "quarter",
 | |
|         s: "second",
 | |
|         seconds: "second",
 | |
|         second: "second",
 | |
|         gg: "weekYear",
 | |
|         weekyears: "weekYear",
 | |
|         weekyear: "weekYear",
 | |
|         GG: "isoWeekYear",
 | |
|         isoweekyears: "isoWeekYear",
 | |
|         isoweekyear: "isoWeekYear",
 | |
|         w: "week",
 | |
|         weeks: "week",
 | |
|         week: "week",
 | |
|         W: "isoWeek",
 | |
|         isoweeks: "isoWeek",
 | |
|         isoweek: "isoWeek",
 | |
|         y: "year",
 | |
|         years: "year",
 | |
|         year: "year"
 | |
|       };
 | |
|       function normalizeUnits(units) {
 | |
|         return typeof units === "string" ? aliases[units] || aliases[units.toLowerCase()] : void 0;
 | |
|       }
 | |
|       function normalizeObjectUnits(inputObject) {
 | |
|         var normalizedInput = {}, normalizedProp, prop;
 | |
|         for (prop in inputObject) {
 | |
|           if (hasOwnProp(inputObject, prop)) {
 | |
|             normalizedProp = normalizeUnits(prop);
 | |
|             if (normalizedProp) {
 | |
|               normalizedInput[normalizedProp] = inputObject[prop];
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         return normalizedInput;
 | |
|       }
 | |
|       var priorities = {
 | |
|         date: 9,
 | |
|         day: 11,
 | |
|         weekday: 11,
 | |
|         isoWeekday: 11,
 | |
|         dayOfYear: 4,
 | |
|         hour: 13,
 | |
|         millisecond: 16,
 | |
|         minute: 14,
 | |
|         month: 8,
 | |
|         quarter: 7,
 | |
|         second: 15,
 | |
|         weekYear: 1,
 | |
|         isoWeekYear: 1,
 | |
|         week: 5,
 | |
|         isoWeek: 5,
 | |
|         year: 1
 | |
|       };
 | |
|       function getPrioritizedUnits(unitsObj) {
 | |
|         var units = [], u2;
 | |
|         for (u2 in unitsObj) {
 | |
|           if (hasOwnProp(unitsObj, u2)) {
 | |
|             units.push({ unit: u2, priority: priorities[u2] });
 | |
|           }
 | |
|         }
 | |
|         units.sort(function(a2, b2) {
 | |
|           return a2.priority - b2.priority;
 | |
|         });
 | |
|         return units;
 | |
|       }
 | |
|       var match1 = /\d/, match2 = /\d\d/, match3 = /\d{3}/, match4 = /\d{4}/, match6 = /[+-]?\d{6}/, match1to2 = /\d\d?/, match3to4 = /\d\d\d\d?/, match5to6 = /\d\d\d\d\d\d?/, match1to3 = /\d{1,3}/, match1to4 = /\d{1,4}/, match1to6 = /[+-]?\d{1,6}/, matchUnsigned = /\d+/, matchSigned = /[+-]?\d+/, matchOffset = /Z|[+-]\d\d:?\d\d/gi, matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, matchTimestamp = /[+-]?\d+(\.\d{1,3})?/, matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i, match1to2NoLeadingZero = /^[1-9]\d?/, match1to2HasZero = /^([1-9]\d|\d)/, regexes;
 | |
|       regexes = {};
 | |
|       function addRegexToken(token2, regex, strictRegex) {
 | |
|         regexes[token2] = isFunction2(regex) ? regex : function(isStrict, localeData2) {
 | |
|           return isStrict && strictRegex ? strictRegex : regex;
 | |
|         };
 | |
|       }
 | |
|       function getParseRegexForToken(token2, config) {
 | |
|         if (!hasOwnProp(regexes, token2)) {
 | |
|           return new RegExp(unescapeFormat(token2));
 | |
|         }
 | |
|         return regexes[token2](config._strict, config._locale);
 | |
|       }
 | |
|       function unescapeFormat(s2) {
 | |
|         return regexEscape(
 | |
|           s2.replace("\\", "").replace(
 | |
|             /\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,
 | |
|             function(matched, p1, p2, p3, p4) {
 | |
|               return p1 || p2 || p3 || p4;
 | |
|             }
 | |
|           )
 | |
|         );
 | |
|       }
 | |
|       function regexEscape(s2) {
 | |
|         return s2.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
 | |
|       }
 | |
|       function absFloor(number) {
 | |
|         if (number < 0) {
 | |
|           return Math.ceil(number) || 0;
 | |
|         } else {
 | |
|           return Math.floor(number);
 | |
|         }
 | |
|       }
 | |
|       function toInt(argumentForCoercion) {
 | |
|         var coercedNumber = +argumentForCoercion, value = 0;
 | |
|         if (coercedNumber !== 0 && isFinite(coercedNumber)) {
 | |
|           value = absFloor(coercedNumber);
 | |
|         }
 | |
|         return value;
 | |
|       }
 | |
|       var tokens = {};
 | |
|       function addParseToken(token2, callback2) {
 | |
|         var i2, func = callback2, tokenLen;
 | |
|         if (typeof token2 === "string") {
 | |
|           token2 = [token2];
 | |
|         }
 | |
|         if (isNumber2(callback2)) {
 | |
|           func = function(input, array) {
 | |
|             array[callback2] = toInt(input);
 | |
|           };
 | |
|         }
 | |
|         tokenLen = token2.length;
 | |
|         for (i2 = 0; i2 < tokenLen; i2++) {
 | |
|           tokens[token2[i2]] = func;
 | |
|         }
 | |
|       }
 | |
|       function addWeekParseToken(token2, callback2) {
 | |
|         addParseToken(token2, function(input, array, config, token3) {
 | |
|           config._w = config._w || {};
 | |
|           callback2(input, config._w, config, token3);
 | |
|         });
 | |
|       }
 | |
|       function addTimeToArrayFromToken(token2, input, config) {
 | |
|         if (input != null && hasOwnProp(tokens, token2)) {
 | |
|           tokens[token2](input, config._a, config, token2);
 | |
|         }
 | |
|       }
 | |
|       function isLeapYear(year) {
 | |
|         return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
 | |
|       }
 | |
|       var YEAR = 0, MONTH = 1, DATE = 2, HOUR = 3, MINUTE = 4, SECOND = 5, MILLISECOND = 6, WEEK = 7, WEEKDAY = 8;
 | |
|       addFormatToken("Y", 0, 0, function() {
 | |
|         var y2 = this.year();
 | |
|         return y2 <= 9999 ? zeroFill(y2, 4) : "+" + y2;
 | |
|       });
 | |
|       addFormatToken(0, ["YY", 2], 0, function() {
 | |
|         return this.year() % 100;
 | |
|       });
 | |
|       addFormatToken(0, ["YYYY", 4], 0, "year");
 | |
|       addFormatToken(0, ["YYYYY", 5], 0, "year");
 | |
|       addFormatToken(0, ["YYYYYY", 6, true], 0, "year");
 | |
|       addRegexToken("Y", matchSigned);
 | |
|       addRegexToken("YY", match1to2, match2);
 | |
|       addRegexToken("YYYY", match1to4, match4);
 | |
|       addRegexToken("YYYYY", match1to6, match6);
 | |
|       addRegexToken("YYYYYY", match1to6, match6);
 | |
|       addParseToken(["YYYYY", "YYYYYY"], YEAR);
 | |
|       addParseToken("YYYY", function(input, array) {
 | |
|         array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
 | |
|       });
 | |
|       addParseToken("YY", function(input, array) {
 | |
|         array[YEAR] = hooks.parseTwoDigitYear(input);
 | |
|       });
 | |
|       addParseToken("Y", function(input, array) {
 | |
|         array[YEAR] = parseInt(input, 10);
 | |
|       });
 | |
|       function daysInYear(year) {
 | |
|         return isLeapYear(year) ? 366 : 365;
 | |
|       }
 | |
|       hooks.parseTwoDigitYear = function(input) {
 | |
|         return toInt(input) + (toInt(input) > 68 ? 1900 : 2e3);
 | |
|       };
 | |
|       var getSetYear = makeGetSet("FullYear", true);
 | |
|       function getIsLeapYear() {
 | |
|         return isLeapYear(this.year());
 | |
|       }
 | |
|       function makeGetSet(unit, keepTime) {
 | |
|         return function(value) {
 | |
|           if (value != null) {
 | |
|             set$1(this, unit, value);
 | |
|             hooks.updateOffset(this, keepTime);
 | |
|             return this;
 | |
|           } else {
 | |
|             return get(this, unit);
 | |
|           }
 | |
|         };
 | |
|       }
 | |
|       function get(mom, unit) {
 | |
|         if (!mom.isValid()) {
 | |
|           return NaN;
 | |
|         }
 | |
|         var d2 = mom._d, isUTC = mom._isUTC;
 | |
|         switch (unit) {
 | |
|           case "Milliseconds":
 | |
|             return isUTC ? d2.getUTCMilliseconds() : d2.getMilliseconds();
 | |
|           case "Seconds":
 | |
|             return isUTC ? d2.getUTCSeconds() : d2.getSeconds();
 | |
|           case "Minutes":
 | |
|             return isUTC ? d2.getUTCMinutes() : d2.getMinutes();
 | |
|           case "Hours":
 | |
|             return isUTC ? d2.getUTCHours() : d2.getHours();
 | |
|           case "Date":
 | |
|             return isUTC ? d2.getUTCDate() : d2.getDate();
 | |
|           case "Day":
 | |
|             return isUTC ? d2.getUTCDay() : d2.getDay();
 | |
|           case "Month":
 | |
|             return isUTC ? d2.getUTCMonth() : d2.getMonth();
 | |
|           case "FullYear":
 | |
|             return isUTC ? d2.getUTCFullYear() : d2.getFullYear();
 | |
|           default:
 | |
|             return NaN;
 | |
|         }
 | |
|       }
 | |
|       function set$1(mom, unit, value) {
 | |
|         var d2, isUTC, year, month, date;
 | |
|         if (!mom.isValid() || isNaN(value)) {
 | |
|           return;
 | |
|         }
 | |
|         d2 = mom._d;
 | |
|         isUTC = mom._isUTC;
 | |
|         switch (unit) {
 | |
|           case "Milliseconds":
 | |
|             return void (isUTC ? d2.setUTCMilliseconds(value) : d2.setMilliseconds(value));
 | |
|           case "Seconds":
 | |
|             return void (isUTC ? d2.setUTCSeconds(value) : d2.setSeconds(value));
 | |
|           case "Minutes":
 | |
|             return void (isUTC ? d2.setUTCMinutes(value) : d2.setMinutes(value));
 | |
|           case "Hours":
 | |
|             return void (isUTC ? d2.setUTCHours(value) : d2.setHours(value));
 | |
|           case "Date":
 | |
|             return void (isUTC ? d2.setUTCDate(value) : d2.setDate(value));
 | |
|           // case 'Day': // Not real
 | |
|           //    return void (isUTC ? d.setUTCDay(value) : d.setDay(value));
 | |
|           // case 'Month': // Not used because we need to pass two variables
 | |
|           //     return void (isUTC ? d.setUTCMonth(value) : d.setMonth(value));
 | |
|           case "FullYear":
 | |
|             break;
 | |
|           // See below ...
 | |
|           default:
 | |
|             return;
 | |
|         }
 | |
|         year = value;
 | |
|         month = mom.month();
 | |
|         date = mom.date();
 | |
|         date = date === 29 && month === 1 && !isLeapYear(year) ? 28 : date;
 | |
|         void (isUTC ? d2.setUTCFullYear(year, month, date) : d2.setFullYear(year, month, date));
 | |
|       }
 | |
|       function stringGet(units) {
 | |
|         units = normalizeUnits(units);
 | |
|         if (isFunction2(this[units])) {
 | |
|           return this[units]();
 | |
|         }
 | |
|         return this;
 | |
|       }
 | |
|       function stringSet(units, value) {
 | |
|         if (typeof units === "object") {
 | |
|           units = normalizeObjectUnits(units);
 | |
|           var prioritized = getPrioritizedUnits(units), i2, prioritizedLen = prioritized.length;
 | |
|           for (i2 = 0; i2 < prioritizedLen; i2++) {
 | |
|             this[prioritized[i2].unit](units[prioritized[i2].unit]);
 | |
|           }
 | |
|         } else {
 | |
|           units = normalizeUnits(units);
 | |
|           if (isFunction2(this[units])) {
 | |
|             return this[units](value);
 | |
|           }
 | |
|         }
 | |
|         return this;
 | |
|       }
 | |
|       function mod(n2, x2) {
 | |
|         return (n2 % x2 + x2) % x2;
 | |
|       }
 | |
|       var indexOf;
 | |
|       if (Array.prototype.indexOf) {
 | |
|         indexOf = Array.prototype.indexOf;
 | |
|       } else {
 | |
|         indexOf = function(o2) {
 | |
|           var i2;
 | |
|           for (i2 = 0; i2 < this.length; ++i2) {
 | |
|             if (this[i2] === o2) {
 | |
|               return i2;
 | |
|             }
 | |
|           }
 | |
|           return -1;
 | |
|         };
 | |
|       }
 | |
|       function daysInMonth(year, month) {
 | |
|         if (isNaN(year) || isNaN(month)) {
 | |
|           return NaN;
 | |
|         }
 | |
|         var modMonth = mod(month, 12);
 | |
|         year += (month - modMonth) / 12;
 | |
|         return modMonth === 1 ? isLeapYear(year) ? 29 : 28 : 31 - modMonth % 7 % 2;
 | |
|       }
 | |
|       addFormatToken("M", ["MM", 2], "Mo", function() {
 | |
|         return this.month() + 1;
 | |
|       });
 | |
|       addFormatToken("MMM", 0, 0, function(format2) {
 | |
|         return this.localeData().monthsShort(this, format2);
 | |
|       });
 | |
|       addFormatToken("MMMM", 0, 0, function(format2) {
 | |
|         return this.localeData().months(this, format2);
 | |
|       });
 | |
|       addRegexToken("M", match1to2, match1to2NoLeadingZero);
 | |
|       addRegexToken("MM", match1to2, match2);
 | |
|       addRegexToken("MMM", function(isStrict, locale3) {
 | |
|         return locale3.monthsShortRegex(isStrict);
 | |
|       });
 | |
|       addRegexToken("MMMM", function(isStrict, locale3) {
 | |
|         return locale3.monthsRegex(isStrict);
 | |
|       });
 | |
|       addParseToken(["M", "MM"], function(input, array) {
 | |
|         array[MONTH] = toInt(input) - 1;
 | |
|       });
 | |
|       addParseToken(["MMM", "MMMM"], function(input, array, config, token2) {
 | |
|         var month = config._locale.monthsParse(input, token2, config._strict);
 | |
|         if (month != null) {
 | |
|           array[MONTH] = month;
 | |
|         } else {
 | |
|           getParsingFlags(config).invalidMonth = input;
 | |
|         }
 | |
|       });
 | |
|       var defaultLocaleMonths = "January_February_March_April_May_June_July_August_September_October_November_December".split(
 | |
|         "_"
 | |
|       ), defaultLocaleMonthsShort = "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/, defaultMonthsShortRegex = matchWord, defaultMonthsRegex = matchWord;
 | |
|       function localeMonths(m2, format2) {
 | |
|         if (!m2) {
 | |
|           return isArray2(this._months) ? this._months : this._months["standalone"];
 | |
|         }
 | |
|         return isArray2(this._months) ? this._months[m2.month()] : this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format2) ? "format" : "standalone"][m2.month()];
 | |
|       }
 | |
|       function localeMonthsShort(m2, format2) {
 | |
|         if (!m2) {
 | |
|           return isArray2(this._monthsShort) ? this._monthsShort : this._monthsShort["standalone"];
 | |
|         }
 | |
|         return isArray2(this._monthsShort) ? this._monthsShort[m2.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format2) ? "format" : "standalone"][m2.month()];
 | |
|       }
 | |
|       function handleStrictParse(monthName, format2, strict) {
 | |
|         var i2, ii, mom, llc = monthName.toLocaleLowerCase();
 | |
|         if (!this._monthsParse) {
 | |
|           this._monthsParse = [];
 | |
|           this._longMonthsParse = [];
 | |
|           this._shortMonthsParse = [];
 | |
|           for (i2 = 0; i2 < 12; ++i2) {
 | |
|             mom = createUTC([2e3, i2]);
 | |
|             this._shortMonthsParse[i2] = this.monthsShort(
 | |
|               mom,
 | |
|               ""
 | |
|             ).toLocaleLowerCase();
 | |
|             this._longMonthsParse[i2] = this.months(mom, "").toLocaleLowerCase();
 | |
|           }
 | |
|         }
 | |
|         if (strict) {
 | |
|           if (format2 === "MMM") {
 | |
|             ii = indexOf.call(this._shortMonthsParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           } else {
 | |
|             ii = indexOf.call(this._longMonthsParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           }
 | |
|         } else {
 | |
|           if (format2 === "MMM") {
 | |
|             ii = indexOf.call(this._shortMonthsParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._longMonthsParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           } else {
 | |
|             ii = indexOf.call(this._longMonthsParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._shortMonthsParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       function localeMonthsParse(monthName, format2, strict) {
 | |
|         var i2, mom, regex;
 | |
|         if (this._monthsParseExact) {
 | |
|           return handleStrictParse.call(this, monthName, format2, strict);
 | |
|         }
 | |
|         if (!this._monthsParse) {
 | |
|           this._monthsParse = [];
 | |
|           this._longMonthsParse = [];
 | |
|           this._shortMonthsParse = [];
 | |
|         }
 | |
|         for (i2 = 0; i2 < 12; i2++) {
 | |
|           mom = createUTC([2e3, i2]);
 | |
|           if (strict && !this._longMonthsParse[i2]) {
 | |
|             this._longMonthsParse[i2] = new RegExp(
 | |
|               "^" + this.months(mom, "").replace(".", "") + "$",
 | |
|               "i"
 | |
|             );
 | |
|             this._shortMonthsParse[i2] = new RegExp(
 | |
|               "^" + this.monthsShort(mom, "").replace(".", "") + "$",
 | |
|               "i"
 | |
|             );
 | |
|           }
 | |
|           if (!strict && !this._monthsParse[i2]) {
 | |
|             regex = "^" + this.months(mom, "") + "|^" + this.monthsShort(mom, "");
 | |
|             this._monthsParse[i2] = new RegExp(regex.replace(".", ""), "i");
 | |
|           }
 | |
|           if (strict && format2 === "MMMM" && this._longMonthsParse[i2].test(monthName)) {
 | |
|             return i2;
 | |
|           } else if (strict && format2 === "MMM" && this._shortMonthsParse[i2].test(monthName)) {
 | |
|             return i2;
 | |
|           } else if (!strict && this._monthsParse[i2].test(monthName)) {
 | |
|             return i2;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       function setMonth(mom, value) {
 | |
|         if (!mom.isValid()) {
 | |
|           return mom;
 | |
|         }
 | |
|         if (typeof value === "string") {
 | |
|           if (/^\d+$/.test(value)) {
 | |
|             value = toInt(value);
 | |
|           } else {
 | |
|             value = mom.localeData().monthsParse(value);
 | |
|             if (!isNumber2(value)) {
 | |
|               return mom;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         var month = value, date = mom.date();
 | |
|         date = date < 29 ? date : Math.min(date, daysInMonth(mom.year(), month));
 | |
|         void (mom._isUTC ? mom._d.setUTCMonth(month, date) : mom._d.setMonth(month, date));
 | |
|         return mom;
 | |
|       }
 | |
|       function getSetMonth(value) {
 | |
|         if (value != null) {
 | |
|           setMonth(this, value);
 | |
|           hooks.updateOffset(this, true);
 | |
|           return this;
 | |
|         } else {
 | |
|           return get(this, "Month");
 | |
|         }
 | |
|       }
 | |
|       function getDaysInMonth() {
 | |
|         return daysInMonth(this.year(), this.month());
 | |
|       }
 | |
|       function monthsShortRegex(isStrict) {
 | |
|         if (this._monthsParseExact) {
 | |
|           if (!hasOwnProp(this, "_monthsRegex")) {
 | |
|             computeMonthsParse.call(this);
 | |
|           }
 | |
|           if (isStrict) {
 | |
|             return this._monthsShortStrictRegex;
 | |
|           } else {
 | |
|             return this._monthsShortRegex;
 | |
|           }
 | |
|         } else {
 | |
|           if (!hasOwnProp(this, "_monthsShortRegex")) {
 | |
|             this._monthsShortRegex = defaultMonthsShortRegex;
 | |
|           }
 | |
|           return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex;
 | |
|         }
 | |
|       }
 | |
|       function monthsRegex(isStrict) {
 | |
|         if (this._monthsParseExact) {
 | |
|           if (!hasOwnProp(this, "_monthsRegex")) {
 | |
|             computeMonthsParse.call(this);
 | |
|           }
 | |
|           if (isStrict) {
 | |
|             return this._monthsStrictRegex;
 | |
|           } else {
 | |
|             return this._monthsRegex;
 | |
|           }
 | |
|         } else {
 | |
|           if (!hasOwnProp(this, "_monthsRegex")) {
 | |
|             this._monthsRegex = defaultMonthsRegex;
 | |
|           }
 | |
|           return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex;
 | |
|         }
 | |
|       }
 | |
|       function computeMonthsParse() {
 | |
|         function cmpLenRev(a2, b2) {
 | |
|           return b2.length - a2.length;
 | |
|         }
 | |
|         var shortPieces = [], longPieces = [], mixedPieces = [], i2, mom, shortP, longP;
 | |
|         for (i2 = 0; i2 < 12; i2++) {
 | |
|           mom = createUTC([2e3, i2]);
 | |
|           shortP = regexEscape(this.monthsShort(mom, ""));
 | |
|           longP = regexEscape(this.months(mom, ""));
 | |
|           shortPieces.push(shortP);
 | |
|           longPieces.push(longP);
 | |
|           mixedPieces.push(longP);
 | |
|           mixedPieces.push(shortP);
 | |
|         }
 | |
|         shortPieces.sort(cmpLenRev);
 | |
|         longPieces.sort(cmpLenRev);
 | |
|         mixedPieces.sort(cmpLenRev);
 | |
|         this._monthsRegex = new RegExp("^(" + mixedPieces.join("|") + ")", "i");
 | |
|         this._monthsShortRegex = this._monthsRegex;
 | |
|         this._monthsStrictRegex = new RegExp(
 | |
|           "^(" + longPieces.join("|") + ")",
 | |
|           "i"
 | |
|         );
 | |
|         this._monthsShortStrictRegex = new RegExp(
 | |
|           "^(" + shortPieces.join("|") + ")",
 | |
|           "i"
 | |
|         );
 | |
|       }
 | |
|       function createDate(y2, m2, d2, h6, M2, s2, ms) {
 | |
|         var date;
 | |
|         if (y2 < 100 && y2 >= 0) {
 | |
|           date = new Date(y2 + 400, m2, d2, h6, M2, s2, ms);
 | |
|           if (isFinite(date.getFullYear())) {
 | |
|             date.setFullYear(y2);
 | |
|           }
 | |
|         } else {
 | |
|           date = new Date(y2, m2, d2, h6, M2, s2, ms);
 | |
|         }
 | |
|         return date;
 | |
|       }
 | |
|       function createUTCDate(y2) {
 | |
|         var date, args;
 | |
|         if (y2 < 100 && y2 >= 0) {
 | |
|           args = Array.prototype.slice.call(arguments);
 | |
|           args[0] = y2 + 400;
 | |
|           date = new Date(Date.UTC.apply(null, args));
 | |
|           if (isFinite(date.getUTCFullYear())) {
 | |
|             date.setUTCFullYear(y2);
 | |
|           }
 | |
|         } else {
 | |
|           date = new Date(Date.UTC.apply(null, arguments));
 | |
|         }
 | |
|         return date;
 | |
|       }
 | |
|       function firstWeekOffset(year, dow, doy) {
 | |
|         var fwd = 7 + dow - doy, fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
 | |
|         return -fwdlw + fwd - 1;
 | |
|       }
 | |
|       function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
 | |
|         var localWeekday = (7 + weekday - dow) % 7, weekOffset = firstWeekOffset(year, dow, doy), dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, resYear, resDayOfYear;
 | |
|         if (dayOfYear <= 0) {
 | |
|           resYear = year - 1;
 | |
|           resDayOfYear = daysInYear(resYear) + dayOfYear;
 | |
|         } else if (dayOfYear > daysInYear(year)) {
 | |
|           resYear = year + 1;
 | |
|           resDayOfYear = dayOfYear - daysInYear(year);
 | |
|         } else {
 | |
|           resYear = year;
 | |
|           resDayOfYear = dayOfYear;
 | |
|         }
 | |
|         return {
 | |
|           year: resYear,
 | |
|           dayOfYear: resDayOfYear
 | |
|         };
 | |
|       }
 | |
|       function weekOfYear(mom, dow, doy) {
 | |
|         var weekOffset = firstWeekOffset(mom.year(), dow, doy), week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, resWeek, resYear;
 | |
|         if (week < 1) {
 | |
|           resYear = mom.year() - 1;
 | |
|           resWeek = week + weeksInYear(resYear, dow, doy);
 | |
|         } else if (week > weeksInYear(mom.year(), dow, doy)) {
 | |
|           resWeek = week - weeksInYear(mom.year(), dow, doy);
 | |
|           resYear = mom.year() + 1;
 | |
|         } else {
 | |
|           resYear = mom.year();
 | |
|           resWeek = week;
 | |
|         }
 | |
|         return {
 | |
|           week: resWeek,
 | |
|           year: resYear
 | |
|         };
 | |
|       }
 | |
|       function weeksInYear(year, dow, doy) {
 | |
|         var weekOffset = firstWeekOffset(year, dow, doy), weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
 | |
|         return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
 | |
|       }
 | |
|       addFormatToken("w", ["ww", 2], "wo", "week");
 | |
|       addFormatToken("W", ["WW", 2], "Wo", "isoWeek");
 | |
|       addRegexToken("w", match1to2, match1to2NoLeadingZero);
 | |
|       addRegexToken("ww", match1to2, match2);
 | |
|       addRegexToken("W", match1to2, match1to2NoLeadingZero);
 | |
|       addRegexToken("WW", match1to2, match2);
 | |
|       addWeekParseToken(
 | |
|         ["w", "ww", "W", "WW"],
 | |
|         function(input, week, config, token2) {
 | |
|           week[token2.substr(0, 1)] = toInt(input);
 | |
|         }
 | |
|       );
 | |
|       function localeWeek(mom) {
 | |
|         return weekOfYear(mom, this._week.dow, this._week.doy).week;
 | |
|       }
 | |
|       var defaultLocaleWeek = {
 | |
|         dow: 0,
 | |
|         // Sunday is the first day of the week.
 | |
|         doy: 6
 | |
|         // The week that contains Jan 6th is the first week of the year.
 | |
|       };
 | |
|       function localeFirstDayOfWeek() {
 | |
|         return this._week.dow;
 | |
|       }
 | |
|       function localeFirstDayOfYear() {
 | |
|         return this._week.doy;
 | |
|       }
 | |
|       function getSetWeek(input) {
 | |
|         var week = this.localeData().week(this);
 | |
|         return input == null ? week : this.add((input - week) * 7, "d");
 | |
|       }
 | |
|       function getSetISOWeek(input) {
 | |
|         var week = weekOfYear(this, 1, 4).week;
 | |
|         return input == null ? week : this.add((input - week) * 7, "d");
 | |
|       }
 | |
|       addFormatToken("d", 0, "do", "day");
 | |
|       addFormatToken("dd", 0, 0, function(format2) {
 | |
|         return this.localeData().weekdaysMin(this, format2);
 | |
|       });
 | |
|       addFormatToken("ddd", 0, 0, function(format2) {
 | |
|         return this.localeData().weekdaysShort(this, format2);
 | |
|       });
 | |
|       addFormatToken("dddd", 0, 0, function(format2) {
 | |
|         return this.localeData().weekdays(this, format2);
 | |
|       });
 | |
|       addFormatToken("e", 0, 0, "weekday");
 | |
|       addFormatToken("E", 0, 0, "isoWeekday");
 | |
|       addRegexToken("d", match1to2);
 | |
|       addRegexToken("e", match1to2);
 | |
|       addRegexToken("E", match1to2);
 | |
|       addRegexToken("dd", function(isStrict, locale3) {
 | |
|         return locale3.weekdaysMinRegex(isStrict);
 | |
|       });
 | |
|       addRegexToken("ddd", function(isStrict, locale3) {
 | |
|         return locale3.weekdaysShortRegex(isStrict);
 | |
|       });
 | |
|       addRegexToken("dddd", function(isStrict, locale3) {
 | |
|         return locale3.weekdaysRegex(isStrict);
 | |
|       });
 | |
|       addWeekParseToken(["dd", "ddd", "dddd"], function(input, week, config, token2) {
 | |
|         var weekday = config._locale.weekdaysParse(input, token2, config._strict);
 | |
|         if (weekday != null) {
 | |
|           week.d = weekday;
 | |
|         } else {
 | |
|           getParsingFlags(config).invalidWeekday = input;
 | |
|         }
 | |
|       });
 | |
|       addWeekParseToken(["d", "e", "E"], function(input, week, config, token2) {
 | |
|         week[token2] = toInt(input);
 | |
|       });
 | |
|       function parseWeekday(input, locale3) {
 | |
|         if (typeof input !== "string") {
 | |
|           return input;
 | |
|         }
 | |
|         if (!isNaN(input)) {
 | |
|           return parseInt(input, 10);
 | |
|         }
 | |
|         input = locale3.weekdaysParse(input);
 | |
|         if (typeof input === "number") {
 | |
|           return input;
 | |
|         }
 | |
|         return null;
 | |
|       }
 | |
|       function parseIsoWeekday(input, locale3) {
 | |
|         if (typeof input === "string") {
 | |
|           return locale3.weekdaysParse(input) % 7 || 7;
 | |
|         }
 | |
|         return isNaN(input) ? null : input;
 | |
|       }
 | |
|       function shiftWeekdays(ws, n2) {
 | |
|         return ws.slice(n2, 7).concat(ws.slice(0, n2));
 | |
|       }
 | |
|       var defaultLocaleWeekdays = "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), defaultLocaleWeekdaysShort = "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), defaultLocaleWeekdaysMin = "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), defaultWeekdaysRegex = matchWord, defaultWeekdaysShortRegex = matchWord, defaultWeekdaysMinRegex = matchWord;
 | |
|       function localeWeekdays(m2, format2) {
 | |
|         var weekdays = isArray2(this._weekdays) ? this._weekdays : this._weekdays[m2 && m2 !== true && this._weekdays.isFormat.test(format2) ? "format" : "standalone"];
 | |
|         return m2 === true ? shiftWeekdays(weekdays, this._week.dow) : m2 ? weekdays[m2.day()] : weekdays;
 | |
|       }
 | |
|       function localeWeekdaysShort(m2) {
 | |
|         return m2 === true ? shiftWeekdays(this._weekdaysShort, this._week.dow) : m2 ? this._weekdaysShort[m2.day()] : this._weekdaysShort;
 | |
|       }
 | |
|       function localeWeekdaysMin(m2) {
 | |
|         return m2 === true ? shiftWeekdays(this._weekdaysMin, this._week.dow) : m2 ? this._weekdaysMin[m2.day()] : this._weekdaysMin;
 | |
|       }
 | |
|       function handleStrictParse$1(weekdayName, format2, strict) {
 | |
|         var i2, ii, mom, llc = weekdayName.toLocaleLowerCase();
 | |
|         if (!this._weekdaysParse) {
 | |
|           this._weekdaysParse = [];
 | |
|           this._shortWeekdaysParse = [];
 | |
|           this._minWeekdaysParse = [];
 | |
|           for (i2 = 0; i2 < 7; ++i2) {
 | |
|             mom = createUTC([2e3, 1]).day(i2);
 | |
|             this._minWeekdaysParse[i2] = this.weekdaysMin(
 | |
|               mom,
 | |
|               ""
 | |
|             ).toLocaleLowerCase();
 | |
|             this._shortWeekdaysParse[i2] = this.weekdaysShort(
 | |
|               mom,
 | |
|               ""
 | |
|             ).toLocaleLowerCase();
 | |
|             this._weekdaysParse[i2] = this.weekdays(mom, "").toLocaleLowerCase();
 | |
|           }
 | |
|         }
 | |
|         if (strict) {
 | |
|           if (format2 === "dddd") {
 | |
|             ii = indexOf.call(this._weekdaysParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           } else if (format2 === "ddd") {
 | |
|             ii = indexOf.call(this._shortWeekdaysParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           } else {
 | |
|             ii = indexOf.call(this._minWeekdaysParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           }
 | |
|         } else {
 | |
|           if (format2 === "dddd") {
 | |
|             ii = indexOf.call(this._weekdaysParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._shortWeekdaysParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._minWeekdaysParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           } else if (format2 === "ddd") {
 | |
|             ii = indexOf.call(this._shortWeekdaysParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._weekdaysParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._minWeekdaysParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           } else {
 | |
|             ii = indexOf.call(this._minWeekdaysParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._weekdaysParse, llc);
 | |
|             if (ii !== -1) {
 | |
|               return ii;
 | |
|             }
 | |
|             ii = indexOf.call(this._shortWeekdaysParse, llc);
 | |
|             return ii !== -1 ? ii : null;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       function localeWeekdaysParse(weekdayName, format2, strict) {
 | |
|         var i2, mom, regex;
 | |
|         if (this._weekdaysParseExact) {
 | |
|           return handleStrictParse$1.call(this, weekdayName, format2, strict);
 | |
|         }
 | |
|         if (!this._weekdaysParse) {
 | |
|           this._weekdaysParse = [];
 | |
|           this._minWeekdaysParse = [];
 | |
|           this._shortWeekdaysParse = [];
 | |
|           this._fullWeekdaysParse = [];
 | |
|         }
 | |
|         for (i2 = 0; i2 < 7; i2++) {
 | |
|           mom = createUTC([2e3, 1]).day(i2);
 | |
|           if (strict && !this._fullWeekdaysParse[i2]) {
 | |
|             this._fullWeekdaysParse[i2] = new RegExp(
 | |
|               "^" + this.weekdays(mom, "").replace(".", "\\.?") + "$",
 | |
|               "i"
 | |
|             );
 | |
|             this._shortWeekdaysParse[i2] = new RegExp(
 | |
|               "^" + this.weekdaysShort(mom, "").replace(".", "\\.?") + "$",
 | |
|               "i"
 | |
|             );
 | |
|             this._minWeekdaysParse[i2] = new RegExp(
 | |
|               "^" + this.weekdaysMin(mom, "").replace(".", "\\.?") + "$",
 | |
|               "i"
 | |
|             );
 | |
|           }
 | |
|           if (!this._weekdaysParse[i2]) {
 | |
|             regex = "^" + this.weekdays(mom, "") + "|^" + this.weekdaysShort(mom, "") + "|^" + this.weekdaysMin(mom, "");
 | |
|             this._weekdaysParse[i2] = new RegExp(regex.replace(".", ""), "i");
 | |
|           }
 | |
|           if (strict && format2 === "dddd" && this._fullWeekdaysParse[i2].test(weekdayName)) {
 | |
|             return i2;
 | |
|           } else if (strict && format2 === "ddd" && this._shortWeekdaysParse[i2].test(weekdayName)) {
 | |
|             return i2;
 | |
|           } else if (strict && format2 === "dd" && this._minWeekdaysParse[i2].test(weekdayName)) {
 | |
|             return i2;
 | |
|           } else if (!strict && this._weekdaysParse[i2].test(weekdayName)) {
 | |
|             return i2;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       function getSetDayOfWeek(input) {
 | |
|         if (!this.isValid()) {
 | |
|           return input != null ? this : NaN;
 | |
|         }
 | |
|         var day = get(this, "Day");
 | |
|         if (input != null) {
 | |
|           input = parseWeekday(input, this.localeData());
 | |
|           return this.add(input - day, "d");
 | |
|         } else {
 | |
|           return day;
 | |
|         }
 | |
|       }
 | |
|       function getSetLocaleDayOfWeek(input) {
 | |
|         if (!this.isValid()) {
 | |
|           return input != null ? this : NaN;
 | |
|         }
 | |
|         var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
 | |
|         return input == null ? weekday : this.add(input - weekday, "d");
 | |
|       }
 | |
|       function getSetISODayOfWeek(input) {
 | |
|         if (!this.isValid()) {
 | |
|           return input != null ? this : NaN;
 | |
|         }
 | |
|         if (input != null) {
 | |
|           var weekday = parseIsoWeekday(input, this.localeData());
 | |
|           return this.day(this.day() % 7 ? weekday : weekday - 7);
 | |
|         } else {
 | |
|           return this.day() || 7;
 | |
|         }
 | |
|       }
 | |
|       function weekdaysRegex(isStrict) {
 | |
|         if (this._weekdaysParseExact) {
 | |
|           if (!hasOwnProp(this, "_weekdaysRegex")) {
 | |
|             computeWeekdaysParse.call(this);
 | |
|           }
 | |
|           if (isStrict) {
 | |
|             return this._weekdaysStrictRegex;
 | |
|           } else {
 | |
|             return this._weekdaysRegex;
 | |
|           }
 | |
|         } else {
 | |
|           if (!hasOwnProp(this, "_weekdaysRegex")) {
 | |
|             this._weekdaysRegex = defaultWeekdaysRegex;
 | |
|           }
 | |
|           return this._weekdaysStrictRegex && isStrict ? this._weekdaysStrictRegex : this._weekdaysRegex;
 | |
|         }
 | |
|       }
 | |
|       function weekdaysShortRegex(isStrict) {
 | |
|         if (this._weekdaysParseExact) {
 | |
|           if (!hasOwnProp(this, "_weekdaysRegex")) {
 | |
|             computeWeekdaysParse.call(this);
 | |
|           }
 | |
|           if (isStrict) {
 | |
|             return this._weekdaysShortStrictRegex;
 | |
|           } else {
 | |
|             return this._weekdaysShortRegex;
 | |
|           }
 | |
|         } else {
 | |
|           if (!hasOwnProp(this, "_weekdaysShortRegex")) {
 | |
|             this._weekdaysShortRegex = defaultWeekdaysShortRegex;
 | |
|           }
 | |
|           return this._weekdaysShortStrictRegex && isStrict ? this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
 | |
|         }
 | |
|       }
 | |
|       function weekdaysMinRegex(isStrict) {
 | |
|         if (this._weekdaysParseExact) {
 | |
|           if (!hasOwnProp(this, "_weekdaysRegex")) {
 | |
|             computeWeekdaysParse.call(this);
 | |
|           }
 | |
|           if (isStrict) {
 | |
|             return this._weekdaysMinStrictRegex;
 | |
|           } else {
 | |
|             return this._weekdaysMinRegex;
 | |
|           }
 | |
|         } else {
 | |
|           if (!hasOwnProp(this, "_weekdaysMinRegex")) {
 | |
|             this._weekdaysMinRegex = defaultWeekdaysMinRegex;
 | |
|           }
 | |
|           return this._weekdaysMinStrictRegex && isStrict ? this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
 | |
|         }
 | |
|       }
 | |
|       function computeWeekdaysParse() {
 | |
|         function cmpLenRev(a2, b2) {
 | |
|           return b2.length - a2.length;
 | |
|         }
 | |
|         var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], i2, mom, minp, shortp, longp;
 | |
|         for (i2 = 0; i2 < 7; i2++) {
 | |
|           mom = createUTC([2e3, 1]).day(i2);
 | |
|           minp = regexEscape(this.weekdaysMin(mom, ""));
 | |
|           shortp = regexEscape(this.weekdaysShort(mom, ""));
 | |
|           longp = regexEscape(this.weekdays(mom, ""));
 | |
|           minPieces.push(minp);
 | |
|           shortPieces.push(shortp);
 | |
|           longPieces.push(longp);
 | |
|           mixedPieces.push(minp);
 | |
|           mixedPieces.push(shortp);
 | |
|           mixedPieces.push(longp);
 | |
|         }
 | |
|         minPieces.sort(cmpLenRev);
 | |
|         shortPieces.sort(cmpLenRev);
 | |
|         longPieces.sort(cmpLenRev);
 | |
|         mixedPieces.sort(cmpLenRev);
 | |
|         this._weekdaysRegex = new RegExp("^(" + mixedPieces.join("|") + ")", "i");
 | |
|         this._weekdaysShortRegex = this._weekdaysRegex;
 | |
|         this._weekdaysMinRegex = this._weekdaysRegex;
 | |
|         this._weekdaysStrictRegex = new RegExp(
 | |
|           "^(" + longPieces.join("|") + ")",
 | |
|           "i"
 | |
|         );
 | |
|         this._weekdaysShortStrictRegex = new RegExp(
 | |
|           "^(" + shortPieces.join("|") + ")",
 | |
|           "i"
 | |
|         );
 | |
|         this._weekdaysMinStrictRegex = new RegExp(
 | |
|           "^(" + minPieces.join("|") + ")",
 | |
|           "i"
 | |
|         );
 | |
|       }
 | |
|       function hFormat() {
 | |
|         return this.hours() % 12 || 12;
 | |
|       }
 | |
|       function kFormat() {
 | |
|         return this.hours() || 24;
 | |
|       }
 | |
|       addFormatToken("H", ["HH", 2], 0, "hour");
 | |
|       addFormatToken("h", ["hh", 2], 0, hFormat);
 | |
|       addFormatToken("k", ["kk", 2], 0, kFormat);
 | |
|       addFormatToken("hmm", 0, 0, function() {
 | |
|         return "" + hFormat.apply(this) + zeroFill(this.minutes(), 2);
 | |
|       });
 | |
|       addFormatToken("hmmss", 0, 0, function() {
 | |
|         return "" + hFormat.apply(this) + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
 | |
|       });
 | |
|       addFormatToken("Hmm", 0, 0, function() {
 | |
|         return "" + this.hours() + zeroFill(this.minutes(), 2);
 | |
|       });
 | |
|       addFormatToken("Hmmss", 0, 0, function() {
 | |
|         return "" + this.hours() + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
 | |
|       });
 | |
|       function meridiem(token2, lowercase) {
 | |
|         addFormatToken(token2, 0, 0, function() {
 | |
|           return this.localeData().meridiem(
 | |
|             this.hours(),
 | |
|             this.minutes(),
 | |
|             lowercase
 | |
|           );
 | |
|         });
 | |
|       }
 | |
|       meridiem("a", true);
 | |
|       meridiem("A", false);
 | |
|       function matchMeridiem(isStrict, locale3) {
 | |
|         return locale3._meridiemParse;
 | |
|       }
 | |
|       addRegexToken("a", matchMeridiem);
 | |
|       addRegexToken("A", matchMeridiem);
 | |
|       addRegexToken("H", match1to2, match1to2HasZero);
 | |
|       addRegexToken("h", match1to2, match1to2NoLeadingZero);
 | |
|       addRegexToken("k", match1to2, match1to2NoLeadingZero);
 | |
|       addRegexToken("HH", match1to2, match2);
 | |
|       addRegexToken("hh", match1to2, match2);
 | |
|       addRegexToken("kk", match1to2, match2);
 | |
|       addRegexToken("hmm", match3to4);
 | |
|       addRegexToken("hmmss", match5to6);
 | |
|       addRegexToken("Hmm", match3to4);
 | |
|       addRegexToken("Hmmss", match5to6);
 | |
|       addParseToken(["H", "HH"], HOUR);
 | |
|       addParseToken(["k", "kk"], function(input, array, config) {
 | |
|         var kInput = toInt(input);
 | |
|         array[HOUR] = kInput === 24 ? 0 : kInput;
 | |
|       });
 | |
|       addParseToken(["a", "A"], function(input, array, config) {
 | |
|         config._isPm = config._locale.isPM(input);
 | |
|         config._meridiem = input;
 | |
|       });
 | |
|       addParseToken(["h", "hh"], function(input, array, config) {
 | |
|         array[HOUR] = toInt(input);
 | |
|         getParsingFlags(config).bigHour = true;
 | |
|       });
 | |
|       addParseToken("hmm", function(input, array, config) {
 | |
|         var pos = input.length - 2;
 | |
|         array[HOUR] = toInt(input.substr(0, pos));
 | |
|         array[MINUTE] = toInt(input.substr(pos));
 | |
|         getParsingFlags(config).bigHour = true;
 | |
|       });
 | |
|       addParseToken("hmmss", function(input, array, config) {
 | |
|         var pos1 = input.length - 4, pos2 = input.length - 2;
 | |
|         array[HOUR] = toInt(input.substr(0, pos1));
 | |
|         array[MINUTE] = toInt(input.substr(pos1, 2));
 | |
|         array[SECOND] = toInt(input.substr(pos2));
 | |
|         getParsingFlags(config).bigHour = true;
 | |
|       });
 | |
|       addParseToken("Hmm", function(input, array, config) {
 | |
|         var pos = input.length - 2;
 | |
|         array[HOUR] = toInt(input.substr(0, pos));
 | |
|         array[MINUTE] = toInt(input.substr(pos));
 | |
|       });
 | |
|       addParseToken("Hmmss", function(input, array, config) {
 | |
|         var pos1 = input.length - 4, pos2 = input.length - 2;
 | |
|         array[HOUR] = toInt(input.substr(0, pos1));
 | |
|         array[MINUTE] = toInt(input.substr(pos1, 2));
 | |
|         array[SECOND] = toInt(input.substr(pos2));
 | |
|       });
 | |
|       function localeIsPM(input) {
 | |
|         return (input + "").toLowerCase().charAt(0) === "p";
 | |
|       }
 | |
|       var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i, getSetHour = makeGetSet("Hours", true);
 | |
|       function localeMeridiem(hours2, minutes2, isLower) {
 | |
|         if (hours2 > 11) {
 | |
|           return isLower ? "pm" : "PM";
 | |
|         } else {
 | |
|           return isLower ? "am" : "AM";
 | |
|         }
 | |
|       }
 | |
|       var baseConfig = {
 | |
|         calendar: defaultCalendar,
 | |
|         longDateFormat: defaultLongDateFormat,
 | |
|         invalidDate: defaultInvalidDate,
 | |
|         ordinal: defaultOrdinal,
 | |
|         dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
 | |
|         relativeTime: defaultRelativeTime,
 | |
|         months: defaultLocaleMonths,
 | |
|         monthsShort: defaultLocaleMonthsShort,
 | |
|         week: defaultLocaleWeek,
 | |
|         weekdays: defaultLocaleWeekdays,
 | |
|         weekdaysMin: defaultLocaleWeekdaysMin,
 | |
|         weekdaysShort: defaultLocaleWeekdaysShort,
 | |
|         meridiemParse: defaultLocaleMeridiemParse
 | |
|       };
 | |
|       var locales = {}, localeFamilies = {}, globalLocale;
 | |
|       function commonPrefix(arr1, arr2) {
 | |
|         var i2, minl = Math.min(arr1.length, arr2.length);
 | |
|         for (i2 = 0; i2 < minl; i2 += 1) {
 | |
|           if (arr1[i2] !== arr2[i2]) {
 | |
|             return i2;
 | |
|           }
 | |
|         }
 | |
|         return minl;
 | |
|       }
 | |
|       function normalizeLocale(key) {
 | |
|         return key ? key.toLowerCase().replace("_", "-") : key;
 | |
|       }
 | |
|       function chooseLocale(names2) {
 | |
|         var i2 = 0, j2, next, locale3, split;
 | |
|         while (i2 < names2.length) {
 | |
|           split = normalizeLocale(names2[i2]).split("-");
 | |
|           j2 = split.length;
 | |
|           next = normalizeLocale(names2[i2 + 1]);
 | |
|           next = next ? next.split("-") : null;
 | |
|           while (j2 > 0) {
 | |
|             locale3 = loadLocale(split.slice(0, j2).join("-"));
 | |
|             if (locale3) {
 | |
|               return locale3;
 | |
|             }
 | |
|             if (next && next.length >= j2 && commonPrefix(split, next) >= j2 - 1) {
 | |
|               break;
 | |
|             }
 | |
|             j2--;
 | |
|           }
 | |
|           i2++;
 | |
|         }
 | |
|         return globalLocale;
 | |
|       }
 | |
|       function isLocaleNameSane(name) {
 | |
|         return !!(name && name.match("^[^/\\\\]*$"));
 | |
|       }
 | |
|       function loadLocale(name) {
 | |
|         var oldLocale = null, aliasedRequire;
 | |
|         if (locales[name] === void 0 && typeof module2 !== "undefined" && module2 && module2.exports && isLocaleNameSane(name)) {
 | |
|           try {
 | |
|             oldLocale = globalLocale._abbr;
 | |
|             aliasedRequire = require;
 | |
|             aliasedRequire("./locale/" + name);
 | |
|             getSetGlobalLocale(oldLocale);
 | |
|           } catch (e2) {
 | |
|             locales[name] = null;
 | |
|           }
 | |
|         }
 | |
|         return locales[name];
 | |
|       }
 | |
|       function getSetGlobalLocale(key, values) {
 | |
|         var data;
 | |
|         if (key) {
 | |
|           if (isUndefined(values)) {
 | |
|             data = getLocale(key);
 | |
|           } else {
 | |
|             data = defineLocale(key, values);
 | |
|           }
 | |
|           if (data) {
 | |
|             globalLocale = data;
 | |
|           } else {
 | |
|             if (typeof console !== "undefined" && console.warn) {
 | |
|               console.warn(
 | |
|                 "Locale " + key + " not found. Did you forget to load it?"
 | |
|               );
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         return globalLocale._abbr;
 | |
|       }
 | |
|       function defineLocale(name, config) {
 | |
|         if (config !== null) {
 | |
|           var locale3, parentConfig = baseConfig;
 | |
|           config.abbr = name;
 | |
|           if (locales[name] != null) {
 | |
|             deprecateSimple(
 | |
|               "defineLocaleOverride",
 | |
|               "use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."
 | |
|             );
 | |
|             parentConfig = locales[name]._config;
 | |
|           } else if (config.parentLocale != null) {
 | |
|             if (locales[config.parentLocale] != null) {
 | |
|               parentConfig = locales[config.parentLocale]._config;
 | |
|             } else {
 | |
|               locale3 = loadLocale(config.parentLocale);
 | |
|               if (locale3 != null) {
 | |
|                 parentConfig = locale3._config;
 | |
|               } else {
 | |
|                 if (!localeFamilies[config.parentLocale]) {
 | |
|                   localeFamilies[config.parentLocale] = [];
 | |
|                 }
 | |
|                 localeFamilies[config.parentLocale].push({
 | |
|                   name,
 | |
|                   config
 | |
|                 });
 | |
|                 return null;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|           locales[name] = new Locale(mergeConfigs(parentConfig, config));
 | |
|           if (localeFamilies[name]) {
 | |
|             localeFamilies[name].forEach(function(x2) {
 | |
|               defineLocale(x2.name, x2.config);
 | |
|             });
 | |
|           }
 | |
|           getSetGlobalLocale(name);
 | |
|           return locales[name];
 | |
|         } else {
 | |
|           delete locales[name];
 | |
|           return null;
 | |
|         }
 | |
|       }
 | |
|       function updateLocale(name, config) {
 | |
|         if (config != null) {
 | |
|           var locale3, tmpLocale, parentConfig = baseConfig;
 | |
|           if (locales[name] != null && locales[name].parentLocale != null) {
 | |
|             locales[name].set(mergeConfigs(locales[name]._config, config));
 | |
|           } else {
 | |
|             tmpLocale = loadLocale(name);
 | |
|             if (tmpLocale != null) {
 | |
|               parentConfig = tmpLocale._config;
 | |
|             }
 | |
|             config = mergeConfigs(parentConfig, config);
 | |
|             if (tmpLocale == null) {
 | |
|               config.abbr = name;
 | |
|             }
 | |
|             locale3 = new Locale(config);
 | |
|             locale3.parentLocale = locales[name];
 | |
|             locales[name] = locale3;
 | |
|           }
 | |
|           getSetGlobalLocale(name);
 | |
|         } else {
 | |
|           if (locales[name] != null) {
 | |
|             if (locales[name].parentLocale != null) {
 | |
|               locales[name] = locales[name].parentLocale;
 | |
|               if (name === getSetGlobalLocale()) {
 | |
|                 getSetGlobalLocale(name);
 | |
|               }
 | |
|             } else if (locales[name] != null) {
 | |
|               delete locales[name];
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         return locales[name];
 | |
|       }
 | |
|       function getLocale(key) {
 | |
|         var locale3;
 | |
|         if (key && key._locale && key._locale._abbr) {
 | |
|           key = key._locale._abbr;
 | |
|         }
 | |
|         if (!key) {
 | |
|           return globalLocale;
 | |
|         }
 | |
|         if (!isArray2(key)) {
 | |
|           locale3 = loadLocale(key);
 | |
|           if (locale3) {
 | |
|             return locale3;
 | |
|           }
 | |
|           key = [key];
 | |
|         }
 | |
|         return chooseLocale(key);
 | |
|       }
 | |
|       function listLocales() {
 | |
|         return keys(locales);
 | |
|       }
 | |
|       function checkOverflow(m2) {
 | |
|         var overflow, a2 = m2._a;
 | |
|         if (a2 && getParsingFlags(m2).overflow === -2) {
 | |
|           overflow = a2[MONTH] < 0 || a2[MONTH] > 11 ? MONTH : a2[DATE] < 1 || a2[DATE] > daysInMonth(a2[YEAR], a2[MONTH]) ? DATE : a2[HOUR] < 0 || a2[HOUR] > 24 || a2[HOUR] === 24 && (a2[MINUTE] !== 0 || a2[SECOND] !== 0 || a2[MILLISECOND] !== 0) ? HOUR : a2[MINUTE] < 0 || a2[MINUTE] > 59 ? MINUTE : a2[SECOND] < 0 || a2[SECOND] > 59 ? SECOND : a2[MILLISECOND] < 0 || a2[MILLISECOND] > 999 ? MILLISECOND : -1;
 | |
|           if (getParsingFlags(m2)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
 | |
|             overflow = DATE;
 | |
|           }
 | |
|           if (getParsingFlags(m2)._overflowWeeks && overflow === -1) {
 | |
|             overflow = WEEK;
 | |
|           }
 | |
|           if (getParsingFlags(m2)._overflowWeekday && overflow === -1) {
 | |
|             overflow = WEEKDAY;
 | |
|           }
 | |
|           getParsingFlags(m2).overflow = overflow;
 | |
|         }
 | |
|         return m2;
 | |
|       }
 | |
|       var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/, basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/, tzRegex = /Z|[+-]\d\d(?::?\d\d)?/, isoDates = [
 | |
|         ["YYYYYY-MM-DD", /[+-]\d{6}-\d\d-\d\d/],
 | |
|         ["YYYY-MM-DD", /\d{4}-\d\d-\d\d/],
 | |
|         ["GGGG-[W]WW-E", /\d{4}-W\d\d-\d/],
 | |
|         ["GGGG-[W]WW", /\d{4}-W\d\d/, false],
 | |
|         ["YYYY-DDD", /\d{4}-\d{3}/],
 | |
|         ["YYYY-MM", /\d{4}-\d\d/, false],
 | |
|         ["YYYYYYMMDD", /[+-]\d{10}/],
 | |
|         ["YYYYMMDD", /\d{8}/],
 | |
|         ["GGGG[W]WWE", /\d{4}W\d{3}/],
 | |
|         ["GGGG[W]WW", /\d{4}W\d{2}/, false],
 | |
|         ["YYYYDDD", /\d{7}/],
 | |
|         ["YYYYMM", /\d{6}/, false],
 | |
|         ["YYYY", /\d{4}/, false]
 | |
|       ], isoTimes = [
 | |
|         ["HH:mm:ss.SSSS", /\d\d:\d\d:\d\d\.\d+/],
 | |
|         ["HH:mm:ss,SSSS", /\d\d:\d\d:\d\d,\d+/],
 | |
|         ["HH:mm:ss", /\d\d:\d\d:\d\d/],
 | |
|         ["HH:mm", /\d\d:\d\d/],
 | |
|         ["HHmmss.SSSS", /\d\d\d\d\d\d\.\d+/],
 | |
|         ["HHmmss,SSSS", /\d\d\d\d\d\d,\d+/],
 | |
|         ["HHmmss", /\d\d\d\d\d\d/],
 | |
|         ["HHmm", /\d\d\d\d/],
 | |
|         ["HH", /\d\d/]
 | |
|       ], aspNetJsonRegex = /^\/?Date\((-?\d+)/i, rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/, obsOffsets = {
 | |
|         UT: 0,
 | |
|         GMT: 0,
 | |
|         EDT: -4 * 60,
 | |
|         EST: -5 * 60,
 | |
|         CDT: -5 * 60,
 | |
|         CST: -6 * 60,
 | |
|         MDT: -6 * 60,
 | |
|         MST: -7 * 60,
 | |
|         PDT: -7 * 60,
 | |
|         PST: -8 * 60
 | |
|       };
 | |
|       function configFromISO(config) {
 | |
|         var i2, l2, string = config._i, match5 = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), allowTime, dateFormat, timeFormat, tzFormat, isoDatesLen = isoDates.length, isoTimesLen = isoTimes.length;
 | |
|         if (match5) {
 | |
|           getParsingFlags(config).iso = true;
 | |
|           for (i2 = 0, l2 = isoDatesLen; i2 < l2; i2++) {
 | |
|             if (isoDates[i2][1].exec(match5[1])) {
 | |
|               dateFormat = isoDates[i2][0];
 | |
|               allowTime = isoDates[i2][2] !== false;
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|           if (dateFormat == null) {
 | |
|             config._isValid = false;
 | |
|             return;
 | |
|           }
 | |
|           if (match5[3]) {
 | |
|             for (i2 = 0, l2 = isoTimesLen; i2 < l2; i2++) {
 | |
|               if (isoTimes[i2][1].exec(match5[3])) {
 | |
|                 timeFormat = (match5[2] || " ") + isoTimes[i2][0];
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
|             if (timeFormat == null) {
 | |
|               config._isValid = false;
 | |
|               return;
 | |
|             }
 | |
|           }
 | |
|           if (!allowTime && timeFormat != null) {
 | |
|             config._isValid = false;
 | |
|             return;
 | |
|           }
 | |
|           if (match5[4]) {
 | |
|             if (tzRegex.exec(match5[4])) {
 | |
|               tzFormat = "Z";
 | |
|             } else {
 | |
|               config._isValid = false;
 | |
|               return;
 | |
|             }
 | |
|           }
 | |
|           config._f = dateFormat + (timeFormat || "") + (tzFormat || "");
 | |
|           configFromStringAndFormat(config);
 | |
|         } else {
 | |
|           config._isValid = false;
 | |
|         }
 | |
|       }
 | |
|       function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
 | |
|         var result = [
 | |
|           untruncateYear(yearStr),
 | |
|           defaultLocaleMonthsShort.indexOf(monthStr),
 | |
|           parseInt(dayStr, 10),
 | |
|           parseInt(hourStr, 10),
 | |
|           parseInt(minuteStr, 10)
 | |
|         ];
 | |
|         if (secondStr) {
 | |
|           result.push(parseInt(secondStr, 10));
 | |
|         }
 | |
|         return result;
 | |
|       }
 | |
|       function untruncateYear(yearStr) {
 | |
|         var year = parseInt(yearStr, 10);
 | |
|         if (year <= 49) {
 | |
|           return 2e3 + year;
 | |
|         } else if (year <= 999) {
 | |
|           return 1900 + year;
 | |
|         }
 | |
|         return year;
 | |
|       }
 | |
|       function preprocessRFC2822(s2) {
 | |
|         return s2.replace(/\([^()]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").replace(/^\s\s*/, "").replace(/\s\s*$/, "");
 | |
|       }
 | |
|       function checkWeekday(weekdayStr, parsedInput, config) {
 | |
|         if (weekdayStr) {
 | |
|           var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), weekdayActual = new Date(
 | |
|             parsedInput[0],
 | |
|             parsedInput[1],
 | |
|             parsedInput[2]
 | |
|           ).getDay();
 | |
|           if (weekdayProvided !== weekdayActual) {
 | |
|             getParsingFlags(config).weekdayMismatch = true;
 | |
|             config._isValid = false;
 | |
|             return false;
 | |
|           }
 | |
|         }
 | |
|         return true;
 | |
|       }
 | |
|       function calculateOffset(obsOffset, militaryOffset, numOffset) {
 | |
|         if (obsOffset) {
 | |
|           return obsOffsets[obsOffset];
 | |
|         } else if (militaryOffset) {
 | |
|           return 0;
 | |
|         } else {
 | |
|           var hm = parseInt(numOffset, 10), m2 = hm % 100, h6 = (hm - m2) / 100;
 | |
|           return h6 * 60 + m2;
 | |
|         }
 | |
|       }
 | |
|       function configFromRFC2822(config) {
 | |
|         var match5 = rfc2822.exec(preprocessRFC2822(config._i)), parsedArray;
 | |
|         if (match5) {
 | |
|           parsedArray = extractFromRFC2822Strings(
 | |
|             match5[4],
 | |
|             match5[3],
 | |
|             match5[2],
 | |
|             match5[5],
 | |
|             match5[6],
 | |
|             match5[7]
 | |
|           );
 | |
|           if (!checkWeekday(match5[1], parsedArray, config)) {
 | |
|             return;
 | |
|           }
 | |
|           config._a = parsedArray;
 | |
|           config._tzm = calculateOffset(match5[8], match5[9], match5[10]);
 | |
|           config._d = createUTCDate.apply(null, config._a);
 | |
|           config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
 | |
|           getParsingFlags(config).rfc2822 = true;
 | |
|         } else {
 | |
|           config._isValid = false;
 | |
|         }
 | |
|       }
 | |
|       function configFromString(config) {
 | |
|         var matched = aspNetJsonRegex.exec(config._i);
 | |
|         if (matched !== null) {
 | |
|           config._d = /* @__PURE__ */ new Date(+matched[1]);
 | |
|           return;
 | |
|         }
 | |
|         configFromISO(config);
 | |
|         if (config._isValid === false) {
 | |
|           delete config._isValid;
 | |
|         } else {
 | |
|           return;
 | |
|         }
 | |
|         configFromRFC2822(config);
 | |
|         if (config._isValid === false) {
 | |
|           delete config._isValid;
 | |
|         } else {
 | |
|           return;
 | |
|         }
 | |
|         if (config._strict) {
 | |
|           config._isValid = false;
 | |
|         } else {
 | |
|           hooks.createFromInputFallback(config);
 | |
|         }
 | |
|       }
 | |
|       hooks.createFromInputFallback = deprecate(
 | |
|         "value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",
 | |
|         function(config) {
 | |
|           config._d = /* @__PURE__ */ new Date(config._i + (config._useUTC ? " UTC" : ""));
 | |
|         }
 | |
|       );
 | |
|       function defaults3(a2, b2, c2) {
 | |
|         if (a2 != null) {
 | |
|           return a2;
 | |
|         }
 | |
|         if (b2 != null) {
 | |
|           return b2;
 | |
|         }
 | |
|         return c2;
 | |
|       }
 | |
|       function currentDateArray(config) {
 | |
|         var nowValue = new Date(hooks.now());
 | |
|         if (config._useUTC) {
 | |
|           return [
 | |
|             nowValue.getUTCFullYear(),
 | |
|             nowValue.getUTCMonth(),
 | |
|             nowValue.getUTCDate()
 | |
|           ];
 | |
|         }
 | |
|         return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
 | |
|       }
 | |
|       function configFromArray(config) {
 | |
|         var i2, date, input = [], currentDate, expectedWeekday, yearToUse;
 | |
|         if (config._d) {
 | |
|           return;
 | |
|         }
 | |
|         currentDate = currentDateArray(config);
 | |
|         if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
 | |
|           dayOfYearFromWeekInfo(config);
 | |
|         }
 | |
|         if (config._dayOfYear != null) {
 | |
|           yearToUse = defaults3(config._a[YEAR], currentDate[YEAR]);
 | |
|           if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
 | |
|             getParsingFlags(config)._overflowDayOfYear = true;
 | |
|           }
 | |
|           date = createUTCDate(yearToUse, 0, config._dayOfYear);
 | |
|           config._a[MONTH] = date.getUTCMonth();
 | |
|           config._a[DATE] = date.getUTCDate();
 | |
|         }
 | |
|         for (i2 = 0; i2 < 3 && config._a[i2] == null; ++i2) {
 | |
|           config._a[i2] = input[i2] = currentDate[i2];
 | |
|         }
 | |
|         for (; i2 < 7; i2++) {
 | |
|           config._a[i2] = input[i2] = config._a[i2] == null ? i2 === 2 ? 1 : 0 : config._a[i2];
 | |
|         }
 | |
|         if (config._a[HOUR] === 24 && config._a[MINUTE] === 0 && config._a[SECOND] === 0 && config._a[MILLISECOND] === 0) {
 | |
|           config._nextDay = true;
 | |
|           config._a[HOUR] = 0;
 | |
|         }
 | |
|         config._d = (config._useUTC ? createUTCDate : createDate).apply(
 | |
|           null,
 | |
|           input
 | |
|         );
 | |
|         expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
 | |
|         if (config._tzm != null) {
 | |
|           config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
 | |
|         }
 | |
|         if (config._nextDay) {
 | |
|           config._a[HOUR] = 24;
 | |
|         }
 | |
|         if (config._w && typeof config._w.d !== "undefined" && config._w.d !== expectedWeekday) {
 | |
|           getParsingFlags(config).weekdayMismatch = true;
 | |
|         }
 | |
|       }
 | |
|       function dayOfYearFromWeekInfo(config) {
 | |
|         var w2, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;
 | |
|         w2 = config._w;
 | |
|         if (w2.GG != null || w2.W != null || w2.E != null) {
 | |
|           dow = 1;
 | |
|           doy = 4;
 | |
|           weekYear = defaults3(
 | |
|             w2.GG,
 | |
|             config._a[YEAR],
 | |
|             weekOfYear(createLocal(), 1, 4).year
 | |
|           );
 | |
|           week = defaults3(w2.W, 1);
 | |
|           weekday = defaults3(w2.E, 1);
 | |
|           if (weekday < 1 || weekday > 7) {
 | |
|             weekdayOverflow = true;
 | |
|           }
 | |
|         } else {
 | |
|           dow = config._locale._week.dow;
 | |
|           doy = config._locale._week.doy;
 | |
|           curWeek = weekOfYear(createLocal(), dow, doy);
 | |
|           weekYear = defaults3(w2.gg, config._a[YEAR], curWeek.year);
 | |
|           week = defaults3(w2.w, curWeek.week);
 | |
|           if (w2.d != null) {
 | |
|             weekday = w2.d;
 | |
|             if (weekday < 0 || weekday > 6) {
 | |
|               weekdayOverflow = true;
 | |
|             }
 | |
|           } else if (w2.e != null) {
 | |
|             weekday = w2.e + dow;
 | |
|             if (w2.e < 0 || w2.e > 6) {
 | |
|               weekdayOverflow = true;
 | |
|             }
 | |
|           } else {
 | |
|             weekday = dow;
 | |
|           }
 | |
|         }
 | |
|         if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
 | |
|           getParsingFlags(config)._overflowWeeks = true;
 | |
|         } else if (weekdayOverflow != null) {
 | |
|           getParsingFlags(config)._overflowWeekday = true;
 | |
|         } else {
 | |
|           temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
 | |
|           config._a[YEAR] = temp.year;
 | |
|           config._dayOfYear = temp.dayOfYear;
 | |
|         }
 | |
|       }
 | |
|       hooks.ISO_8601 = function() {
 | |
|       };
 | |
|       hooks.RFC_2822 = function() {
 | |
|       };
 | |
|       function configFromStringAndFormat(config) {
 | |
|         if (config._f === hooks.ISO_8601) {
 | |
|           configFromISO(config);
 | |
|           return;
 | |
|         }
 | |
|         if (config._f === hooks.RFC_2822) {
 | |
|           configFromRFC2822(config);
 | |
|           return;
 | |
|         }
 | |
|         config._a = [];
 | |
|         getParsingFlags(config).empty = true;
 | |
|         var string = "" + config._i, i2, parsedInput, tokens2, token2, skipped, stringLength = string.length, totalParsedInputLength = 0, era, tokenLen;
 | |
|         tokens2 = expandFormat(config._f, config._locale).match(formattingTokens) || [];
 | |
|         tokenLen = tokens2.length;
 | |
|         for (i2 = 0; i2 < tokenLen; i2++) {
 | |
|           token2 = tokens2[i2];
 | |
|           parsedInput = (string.match(getParseRegexForToken(token2, config)) || [])[0];
 | |
|           if (parsedInput) {
 | |
|             skipped = string.substr(0, string.indexOf(parsedInput));
 | |
|             if (skipped.length > 0) {
 | |
|               getParsingFlags(config).unusedInput.push(skipped);
 | |
|             }
 | |
|             string = string.slice(
 | |
|               string.indexOf(parsedInput) + parsedInput.length
 | |
|             );
 | |
|             totalParsedInputLength += parsedInput.length;
 | |
|           }
 | |
|           if (formatTokenFunctions[token2]) {
 | |
|             if (parsedInput) {
 | |
|               getParsingFlags(config).empty = false;
 | |
|             } else {
 | |
|               getParsingFlags(config).unusedTokens.push(token2);
 | |
|             }
 | |
|             addTimeToArrayFromToken(token2, parsedInput, config);
 | |
|           } else if (config._strict && !parsedInput) {
 | |
|             getParsingFlags(config).unusedTokens.push(token2);
 | |
|           }
 | |
|         }
 | |
|         getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
 | |
|         if (string.length > 0) {
 | |
|           getParsingFlags(config).unusedInput.push(string);
 | |
|         }
 | |
|         if (config._a[HOUR] <= 12 && getParsingFlags(config).bigHour === true && config._a[HOUR] > 0) {
 | |
|           getParsingFlags(config).bigHour = void 0;
 | |
|         }
 | |
|         getParsingFlags(config).parsedDateParts = config._a.slice(0);
 | |
|         getParsingFlags(config).meridiem = config._meridiem;
 | |
|         config._a[HOUR] = meridiemFixWrap(
 | |
|           config._locale,
 | |
|           config._a[HOUR],
 | |
|           config._meridiem
 | |
|         );
 | |
|         era = getParsingFlags(config).era;
 | |
|         if (era !== null) {
 | |
|           config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
 | |
|         }
 | |
|         configFromArray(config);
 | |
|         checkOverflow(config);
 | |
|       }
 | |
|       function meridiemFixWrap(locale3, hour, meridiem2) {
 | |
|         var isPm;
 | |
|         if (meridiem2 == null) {
 | |
|           return hour;
 | |
|         }
 | |
|         if (locale3.meridiemHour != null) {
 | |
|           return locale3.meridiemHour(hour, meridiem2);
 | |
|         } else if (locale3.isPM != null) {
 | |
|           isPm = locale3.isPM(meridiem2);
 | |
|           if (isPm && hour < 12) {
 | |
|             hour += 12;
 | |
|           }
 | |
|           if (!isPm && hour === 12) {
 | |
|             hour = 0;
 | |
|           }
 | |
|           return hour;
 | |
|         } else {
 | |
|           return hour;
 | |
|         }
 | |
|       }
 | |
|       function configFromStringAndArray(config) {
 | |
|         var tempConfig, bestMoment, scoreToBeat, i2, currentScore, validFormatFound, bestFormatIsValid = false, configfLen = config._f.length;
 | |
|         if (configfLen === 0) {
 | |
|           getParsingFlags(config).invalidFormat = true;
 | |
|           config._d = /* @__PURE__ */ new Date(NaN);
 | |
|           return;
 | |
|         }
 | |
|         for (i2 = 0; i2 < configfLen; i2++) {
 | |
|           currentScore = 0;
 | |
|           validFormatFound = false;
 | |
|           tempConfig = copyConfig({}, config);
 | |
|           if (config._useUTC != null) {
 | |
|             tempConfig._useUTC = config._useUTC;
 | |
|           }
 | |
|           tempConfig._f = config._f[i2];
 | |
|           configFromStringAndFormat(tempConfig);
 | |
|           if (isValid(tempConfig)) {
 | |
|             validFormatFound = true;
 | |
|           }
 | |
|           currentScore += getParsingFlags(tempConfig).charsLeftOver;
 | |
|           currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
 | |
|           getParsingFlags(tempConfig).score = currentScore;
 | |
|           if (!bestFormatIsValid) {
 | |
|             if (scoreToBeat == null || currentScore < scoreToBeat || validFormatFound) {
 | |
|               scoreToBeat = currentScore;
 | |
|               bestMoment = tempConfig;
 | |
|               if (validFormatFound) {
 | |
|                 bestFormatIsValid = true;
 | |
|               }
 | |
|             }
 | |
|           } else {
 | |
|             if (currentScore < scoreToBeat) {
 | |
|               scoreToBeat = currentScore;
 | |
|               bestMoment = tempConfig;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         extend(config, bestMoment || tempConfig);
 | |
|       }
 | |
|       function configFromObject(config) {
 | |
|         if (config._d) {
 | |
|           return;
 | |
|         }
 | |
|         var i2 = normalizeObjectUnits(config._i), dayOrDate = i2.day === void 0 ? i2.date : i2.day;
 | |
|         config._a = map3(
 | |
|           [i2.year, i2.month, dayOrDate, i2.hour, i2.minute, i2.second, i2.millisecond],
 | |
|           function(obj) {
 | |
|             return obj && parseInt(obj, 10);
 | |
|           }
 | |
|         );
 | |
|         configFromArray(config);
 | |
|       }
 | |
|       function createFromConfig(config) {
 | |
|         var res = new Moment3(checkOverflow(prepareConfig(config)));
 | |
|         if (res._nextDay) {
 | |
|           res.add(1, "d");
 | |
|           res._nextDay = void 0;
 | |
|         }
 | |
|         return res;
 | |
|       }
 | |
|       function prepareConfig(config) {
 | |
|         var input = config._i, format2 = config._f;
 | |
|         config._locale = config._locale || getLocale(config._l);
 | |
|         if (input === null || format2 === void 0 && input === "") {
 | |
|           return createInvalid({ nullInput: true });
 | |
|         }
 | |
|         if (typeof input === "string") {
 | |
|           config._i = input = config._locale.preparse(input);
 | |
|         }
 | |
|         if (isMoment(input)) {
 | |
|           return new Moment3(checkOverflow(input));
 | |
|         } else if (isDate(input)) {
 | |
|           config._d = input;
 | |
|         } else if (isArray2(format2)) {
 | |
|           configFromStringAndArray(config);
 | |
|         } else if (format2) {
 | |
|           configFromStringAndFormat(config);
 | |
|         } else {
 | |
|           configFromInput(config);
 | |
|         }
 | |
|         if (!isValid(config)) {
 | |
|           config._d = null;
 | |
|         }
 | |
|         return config;
 | |
|       }
 | |
|       function configFromInput(config) {
 | |
|         var input = config._i;
 | |
|         if (isUndefined(input)) {
 | |
|           config._d = new Date(hooks.now());
 | |
|         } else if (isDate(input)) {
 | |
|           config._d = new Date(input.valueOf());
 | |
|         } else if (typeof input === "string") {
 | |
|           configFromString(config);
 | |
|         } else if (isArray2(input)) {
 | |
|           config._a = map3(input.slice(0), function(obj) {
 | |
|             return parseInt(obj, 10);
 | |
|           });
 | |
|           configFromArray(config);
 | |
|         } else if (isObject2(input)) {
 | |
|           configFromObject(config);
 | |
|         } else if (isNumber2(input)) {
 | |
|           config._d = new Date(input);
 | |
|         } else {
 | |
|           hooks.createFromInputFallback(config);
 | |
|         }
 | |
|       }
 | |
|       function createLocalOrUTC(input, format2, locale3, strict, isUTC) {
 | |
|         var c2 = {};
 | |
|         if (format2 === true || format2 === false) {
 | |
|           strict = format2;
 | |
|           format2 = void 0;
 | |
|         }
 | |
|         if (locale3 === true || locale3 === false) {
 | |
|           strict = locale3;
 | |
|           locale3 = void 0;
 | |
|         }
 | |
|         if (isObject2(input) && isObjectEmpty(input) || isArray2(input) && input.length === 0) {
 | |
|           input = void 0;
 | |
|         }
 | |
|         c2._isAMomentObject = true;
 | |
|         c2._useUTC = c2._isUTC = isUTC;
 | |
|         c2._l = locale3;
 | |
|         c2._i = input;
 | |
|         c2._f = format2;
 | |
|         c2._strict = strict;
 | |
|         return createFromConfig(c2);
 | |
|       }
 | |
|       function createLocal(input, format2, locale3, strict) {
 | |
|         return createLocalOrUTC(input, format2, locale3, strict, false);
 | |
|       }
 | |
|       var prototypeMin = deprecate(
 | |
|         "moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",
 | |
|         function() {
 | |
|           var other = createLocal.apply(null, arguments);
 | |
|           if (this.isValid() && other.isValid()) {
 | |
|             return other < this ? this : other;
 | |
|           } else {
 | |
|             return createInvalid();
 | |
|           }
 | |
|         }
 | |
|       ), prototypeMax = deprecate(
 | |
|         "moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",
 | |
|         function() {
 | |
|           var other = createLocal.apply(null, arguments);
 | |
|           if (this.isValid() && other.isValid()) {
 | |
|             return other > this ? this : other;
 | |
|           } else {
 | |
|             return createInvalid();
 | |
|           }
 | |
|         }
 | |
|       );
 | |
|       function pickBy(fn2, moments) {
 | |
|         var res, i2;
 | |
|         if (moments.length === 1 && isArray2(moments[0])) {
 | |
|           moments = moments[0];
 | |
|         }
 | |
|         if (!moments.length) {
 | |
|           return createLocal();
 | |
|         }
 | |
|         res = moments[0];
 | |
|         for (i2 = 1; i2 < moments.length; ++i2) {
 | |
|           if (!moments[i2].isValid() || moments[i2][fn2](res)) {
 | |
|             res = moments[i2];
 | |
|           }
 | |
|         }
 | |
|         return res;
 | |
|       }
 | |
|       function min() {
 | |
|         var args = [].slice.call(arguments, 0);
 | |
|         return pickBy("isBefore", args);
 | |
|       }
 | |
|       function max() {
 | |
|         var args = [].slice.call(arguments, 0);
 | |
|         return pickBy("isAfter", args);
 | |
|       }
 | |
|       var now2 = function() {
 | |
|         return Date.now ? Date.now() : +/* @__PURE__ */ new Date();
 | |
|       };
 | |
|       var ordering = [
 | |
|         "year",
 | |
|         "quarter",
 | |
|         "month",
 | |
|         "week",
 | |
|         "day",
 | |
|         "hour",
 | |
|         "minute",
 | |
|         "second",
 | |
|         "millisecond"
 | |
|       ];
 | |
|       function isDurationValid(m2) {
 | |
|         var key, unitHasDecimal = false, i2, orderLen = ordering.length;
 | |
|         for (key in m2) {
 | |
|           if (hasOwnProp(m2, key) && !(indexOf.call(ordering, key) !== -1 && (m2[key] == null || !isNaN(m2[key])))) {
 | |
|             return false;
 | |
|           }
 | |
|         }
 | |
|         for (i2 = 0; i2 < orderLen; ++i2) {
 | |
|           if (m2[ordering[i2]]) {
 | |
|             if (unitHasDecimal) {
 | |
|               return false;
 | |
|             }
 | |
|             if (parseFloat(m2[ordering[i2]]) !== toInt(m2[ordering[i2]])) {
 | |
|               unitHasDecimal = true;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         return true;
 | |
|       }
 | |
|       function isValid$1() {
 | |
|         return this._isValid;
 | |
|       }
 | |
|       function createInvalid$1() {
 | |
|         return createDuration(NaN);
 | |
|       }
 | |
|       function Duration(duration) {
 | |
|         var normalizedInput = normalizeObjectUnits(duration), years2 = normalizedInput.year || 0, quarters = normalizedInput.quarter || 0, months2 = normalizedInput.month || 0, weeks2 = normalizedInput.week || normalizedInput.isoWeek || 0, days2 = normalizedInput.day || 0, hours2 = normalizedInput.hour || 0, minutes2 = normalizedInput.minute || 0, seconds2 = normalizedInput.second || 0, milliseconds2 = normalizedInput.millisecond || 0;
 | |
|         this._isValid = isDurationValid(normalizedInput);
 | |
|         this._milliseconds = +milliseconds2 + seconds2 * 1e3 + // 1000
 | |
|         minutes2 * 6e4 + // 1000 * 60
 | |
|         hours2 * 1e3 * 60 * 60;
 | |
|         this._days = +days2 + weeks2 * 7;
 | |
|         this._months = +months2 + quarters * 3 + years2 * 12;
 | |
|         this._data = {};
 | |
|         this._locale = getLocale();
 | |
|         this._bubble();
 | |
|       }
 | |
|       function isDuration(obj) {
 | |
|         return obj instanceof Duration;
 | |
|       }
 | |
|       function absRound(number) {
 | |
|         if (number < 0) {
 | |
|           return Math.round(-1 * number) * -1;
 | |
|         } else {
 | |
|           return Math.round(number);
 | |
|         }
 | |
|       }
 | |
|       function compareArrays(array1, array2, dontConvert) {
 | |
|         var len = Math.min(array1.length, array2.length), lengthDiff = Math.abs(array1.length - array2.length), diffs = 0, i2;
 | |
|         for (i2 = 0; i2 < len; i2++) {
 | |
|           if (dontConvert && array1[i2] !== array2[i2] || !dontConvert && toInt(array1[i2]) !== toInt(array2[i2])) {
 | |
|             diffs++;
 | |
|           }
 | |
|         }
 | |
|         return diffs + lengthDiff;
 | |
|       }
 | |
|       function offset(token2, separator) {
 | |
|         addFormatToken(token2, 0, 0, function() {
 | |
|           var offset2 = this.utcOffset(), sign3 = "+";
 | |
|           if (offset2 < 0) {
 | |
|             offset2 = -offset2;
 | |
|             sign3 = "-";
 | |
|           }
 | |
|           return sign3 + zeroFill(~~(offset2 / 60), 2) + separator + zeroFill(~~offset2 % 60, 2);
 | |
|         });
 | |
|       }
 | |
|       offset("Z", ":");
 | |
|       offset("ZZ", "");
 | |
|       addRegexToken("Z", matchShortOffset);
 | |
|       addRegexToken("ZZ", matchShortOffset);
 | |
|       addParseToken(["Z", "ZZ"], function(input, array, config) {
 | |
|         config._useUTC = true;
 | |
|         config._tzm = offsetFromString(matchShortOffset, input);
 | |
|       });
 | |
|       var chunkOffset = /([\+\-]|\d\d)/gi;
 | |
|       function offsetFromString(matcher, string) {
 | |
|         var matches = (string || "").match(matcher), chunk, parts, minutes2;
 | |
|         if (matches === null) {
 | |
|           return null;
 | |
|         }
 | |
|         chunk = matches[matches.length - 1] || [];
 | |
|         parts = (chunk + "").match(chunkOffset) || ["-", 0, 0];
 | |
|         minutes2 = +(parts[1] * 60) + toInt(parts[2]);
 | |
|         return minutes2 === 0 ? 0 : parts[0] === "+" ? minutes2 : -minutes2;
 | |
|       }
 | |
|       function cloneWithOffset(input, model) {
 | |
|         var res, diff2;
 | |
|         if (model._isUTC) {
 | |
|           res = model.clone();
 | |
|           diff2 = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
 | |
|           res._d.setTime(res._d.valueOf() + diff2);
 | |
|           hooks.updateOffset(res, false);
 | |
|           return res;
 | |
|         } else {
 | |
|           return createLocal(input).local();
 | |
|         }
 | |
|       }
 | |
|       function getDateOffset(m2) {
 | |
|         return -Math.round(m2._d.getTimezoneOffset());
 | |
|       }
 | |
|       hooks.updateOffset = function() {
 | |
|       };
 | |
|       function getSetOffset(input, keepLocalTime, keepMinutes) {
 | |
|         var offset2 = this._offset || 0, localAdjust;
 | |
|         if (!this.isValid()) {
 | |
|           return input != null ? this : NaN;
 | |
|         }
 | |
|         if (input != null) {
 | |
|           if (typeof input === "string") {
 | |
|             input = offsetFromString(matchShortOffset, input);
 | |
|             if (input === null) {
 | |
|               return this;
 | |
|             }
 | |
|           } else if (Math.abs(input) < 16 && !keepMinutes) {
 | |
|             input = input * 60;
 | |
|           }
 | |
|           if (!this._isUTC && keepLocalTime) {
 | |
|             localAdjust = getDateOffset(this);
 | |
|           }
 | |
|           this._offset = input;
 | |
|           this._isUTC = true;
 | |
|           if (localAdjust != null) {
 | |
|             this.add(localAdjust, "m");
 | |
|           }
 | |
|           if (offset2 !== input) {
 | |
|             if (!keepLocalTime || this._changeInProgress) {
 | |
|               addSubtract(
 | |
|                 this,
 | |
|                 createDuration(input - offset2, "m"),
 | |
|                 1,
 | |
|                 false
 | |
|               );
 | |
|             } else if (!this._changeInProgress) {
 | |
|               this._changeInProgress = true;
 | |
|               hooks.updateOffset(this, true);
 | |
|               this._changeInProgress = null;
 | |
|             }
 | |
|           }
 | |
|           return this;
 | |
|         } else {
 | |
|           return this._isUTC ? offset2 : getDateOffset(this);
 | |
|         }
 | |
|       }
 | |
|       function getSetZone(input, keepLocalTime) {
 | |
|         if (input != null) {
 | |
|           if (typeof input !== "string") {
 | |
|             input = -input;
 | |
|           }
 | |
|           this.utcOffset(input, keepLocalTime);
 | |
|           return this;
 | |
|         } else {
 | |
|           return -this.utcOffset();
 | |
|         }
 | |
|       }
 | |
|       function setOffsetToUTC(keepLocalTime) {
 | |
|         return this.utcOffset(0, keepLocalTime);
 | |
|       }
 | |
|       function setOffsetToLocal(keepLocalTime) {
 | |
|         if (this._isUTC) {
 | |
|           this.utcOffset(0, keepLocalTime);
 | |
|           this._isUTC = false;
 | |
|           if (keepLocalTime) {
 | |
|             this.subtract(getDateOffset(this), "m");
 | |
|           }
 | |
|         }
 | |
|         return this;
 | |
|       }
 | |
|       function setOffsetToParsedOffset() {
 | |
|         if (this._tzm != null) {
 | |
|           this.utcOffset(this._tzm, false, true);
 | |
|         } else if (typeof this._i === "string") {
 | |
|           var tZone = offsetFromString(matchOffset, this._i);
 | |
|           if (tZone != null) {
 | |
|             this.utcOffset(tZone);
 | |
|           } else {
 | |
|             this.utcOffset(0, true);
 | |
|           }
 | |
|         }
 | |
|         return this;
 | |
|       }
 | |
|       function hasAlignedHourOffset(input) {
 | |
|         if (!this.isValid()) {
 | |
|           return false;
 | |
|         }
 | |
|         input = input ? createLocal(input).utcOffset() : 0;
 | |
|         return (this.utcOffset() - input) % 60 === 0;
 | |
|       }
 | |
|       function isDaylightSavingTime() {
 | |
|         return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset();
 | |
|       }
 | |
|       function isDaylightSavingTimeShifted() {
 | |
|         if (!isUndefined(this._isDSTShifted)) {
 | |
|           return this._isDSTShifted;
 | |
|         }
 | |
|         var c2 = {}, other;
 | |
|         copyConfig(c2, this);
 | |
|         c2 = prepareConfig(c2);
 | |
|         if (c2._a) {
 | |
|           other = c2._isUTC ? createUTC(c2._a) : createLocal(c2._a);
 | |
|           this._isDSTShifted = this.isValid() && compareArrays(c2._a, other.toArray()) > 0;
 | |
|         } else {
 | |
|           this._isDSTShifted = false;
 | |
|         }
 | |
|         return this._isDSTShifted;
 | |
|       }
 | |
|       function isLocal() {
 | |
|         return this.isValid() ? !this._isUTC : false;
 | |
|       }
 | |
|       function isUtcOffset() {
 | |
|         return this.isValid() ? this._isUTC : false;
 | |
|       }
 | |
|       function isUtc() {
 | |
|         return this.isValid() ? this._isUTC && this._offset === 0 : false;
 | |
|       }
 | |
|       var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/, isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
 | |
|       function createDuration(input, key) {
 | |
|         var duration = input, match5 = null, sign3, ret, diffRes;
 | |
|         if (isDuration(input)) {
 | |
|           duration = {
 | |
|             ms: input._milliseconds,
 | |
|             d: input._days,
 | |
|             M: input._months
 | |
|           };
 | |
|         } else if (isNumber2(input) || !isNaN(+input)) {
 | |
|           duration = {};
 | |
|           if (key) {
 | |
|             duration[key] = +input;
 | |
|           } else {
 | |
|             duration.milliseconds = +input;
 | |
|           }
 | |
|         } else if (match5 = aspNetRegex.exec(input)) {
 | |
|           sign3 = match5[1] === "-" ? -1 : 1;
 | |
|           duration = {
 | |
|             y: 0,
 | |
|             d: toInt(match5[DATE]) * sign3,
 | |
|             h: toInt(match5[HOUR]) * sign3,
 | |
|             m: toInt(match5[MINUTE]) * sign3,
 | |
|             s: toInt(match5[SECOND]) * sign3,
 | |
|             ms: toInt(absRound(match5[MILLISECOND] * 1e3)) * sign3
 | |
|             // the millisecond decimal point is included in the match
 | |
|           };
 | |
|         } else if (match5 = isoRegex.exec(input)) {
 | |
|           sign3 = match5[1] === "-" ? -1 : 1;
 | |
|           duration = {
 | |
|             y: parseIso(match5[2], sign3),
 | |
|             M: parseIso(match5[3], sign3),
 | |
|             w: parseIso(match5[4], sign3),
 | |
|             d: parseIso(match5[5], sign3),
 | |
|             h: parseIso(match5[6], sign3),
 | |
|             m: parseIso(match5[7], sign3),
 | |
|             s: parseIso(match5[8], sign3)
 | |
|           };
 | |
|         } else if (duration == null) {
 | |
|           duration = {};
 | |
|         } else if (typeof duration === "object" && ("from" in duration || "to" in duration)) {
 | |
|           diffRes = momentsDifference(
 | |
|             createLocal(duration.from),
 | |
|             createLocal(duration.to)
 | |
|           );
 | |
|           duration = {};
 | |
|           duration.ms = diffRes.milliseconds;
 | |
|           duration.M = diffRes.months;
 | |
|         }
 | |
|         ret = new Duration(duration);
 | |
|         if (isDuration(input) && hasOwnProp(input, "_locale")) {
 | |
|           ret._locale = input._locale;
 | |
|         }
 | |
|         if (isDuration(input) && hasOwnProp(input, "_isValid")) {
 | |
|           ret._isValid = input._isValid;
 | |
|         }
 | |
|         return ret;
 | |
|       }
 | |
|       createDuration.fn = Duration.prototype;
 | |
|       createDuration.invalid = createInvalid$1;
 | |
|       function parseIso(inp, sign3) {
 | |
|         var res = inp && parseFloat(inp.replace(",", "."));
 | |
|         return (isNaN(res) ? 0 : res) * sign3;
 | |
|       }
 | |
|       function positiveMomentsDifference(base, other) {
 | |
|         var res = {};
 | |
|         res.months = other.month() - base.month() + (other.year() - base.year()) * 12;
 | |
|         if (base.clone().add(res.months, "M").isAfter(other)) {
 | |
|           --res.months;
 | |
|         }
 | |
|         res.milliseconds = +other - +base.clone().add(res.months, "M");
 | |
|         return res;
 | |
|       }
 | |
|       function momentsDifference(base, other) {
 | |
|         var res;
 | |
|         if (!(base.isValid() && other.isValid())) {
 | |
|           return { milliseconds: 0, months: 0 };
 | |
|         }
 | |
|         other = cloneWithOffset(other, base);
 | |
|         if (base.isBefore(other)) {
 | |
|           res = positiveMomentsDifference(base, other);
 | |
|         } else {
 | |
|           res = positiveMomentsDifference(other, base);
 | |
|           res.milliseconds = -res.milliseconds;
 | |
|           res.months = -res.months;
 | |
|         }
 | |
|         return res;
 | |
|       }
 | |
|       function createAdder(direction, name) {
 | |
|         return function(val, period) {
 | |
|           var dur, tmp;
 | |
|           if (period !== null && !isNaN(+period)) {
 | |
|             deprecateSimple(
 | |
|               name,
 | |
|               "moment()." + name + "(period, number) is deprecated. Please use moment()." + name + "(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."
 | |
|             );
 | |
|             tmp = val;
 | |
|             val = period;
 | |
|             period = tmp;
 | |
|           }
 | |
|           dur = createDuration(val, period);
 | |
|           addSubtract(this, dur, direction);
 | |
|           return this;
 | |
|         };
 | |
|       }
 | |
|       function addSubtract(mom, duration, isAdding, updateOffset) {
 | |
|         var milliseconds2 = duration._milliseconds, days2 = absRound(duration._days), months2 = absRound(duration._months);
 | |
|         if (!mom.isValid()) {
 | |
|           return;
 | |
|         }
 | |
|         updateOffset = updateOffset == null ? true : updateOffset;
 | |
|         if (months2) {
 | |
|           setMonth(mom, get(mom, "Month") + months2 * isAdding);
 | |
|         }
 | |
|         if (days2) {
 | |
|           set$1(mom, "Date", get(mom, "Date") + days2 * isAdding);
 | |
|         }
 | |
|         if (milliseconds2) {
 | |
|           mom._d.setTime(mom._d.valueOf() + milliseconds2 * isAdding);
 | |
|         }
 | |
|         if (updateOffset) {
 | |
|           hooks.updateOffset(mom, days2 || months2);
 | |
|         }
 | |
|       }
 | |
|       var add = createAdder(1, "add"), subtract = createAdder(-1, "subtract");
 | |
|       function isString(input) {
 | |
|         return typeof input === "string" || input instanceof String;
 | |
|       }
 | |
|       function isMomentInput(input) {
 | |
|         return isMoment(input) || isDate(input) || isString(input) || isNumber2(input) || isNumberOrStringArray(input) || isMomentInputObject(input) || input === null || input === void 0;
 | |
|       }
 | |
|       function isMomentInputObject(input) {
 | |
|         var objectTest = isObject2(input) && !isObjectEmpty(input), propertyTest = false, properties = [
 | |
|           "years",
 | |
|           "year",
 | |
|           "y",
 | |
|           "months",
 | |
|           "month",
 | |
|           "M",
 | |
|           "days",
 | |
|           "day",
 | |
|           "d",
 | |
|           "dates",
 | |
|           "date",
 | |
|           "D",
 | |
|           "hours",
 | |
|           "hour",
 | |
|           "h",
 | |
|           "minutes",
 | |
|           "minute",
 | |
|           "m",
 | |
|           "seconds",
 | |
|           "second",
 | |
|           "s",
 | |
|           "milliseconds",
 | |
|           "millisecond",
 | |
|           "ms"
 | |
|         ], i2, property, propertyLen = properties.length;
 | |
|         for (i2 = 0; i2 < propertyLen; i2 += 1) {
 | |
|           property = properties[i2];
 | |
|           propertyTest = propertyTest || hasOwnProp(input, property);
 | |
|         }
 | |
|         return objectTest && propertyTest;
 | |
|       }
 | |
|       function isNumberOrStringArray(input) {
 | |
|         var arrayTest = isArray2(input), dataTypeTest = false;
 | |
|         if (arrayTest) {
 | |
|           dataTypeTest = input.filter(function(item) {
 | |
|             return !isNumber2(item) && isString(input);
 | |
|           }).length === 0;
 | |
|         }
 | |
|         return arrayTest && dataTypeTest;
 | |
|       }
 | |
|       function isCalendarSpec(input) {
 | |
|         var objectTest = isObject2(input) && !isObjectEmpty(input), propertyTest = false, properties = [
 | |
|           "sameDay",
 | |
|           "nextDay",
 | |
|           "lastDay",
 | |
|           "nextWeek",
 | |
|           "lastWeek",
 | |
|           "sameElse"
 | |
|         ], i2, property;
 | |
|         for (i2 = 0; i2 < properties.length; i2 += 1) {
 | |
|           property = properties[i2];
 | |
|           propertyTest = propertyTest || hasOwnProp(input, property);
 | |
|         }
 | |
|         return objectTest && propertyTest;
 | |
|       }
 | |
|       function getCalendarFormat(myMoment, now3) {
 | |
|         var diff2 = myMoment.diff(now3, "days", true);
 | |
|         return diff2 < -6 ? "sameElse" : diff2 < -1 ? "lastWeek" : diff2 < 0 ? "lastDay" : diff2 < 1 ? "sameDay" : diff2 < 2 ? "nextDay" : diff2 < 7 ? "nextWeek" : "sameElse";
 | |
|       }
 | |
|       function calendar$1(time, formats) {
 | |
|         if (arguments.length === 1) {
 | |
|           if (!arguments[0]) {
 | |
|             time = void 0;
 | |
|             formats = void 0;
 | |
|           } else if (isMomentInput(arguments[0])) {
 | |
|             time = arguments[0];
 | |
|             formats = void 0;
 | |
|           } else if (isCalendarSpec(arguments[0])) {
 | |
|             formats = arguments[0];
 | |
|             time = void 0;
 | |
|           }
 | |
|         }
 | |
|         var now3 = time || createLocal(), sod = cloneWithOffset(now3, this).startOf("day"), format2 = hooks.calendarFormat(this, sod) || "sameElse", output = formats && (isFunction2(formats[format2]) ? formats[format2].call(this, now3) : formats[format2]);
 | |
|         return this.format(
 | |
|           output || this.localeData().calendar(format2, this, createLocal(now3))
 | |
|         );
 | |
|       }
 | |
|       function clone3() {
 | |
|         return new Moment3(this);
 | |
|       }
 | |
|       function isAfter(input, units) {
 | |
|         var localInput = isMoment(input) ? input : createLocal(input);
 | |
|         if (!(this.isValid() && localInput.isValid())) {
 | |
|           return false;
 | |
|         }
 | |
|         units = normalizeUnits(units) || "millisecond";
 | |
|         if (units === "millisecond") {
 | |
|           return this.valueOf() > localInput.valueOf();
 | |
|         } else {
 | |
|           return localInput.valueOf() < this.clone().startOf(units).valueOf();
 | |
|         }
 | |
|       }
 | |
|       function isBefore(input, units) {
 | |
|         var localInput = isMoment(input) ? input : createLocal(input);
 | |
|         if (!(this.isValid() && localInput.isValid())) {
 | |
|           return false;
 | |
|         }
 | |
|         units = normalizeUnits(units) || "millisecond";
 | |
|         if (units === "millisecond") {
 | |
|           return this.valueOf() < localInput.valueOf();
 | |
|         } else {
 | |
|           return this.clone().endOf(units).valueOf() < localInput.valueOf();
 | |
|         }
 | |
|       }
 | |
|       function isBetween(from3, to3, units, inclusivity) {
 | |
|         var localFrom = isMoment(from3) ? from3 : createLocal(from3), localTo = isMoment(to3) ? to3 : createLocal(to3);
 | |
|         if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
 | |
|           return false;
 | |
|         }
 | |
|         inclusivity = inclusivity || "()";
 | |
|         return (inclusivity[0] === "(" ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && (inclusivity[1] === ")" ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
 | |
|       }
 | |
|       function isSame(input, units) {
 | |
|         var localInput = isMoment(input) ? input : createLocal(input), inputMs;
 | |
|         if (!(this.isValid() && localInput.isValid())) {
 | |
|           return false;
 | |
|         }
 | |
|         units = normalizeUnits(units) || "millisecond";
 | |
|         if (units === "millisecond") {
 | |
|           return this.valueOf() === localInput.valueOf();
 | |
|         } else {
 | |
|           inputMs = localInput.valueOf();
 | |
|           return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
 | |
|         }
 | |
|       }
 | |
|       function isSameOrAfter(input, units) {
 | |
|         return this.isSame(input, units) || this.isAfter(input, units);
 | |
|       }
 | |
|       function isSameOrBefore(input, units) {
 | |
|         return this.isSame(input, units) || this.isBefore(input, units);
 | |
|       }
 | |
|       function diff(input, units, asFloat) {
 | |
|         var that, zoneDelta, output;
 | |
|         if (!this.isValid()) {
 | |
|           return NaN;
 | |
|         }
 | |
|         that = cloneWithOffset(input, this);
 | |
|         if (!that.isValid()) {
 | |
|           return NaN;
 | |
|         }
 | |
|         zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
 | |
|         units = normalizeUnits(units);
 | |
|         switch (units) {
 | |
|           case "year":
 | |
|             output = monthDiff(this, that) / 12;
 | |
|             break;
 | |
|           case "month":
 | |
|             output = monthDiff(this, that);
 | |
|             break;
 | |
|           case "quarter":
 | |
|             output = monthDiff(this, that) / 3;
 | |
|             break;
 | |
|           case "second":
 | |
|             output = (this - that) / 1e3;
 | |
|             break;
 | |
|           // 1000
 | |
|           case "minute":
 | |
|             output = (this - that) / 6e4;
 | |
|             break;
 | |
|           // 1000 * 60
 | |
|           case "hour":
 | |
|             output = (this - that) / 36e5;
 | |
|             break;
 | |
|           // 1000 * 60 * 60
 | |
|           case "day":
 | |
|             output = (this - that - zoneDelta) / 864e5;
 | |
|             break;
 | |
|           // 1000 * 60 * 60 * 24, negate dst
 | |
|           case "week":
 | |
|             output = (this - that - zoneDelta) / 6048e5;
 | |
|             break;
 | |
|           // 1000 * 60 * 60 * 24 * 7, negate dst
 | |
|           default:
 | |
|             output = this - that;
 | |
|         }
 | |
|         return asFloat ? output : absFloor(output);
 | |
|       }
 | |
|       function monthDiff(a2, b2) {
 | |
|         if (a2.date() < b2.date()) {
 | |
|           return -monthDiff(b2, a2);
 | |
|         }
 | |
|         var wholeMonthDiff = (b2.year() - a2.year()) * 12 + (b2.month() - a2.month()), anchor = a2.clone().add(wholeMonthDiff, "months"), anchor2, adjust;
 | |
|         if (b2 - anchor < 0) {
 | |
|           anchor2 = a2.clone().add(wholeMonthDiff - 1, "months");
 | |
|           adjust = (b2 - anchor) / (anchor - anchor2);
 | |
|         } else {
 | |
|           anchor2 = a2.clone().add(wholeMonthDiff + 1, "months");
 | |
|           adjust = (b2 - anchor) / (anchor2 - anchor);
 | |
|         }
 | |
|         return -(wholeMonthDiff + adjust) || 0;
 | |
|       }
 | |
|       hooks.defaultFormat = "YYYY-MM-DDTHH:mm:ssZ";
 | |
|       hooks.defaultFormatUtc = "YYYY-MM-DDTHH:mm:ss[Z]";
 | |
|       function toString() {
 | |
|         return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
 | |
|       }
 | |
|       function toISOString(keepOffset) {
 | |
|         if (!this.isValid()) {
 | |
|           return null;
 | |
|         }
 | |
|         var utc = keepOffset !== true, m2 = utc ? this.clone().utc() : this;
 | |
|         if (m2.year() < 0 || m2.year() > 9999) {
 | |
|           return formatMoment(
 | |
|             m2,
 | |
|             utc ? "YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]" : "YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"
 | |
|           );
 | |
|         }
 | |
|         if (isFunction2(Date.prototype.toISOString)) {
 | |
|           if (utc) {
 | |
|             return this.toDate().toISOString();
 | |
|           } else {
 | |
|             return new Date(this.valueOf() + this.utcOffset() * 60 * 1e3).toISOString().replace("Z", formatMoment(m2, "Z"));
 | |
|           }
 | |
|         }
 | |
|         return formatMoment(
 | |
|           m2,
 | |
|           utc ? "YYYY-MM-DD[T]HH:mm:ss.SSS[Z]" : "YYYY-MM-DD[T]HH:mm:ss.SSSZ"
 | |
|         );
 | |
|       }
 | |
|       function inspect() {
 | |
|         if (!this.isValid()) {
 | |
|           return "moment.invalid(/* " + this._i + " */)";
 | |
|         }
 | |
|         var func = "moment", zone = "", prefix, year, datetime, suffix;
 | |
|         if (!this.isLocal()) {
 | |
|           func = this.utcOffset() === 0 ? "moment.utc" : "moment.parseZone";
 | |
|           zone = "Z";
 | |
|         }
 | |
|         prefix = "[" + func + '("]';
 | |
|         year = 0 <= this.year() && this.year() <= 9999 ? "YYYY" : "YYYYYY";
 | |
|         datetime = "-MM-DD[T]HH:mm:ss.SSS";
 | |
|         suffix = zone + '[")]';
 | |
|         return this.format(prefix + year + datetime + suffix);
 | |
|       }
 | |
|       function format(inputString) {
 | |
|         if (!inputString) {
 | |
|           inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
 | |
|         }
 | |
|         var output = formatMoment(this, inputString);
 | |
|         return this.localeData().postformat(output);
 | |
|       }
 | |
|       function from2(time, withoutSuffix) {
 | |
|         if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
 | |
|           return createDuration({ to: this, from: time }).locale(this.locale()).humanize(!withoutSuffix);
 | |
|         } else {
 | |
|           return this.localeData().invalidDate();
 | |
|         }
 | |
|       }
 | |
|       function fromNow(withoutSuffix) {
 | |
|         return this.from(createLocal(), withoutSuffix);
 | |
|       }
 | |
|       function to2(time, withoutSuffix) {
 | |
|         if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
 | |
|           return createDuration({ from: this, to: time }).locale(this.locale()).humanize(!withoutSuffix);
 | |
|         } else {
 | |
|           return this.localeData().invalidDate();
 | |
|         }
 | |
|       }
 | |
|       function toNow(withoutSuffix) {
 | |
|         return this.to(createLocal(), withoutSuffix);
 | |
|       }
 | |
|       function locale2(key) {
 | |
|         var newLocaleData;
 | |
|         if (key === void 0) {
 | |
|           return this._locale._abbr;
 | |
|         } else {
 | |
|           newLocaleData = getLocale(key);
 | |
|           if (newLocaleData != null) {
 | |
|             this._locale = newLocaleData;
 | |
|           }
 | |
|           return this;
 | |
|         }
 | |
|       }
 | |
|       var lang = deprecate(
 | |
|         "moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",
 | |
|         function(key) {
 | |
|           if (key === void 0) {
 | |
|             return this.localeData();
 | |
|           } else {
 | |
|             return this.locale(key);
 | |
|           }
 | |
|         }
 | |
|       );
 | |
|       function localeData() {
 | |
|         return this._locale;
 | |
|       }
 | |
|       var MS_PER_SECOND = 1e3, MS_PER_MINUTE = 60 * MS_PER_SECOND, MS_PER_HOUR = 60 * MS_PER_MINUTE, MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
 | |
|       function mod$1(dividend, divisor) {
 | |
|         return (dividend % divisor + divisor) % divisor;
 | |
|       }
 | |
|       function localStartOfDate(y2, m2, d2) {
 | |
|         if (y2 < 100 && y2 >= 0) {
 | |
|           return new Date(y2 + 400, m2, d2) - MS_PER_400_YEARS;
 | |
|         } else {
 | |
|           return new Date(y2, m2, d2).valueOf();
 | |
|         }
 | |
|       }
 | |
|       function utcStartOfDate(y2, m2, d2) {
 | |
|         if (y2 < 100 && y2 >= 0) {
 | |
|           return Date.UTC(y2 + 400, m2, d2) - MS_PER_400_YEARS;
 | |
|         } else {
 | |
|           return Date.UTC(y2, m2, d2);
 | |
|         }
 | |
|       }
 | |
|       function startOf(units) {
 | |
|         var time, startOfDate;
 | |
|         units = normalizeUnits(units);
 | |
|         if (units === void 0 || units === "millisecond" || !this.isValid()) {
 | |
|           return this;
 | |
|         }
 | |
|         startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
 | |
|         switch (units) {
 | |
|           case "year":
 | |
|             time = startOfDate(this.year(), 0, 1);
 | |
|             break;
 | |
|           case "quarter":
 | |
|             time = startOfDate(
 | |
|               this.year(),
 | |
|               this.month() - this.month() % 3,
 | |
|               1
 | |
|             );
 | |
|             break;
 | |
|           case "month":
 | |
|             time = startOfDate(this.year(), this.month(), 1);
 | |
|             break;
 | |
|           case "week":
 | |
|             time = startOfDate(
 | |
|               this.year(),
 | |
|               this.month(),
 | |
|               this.date() - this.weekday()
 | |
|             );
 | |
|             break;
 | |
|           case "isoWeek":
 | |
|             time = startOfDate(
 | |
|               this.year(),
 | |
|               this.month(),
 | |
|               this.date() - (this.isoWeekday() - 1)
 | |
|             );
 | |
|             break;
 | |
|           case "day":
 | |
|           case "date":
 | |
|             time = startOfDate(this.year(), this.month(), this.date());
 | |
|             break;
 | |
|           case "hour":
 | |
|             time = this._d.valueOf();
 | |
|             time -= mod$1(
 | |
|               time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
 | |
|               MS_PER_HOUR
 | |
|             );
 | |
|             break;
 | |
|           case "minute":
 | |
|             time = this._d.valueOf();
 | |
|             time -= mod$1(time, MS_PER_MINUTE);
 | |
|             break;
 | |
|           case "second":
 | |
|             time = this._d.valueOf();
 | |
|             time -= mod$1(time, MS_PER_SECOND);
 | |
|             break;
 | |
|         }
 | |
|         this._d.setTime(time);
 | |
|         hooks.updateOffset(this, true);
 | |
|         return this;
 | |
|       }
 | |
|       function endOf(units) {
 | |
|         var time, startOfDate;
 | |
|         units = normalizeUnits(units);
 | |
|         if (units === void 0 || units === "millisecond" || !this.isValid()) {
 | |
|           return this;
 | |
|         }
 | |
|         startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
 | |
|         switch (units) {
 | |
|           case "year":
 | |
|             time = startOfDate(this.year() + 1, 0, 1) - 1;
 | |
|             break;
 | |
|           case "quarter":
 | |
|             time = startOfDate(
 | |
|               this.year(),
 | |
|               this.month() - this.month() % 3 + 3,
 | |
|               1
 | |
|             ) - 1;
 | |
|             break;
 | |
|           case "month":
 | |
|             time = startOfDate(this.year(), this.month() + 1, 1) - 1;
 | |
|             break;
 | |
|           case "week":
 | |
|             time = startOfDate(
 | |
|               this.year(),
 | |
|               this.month(),
 | |
|               this.date() - this.weekday() + 7
 | |
|             ) - 1;
 | |
|             break;
 | |
|           case "isoWeek":
 | |
|             time = startOfDate(
 | |
|               this.year(),
 | |
|               this.month(),
 | |
|               this.date() - (this.isoWeekday() - 1) + 7
 | |
|             ) - 1;
 | |
|             break;
 | |
|           case "day":
 | |
|           case "date":
 | |
|             time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
 | |
|             break;
 | |
|           case "hour":
 | |
|             time = this._d.valueOf();
 | |
|             time += MS_PER_HOUR - mod$1(
 | |
|               time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
 | |
|               MS_PER_HOUR
 | |
|             ) - 1;
 | |
|             break;
 | |
|           case "minute":
 | |
|             time = this._d.valueOf();
 | |
|             time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
 | |
|             break;
 | |
|           case "second":
 | |
|             time = this._d.valueOf();
 | |
|             time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
 | |
|             break;
 | |
|         }
 | |
|         this._d.setTime(time);
 | |
|         hooks.updateOffset(this, true);
 | |
|         return this;
 | |
|       }
 | |
|       function valueOf() {
 | |
|         return this._d.valueOf() - (this._offset || 0) * 6e4;
 | |
|       }
 | |
|       function unix() {
 | |
|         return Math.floor(this.valueOf() / 1e3);
 | |
|       }
 | |
|       function toDate() {
 | |
|         return new Date(this.valueOf());
 | |
|       }
 | |
|       function toArray() {
 | |
|         var m2 = this;
 | |
|         return [
 | |
|           m2.year(),
 | |
|           m2.month(),
 | |
|           m2.date(),
 | |
|           m2.hour(),
 | |
|           m2.minute(),
 | |
|           m2.second(),
 | |
|           m2.millisecond()
 | |
|         ];
 | |
|       }
 | |
|       function toObject() {
 | |
|         var m2 = this;
 | |
|         return {
 | |
|           years: m2.year(),
 | |
|           months: m2.month(),
 | |
|           date: m2.date(),
 | |
|           hours: m2.hours(),
 | |
|           minutes: m2.minutes(),
 | |
|           seconds: m2.seconds(),
 | |
|           milliseconds: m2.milliseconds()
 | |
|         };
 | |
|       }
 | |
|       function toJSON() {
 | |
|         return this.isValid() ? this.toISOString() : null;
 | |
|       }
 | |
|       function isValid$2() {
 | |
|         return isValid(this);
 | |
|       }
 | |
|       function parsingFlags() {
 | |
|         return extend({}, getParsingFlags(this));
 | |
|       }
 | |
|       function invalidAt() {
 | |
|         return getParsingFlags(this).overflow;
 | |
|       }
 | |
|       function creationData() {
 | |
|         return {
 | |
|           input: this._i,
 | |
|           format: this._f,
 | |
|           locale: this._locale,
 | |
|           isUTC: this._isUTC,
 | |
|           strict: this._strict
 | |
|         };
 | |
|       }
 | |
|       addFormatToken("N", 0, 0, "eraAbbr");
 | |
|       addFormatToken("NN", 0, 0, "eraAbbr");
 | |
|       addFormatToken("NNN", 0, 0, "eraAbbr");
 | |
|       addFormatToken("NNNN", 0, 0, "eraName");
 | |
|       addFormatToken("NNNNN", 0, 0, "eraNarrow");
 | |
|       addFormatToken("y", ["y", 1], "yo", "eraYear");
 | |
|       addFormatToken("y", ["yy", 2], 0, "eraYear");
 | |
|       addFormatToken("y", ["yyy", 3], 0, "eraYear");
 | |
|       addFormatToken("y", ["yyyy", 4], 0, "eraYear");
 | |
|       addRegexToken("N", matchEraAbbr);
 | |
|       addRegexToken("NN", matchEraAbbr);
 | |
|       addRegexToken("NNN", matchEraAbbr);
 | |
|       addRegexToken("NNNN", matchEraName);
 | |
|       addRegexToken("NNNNN", matchEraNarrow);
 | |
|       addParseToken(
 | |
|         ["N", "NN", "NNN", "NNNN", "NNNNN"],
 | |
|         function(input, array, config, token2) {
 | |
|           var era = config._locale.erasParse(input, token2, config._strict);
 | |
|           if (era) {
 | |
|             getParsingFlags(config).era = era;
 | |
|           } else {
 | |
|             getParsingFlags(config).invalidEra = input;
 | |
|           }
 | |
|         }
 | |
|       );
 | |
|       addRegexToken("y", matchUnsigned);
 | |
|       addRegexToken("yy", matchUnsigned);
 | |
|       addRegexToken("yyy", matchUnsigned);
 | |
|       addRegexToken("yyyy", matchUnsigned);
 | |
|       addRegexToken("yo", matchEraYearOrdinal);
 | |
|       addParseToken(["y", "yy", "yyy", "yyyy"], YEAR);
 | |
|       addParseToken(["yo"], function(input, array, config, token2) {
 | |
|         var match5;
 | |
|         if (config._locale._eraYearOrdinalRegex) {
 | |
|           match5 = input.match(config._locale._eraYearOrdinalRegex);
 | |
|         }
 | |
|         if (config._locale.eraYearOrdinalParse) {
 | |
|           array[YEAR] = config._locale.eraYearOrdinalParse(input, match5);
 | |
|         } else {
 | |
|           array[YEAR] = parseInt(input, 10);
 | |
|         }
 | |
|       });
 | |
|       function localeEras(m2, format2) {
 | |
|         var i2, l2, date, eras = this._eras || getLocale("en")._eras;
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           switch (typeof eras[i2].since) {
 | |
|             case "string":
 | |
|               date = hooks(eras[i2].since).startOf("day");
 | |
|               eras[i2].since = date.valueOf();
 | |
|               break;
 | |
|           }
 | |
|           switch (typeof eras[i2].until) {
 | |
|             case "undefined":
 | |
|               eras[i2].until = Infinity;
 | |
|               break;
 | |
|             case "string":
 | |
|               date = hooks(eras[i2].until).startOf("day").valueOf();
 | |
|               eras[i2].until = date.valueOf();
 | |
|               break;
 | |
|           }
 | |
|         }
 | |
|         return eras;
 | |
|       }
 | |
|       function localeErasParse(eraName, format2, strict) {
 | |
|         var i2, l2, eras = this.eras(), name, abbr, narrow;
 | |
|         eraName = eraName.toUpperCase();
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           name = eras[i2].name.toUpperCase();
 | |
|           abbr = eras[i2].abbr.toUpperCase();
 | |
|           narrow = eras[i2].narrow.toUpperCase();
 | |
|           if (strict) {
 | |
|             switch (format2) {
 | |
|               case "N":
 | |
|               case "NN":
 | |
|               case "NNN":
 | |
|                 if (abbr === eraName) {
 | |
|                   return eras[i2];
 | |
|                 }
 | |
|                 break;
 | |
|               case "NNNN":
 | |
|                 if (name === eraName) {
 | |
|                   return eras[i2];
 | |
|                 }
 | |
|                 break;
 | |
|               case "NNNNN":
 | |
|                 if (narrow === eraName) {
 | |
|                   return eras[i2];
 | |
|                 }
 | |
|                 break;
 | |
|             }
 | |
|           } else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
 | |
|             return eras[i2];
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       function localeErasConvertYear(era, year) {
 | |
|         var dir = era.since <= era.until ? 1 : -1;
 | |
|         if (year === void 0) {
 | |
|           return hooks(era.since).year();
 | |
|         } else {
 | |
|           return hooks(era.since).year() + (year - era.offset) * dir;
 | |
|         }
 | |
|       }
 | |
|       function getEraName() {
 | |
|         var i2, l2, val, eras = this.localeData().eras();
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           val = this.clone().startOf("day").valueOf();
 | |
|           if (eras[i2].since <= val && val <= eras[i2].until) {
 | |
|             return eras[i2].name;
 | |
|           }
 | |
|           if (eras[i2].until <= val && val <= eras[i2].since) {
 | |
|             return eras[i2].name;
 | |
|           }
 | |
|         }
 | |
|         return "";
 | |
|       }
 | |
|       function getEraNarrow() {
 | |
|         var i2, l2, val, eras = this.localeData().eras();
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           val = this.clone().startOf("day").valueOf();
 | |
|           if (eras[i2].since <= val && val <= eras[i2].until) {
 | |
|             return eras[i2].narrow;
 | |
|           }
 | |
|           if (eras[i2].until <= val && val <= eras[i2].since) {
 | |
|             return eras[i2].narrow;
 | |
|           }
 | |
|         }
 | |
|         return "";
 | |
|       }
 | |
|       function getEraAbbr() {
 | |
|         var i2, l2, val, eras = this.localeData().eras();
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           val = this.clone().startOf("day").valueOf();
 | |
|           if (eras[i2].since <= val && val <= eras[i2].until) {
 | |
|             return eras[i2].abbr;
 | |
|           }
 | |
|           if (eras[i2].until <= val && val <= eras[i2].since) {
 | |
|             return eras[i2].abbr;
 | |
|           }
 | |
|         }
 | |
|         return "";
 | |
|       }
 | |
|       function getEraYear() {
 | |
|         var i2, l2, dir, val, eras = this.localeData().eras();
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           dir = eras[i2].since <= eras[i2].until ? 1 : -1;
 | |
|           val = this.clone().startOf("day").valueOf();
 | |
|           if (eras[i2].since <= val && val <= eras[i2].until || eras[i2].until <= val && val <= eras[i2].since) {
 | |
|             return (this.year() - hooks(eras[i2].since).year()) * dir + eras[i2].offset;
 | |
|           }
 | |
|         }
 | |
|         return this.year();
 | |
|       }
 | |
|       function erasNameRegex(isStrict) {
 | |
|         if (!hasOwnProp(this, "_erasNameRegex")) {
 | |
|           computeErasParse.call(this);
 | |
|         }
 | |
|         return isStrict ? this._erasNameRegex : this._erasRegex;
 | |
|       }
 | |
|       function erasAbbrRegex(isStrict) {
 | |
|         if (!hasOwnProp(this, "_erasAbbrRegex")) {
 | |
|           computeErasParse.call(this);
 | |
|         }
 | |
|         return isStrict ? this._erasAbbrRegex : this._erasRegex;
 | |
|       }
 | |
|       function erasNarrowRegex(isStrict) {
 | |
|         if (!hasOwnProp(this, "_erasNarrowRegex")) {
 | |
|           computeErasParse.call(this);
 | |
|         }
 | |
|         return isStrict ? this._erasNarrowRegex : this._erasRegex;
 | |
|       }
 | |
|       function matchEraAbbr(isStrict, locale3) {
 | |
|         return locale3.erasAbbrRegex(isStrict);
 | |
|       }
 | |
|       function matchEraName(isStrict, locale3) {
 | |
|         return locale3.erasNameRegex(isStrict);
 | |
|       }
 | |
|       function matchEraNarrow(isStrict, locale3) {
 | |
|         return locale3.erasNarrowRegex(isStrict);
 | |
|       }
 | |
|       function matchEraYearOrdinal(isStrict, locale3) {
 | |
|         return locale3._eraYearOrdinalRegex || matchUnsigned;
 | |
|       }
 | |
|       function computeErasParse() {
 | |
|         var abbrPieces = [], namePieces = [], narrowPieces = [], mixedPieces = [], i2, l2, erasName, erasAbbr, erasNarrow, eras = this.eras();
 | |
|         for (i2 = 0, l2 = eras.length; i2 < l2; ++i2) {
 | |
|           erasName = regexEscape(eras[i2].name);
 | |
|           erasAbbr = regexEscape(eras[i2].abbr);
 | |
|           erasNarrow = regexEscape(eras[i2].narrow);
 | |
|           namePieces.push(erasName);
 | |
|           abbrPieces.push(erasAbbr);
 | |
|           narrowPieces.push(erasNarrow);
 | |
|           mixedPieces.push(erasName);
 | |
|           mixedPieces.push(erasAbbr);
 | |
|           mixedPieces.push(erasNarrow);
 | |
|         }
 | |
|         this._erasRegex = new RegExp("^(" + mixedPieces.join("|") + ")", "i");
 | |
|         this._erasNameRegex = new RegExp("^(" + namePieces.join("|") + ")", "i");
 | |
|         this._erasAbbrRegex = new RegExp("^(" + abbrPieces.join("|") + ")", "i");
 | |
|         this._erasNarrowRegex = new RegExp(
 | |
|           "^(" + narrowPieces.join("|") + ")",
 | |
|           "i"
 | |
|         );
 | |
|       }
 | |
|       addFormatToken(0, ["gg", 2], 0, function() {
 | |
|         return this.weekYear() % 100;
 | |
|       });
 | |
|       addFormatToken(0, ["GG", 2], 0, function() {
 | |
|         return this.isoWeekYear() % 100;
 | |
|       });
 | |
|       function addWeekYearFormatToken(token2, getter) {
 | |
|         addFormatToken(0, [token2, token2.length], 0, getter);
 | |
|       }
 | |
|       addWeekYearFormatToken("gggg", "weekYear");
 | |
|       addWeekYearFormatToken("ggggg", "weekYear");
 | |
|       addWeekYearFormatToken("GGGG", "isoWeekYear");
 | |
|       addWeekYearFormatToken("GGGGG", "isoWeekYear");
 | |
|       addRegexToken("G", matchSigned);
 | |
|       addRegexToken("g", matchSigned);
 | |
|       addRegexToken("GG", match1to2, match2);
 | |
|       addRegexToken("gg", match1to2, match2);
 | |
|       addRegexToken("GGGG", match1to4, match4);
 | |
|       addRegexToken("gggg", match1to4, match4);
 | |
|       addRegexToken("GGGGG", match1to6, match6);
 | |
|       addRegexToken("ggggg", match1to6, match6);
 | |
|       addWeekParseToken(
 | |
|         ["gggg", "ggggg", "GGGG", "GGGGG"],
 | |
|         function(input, week, config, token2) {
 | |
|           week[token2.substr(0, 2)] = toInt(input);
 | |
|         }
 | |
|       );
 | |
|       addWeekParseToken(["gg", "GG"], function(input, week, config, token2) {
 | |
|         week[token2] = hooks.parseTwoDigitYear(input);
 | |
|       });
 | |
|       function getSetWeekYear(input) {
 | |
|         return getSetWeekYearHelper.call(
 | |
|           this,
 | |
|           input,
 | |
|           this.week(),
 | |
|           this.weekday() + this.localeData()._week.dow,
 | |
|           this.localeData()._week.dow,
 | |
|           this.localeData()._week.doy
 | |
|         );
 | |
|       }
 | |
|       function getSetISOWeekYear(input) {
 | |
|         return getSetWeekYearHelper.call(
 | |
|           this,
 | |
|           input,
 | |
|           this.isoWeek(),
 | |
|           this.isoWeekday(),
 | |
|           1,
 | |
|           4
 | |
|         );
 | |
|       }
 | |
|       function getISOWeeksInYear() {
 | |
|         return weeksInYear(this.year(), 1, 4);
 | |
|       }
 | |
|       function getISOWeeksInISOWeekYear() {
 | |
|         return weeksInYear(this.isoWeekYear(), 1, 4);
 | |
|       }
 | |
|       function getWeeksInYear() {
 | |
|         var weekInfo = this.localeData()._week;
 | |
|         return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
 | |
|       }
 | |
|       function getWeeksInWeekYear() {
 | |
|         var weekInfo = this.localeData()._week;
 | |
|         return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy);
 | |
|       }
 | |
|       function getSetWeekYearHelper(input, week, weekday, dow, doy) {
 | |
|         var weeksTarget;
 | |
|         if (input == null) {
 | |
|           return weekOfYear(this, dow, doy).year;
 | |
|         } else {
 | |
|           weeksTarget = weeksInYear(input, dow, doy);
 | |
|           if (week > weeksTarget) {
 | |
|             week = weeksTarget;
 | |
|           }
 | |
|           return setWeekAll.call(this, input, week, weekday, dow, doy);
 | |
|         }
 | |
|       }
 | |
|       function setWeekAll(weekYear, week, weekday, dow, doy) {
 | |
|         var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
 | |
|         this.year(date.getUTCFullYear());
 | |
|         this.month(date.getUTCMonth());
 | |
|         this.date(date.getUTCDate());
 | |
|         return this;
 | |
|       }
 | |
|       addFormatToken("Q", 0, "Qo", "quarter");
 | |
|       addRegexToken("Q", match1);
 | |
|       addParseToken("Q", function(input, array) {
 | |
|         array[MONTH] = (toInt(input) - 1) * 3;
 | |
|       });
 | |
|       function getSetQuarter(input) {
 | |
|         return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
 | |
|       }
 | |
|       addFormatToken("D", ["DD", 2], "Do", "date");
 | |
|       addRegexToken("D", match1to2, match1to2NoLeadingZero);
 | |
|       addRegexToken("DD", match1to2, match2);
 | |
|       addRegexToken("Do", function(isStrict, locale3) {
 | |
|         return isStrict ? locale3._dayOfMonthOrdinalParse || locale3._ordinalParse : locale3._dayOfMonthOrdinalParseLenient;
 | |
|       });
 | |
|       addParseToken(["D", "DD"], DATE);
 | |
|       addParseToken("Do", function(input, array) {
 | |
|         array[DATE] = toInt(input.match(match1to2)[0]);
 | |
|       });
 | |
|       var getSetDayOfMonth = makeGetSet("Date", true);
 | |
|       addFormatToken("DDD", ["DDDD", 3], "DDDo", "dayOfYear");
 | |
|       addRegexToken("DDD", match1to3);
 | |
|       addRegexToken("DDDD", match3);
 | |
|       addParseToken(["DDD", "DDDD"], function(input, array, config) {
 | |
|         config._dayOfYear = toInt(input);
 | |
|       });
 | |
|       function getSetDayOfYear(input) {
 | |
|         var dayOfYear = Math.round(
 | |
|           (this.clone().startOf("day") - this.clone().startOf("year")) / 864e5
 | |
|         ) + 1;
 | |
|         return input == null ? dayOfYear : this.add(input - dayOfYear, "d");
 | |
|       }
 | |
|       addFormatToken("m", ["mm", 2], 0, "minute");
 | |
|       addRegexToken("m", match1to2, match1to2HasZero);
 | |
|       addRegexToken("mm", match1to2, match2);
 | |
|       addParseToken(["m", "mm"], MINUTE);
 | |
|       var getSetMinute = makeGetSet("Minutes", false);
 | |
|       addFormatToken("s", ["ss", 2], 0, "second");
 | |
|       addRegexToken("s", match1to2, match1to2HasZero);
 | |
|       addRegexToken("ss", match1to2, match2);
 | |
|       addParseToken(["s", "ss"], SECOND);
 | |
|       var getSetSecond = makeGetSet("Seconds", false);
 | |
|       addFormatToken("S", 0, 0, function() {
 | |
|         return ~~(this.millisecond() / 100);
 | |
|       });
 | |
|       addFormatToken(0, ["SS", 2], 0, function() {
 | |
|         return ~~(this.millisecond() / 10);
 | |
|       });
 | |
|       addFormatToken(0, ["SSS", 3], 0, "millisecond");
 | |
|       addFormatToken(0, ["SSSS", 4], 0, function() {
 | |
|         return this.millisecond() * 10;
 | |
|       });
 | |
|       addFormatToken(0, ["SSSSS", 5], 0, function() {
 | |
|         return this.millisecond() * 100;
 | |
|       });
 | |
|       addFormatToken(0, ["SSSSSS", 6], 0, function() {
 | |
|         return this.millisecond() * 1e3;
 | |
|       });
 | |
|       addFormatToken(0, ["SSSSSSS", 7], 0, function() {
 | |
|         return this.millisecond() * 1e4;
 | |
|       });
 | |
|       addFormatToken(0, ["SSSSSSSS", 8], 0, function() {
 | |
|         return this.millisecond() * 1e5;
 | |
|       });
 | |
|       addFormatToken(0, ["SSSSSSSSS", 9], 0, function() {
 | |
|         return this.millisecond() * 1e6;
 | |
|       });
 | |
|       addRegexToken("S", match1to3, match1);
 | |
|       addRegexToken("SS", match1to3, match2);
 | |
|       addRegexToken("SSS", match1to3, match3);
 | |
|       var token, getSetMillisecond;
 | |
|       for (token = "SSSS"; token.length <= 9; token += "S") {
 | |
|         addRegexToken(token, matchUnsigned);
 | |
|       }
 | |
|       function parseMs(input, array) {
 | |
|         array[MILLISECOND] = toInt(("0." + input) * 1e3);
 | |
|       }
 | |
|       for (token = "S"; token.length <= 9; token += "S") {
 | |
|         addParseToken(token, parseMs);
 | |
|       }
 | |
|       getSetMillisecond = makeGetSet("Milliseconds", false);
 | |
|       addFormatToken("z", 0, 0, "zoneAbbr");
 | |
|       addFormatToken("zz", 0, 0, "zoneName");
 | |
|       function getZoneAbbr() {
 | |
|         return this._isUTC ? "UTC" : "";
 | |
|       }
 | |
|       function getZoneName() {
 | |
|         return this._isUTC ? "Coordinated Universal Time" : "";
 | |
|       }
 | |
|       var proto = Moment3.prototype;
 | |
|       proto.add = add;
 | |
|       proto.calendar = calendar$1;
 | |
|       proto.clone = clone3;
 | |
|       proto.diff = diff;
 | |
|       proto.endOf = endOf;
 | |
|       proto.format = format;
 | |
|       proto.from = from2;
 | |
|       proto.fromNow = fromNow;
 | |
|       proto.to = to2;
 | |
|       proto.toNow = toNow;
 | |
|       proto.get = stringGet;
 | |
|       proto.invalidAt = invalidAt;
 | |
|       proto.isAfter = isAfter;
 | |
|       proto.isBefore = isBefore;
 | |
|       proto.isBetween = isBetween;
 | |
|       proto.isSame = isSame;
 | |
|       proto.isSameOrAfter = isSameOrAfter;
 | |
|       proto.isSameOrBefore = isSameOrBefore;
 | |
|       proto.isValid = isValid$2;
 | |
|       proto.lang = lang;
 | |
|       proto.locale = locale2;
 | |
|       proto.localeData = localeData;
 | |
|       proto.max = prototypeMax;
 | |
|       proto.min = prototypeMin;
 | |
|       proto.parsingFlags = parsingFlags;
 | |
|       proto.set = stringSet;
 | |
|       proto.startOf = startOf;
 | |
|       proto.subtract = subtract;
 | |
|       proto.toArray = toArray;
 | |
|       proto.toObject = toObject;
 | |
|       proto.toDate = toDate;
 | |
|       proto.toISOString = toISOString;
 | |
|       proto.inspect = inspect;
 | |
|       if (typeof Symbol !== "undefined" && Symbol.for != null) {
 | |
|         proto[Symbol.for("nodejs.util.inspect.custom")] = function() {
 | |
|           return "Moment<" + this.format() + ">";
 | |
|         };
 | |
|       }
 | |
|       proto.toJSON = toJSON;
 | |
|       proto.toString = toString;
 | |
|       proto.unix = unix;
 | |
|       proto.valueOf = valueOf;
 | |
|       proto.creationData = creationData;
 | |
|       proto.eraName = getEraName;
 | |
|       proto.eraNarrow = getEraNarrow;
 | |
|       proto.eraAbbr = getEraAbbr;
 | |
|       proto.eraYear = getEraYear;
 | |
|       proto.year = getSetYear;
 | |
|       proto.isLeapYear = getIsLeapYear;
 | |
|       proto.weekYear = getSetWeekYear;
 | |
|       proto.isoWeekYear = getSetISOWeekYear;
 | |
|       proto.quarter = proto.quarters = getSetQuarter;
 | |
|       proto.month = getSetMonth;
 | |
|       proto.daysInMonth = getDaysInMonth;
 | |
|       proto.week = proto.weeks = getSetWeek;
 | |
|       proto.isoWeek = proto.isoWeeks = getSetISOWeek;
 | |
|       proto.weeksInYear = getWeeksInYear;
 | |
|       proto.weeksInWeekYear = getWeeksInWeekYear;
 | |
|       proto.isoWeeksInYear = getISOWeeksInYear;
 | |
|       proto.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;
 | |
|       proto.date = getSetDayOfMonth;
 | |
|       proto.day = proto.days = getSetDayOfWeek;
 | |
|       proto.weekday = getSetLocaleDayOfWeek;
 | |
|       proto.isoWeekday = getSetISODayOfWeek;
 | |
|       proto.dayOfYear = getSetDayOfYear;
 | |
|       proto.hour = proto.hours = getSetHour;
 | |
|       proto.minute = proto.minutes = getSetMinute;
 | |
|       proto.second = proto.seconds = getSetSecond;
 | |
|       proto.millisecond = proto.milliseconds = getSetMillisecond;
 | |
|       proto.utcOffset = getSetOffset;
 | |
|       proto.utc = setOffsetToUTC;
 | |
|       proto.local = setOffsetToLocal;
 | |
|       proto.parseZone = setOffsetToParsedOffset;
 | |
|       proto.hasAlignedHourOffset = hasAlignedHourOffset;
 | |
|       proto.isDST = isDaylightSavingTime;
 | |
|       proto.isLocal = isLocal;
 | |
|       proto.isUtcOffset = isUtcOffset;
 | |
|       proto.isUtc = isUtc;
 | |
|       proto.isUTC = isUtc;
 | |
|       proto.zoneAbbr = getZoneAbbr;
 | |
|       proto.zoneName = getZoneName;
 | |
|       proto.dates = deprecate(
 | |
|         "dates accessor is deprecated. Use date instead.",
 | |
|         getSetDayOfMonth
 | |
|       );
 | |
|       proto.months = deprecate(
 | |
|         "months accessor is deprecated. Use month instead",
 | |
|         getSetMonth
 | |
|       );
 | |
|       proto.years = deprecate(
 | |
|         "years accessor is deprecated. Use year instead",
 | |
|         getSetYear
 | |
|       );
 | |
|       proto.zone = deprecate(
 | |
|         "moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",
 | |
|         getSetZone
 | |
|       );
 | |
|       proto.isDSTShifted = deprecate(
 | |
|         "isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",
 | |
|         isDaylightSavingTimeShifted
 | |
|       );
 | |
|       function createUnix(input) {
 | |
|         return createLocal(input * 1e3);
 | |
|       }
 | |
|       function createInZone() {
 | |
|         return createLocal.apply(null, arguments).parseZone();
 | |
|       }
 | |
|       function preParsePostFormat(string) {
 | |
|         return string;
 | |
|       }
 | |
|       var proto$1 = Locale.prototype;
 | |
|       proto$1.calendar = calendar;
 | |
|       proto$1.longDateFormat = longDateFormat;
 | |
|       proto$1.invalidDate = invalidDate;
 | |
|       proto$1.ordinal = ordinal;
 | |
|       proto$1.preparse = preParsePostFormat;
 | |
|       proto$1.postformat = preParsePostFormat;
 | |
|       proto$1.relativeTime = relativeTime;
 | |
|       proto$1.pastFuture = pastFuture;
 | |
|       proto$1.set = set2;
 | |
|       proto$1.eras = localeEras;
 | |
|       proto$1.erasParse = localeErasParse;
 | |
|       proto$1.erasConvertYear = localeErasConvertYear;
 | |
|       proto$1.erasAbbrRegex = erasAbbrRegex;
 | |
|       proto$1.erasNameRegex = erasNameRegex;
 | |
|       proto$1.erasNarrowRegex = erasNarrowRegex;
 | |
|       proto$1.months = localeMonths;
 | |
|       proto$1.monthsShort = localeMonthsShort;
 | |
|       proto$1.monthsParse = localeMonthsParse;
 | |
|       proto$1.monthsRegex = monthsRegex;
 | |
|       proto$1.monthsShortRegex = monthsShortRegex;
 | |
|       proto$1.week = localeWeek;
 | |
|       proto$1.firstDayOfYear = localeFirstDayOfYear;
 | |
|       proto$1.firstDayOfWeek = localeFirstDayOfWeek;
 | |
|       proto$1.weekdays = localeWeekdays;
 | |
|       proto$1.weekdaysMin = localeWeekdaysMin;
 | |
|       proto$1.weekdaysShort = localeWeekdaysShort;
 | |
|       proto$1.weekdaysParse = localeWeekdaysParse;
 | |
|       proto$1.weekdaysRegex = weekdaysRegex;
 | |
|       proto$1.weekdaysShortRegex = weekdaysShortRegex;
 | |
|       proto$1.weekdaysMinRegex = weekdaysMinRegex;
 | |
|       proto$1.isPM = localeIsPM;
 | |
|       proto$1.meridiem = localeMeridiem;
 | |
|       function get$1(format2, index, field, setter) {
 | |
|         var locale3 = getLocale(), utc = createUTC().set(setter, index);
 | |
|         return locale3[field](utc, format2);
 | |
|       }
 | |
|       function listMonthsImpl(format2, index, field) {
 | |
|         if (isNumber2(format2)) {
 | |
|           index = format2;
 | |
|           format2 = void 0;
 | |
|         }
 | |
|         format2 = format2 || "";
 | |
|         if (index != null) {
 | |
|           return get$1(format2, index, field, "month");
 | |
|         }
 | |
|         var i2, out = [];
 | |
|         for (i2 = 0; i2 < 12; i2++) {
 | |
|           out[i2] = get$1(format2, i2, field, "month");
 | |
|         }
 | |
|         return out;
 | |
|       }
 | |
|       function listWeekdaysImpl(localeSorted, format2, index, field) {
 | |
|         if (typeof localeSorted === "boolean") {
 | |
|           if (isNumber2(format2)) {
 | |
|             index = format2;
 | |
|             format2 = void 0;
 | |
|           }
 | |
|           format2 = format2 || "";
 | |
|         } else {
 | |
|           format2 = localeSorted;
 | |
|           index = format2;
 | |
|           localeSorted = false;
 | |
|           if (isNumber2(format2)) {
 | |
|             index = format2;
 | |
|             format2 = void 0;
 | |
|           }
 | |
|           format2 = format2 || "";
 | |
|         }
 | |
|         var locale3 = getLocale(), shift = localeSorted ? locale3._week.dow : 0, i2, out = [];
 | |
|         if (index != null) {
 | |
|           return get$1(format2, (index + shift) % 7, field, "day");
 | |
|         }
 | |
|         for (i2 = 0; i2 < 7; i2++) {
 | |
|           out[i2] = get$1(format2, (i2 + shift) % 7, field, "day");
 | |
|         }
 | |
|         return out;
 | |
|       }
 | |
|       function listMonths(format2, index) {
 | |
|         return listMonthsImpl(format2, index, "months");
 | |
|       }
 | |
|       function listMonthsShort(format2, index) {
 | |
|         return listMonthsImpl(format2, index, "monthsShort");
 | |
|       }
 | |
|       function listWeekdays(localeSorted, format2, index) {
 | |
|         return listWeekdaysImpl(localeSorted, format2, index, "weekdays");
 | |
|       }
 | |
|       function listWeekdaysShort(localeSorted, format2, index) {
 | |
|         return listWeekdaysImpl(localeSorted, format2, index, "weekdaysShort");
 | |
|       }
 | |
|       function listWeekdaysMin(localeSorted, format2, index) {
 | |
|         return listWeekdaysImpl(localeSorted, format2, index, "weekdaysMin");
 | |
|       }
 | |
|       getSetGlobalLocale("en", {
 | |
|         eras: [
 | |
|           {
 | |
|             since: "0001-01-01",
 | |
|             until: Infinity,
 | |
|             offset: 1,
 | |
|             name: "Anno Domini",
 | |
|             narrow: "AD",
 | |
|             abbr: "AD"
 | |
|           },
 | |
|           {
 | |
|             since: "0000-12-31",
 | |
|             until: -Infinity,
 | |
|             offset: 1,
 | |
|             name: "Before Christ",
 | |
|             narrow: "BC",
 | |
|             abbr: "BC"
 | |
|           }
 | |
|         ],
 | |
|         dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
 | |
|         ordinal: function(number) {
 | |
|           var b2 = number % 10, output = toInt(number % 100 / 10) === 1 ? "th" : b2 === 1 ? "st" : b2 === 2 ? "nd" : b2 === 3 ? "rd" : "th";
 | |
|           return number + output;
 | |
|         }
 | |
|       });
 | |
|       hooks.lang = deprecate(
 | |
|         "moment.lang is deprecated. Use moment.locale instead.",
 | |
|         getSetGlobalLocale
 | |
|       );
 | |
|       hooks.langData = deprecate(
 | |
|         "moment.langData is deprecated. Use moment.localeData instead.",
 | |
|         getLocale
 | |
|       );
 | |
|       var mathAbs = Math.abs;
 | |
|       function abs() {
 | |
|         var data = this._data;
 | |
|         this._milliseconds = mathAbs(this._milliseconds);
 | |
|         this._days = mathAbs(this._days);
 | |
|         this._months = mathAbs(this._months);
 | |
|         data.milliseconds = mathAbs(data.milliseconds);
 | |
|         data.seconds = mathAbs(data.seconds);
 | |
|         data.minutes = mathAbs(data.minutes);
 | |
|         data.hours = mathAbs(data.hours);
 | |
|         data.months = mathAbs(data.months);
 | |
|         data.years = mathAbs(data.years);
 | |
|         return this;
 | |
|       }
 | |
|       function addSubtract$1(duration, input, value, direction) {
 | |
|         var other = createDuration(input, value);
 | |
|         duration._milliseconds += direction * other._milliseconds;
 | |
|         duration._days += direction * other._days;
 | |
|         duration._months += direction * other._months;
 | |
|         return duration._bubble();
 | |
|       }
 | |
|       function add$1(input, value) {
 | |
|         return addSubtract$1(this, input, value, 1);
 | |
|       }
 | |
|       function subtract$1(input, value) {
 | |
|         return addSubtract$1(this, input, value, -1);
 | |
|       }
 | |
|       function absCeil(number) {
 | |
|         if (number < 0) {
 | |
|           return Math.floor(number);
 | |
|         } else {
 | |
|           return Math.ceil(number);
 | |
|         }
 | |
|       }
 | |
|       function bubble() {
 | |
|         var milliseconds2 = this._milliseconds, days2 = this._days, months2 = this._months, data = this._data, seconds2, minutes2, hours2, years2, monthsFromDays;
 | |
|         if (!(milliseconds2 >= 0 && days2 >= 0 && months2 >= 0 || milliseconds2 <= 0 && days2 <= 0 && months2 <= 0)) {
 | |
|           milliseconds2 += absCeil(monthsToDays(months2) + days2) * 864e5;
 | |
|           days2 = 0;
 | |
|           months2 = 0;
 | |
|         }
 | |
|         data.milliseconds = milliseconds2 % 1e3;
 | |
|         seconds2 = absFloor(milliseconds2 / 1e3);
 | |
|         data.seconds = seconds2 % 60;
 | |
|         minutes2 = absFloor(seconds2 / 60);
 | |
|         data.minutes = minutes2 % 60;
 | |
|         hours2 = absFloor(minutes2 / 60);
 | |
|         data.hours = hours2 % 24;
 | |
|         days2 += absFloor(hours2 / 24);
 | |
|         monthsFromDays = absFloor(daysToMonths(days2));
 | |
|         months2 += monthsFromDays;
 | |
|         days2 -= absCeil(monthsToDays(monthsFromDays));
 | |
|         years2 = absFloor(months2 / 12);
 | |
|         months2 %= 12;
 | |
|         data.days = days2;
 | |
|         data.months = months2;
 | |
|         data.years = years2;
 | |
|         return this;
 | |
|       }
 | |
|       function daysToMonths(days2) {
 | |
|         return days2 * 4800 / 146097;
 | |
|       }
 | |
|       function monthsToDays(months2) {
 | |
|         return months2 * 146097 / 4800;
 | |
|       }
 | |
|       function as(units) {
 | |
|         if (!this.isValid()) {
 | |
|           return NaN;
 | |
|         }
 | |
|         var days2, months2, milliseconds2 = this._milliseconds;
 | |
|         units = normalizeUnits(units);
 | |
|         if (units === "month" || units === "quarter" || units === "year") {
 | |
|           days2 = this._days + milliseconds2 / 864e5;
 | |
|           months2 = this._months + daysToMonths(days2);
 | |
|           switch (units) {
 | |
|             case "month":
 | |
|               return months2;
 | |
|             case "quarter":
 | |
|               return months2 / 3;
 | |
|             case "year":
 | |
|               return months2 / 12;
 | |
|           }
 | |
|         } else {
 | |
|           days2 = this._days + Math.round(monthsToDays(this._months));
 | |
|           switch (units) {
 | |
|             case "week":
 | |
|               return days2 / 7 + milliseconds2 / 6048e5;
 | |
|             case "day":
 | |
|               return days2 + milliseconds2 / 864e5;
 | |
|             case "hour":
 | |
|               return days2 * 24 + milliseconds2 / 36e5;
 | |
|             case "minute":
 | |
|               return days2 * 1440 + milliseconds2 / 6e4;
 | |
|             case "second":
 | |
|               return days2 * 86400 + milliseconds2 / 1e3;
 | |
|             // Math.floor prevents floating point math errors here
 | |
|             case "millisecond":
 | |
|               return Math.floor(days2 * 864e5) + milliseconds2;
 | |
|             default:
 | |
|               throw new Error("Unknown unit " + units);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       function makeAs(alias) {
 | |
|         return function() {
 | |
|           return this.as(alias);
 | |
|         };
 | |
|       }
 | |
|       var asMilliseconds = makeAs("ms"), asSeconds = makeAs("s"), asMinutes = makeAs("m"), asHours = makeAs("h"), asDays = makeAs("d"), asWeeks = makeAs("w"), asMonths = makeAs("M"), asQuarters = makeAs("Q"), asYears = makeAs("y"), valueOf$1 = asMilliseconds;
 | |
|       function clone$1() {
 | |
|         return createDuration(this);
 | |
|       }
 | |
|       function get$2(units) {
 | |
|         units = normalizeUnits(units);
 | |
|         return this.isValid() ? this[units + "s"]() : NaN;
 | |
|       }
 | |
|       function makeGetter(name) {
 | |
|         return function() {
 | |
|           return this.isValid() ? this._data[name] : NaN;
 | |
|         };
 | |
|       }
 | |
|       var milliseconds = makeGetter("milliseconds"), seconds = makeGetter("seconds"), minutes = makeGetter("minutes"), hours = makeGetter("hours"), days = makeGetter("days"), months = makeGetter("months"), years = makeGetter("years");
 | |
|       function weeks() {
 | |
|         return absFloor(this.days() / 7);
 | |
|       }
 | |
|       var round2 = Math.round, thresholds = {
 | |
|         ss: 44,
 | |
|         // a few seconds to seconds
 | |
|         s: 45,
 | |
|         // seconds to minute
 | |
|         m: 45,
 | |
|         // minutes to hour
 | |
|         h: 22,
 | |
|         // hours to day
 | |
|         d: 26,
 | |
|         // days to month/week
 | |
|         w: null,
 | |
|         // weeks to month
 | |
|         M: 11
 | |
|         // months to year
 | |
|       };
 | |
|       function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale3) {
 | |
|         return locale3.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
 | |
|       }
 | |
|       function relativeTime$1(posNegDuration, withoutSuffix, thresholds2, locale3) {
 | |
|         var duration = createDuration(posNegDuration).abs(), seconds2 = round2(duration.as("s")), minutes2 = round2(duration.as("m")), hours2 = round2(duration.as("h")), days2 = round2(duration.as("d")), months2 = round2(duration.as("M")), weeks2 = round2(duration.as("w")), years2 = round2(duration.as("y")), a2 = seconds2 <= thresholds2.ss && ["s", seconds2] || seconds2 < thresholds2.s && ["ss", seconds2] || minutes2 <= 1 && ["m"] || minutes2 < thresholds2.m && ["mm", minutes2] || hours2 <= 1 && ["h"] || hours2 < thresholds2.h && ["hh", hours2] || days2 <= 1 && ["d"] || days2 < thresholds2.d && ["dd", days2];
 | |
|         if (thresholds2.w != null) {
 | |
|           a2 = a2 || weeks2 <= 1 && ["w"] || weeks2 < thresholds2.w && ["ww", weeks2];
 | |
|         }
 | |
|         a2 = a2 || months2 <= 1 && ["M"] || months2 < thresholds2.M && ["MM", months2] || years2 <= 1 && ["y"] || ["yy", years2];
 | |
|         a2[2] = withoutSuffix;
 | |
|         a2[3] = +posNegDuration > 0;
 | |
|         a2[4] = locale3;
 | |
|         return substituteTimeAgo.apply(null, a2);
 | |
|       }
 | |
|       function getSetRelativeTimeRounding(roundingFunction) {
 | |
|         if (roundingFunction === void 0) {
 | |
|           return round2;
 | |
|         }
 | |
|         if (typeof roundingFunction === "function") {
 | |
|           round2 = roundingFunction;
 | |
|           return true;
 | |
|         }
 | |
|         return false;
 | |
|       }
 | |
|       function getSetRelativeTimeThreshold(threshold, limit) {
 | |
|         if (thresholds[threshold] === void 0) {
 | |
|           return false;
 | |
|         }
 | |
|         if (limit === void 0) {
 | |
|           return thresholds[threshold];
 | |
|         }
 | |
|         thresholds[threshold] = limit;
 | |
|         if (threshold === "s") {
 | |
|           thresholds.ss = limit - 1;
 | |
|         }
 | |
|         return true;
 | |
|       }
 | |
|       function humanize(argWithSuffix, argThresholds) {
 | |
|         if (!this.isValid()) {
 | |
|           return this.localeData().invalidDate();
 | |
|         }
 | |
|         var withSuffix = false, th = thresholds, locale3, output;
 | |
|         if (typeof argWithSuffix === "object") {
 | |
|           argThresholds = argWithSuffix;
 | |
|           argWithSuffix = false;
 | |
|         }
 | |
|         if (typeof argWithSuffix === "boolean") {
 | |
|           withSuffix = argWithSuffix;
 | |
|         }
 | |
|         if (typeof argThresholds === "object") {
 | |
|           th = Object.assign({}, thresholds, argThresholds);
 | |
|           if (argThresholds.s != null && argThresholds.ss == null) {
 | |
|             th.ss = argThresholds.s - 1;
 | |
|           }
 | |
|         }
 | |
|         locale3 = this.localeData();
 | |
|         output = relativeTime$1(this, !withSuffix, th, locale3);
 | |
|         if (withSuffix) {
 | |
|           output = locale3.pastFuture(+this, output);
 | |
|         }
 | |
|         return locale3.postformat(output);
 | |
|       }
 | |
|       var abs$1 = Math.abs;
 | |
|       function sign2(x2) {
 | |
|         return (x2 > 0) - (x2 < 0) || +x2;
 | |
|       }
 | |
|       function toISOString$1() {
 | |
|         if (!this.isValid()) {
 | |
|           return this.localeData().invalidDate();
 | |
|         }
 | |
|         var seconds2 = abs$1(this._milliseconds) / 1e3, days2 = abs$1(this._days), months2 = abs$1(this._months), minutes2, hours2, years2, s2, total = this.asSeconds(), totalSign, ymSign, daysSign, hmsSign;
 | |
|         if (!total) {
 | |
|           return "P0D";
 | |
|         }
 | |
|         minutes2 = absFloor(seconds2 / 60);
 | |
|         hours2 = absFloor(minutes2 / 60);
 | |
|         seconds2 %= 60;
 | |
|         minutes2 %= 60;
 | |
|         years2 = absFloor(months2 / 12);
 | |
|         months2 %= 12;
 | |
|         s2 = seconds2 ? seconds2.toFixed(3).replace(/\.?0+$/, "") : "";
 | |
|         totalSign = total < 0 ? "-" : "";
 | |
|         ymSign = sign2(this._months) !== sign2(total) ? "-" : "";
 | |
|         daysSign = sign2(this._days) !== sign2(total) ? "-" : "";
 | |
|         hmsSign = sign2(this._milliseconds) !== sign2(total) ? "-" : "";
 | |
|         return totalSign + "P" + (years2 ? ymSign + years2 + "Y" : "") + (months2 ? ymSign + months2 + "M" : "") + (days2 ? daysSign + days2 + "D" : "") + (hours2 || minutes2 || seconds2 ? "T" : "") + (hours2 ? hmsSign + hours2 + "H" : "") + (minutes2 ? hmsSign + minutes2 + "M" : "") + (seconds2 ? hmsSign + s2 + "S" : "");
 | |
|       }
 | |
|       var proto$2 = Duration.prototype;
 | |
|       proto$2.isValid = isValid$1;
 | |
|       proto$2.abs = abs;
 | |
|       proto$2.add = add$1;
 | |
|       proto$2.subtract = subtract$1;
 | |
|       proto$2.as = as;
 | |
|       proto$2.asMilliseconds = asMilliseconds;
 | |
|       proto$2.asSeconds = asSeconds;
 | |
|       proto$2.asMinutes = asMinutes;
 | |
|       proto$2.asHours = asHours;
 | |
|       proto$2.asDays = asDays;
 | |
|       proto$2.asWeeks = asWeeks;
 | |
|       proto$2.asMonths = asMonths;
 | |
|       proto$2.asQuarters = asQuarters;
 | |
|       proto$2.asYears = asYears;
 | |
|       proto$2.valueOf = valueOf$1;
 | |
|       proto$2._bubble = bubble;
 | |
|       proto$2.clone = clone$1;
 | |
|       proto$2.get = get$2;
 | |
|       proto$2.milliseconds = milliseconds;
 | |
|       proto$2.seconds = seconds;
 | |
|       proto$2.minutes = minutes;
 | |
|       proto$2.hours = hours;
 | |
|       proto$2.days = days;
 | |
|       proto$2.weeks = weeks;
 | |
|       proto$2.months = months;
 | |
|       proto$2.years = years;
 | |
|       proto$2.humanize = humanize;
 | |
|       proto$2.toISOString = toISOString$1;
 | |
|       proto$2.toString = toISOString$1;
 | |
|       proto$2.toJSON = toISOString$1;
 | |
|       proto$2.locale = locale2;
 | |
|       proto$2.localeData = localeData;
 | |
|       proto$2.toIsoString = deprecate(
 | |
|         "toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",
 | |
|         toISOString$1
 | |
|       );
 | |
|       proto$2.lang = lang;
 | |
|       addFormatToken("X", 0, 0, "unix");
 | |
|       addFormatToken("x", 0, 0, "valueOf");
 | |
|       addRegexToken("x", matchSigned);
 | |
|       addRegexToken("X", matchTimestamp);
 | |
|       addParseToken("X", function(input, array, config) {
 | |
|         config._d = new Date(parseFloat(input) * 1e3);
 | |
|       });
 | |
|       addParseToken("x", function(input, array, config) {
 | |
|         config._d = new Date(toInt(input));
 | |
|       });
 | |
|       hooks.version = "2.30.1";
 | |
|       setHookCallback(createLocal);
 | |
|       hooks.fn = proto;
 | |
|       hooks.min = min;
 | |
|       hooks.max = max;
 | |
|       hooks.now = now2;
 | |
|       hooks.utc = createUTC;
 | |
|       hooks.unix = createUnix;
 | |
|       hooks.months = listMonths;
 | |
|       hooks.isDate = isDate;
 | |
|       hooks.locale = getSetGlobalLocale;
 | |
|       hooks.invalid = createInvalid;
 | |
|       hooks.duration = createDuration;
 | |
|       hooks.isMoment = isMoment;
 | |
|       hooks.weekdays = listWeekdays;
 | |
|       hooks.parseZone = createInZone;
 | |
|       hooks.localeData = getLocale;
 | |
|       hooks.isDuration = isDuration;
 | |
|       hooks.monthsShort = listMonthsShort;
 | |
|       hooks.weekdaysMin = listWeekdaysMin;
 | |
|       hooks.defineLocale = defineLocale;
 | |
|       hooks.updateLocale = updateLocale;
 | |
|       hooks.locales = listLocales;
 | |
|       hooks.weekdaysShort = listWeekdaysShort;
 | |
|       hooks.normalizeUnits = normalizeUnits;
 | |
|       hooks.relativeTimeRounding = getSetRelativeTimeRounding;
 | |
|       hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
 | |
|       hooks.calendarFormat = getCalendarFormat;
 | |
|       hooks.prototype = proto;
 | |
|       hooks.HTML5_FMT = {
 | |
|         DATETIME_LOCAL: "YYYY-MM-DDTHH:mm",
 | |
|         // <input type="datetime-local" />
 | |
|         DATETIME_LOCAL_SECONDS: "YYYY-MM-DDTHH:mm:ss",
 | |
|         // <input type="datetime-local" step="1" />
 | |
|         DATETIME_LOCAL_MS: "YYYY-MM-DDTHH:mm:ss.SSS",
 | |
|         // <input type="datetime-local" step="0.001" />
 | |
|         DATE: "YYYY-MM-DD",
 | |
|         // <input type="date" />
 | |
|         TIME: "HH:mm",
 | |
|         // <input type="time" />
 | |
|         TIME_SECONDS: "HH:mm:ss",
 | |
|         // <input type="time" step="1" />
 | |
|         TIME_MS: "HH:mm:ss.SSS",
 | |
|         // <input type="time" step="0.001" />
 | |
|         WEEK: "GGGG-[W]WW",
 | |
|         // <input type="week" />
 | |
|         MONTH: "YYYY-MM"
 | |
|         // <input type="month" />
 | |
|       };
 | |
|       return hooks;
 | |
|     });
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/pagerank.js@1.0.2/node_modules/pagerank.js/lib/index.js
 | |
| var require_lib = __commonJS({
 | |
|   "node_modules/.pnpm/pagerank.js@1.0.2/node_modules/pagerank.js/lib/index.js"(exports, module2) {
 | |
|     "use strict";
 | |
|     function forOwn(object, callback2) {
 | |
|       if (typeof object === "object" && typeof callback2 === "function") {
 | |
|         for (var key in object) {
 | |
|           if (object.hasOwnProperty(key) === true) {
 | |
|             if (callback2(key, object[key]) === false) {
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     module2.exports = function() {
 | |
|       var self = {
 | |
|         count: 0,
 | |
|         edges: {},
 | |
|         nodes: {}
 | |
|       };
 | |
|       self.link = function(source, target, weight) {
 | |
|         if (isFinite(weight) !== true || weight === null) {
 | |
|           weight = 1;
 | |
|         }
 | |
|         weight = parseFloat(weight);
 | |
|         if (self.nodes.hasOwnProperty(source) !== true) {
 | |
|           self.count++;
 | |
|           self.nodes[source] = {
 | |
|             weight: 0,
 | |
|             outbound: 0
 | |
|           };
 | |
|         }
 | |
|         self.nodes[source].outbound += weight;
 | |
|         if (self.nodes.hasOwnProperty(target) !== true) {
 | |
|           self.count++;
 | |
|           self.nodes[target] = {
 | |
|             weight: 0,
 | |
|             outbound: 0
 | |
|           };
 | |
|         }
 | |
|         if (self.edges.hasOwnProperty(source) !== true) {
 | |
|           self.edges[source] = {};
 | |
|         }
 | |
|         if (self.edges[source].hasOwnProperty(target) !== true) {
 | |
|           self.edges[source][target] = 0;
 | |
|         }
 | |
|         self.edges[source][target] += weight;
 | |
|       };
 | |
|       self.rank = function(alpha2, epsilon, callback2) {
 | |
|         var delta = 1, inverse = 1 / self.count;
 | |
|         forOwn(self.edges, function(source) {
 | |
|           if (self.nodes[source].outbound > 0) {
 | |
|             forOwn(self.edges[source], function(target) {
 | |
|               self.edges[source][target] /= self.nodes[source].outbound;
 | |
|             });
 | |
|           }
 | |
|         });
 | |
|         forOwn(self.nodes, function(key) {
 | |
|           self.nodes[key].weight = inverse;
 | |
|         });
 | |
|         while (delta > epsilon) {
 | |
|           var leak = 0, nodes = {};
 | |
|           forOwn(self.nodes, function(key, value) {
 | |
|             nodes[key] = value.weight;
 | |
|             if (value.outbound === 0) {
 | |
|               leak += value.weight;
 | |
|             }
 | |
|             self.nodes[key].weight = 0;
 | |
|           });
 | |
|           leak *= alpha2;
 | |
|           forOwn(self.nodes, function(source) {
 | |
|             forOwn(self.edges[source], function(target, weight) {
 | |
|               self.nodes[target].weight += alpha2 * nodes[source] * weight;
 | |
|             });
 | |
|             self.nodes[source].weight += (1 - alpha2) * inverse + leak * inverse;
 | |
|           });
 | |
|           delta = 0;
 | |
|           forOwn(self.nodes, function(key, value) {
 | |
|             delta += Math.abs(value.weight - nodes[key]);
 | |
|           });
 | |
|         }
 | |
|         forOwn(self.nodes, function(key) {
 | |
|           return callback2(key, self.nodes[key].weight);
 | |
|         });
 | |
|       };
 | |
|       self.reset = function() {
 | |
|         self.count = 0;
 | |
|         self.edges = {};
 | |
|         self.nodes = {};
 | |
|       };
 | |
|       return self;
 | |
|     }();
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js
 | |
| var require_balanced_match = __commonJS({
 | |
|   "node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js"(exports, module2) {
 | |
|     "use strict";
 | |
|     module2.exports = balanced;
 | |
|     function balanced(a2, b2, str) {
 | |
|       if (a2 instanceof RegExp) a2 = maybeMatch(a2, str);
 | |
|       if (b2 instanceof RegExp) b2 = maybeMatch(b2, str);
 | |
|       var r2 = range(a2, b2, str);
 | |
|       return r2 && {
 | |
|         start: r2[0],
 | |
|         end: r2[1],
 | |
|         pre: str.slice(0, r2[0]),
 | |
|         body: str.slice(r2[0] + a2.length, r2[1]),
 | |
|         post: str.slice(r2[1] + b2.length)
 | |
|       };
 | |
|     }
 | |
|     function maybeMatch(reg, str) {
 | |
|       var m2 = str.match(reg);
 | |
|       return m2 ? m2[0] : null;
 | |
|     }
 | |
|     balanced.range = range;
 | |
|     function range(a2, b2, str) {
 | |
|       var begs, beg, left, right, result;
 | |
|       var ai = str.indexOf(a2);
 | |
|       var bi = str.indexOf(b2, ai + 1);
 | |
|       var i2 = ai;
 | |
|       if (ai >= 0 && bi > 0) {
 | |
|         if (a2 === b2) {
 | |
|           return [ai, bi];
 | |
|         }
 | |
|         begs = [];
 | |
|         left = str.length;
 | |
|         while (i2 >= 0 && !result) {
 | |
|           if (i2 == ai) {
 | |
|             begs.push(i2);
 | |
|             ai = str.indexOf(a2, i2 + 1);
 | |
|           } else if (begs.length == 1) {
 | |
|             result = [begs.pop(), bi];
 | |
|           } else {
 | |
|             beg = begs.pop();
 | |
|             if (beg < left) {
 | |
|               left = beg;
 | |
|               right = bi;
 | |
|             }
 | |
|             bi = str.indexOf(b2, i2 + 1);
 | |
|           }
 | |
|           i2 = ai < bi && ai >= 0 ? ai : bi;
 | |
|         }
 | |
|         if (begs.length) {
 | |
|           result = [left, right];
 | |
|         }
 | |
|       }
 | |
|       return result;
 | |
|     }
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/brace-expansion@2.0.1/node_modules/brace-expansion/index.js
 | |
| var require_brace_expansion = __commonJS({
 | |
|   "node_modules/.pnpm/brace-expansion@2.0.1/node_modules/brace-expansion/index.js"(exports, module2) {
 | |
|     var balanced = require_balanced_match();
 | |
|     module2.exports = expandTop;
 | |
|     var escSlash = "\0SLASH" + Math.random() + "\0";
 | |
|     var escOpen = "\0OPEN" + Math.random() + "\0";
 | |
|     var escClose = "\0CLOSE" + Math.random() + "\0";
 | |
|     var escComma = "\0COMMA" + Math.random() + "\0";
 | |
|     var escPeriod = "\0PERIOD" + Math.random() + "\0";
 | |
|     function numeric(str) {
 | |
|       return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
 | |
|     }
 | |
|     function escapeBraces(str) {
 | |
|       return str.split("\\\\").join(escSlash).split("\\{").join(escOpen).split("\\}").join(escClose).split("\\,").join(escComma).split("\\.").join(escPeriod);
 | |
|     }
 | |
|     function unescapeBraces(str) {
 | |
|       return str.split(escSlash).join("\\").split(escOpen).join("{").split(escClose).join("}").split(escComma).join(",").split(escPeriod).join(".");
 | |
|     }
 | |
|     function parseCommaParts(str) {
 | |
|       if (!str)
 | |
|         return [""];
 | |
|       var parts = [];
 | |
|       var m2 = balanced("{", "}", str);
 | |
|       if (!m2)
 | |
|         return str.split(",");
 | |
|       var pre = m2.pre;
 | |
|       var body = m2.body;
 | |
|       var post = m2.post;
 | |
|       var p2 = pre.split(",");
 | |
|       p2[p2.length - 1] += "{" + body + "}";
 | |
|       var postParts = parseCommaParts(post);
 | |
|       if (post.length) {
 | |
|         p2[p2.length - 1] += postParts.shift();
 | |
|         p2.push.apply(p2, postParts);
 | |
|       }
 | |
|       parts.push.apply(parts, p2);
 | |
|       return parts;
 | |
|     }
 | |
|     function expandTop(str) {
 | |
|       if (!str)
 | |
|         return [];
 | |
|       if (str.substr(0, 2) === "{}") {
 | |
|         str = "\\{\\}" + str.substr(2);
 | |
|       }
 | |
|       return expand2(escapeBraces(str), true).map(unescapeBraces);
 | |
|     }
 | |
|     function embrace(str) {
 | |
|       return "{" + str + "}";
 | |
|     }
 | |
|     function isPadded(el) {
 | |
|       return /^-?0\d/.test(el);
 | |
|     }
 | |
|     function lte(i2, y2) {
 | |
|       return i2 <= y2;
 | |
|     }
 | |
|     function gte(i2, y2) {
 | |
|       return i2 >= y2;
 | |
|     }
 | |
|     function expand2(str, isTop) {
 | |
|       var expansions = [];
 | |
|       var m2 = balanced("{", "}", str);
 | |
|       if (!m2) return [str];
 | |
|       var pre = m2.pre;
 | |
|       var post = m2.post.length ? expand2(m2.post, false) : [""];
 | |
|       if (/\$$/.test(m2.pre)) {
 | |
|         for (var k = 0; k < post.length; k++) {
 | |
|           var expansion = pre + "{" + m2.body + "}" + post[k];
 | |
|           expansions.push(expansion);
 | |
|         }
 | |
|       } else {
 | |
|         var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m2.body);
 | |
|         var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m2.body);
 | |
|         var isSequence = isNumericSequence || isAlphaSequence;
 | |
|         var isOptions = m2.body.indexOf(",") >= 0;
 | |
|         if (!isSequence && !isOptions) {
 | |
|           if (m2.post.match(/,.*\}/)) {
 | |
|             str = m2.pre + "{" + m2.body + escClose + m2.post;
 | |
|             return expand2(str);
 | |
|           }
 | |
|           return [str];
 | |
|         }
 | |
|         var n2;
 | |
|         if (isSequence) {
 | |
|           n2 = m2.body.split(/\.\./);
 | |
|         } else {
 | |
|           n2 = parseCommaParts(m2.body);
 | |
|           if (n2.length === 1) {
 | |
|             n2 = expand2(n2[0], false).map(embrace);
 | |
|             if (n2.length === 1) {
 | |
|               return post.map(function(p2) {
 | |
|                 return m2.pre + n2[0] + p2;
 | |
|               });
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         var N2;
 | |
|         if (isSequence) {
 | |
|           var x2 = numeric(n2[0]);
 | |
|           var y2 = numeric(n2[1]);
 | |
|           var width = Math.max(n2[0].length, n2[1].length);
 | |
|           var incr = n2.length == 3 ? Math.abs(numeric(n2[2])) : 1;
 | |
|           var test = lte;
 | |
|           var reverse = y2 < x2;
 | |
|           if (reverse) {
 | |
|             incr *= -1;
 | |
|             test = gte;
 | |
|           }
 | |
|           var pad = n2.some(isPadded);
 | |
|           N2 = [];
 | |
|           for (var i2 = x2; test(i2, y2); i2 += incr) {
 | |
|             var c2;
 | |
|             if (isAlphaSequence) {
 | |
|               c2 = String.fromCharCode(i2);
 | |
|               if (c2 === "\\")
 | |
|                 c2 = "";
 | |
|             } else {
 | |
|               c2 = String(i2);
 | |
|               if (pad) {
 | |
|                 var need = width - c2.length;
 | |
|                 if (need > 0) {
 | |
|                   var z2 = new Array(need + 1).join("0");
 | |
|                   if (i2 < 0)
 | |
|                     c2 = "-" + z2 + c2.slice(1);
 | |
|                   else
 | |
|                     c2 = z2 + c2;
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|             N2.push(c2);
 | |
|           }
 | |
|         } else {
 | |
|           N2 = [];
 | |
|           for (var j2 = 0; j2 < n2.length; j2++) {
 | |
|             N2.push.apply(N2, expand2(n2[j2], false));
 | |
|           }
 | |
|         }
 | |
|         for (var j2 = 0; j2 < N2.length; j2++) {
 | |
|           for (var k = 0; k < post.length; k++) {
 | |
|             var expansion = pre + N2[j2] + post[k];
 | |
|             if (!isTop || isSequence || expansion)
 | |
|               expansions.push(expansion);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       return expansions;
 | |
|     }
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/utils.js
 | |
| var require_utils = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/utils.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.simpleFormatter = exports.htmlFormatter = exports.escapeRegexString = void 0;
 | |
|     function escapeRegexString(str) {
 | |
|       return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
 | |
|     }
 | |
|     exports.escapeRegexString = escapeRegexString;
 | |
|     var htmlFormatter = class {
 | |
|       asking(answer, hint) {
 | |
|         return `<span style='color:#2196f3'>${!hint ? "[...]" : `[${hint}]`}</span>`;
 | |
|       }
 | |
|       showingAnswer(answer, hint) {
 | |
|         return `<span style='color:#2196f3'>${answer}</span>`;
 | |
|       }
 | |
|       hiding(answer, hint) {
 | |
|         return `${!hint ? "..." : `[${hint}]`} `;
 | |
|       }
 | |
|     };
 | |
|     exports.htmlFormatter = htmlFormatter;
 | |
|     var simpleFormatter = class {
 | |
|       asking(answer, hint) {
 | |
|         return `${!hint ? "[...]" : `[${hint}]`}`;
 | |
|       }
 | |
|       showingAnswer(answer, hint) {
 | |
|         return answer;
 | |
|       }
 | |
|       hiding(answer, hint) {
 | |
|         return `...`;
 | |
|       }
 | |
|     };
 | |
|     exports.simpleFormatter = simpleFormatter;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeFieldEnum.js
 | |
| var require_ClozeFieldEnum = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeFieldEnum.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeFieldEnum = void 0;
 | |
|     var ClozeFieldEnum;
 | |
|     (function(ClozeFieldEnum2) {
 | |
|       ClozeFieldEnum2["seq"] = "seq";
 | |
|       ClozeFieldEnum2["answer"] = "answer";
 | |
|       ClozeFieldEnum2["hint"] = "hint";
 | |
|     })(ClozeFieldEnum || (exports.ClozeFieldEnum = ClozeFieldEnum = {}));
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeRegExp.js
 | |
| var require_ClozeRegExp = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeRegExp.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeRegExp = void 0;
 | |
|     var ClozeFieldEnum_1 = require_ClozeFieldEnum();
 | |
|     var ClozeRegExp = class {
 | |
|       constructor(pattern, clozeFieldsOrder, flags) {
 | |
|         this.regex = new RegExp(pattern, flags);
 | |
|         this.clozeFieldsOrder = clozeFieldsOrder;
 | |
|       }
 | |
|       exec(str) {
 | |
|         let match2 = this.regex.exec(str);
 | |
|         if (!match2) {
 | |
|           return null;
 | |
|         }
 | |
|         if (this.clozeFieldsOrder.indexOf(ClozeFieldEnum_1.ClozeFieldEnum.answer) == -1) {
 | |
|           throw new Error("Cloze text not found in clozeFieldsOrder");
 | |
|         }
 | |
|         if (this.clozeFieldsOrder.indexOf(ClozeFieldEnum_1.ClozeFieldEnum.hint) == -1) {
 | |
|           throw new Error("Cloze hint not found in clozeFieldsOrder");
 | |
|         }
 | |
|         if (this.clozeFieldsOrder.indexOf(ClozeFieldEnum_1.ClozeFieldEnum.seq) == -1) {
 | |
|           match2.seq = null;
 | |
|         } else {
 | |
|           match2.seq = match2[this.clozeFieldsOrder.indexOf(ClozeFieldEnum_1.ClozeFieldEnum.seq) + 1];
 | |
|         }
 | |
|         match2.raw = match2[0];
 | |
|         match2.answer = match2[this.clozeFieldsOrder.indexOf(ClozeFieldEnum_1.ClozeFieldEnum.answer) + 1];
 | |
|         match2.hint = match2[this.clozeFieldsOrder.indexOf(ClozeFieldEnum_1.ClozeFieldEnum.hint) + 1];
 | |
|         return match2;
 | |
|       }
 | |
|       test(str) {
 | |
|         return this.regex.test(str);
 | |
|       }
 | |
|     };
 | |
|     exports.ClozeRegExp = ClozeRegExp;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNote.js
 | |
| var require_ClozeNote = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNote.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeNote = void 0;
 | |
|     var ClozeNote = class {
 | |
|       /**
 | |
|        * Creates a new ClozeNote instance.
 | |
|        *
 | |
|        * @param raw The raw text of the cloze note before processing.
 | |
|        */
 | |
|       constructor(raw, patterns) {
 | |
|         this._raw = raw;
 | |
|         const { clozeDeletions, numCards } = this.initParsing(raw, patterns);
 | |
|         this._clozeDeletions = clozeDeletions;
 | |
|         this._numCards = numCards;
 | |
|       }
 | |
|       get raw() {
 | |
|         return this._raw;
 | |
|       }
 | |
|       get numCards() {
 | |
|         return this._numCards;
 | |
|       }
 | |
|     };
 | |
|     exports.ClozeNote = ClozeNote;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNoteClassic.js
 | |
| var require_ClozeNoteClassic = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNoteClassic.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeNoteClassic = void 0;
 | |
|     var ClozeNote_1 = require_ClozeNote();
 | |
|     var utils_1 = require_utils();
 | |
|     var ClozeTypeEnum_1 = require_ClozeTypeEnum();
 | |
|     var ClozeNoteClassic = class extends ClozeNote_1.ClozeNote {
 | |
|       constructor(raw, patterns) {
 | |
|         super(raw, patterns);
 | |
|       }
 | |
|       get clozeType() {
 | |
|         return ClozeTypeEnum_1.ClozeTypeEnum.CLASSIC;
 | |
|       }
 | |
|       initParsing(rawNote, patterns) {
 | |
|         let clozeDeletions = [];
 | |
|         let numCards = 0;
 | |
|         patterns.forEach((pattern) => {
 | |
|           const regex = pattern.getClozeRegex(ClozeTypeEnum_1.ClozeTypeEnum.CLASSIC);
 | |
|           let match2;
 | |
|           while (match2 = regex.exec(rawNote)) {
 | |
|             if (!match2.seq) {
 | |
|               break;
 | |
|             }
 | |
|             let newCloze = {
 | |
|               raw: match2.raw,
 | |
|               answer: match2.answer,
 | |
|               seq: parseInt(match2.seq),
 | |
|               hint: match2.hint
 | |
|             };
 | |
|             clozeDeletions.push(newCloze);
 | |
|             if (numCards < newCloze.seq) {
 | |
|               numCards = newCloze.seq;
 | |
|             }
 | |
|           }
 | |
|         });
 | |
|         return { clozeDeletions, numCards };
 | |
|       }
 | |
|       getCardFront(cardIndex, formatter) {
 | |
|         if (cardIndex >= this._numCards || cardIndex < 0) {
 | |
|           throw new Error(`Card ${cardIndex} does not exist`);
 | |
|         }
 | |
|         if (!formatter) {
 | |
|           formatter = new utils_1.simpleFormatter();
 | |
|         }
 | |
|         let frontText = this.raw;
 | |
|         for (const deletion of this._clozeDeletions) {
 | |
|           if (deletion.seq !== cardIndex + 1) {
 | |
|             frontText = frontText.replace(deletion.raw, deletion.answer);
 | |
|             continue;
 | |
|           }
 | |
|           frontText = frontText.replace(deletion.raw, formatter.asking(deletion.answer, deletion.hint));
 | |
|         }
 | |
|         return frontText;
 | |
|       }
 | |
|       getCardBack(cardIndex, formatter) {
 | |
|         if (cardIndex >= this._numCards || cardIndex < 0) {
 | |
|           throw new Error(`Card ${cardIndex} does not exist`);
 | |
|         }
 | |
|         if (!formatter) {
 | |
|           formatter = new utils_1.simpleFormatter();
 | |
|         }
 | |
|         let backText = this.raw;
 | |
|         for (const deletion of this._clozeDeletions) {
 | |
|           if (deletion.seq === cardIndex + 1) {
 | |
|             backText = backText.replace(deletion.raw, formatter.showingAnswer(deletion.answer, deletion.hint));
 | |
|           } else {
 | |
|             backText = backText.replace(deletion.raw, deletion.answer);
 | |
|           }
 | |
|         }
 | |
|         return backText;
 | |
|       }
 | |
|     };
 | |
|     exports.ClozeNoteClassic = ClozeNoteClassic;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNoteOL.js
 | |
| var require_ClozeNoteOL = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNoteOL.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeNoteOL = void 0;
 | |
|     var ClozeNote_1 = require_ClozeNote();
 | |
|     var utils_1 = require_utils();
 | |
|     var ClozeTypeEnum_1 = require_ClozeTypeEnum();
 | |
|     var ClozeNoteOL = class extends ClozeNote_1.ClozeNote {
 | |
|       constructor(raw, patterns) {
 | |
|         super(raw, patterns);
 | |
|       }
 | |
|       get clozeType() {
 | |
|         return ClozeTypeEnum_1.ClozeTypeEnum.OVERLAPPING;
 | |
|       }
 | |
|       initParsing(rawNote, patterns) {
 | |
|         let clozeDeletions = [];
 | |
|         let numCards = 0;
 | |
|         patterns.forEach((pattern) => {
 | |
|           const regex = pattern.getClozeRegex(ClozeTypeEnum_1.ClozeTypeEnum.OVERLAPPING);
 | |
|           let match2;
 | |
|           while (match2 = regex.exec(rawNote)) {
 | |
|             if (!match2.seq) {
 | |
|               break;
 | |
|             }
 | |
|             let newCloze = {
 | |
|               raw: match2.raw,
 | |
|               answer: match2.answer,
 | |
|               seq: match2.seq,
 | |
|               hint: match2.hint
 | |
|             };
 | |
|             clozeDeletions.push(newCloze);
 | |
|             if (numCards < newCloze.seq.length) {
 | |
|               numCards = newCloze.seq.length;
 | |
|             }
 | |
|           }
 | |
|         });
 | |
|         return { clozeDeletions, numCards };
 | |
|       }
 | |
|       getCardFront(cardIndex, formatter) {
 | |
|         if (cardIndex >= this._numCards || cardIndex < 0) {
 | |
|           throw new Error(`Card ${cardIndex} does not exist`);
 | |
|         }
 | |
|         if (!formatter) {
 | |
|           formatter = new utils_1.simpleFormatter();
 | |
|         }
 | |
|         let frontText = this.raw;
 | |
|         for (const deletion of this._clozeDeletions) {
 | |
|           let clozeAction = "s";
 | |
|           if (cardIndex < deletion.seq.length) {
 | |
|             clozeAction = deletion.seq[cardIndex];
 | |
|           }
 | |
|           switch (clozeAction) {
 | |
|             case "a":
 | |
|               frontText = frontText.replace(deletion.raw, formatter.asking(deletion.answer, deletion.hint));
 | |
|               break;
 | |
|             case "h":
 | |
|               frontText = frontText.replace(deletion.raw, formatter.hiding(deletion.answer, deletion.hint));
 | |
|               break;
 | |
|             case "s":
 | |
|               frontText = frontText.replace(deletion.raw, deletion.answer);
 | |
|               break;
 | |
|           }
 | |
|         }
 | |
|         return frontText;
 | |
|       }
 | |
|       getCardBack(cardIndex, formatter) {
 | |
|         if (cardIndex >= this._numCards || cardIndex < 0) {
 | |
|           throw new Error(`Card ${cardIndex} does not exist`);
 | |
|         }
 | |
|         if (!formatter) {
 | |
|           formatter = new utils_1.simpleFormatter();
 | |
|         }
 | |
|         let backText = this.raw;
 | |
|         for (const deletion of this._clozeDeletions) {
 | |
|           let clozeAction = "s";
 | |
|           if (cardIndex < deletion.seq.length) {
 | |
|             clozeAction = deletion.seq[cardIndex];
 | |
|           }
 | |
|           switch (clozeAction) {
 | |
|             case "a":
 | |
|               backText = backText.replace(deletion.raw, formatter.showingAnswer(deletion.answer, deletion.hint));
 | |
|               break;
 | |
|             case "h":
 | |
|               backText = backText.replace(deletion.raw, formatter.hiding(deletion.answer, deletion.hint));
 | |
|               break;
 | |
|             case "s":
 | |
|               backText = backText.replace(deletion.raw, deletion.answer);
 | |
|               break;
 | |
|           }
 | |
|         }
 | |
|         return backText;
 | |
|       }
 | |
|     };
 | |
|     exports.ClozeNoteOL = ClozeNoteOL;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNoteSimple.js
 | |
| var require_ClozeNoteSimple = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeNoteSimple.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeNoteSimple = void 0;
 | |
|     var ClozeNote_1 = require_ClozeNote();
 | |
|     var ClozeTypeEnum_1 = require_ClozeTypeEnum();
 | |
|     var utils_1 = require_utils();
 | |
|     var ClozeNoteSimple = class extends ClozeNote_1.ClozeNote {
 | |
|       constructor(raw, patterns) {
 | |
|         super(raw, patterns);
 | |
|       }
 | |
|       get clozeType() {
 | |
|         return ClozeTypeEnum_1.ClozeTypeEnum.SIMPLE;
 | |
|       }
 | |
|       initParsing(rawNote, patterns) {
 | |
|         let clozeDeletions = [];
 | |
|         let numCards = 0;
 | |
|         patterns.forEach((pattern) => {
 | |
|           const regex = pattern.getClozeRegex(ClozeTypeEnum_1.ClozeTypeEnum.SIMPLE);
 | |
|           let match2;
 | |
|           while (match2 = regex.exec(rawNote)) {
 | |
|             numCards++;
 | |
|             let newCloze = {
 | |
|               raw: match2.raw,
 | |
|               answer: match2.answer,
 | |
|               seq: numCards,
 | |
|               hint: match2.hint
 | |
|             };
 | |
|             clozeDeletions.push(newCloze);
 | |
|           }
 | |
|         });
 | |
|         return { clozeDeletions, numCards };
 | |
|       }
 | |
|       getCardFront(cardIndex, formatter) {
 | |
|         if (cardIndex >= this._numCards || cardIndex < 0) {
 | |
|           throw new Error(`Card ${cardIndex} does not exist`);
 | |
|         }
 | |
|         if (!formatter) {
 | |
|           formatter = new utils_1.simpleFormatter();
 | |
|         }
 | |
|         let frontText = this.raw;
 | |
|         for (const deletion of this._clozeDeletions) {
 | |
|           if (deletion.seq !== cardIndex + 1) {
 | |
|             frontText = frontText.replace(deletion.raw, deletion.answer);
 | |
|             continue;
 | |
|           }
 | |
|           frontText = frontText.replace(deletion.raw, formatter.asking(deletion.answer, deletion.hint));
 | |
|         }
 | |
|         return frontText;
 | |
|       }
 | |
|       getCardBack(cardIndex, formatter) {
 | |
|         if (cardIndex >= this._numCards || cardIndex < 0) {
 | |
|           throw new Error(`Card ${cardIndex} does not exist`);
 | |
|         }
 | |
|         if (!formatter) {
 | |
|           formatter = new utils_1.simpleFormatter();
 | |
|         }
 | |
|         let backText = this.raw;
 | |
|         for (const deletion of this._clozeDeletions) {
 | |
|           if (deletion.seq === cardIndex + 1) {
 | |
|             backText = backText.replace(deletion.raw, formatter.showingAnswer(deletion.answer, deletion.hint));
 | |
|           } else {
 | |
|             backText = backText.replace(deletion.raw, deletion.answer);
 | |
|           }
 | |
|         }
 | |
|         return backText;
 | |
|       }
 | |
|     };
 | |
|     exports.ClozeNoteSimple = ClozeNoteSimple;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeTypeEnum.js
 | |
| var require_ClozeTypeEnum = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeTypeEnum.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.NoteClassByClozeType = exports.ClozeTypesPriority = exports.ClozeTypeEnum = void 0;
 | |
|     var ClozeNoteClassic_1 = require_ClozeNoteClassic();
 | |
|     var ClozeNoteOL_1 = require_ClozeNoteOL();
 | |
|     var ClozeNoteSimple_1 = require_ClozeNoteSimple();
 | |
|     var ClozeTypeEnum;
 | |
|     (function(ClozeTypeEnum2) {
 | |
|       ClozeTypeEnum2["CLASSIC"] = "classic";
 | |
|       ClozeTypeEnum2["OVERLAPPING"] = "overlapping";
 | |
|       ClozeTypeEnum2["SIMPLE"] = "simple";
 | |
|     })(ClozeTypeEnum || (exports.ClozeTypeEnum = ClozeTypeEnum = {}));
 | |
|     exports.ClozeTypesPriority = [
 | |
|       ClozeTypeEnum.CLASSIC,
 | |
|       ClozeTypeEnum.OVERLAPPING,
 | |
|       ClozeTypeEnum.SIMPLE
 | |
|       // Cloze Simple must be the last one because it is a subset of Cloze Classic and Cloze Overlapping
 | |
|     ];
 | |
|     exports.NoteClassByClozeType = {
 | |
|       [ClozeTypeEnum.CLASSIC]: ClozeNoteClassic_1.ClozeNoteClassic,
 | |
|       [ClozeTypeEnum.OVERLAPPING]: ClozeNoteOL_1.ClozeNoteOL,
 | |
|       [ClozeTypeEnum.SIMPLE]: ClozeNoteSimple_1.ClozeNoteSimple
 | |
|     };
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozePattern.js
 | |
| var require_ClozePattern = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozePattern.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozePattern = void 0;
 | |
|     var utils_1 = require_utils();
 | |
|     var ClozeRegExp_1 = require_ClozeRegExp();
 | |
|     var ClozeFieldEnum_1 = require_ClozeFieldEnum();
 | |
|     var ClozeTypeEnum_1 = require_ClozeTypeEnum();
 | |
|     var numPatternRegex = new RegExp(`\\[(?:(?:\\\\\\])?[^\\]]?)+?\\d+(?:(?:\\\\\\])?[^\\]]?)+?\\]`);
 | |
|     var hintPatternRegex = new RegExp(`\\[(?:(?:\\\\\\])?[^\\]]?)+?hint(?:(?:\\\\\\])?[^\\]]?)+?\\]`);
 | |
|     var answerKeyword = `answer`;
 | |
|     var ClozePattern = class _ClozePattern {
 | |
|       constructor(raw) {
 | |
|         this.clozeRegexByType = {
 | |
|           [ClozeTypeEnum_1.ClozeTypeEnum.CLASSIC]: void 0,
 | |
|           [ClozeTypeEnum_1.ClozeTypeEnum.OVERLAPPING]: void 0,
 | |
|           [ClozeTypeEnum_1.ClozeTypeEnum.SIMPLE]: void 0
 | |
|         };
 | |
|         this.generateClozeRegexByType = {
 | |
|           [ClozeTypeEnum_1.ClozeTypeEnum.CLASSIC]: this.generateClozeClassicRegex,
 | |
|           [ClozeTypeEnum_1.ClozeTypeEnum.OVERLAPPING]: this.generateClozeOLRegex,
 | |
|           [ClozeTypeEnum_1.ClozeTypeEnum.SIMPLE]: this.generateClozeSimpleRegex
 | |
|         };
 | |
|         this._raw = raw;
 | |
|         let _numMatch = numPatternRegex.exec(raw);
 | |
|         let _hintMatch = hintPatternRegex.exec(raw);
 | |
|         if (!_numMatch) {
 | |
|           throw new Error("No cloze number pattern found");
 | |
|         }
 | |
|         if (!_hintMatch) {
 | |
|           throw new Error("No cloze hint pattern found");
 | |
|         }
 | |
|         if (raw.indexOf(answerKeyword) == -1) {
 | |
|           throw new Error(`No answer keyword (${answerKeyword}) found in the pattern.`);
 | |
|         }
 | |
|         this.numPattern = _numMatch;
 | |
|         this.hintPattern = _hintMatch;
 | |
|         this.numRegex = _ClozePattern.processPattern(_numMatch[0], (text) => text.replace(/\d+/g, "(\\d+)"));
 | |
|         this.seqRegex = _ClozePattern.processPattern(_numMatch[0], (text) => text.replace(/\d+/g, "([ash]+)"));
 | |
|         this.hintRegex = _ClozePattern.processPattern(_hintMatch[0], (text) => text.replace(/hint/g, "(.+?)"));
 | |
|         this.hintRegex = "(?:" + this.hintRegex + ")?";
 | |
|         this._clozeFieldOrder = [ClozeFieldEnum_1.ClozeFieldEnum.answer, ClozeFieldEnum_1.ClozeFieldEnum.hint, ClozeFieldEnum_1.ClozeFieldEnum.seq];
 | |
|         let positions2 = {
 | |
|           [ClozeFieldEnum_1.ClozeFieldEnum.answer]: raw.indexOf(answerKeyword),
 | |
|           [ClozeFieldEnum_1.ClozeFieldEnum.hint]: this.hintPattern.index,
 | |
|           [ClozeFieldEnum_1.ClozeFieldEnum.seq]: this.numPattern.index
 | |
|         };
 | |
|         this._clozeFieldOrder.sort((a2, b2) => positions2[a2] - positions2[b2]);
 | |
|       }
 | |
|       static processPattern(text, rplc) {
 | |
|         let ans = text.substring(1, text.length - 1);
 | |
|         ans = ans.replace(/\\\[/g, "[").replace(/\\]/g, "]");
 | |
|         ans = (0, utils_1.escapeRegexString)(ans);
 | |
|         ans = rplc(ans);
 | |
|         return ans;
 | |
|       }
 | |
|       generateClozeRegexStr(first, firstReplace, second, secondReplace) {
 | |
|         let begin = this._raw.slice(0, first.index);
 | |
|         let middle = this._raw.slice(first.index + first[0].length, second.index);
 | |
|         let ending = this._raw.slice(second.index + second[0].length, this._raw.length);
 | |
|         let regexStr = (0, utils_1.escapeRegexString)(begin) + firstReplace + (0, utils_1.escapeRegexString)(middle) + secondReplace + (0, utils_1.escapeRegexString)(ending);
 | |
|         regexStr = regexStr.replace(answerKeyword, "(.+?)");
 | |
|         return regexStr;
 | |
|       }
 | |
|       generateClozeSimpleRegex(pattern) {
 | |
|         let regexStr;
 | |
|         if (pattern.numPattern.index < pattern.hintPattern.index) {
 | |
|           regexStr = pattern.generateClozeRegexStr(pattern.numPattern, "", pattern.hintPattern, pattern.hintRegex);
 | |
|         } else {
 | |
|           regexStr = pattern.generateClozeRegexStr(pattern.hintPattern, pattern.hintRegex, pattern.numPattern, "");
 | |
|         }
 | |
|         let clozeFieldsOrderWithoutSeq = pattern._clozeFieldOrder.filter((x2) => x2 != ClozeFieldEnum_1.ClozeFieldEnum.seq);
 | |
|         return new ClozeRegExp_1.ClozeRegExp(regexStr, clozeFieldsOrderWithoutSeq, "g");
 | |
|       }
 | |
|       generateClozeClassicRegex(pattern) {
 | |
|         let regexStr;
 | |
|         if (pattern.numPattern.index < pattern.hintPattern.index) {
 | |
|           regexStr = pattern.generateClozeRegexStr(pattern.numPattern, pattern.numRegex, pattern.hintPattern, pattern.hintRegex);
 | |
|         } else {
 | |
|           regexStr = pattern.generateClozeRegexStr(pattern.hintPattern, pattern.hintRegex, pattern.numPattern, pattern.numRegex);
 | |
|         }
 | |
|         return new ClozeRegExp_1.ClozeRegExp(regexStr, pattern._clozeFieldOrder, "g");
 | |
|       }
 | |
|       generateClozeOLRegex(pattern) {
 | |
|         let regexStr;
 | |
|         if (pattern.numPattern.index < pattern.hintPattern.index) {
 | |
|           regexStr = pattern.generateClozeRegexStr(pattern.numPattern, pattern.seqRegex, pattern.hintPattern, pattern.hintRegex);
 | |
|         } else {
 | |
|           regexStr = pattern.generateClozeRegexStr(pattern.hintPattern, pattern.hintRegex, pattern.numPattern, pattern.seqRegex);
 | |
|         }
 | |
|         return new ClozeRegExp_1.ClozeRegExp(regexStr, pattern._clozeFieldOrder, "g");
 | |
|       }
 | |
|       get clozeFieldsOrder() {
 | |
|         return this._clozeFieldOrder;
 | |
|       }
 | |
|       getClozeRegex(clozeType) {
 | |
|         let clozeRegex = this.clozeRegexByType[clozeType];
 | |
|         if (clozeRegex != void 0) {
 | |
|           clozeRegex.regex.lastIndex = 0;
 | |
|           return clozeRegex;
 | |
|         }
 | |
|         clozeRegex = this.generateClozeRegexByType[clozeType](this);
 | |
|         this.clozeRegexByType[clozeType] = clozeRegex;
 | |
|         return clozeRegex;
 | |
|       }
 | |
|       hasClozeType(text, clozeType) {
 | |
|         for (const priorityType of ClozeTypeEnum_1.ClozeTypesPriority) {
 | |
|           if (this.getClozeRegex(priorityType).test(text)) {
 | |
|             return clozeType == priorityType;
 | |
|           }
 | |
|         }
 | |
|         return false;
 | |
|       }
 | |
|       getClozeTypes(text) {
 | |
|         const clozeTypes = [];
 | |
|         for (const priorityType of ClozeTypeEnum_1.ClozeTypesPriority) {
 | |
|           if (this.getClozeRegex(priorityType).test(text)) {
 | |
|             clozeTypes.push(priorityType);
 | |
|           }
 | |
|         }
 | |
|         return clozeTypes;
 | |
|       }
 | |
|       getMainClozeType(text) {
 | |
|         for (const priorityType of ClozeTypeEnum_1.ClozeTypesPriority) {
 | |
|           if (this.getClozeRegex(priorityType).test(text)) {
 | |
|             return priorityType;
 | |
|           }
 | |
|         }
 | |
|         return null;
 | |
|       }
 | |
|     };
 | |
|     exports.ClozePattern = ClozePattern;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeCrafter.js
 | |
| var require_ClozeCrafter = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/implementation/ClozeCrafter.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeCrafter = void 0;
 | |
|     var ClozePattern_1 = require_ClozePattern();
 | |
|     var ClozeTypeEnum_1 = require_ClozeTypeEnum();
 | |
|     var ClozeCrafter3 = class {
 | |
|       constructor(patterns) {
 | |
|         this.patterns = patterns.map((patternStr) => new ClozePattern_1.ClozePattern(patternStr));
 | |
|       }
 | |
|       createClozeNote(text) {
 | |
|         const noteType = this.getNoteType(text);
 | |
|         if (noteType === null) {
 | |
|           return null;
 | |
|         }
 | |
|         const selectedClass = ClozeTypeEnum_1.NoteClassByClozeType[noteType];
 | |
|         const clozeNote = new selectedClass(text, this.patterns);
 | |
|         return clozeNote;
 | |
|       }
 | |
|       getNoteType(text) {
 | |
|         let noteType = null;
 | |
|         for (const pattern of this.patterns) {
 | |
|           const currentType = pattern.getMainClozeType(text);
 | |
|           if (currentType !== null && (noteType === null || ClozeTypeEnum_1.ClozeTypesPriority.indexOf(currentType) < ClozeTypeEnum_1.ClozeTypesPriority.indexOf(noteType))) {
 | |
|             noteType = currentType;
 | |
|           }
 | |
|         }
 | |
|         return noteType;
 | |
|       }
 | |
|       isClozeNote(text) {
 | |
|         return this.getNoteType(text) !== null;
 | |
|       }
 | |
|     };
 | |
|     exports.ClozeCrafter = ClozeCrafter3;
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/index.js
 | |
| var require_dist = __commonJS({
 | |
|   "node_modules/.pnpm/clozecraft@0.4.0/node_modules/clozecraft/dist/index.js"(exports) {
 | |
|     "use strict";
 | |
|     Object.defineProperty(exports, "__esModule", { value: true });
 | |
|     exports.ClozeTypesPriority = exports.ClozeTypeEnum = exports.ClozeCrafter = void 0;
 | |
|     var ClozeCrafter_1 = require_ClozeCrafter();
 | |
|     Object.defineProperty(exports, "ClozeCrafter", { enumerable: true, get: function() {
 | |
|       return ClozeCrafter_1.ClozeCrafter;
 | |
|     } });
 | |
|     var ClozeTypeEnum_1 = require_ClozeTypeEnum();
 | |
|     Object.defineProperty(exports, "ClozeTypeEnum", { enumerable: true, get: function() {
 | |
|       return ClozeTypeEnum_1.ClozeTypeEnum;
 | |
|     } });
 | |
|     Object.defineProperty(exports, "ClozeTypesPriority", { enumerable: true, get: function() {
 | |
|       return ClozeTypeEnum_1.ClozeTypesPriority;
 | |
|     } });
 | |
|   }
 | |
| });
 | |
| 
 | |
| // node_modules/.pnpm/vhtml@2.2.0/node_modules/vhtml/dist/vhtml.js
 | |
| var require_vhtml = __commonJS({
 | |
|   "node_modules/.pnpm/vhtml@2.2.0/node_modules/vhtml/dist/vhtml.js"(exports, module2) {
 | |
|     (function(global, factory) {
 | |
|       typeof exports === "object" && typeof module2 !== "undefined" ? module2.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.vhtml = factory();
 | |
|     })(exports, function() {
 | |
|       "use strict";
 | |
|       var emptyTags = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"];
 | |
|       var esc = function esc2(str) {
 | |
|         return String(str).replace(/[&<>"']/g, function(s2) {
 | |
|           return "&" + map3[s2] + ";";
 | |
|         });
 | |
|       };
 | |
|       var map3 = { "&": "amp", "<": "lt", ">": "gt", '"': "quot", "'": "apos" };
 | |
|       var setInnerHTMLAttr = "dangerouslySetInnerHTML";
 | |
|       var DOMAttributeNames = {
 | |
|         className: "class",
 | |
|         htmlFor: "for"
 | |
|       };
 | |
|       var sanitized = {};
 | |
|       function h6(name, attrs) {
 | |
|         var stack = [], s2 = "";
 | |
|         attrs = attrs || {};
 | |
|         for (var i2 = arguments.length; i2-- > 2; ) {
 | |
|           stack.push(arguments[i2]);
 | |
|         }
 | |
|         if (typeof name === "function") {
 | |
|           attrs.children = stack.reverse();
 | |
|           return name(attrs);
 | |
|         }
 | |
|         if (name) {
 | |
|           s2 += "<" + name;
 | |
|           if (attrs) for (var _i in attrs) {
 | |
|             if (attrs[_i] !== false && attrs[_i] != null && _i !== setInnerHTMLAttr) {
 | |
|               s2 += " " + (DOMAttributeNames[_i] ? DOMAttributeNames[_i] : esc(_i)) + '="' + esc(attrs[_i]) + '"';
 | |
|             }
 | |
|           }
 | |
|           s2 += ">";
 | |
|         }
 | |
|         if (emptyTags.indexOf(name) === -1) {
 | |
|           if (attrs[setInnerHTMLAttr]) {
 | |
|             s2 += attrs[setInnerHTMLAttr].__html;
 | |
|           } else while (stack.length) {
 | |
|             var child = stack.pop();
 | |
|             if (child) {
 | |
|               if (child.pop) {
 | |
|                 for (var _i2 = child.length; _i2--; ) {
 | |
|                   stack.push(child[_i2]);
 | |
|                 }
 | |
|               } else {
 | |
|                 s2 += sanitized[child] === true ? child : esc(child);
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|           s2 += name ? "</" + name + ">" : "";
 | |
|         }
 | |
|         sanitized[s2] = true;
 | |
|         return s2;
 | |
|       }
 | |
|       return h6;
 | |
|     });
 | |
|   }
 | |
| });
 | |
| 
 | |
| // src/main.ts
 | |
| var main_exports = {};
 | |
| __export(main_exports, {
 | |
|   default: () => SRPlugin
 | |
| });
 | |
| module.exports = __toCommonJS(main_exports);
 | |
| var import_obsidian15 = require("obsidian");
 | |
| 
 | |
| // src/algorithms/base/repetition-item.ts
 | |
| var RepetitionItem = class {
 | |
|   // scheduling
 | |
|   get hasSchedule() {
 | |
|     return this.scheduleInfo != null;
 | |
|   }
 | |
|   get isNew() {
 | |
|     return !this.hasSchedule;
 | |
|   }
 | |
|   get isDue() {
 | |
|     return this.hasSchedule && this.scheduleInfo.isDue();
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/algorithms/base/srs-algorithm.ts
 | |
| var SrsAlgorithm = class _SrsAlgorithm {
 | |
|   static getInstance() {
 | |
|     if (!_SrsAlgorithm.instance) {
 | |
|       throw new Error("there is no SrsAlgorithm instance.");
 | |
|     }
 | |
|     return _SrsAlgorithm.instance;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/algorithms/osr/obsidian-vault-notelink-info-finder.ts
 | |
| var ObsidianVaultNoteLinkInfoFinder = class {
 | |
|   constructor(metadataCache) {
 | |
|     this.metadataCache = metadataCache;
 | |
|   }
 | |
|   getResolvedTargetLinksForNotePath(path3) {
 | |
|     return this.metadataCache.resolvedLinks[path3];
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/algorithms/osr/srs-algorithm-osr.ts
 | |
| var import_moment2 = __toESM(require_moment());
 | |
| 
 | |
| // src/constants.ts
 | |
| var SCHEDULING_INFO_REGEX = /^---\r?\n((?:.*\r?\n)*)sr-due: (.+)\r?\nsr-interval: (\d+)\r?\nsr-ease: (\d+)\r?\n((?:.*\r?\n)?)---/;
 | |
| var YAML_FRONT_MATTER_REGEX = /^---\r?\n((?:.*\r?\n)*?)---/;
 | |
| var MULTI_SCHEDULING_EXTRACTOR = /!([\d-]+),(\d+),(\d+)/gm;
 | |
| var LEGACY_SCHEDULING_EXTRACTOR = /<!--SR:([\d-]+),(\d+),(\d+)-->/gm;
 | |
| var OBSIDIAN_TAG_AT_STARTOFLINE_REGEX = /^#[^\s#]+/gi;
 | |
| var OBSIDIAN_BLOCK_ID_ENDOFLINE_REGEX = / (\^[a-zA-Z0-9-]+)$/;
 | |
| var PREFERRED_DATE_FORMAT = "YYYY-MM-DD";
 | |
| var ALLOWED_DATE_FORMATS = [PREFERRED_DATE_FORMAT, "DD-MM-YYYY", "ddd MMM DD YYYY"];
 | |
| var IMAGE_FORMATS = [
 | |
|   "jpg",
 | |
|   "jpeg",
 | |
|   "gif",
 | |
|   "png",
 | |
|   "svg",
 | |
|   "webp",
 | |
|   "apng",
 | |
|   "avif",
 | |
|   "jfif",
 | |
|   "pjpeg",
 | |
|   "pjp",
 | |
|   "bmp"
 | |
| ];
 | |
| var AUDIO_FORMATS = ["mp3", "webm", "m4a", "wav", "ogg"];
 | |
| var VIDEO_FORMATS = ["mp4", "mkv", "avi", "mov"];
 | |
| var COLLAPSE_ICON = '<svg viewBox="0 0 100 100" width="8" height="8" class="svg-icon right-triangle"><path fill="currentColor" stroke="currentColor" d="M94.9,20.8c-1.4-2.5-4.1-4.1-7.1-4.1H12.2c-3,0-5.7,1.6-7.1,4.1c-1.3,2.4-1.2,5.2,0.2,7.6L43.1,88c1.5,2.3,4,3.7,6.9,3.7 s5.4-1.4,6.9-3.7l37.8-59.6C96.1,26,96.2,23.2,94.9,20.8L94.9,20.8z"></path></svg>';
 | |
| var TICKS_PER_DAY = 24 * 3600 * 1e3;
 | |
| var SR_HTML_COMMENT_BEGIN = "<!--SR:";
 | |
| var SR_HTML_COMMENT_END = "-->";
 | |
| var SR_TAB_VIEW = "spaced-repetition-tab-view";
 | |
| 
 | |
| // src/lang/helpers.ts
 | |
| var import_obsidian = require("obsidian");
 | |
| 
 | |
| // src/lang/locale/af.ts
 | |
| var af_default = {};
 | |
| 
 | |
| // src/lang/locale/ar.ts
 | |
| var ar_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "\u0627\u0644\u0631\u064F\u0632\u0645\u064E\u0627\u062A",
 | |
|   DUE_CARDS: "\u0628\u0637\u0627\u0642\u0627\u062A \u0645\u064F\u0633\u062A\u062D\u0642\u0629",
 | |
|   NEW_CARDS: "\u0628\u0637\u0627\u0642\u0627\u062A \u062C\u062F\u064A\u062F\u0629",
 | |
|   TOTAL_CARDS: "\u0625\u062C\u0645\u0627\u0644\u064A \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   BACK: "\u0631\u062C\u0648\u0639",
 | |
|   SKIP: "Skip",
 | |
|   EDIT_CARD: "\u062A\u0639\u062F\u064A\u0644 \u0627\u0644\u0628\u0637\u0627\u0642\u0629",
 | |
|   RESET_CARD_PROGRESS: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646 \u062A\u0642\u062F\u0651\u064F\u0645\u0652 \u0627\u0644\u0628\u0637\u0627\u0642\u0629",
 | |
|   HARD: "\u0635\u0639\u0628",
 | |
|   GOOD: "\u062C\u064A\u062F",
 | |
|   EASY: "\u0633\u0647\u0644",
 | |
|   SHOW_ANSWER: "\u0623\u0638\u0647\u0650\u0631 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
 | |
|   CARD_PROGRESS_RESET: ".\u062A\u0645\u0651\u064E\u062A \u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646 \u062A\u0642\u062F\u0651\u064F\u0645 \u0627\u0644\u0628\u0637\u0627\u0642\u0629",
 | |
|   SAVE: "\u062D\u0641\u0638",
 | |
|   CANCEL: "\u0625\u0644\u063A\u0627\u0621",
 | |
|   NO_INPUT: ".\u0644\u0645 \u064A\u062A\u0650\u0645 \u062A\u0642\u062F\u064A\u0645 \u0623\u064A \u0645\u064F\u062F\u062E\u0644\u0627\u062A",
 | |
|   CURRENT_EASE_HELP_TEXT: ":\u0627\u0644\u0633\u0647\u0648\u0644\u0629 \u0627\u0644\u062D\u0627\u0644\u064A\u0629",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: ":\u0627\u0644\u0641\u0627\u0635\u0644 \u0627\u0644\u0632\u0645\u0646\u064A \u0627\u0644\u062D\u0627\u0644\u064A",
 | |
|   CARD_GENERATED_FROM: "${notePath} :\u062A\u0645 \u0625\u0646\u0634\u0627\u0624\u0647\u0627 \u0645\u0646",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "\u0627\u0641\u062A\u062D \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629 \u0644\u0644\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   REVIEW_CARDS: "\u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "${difficulty} :\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "${difficulty} \u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629 \u0643\u0640",
 | |
|   CRAM_ALL_CARDS: "\u062D\u062F\u062F \u0631\u064F\u0632\u0645\u064E\u0629 \u0644\u0644\u062D\u0634\u0631",
 | |
|   REVIEW_ALL_CARDS: "\u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0645\u0646 \u062C\u0645\u064A\u0639 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0627\u062A",
 | |
|   REVIEW_CARDS_IN_NOTE: "\u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A  \u0645\u0646 \u0647\u0630\u0647 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629",
 | |
|   CRAM_CARDS_IN_NOTE: "\u0623\u062D\u0634\u0631 \u062C\u0645\u064A\u0639 \u0628\u0637\u0627\u0642\u0627\u062A \u0647\u0630\u0647 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629",
 | |
|   VIEW_STATS: "\u0639\u0631\u0636 \u0627\u0644\u0625\u062D\u0635\u0627\u0626\u064A\u0627\u062A",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "\u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0645\u0633\u062A\u062D\u0642\u0629 ${dueFlashcardsCount},\u0645\u0644\u0627\u062D\u0638\u0627\u062A ${dueNotesCount}:\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   SYNC_TIME_TAKEN: "${t}ms \u0627\u0633\u062A\u063A\u0631\u0627\u0642 \u0627\u0644\u0645\u0632\u0627\u0645\u0646\u0629",
 | |
|   NOTE_IN_IGNORED_FOLDER: ".\u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629 \u064A\u062A\u0645 \u062D\u0641\u0638\u0647\u0627 \u0636\u0645\u0646 \u0627\u0644\u0645\u062C\u0644\u062F \u0627\u0644\u0630\u064A \u062A\u0645 \u062A\u062C\u0627\u0647\u0644\u0647 (\u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A)",
 | |
|   PLEASE_TAG_NOTE: ".\u064A\u0631\u062C\u0649 \u0648\u0636\u0639 \u0648\u0633\u0645 \u0639\u0644\u0649 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629 \u0628\u0634\u0643\u0644 \u0645\u0646\u0627\u0633\u0628 \u0644\u0644\u0645\u0631\u0627\u062C\u0639\u0629 (\u0641\u064A \u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A)",
 | |
|   RESPONSE_RECEIVED: ".\u0627\u0633\u062A\u064F\u0644\u0645\u062A \u0627\u0644\u0627\u0633\u062A\u062C\u0627\u0628\u0629",
 | |
|   NO_DECK_EXISTS: "${deckName} \u0644\u0627 \u064A\u0648\u062C\u062F \u0631\u064F\u0632\u0645\u064E\u0629",
 | |
|   ALL_CAUGHT_UP: "\u{1F606} \u0644\u0642\u062F \u062A\u0645 \u0627\u0644\u0642\u0628\u0636 \u0639\u0644\u064A\u0643\u0645 \u062C\u0645\u064A\u0639\u0627 \u0627\u0644\u0622\u0646",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "\u064A\u0648\u0645/\u0623\u064A\u0627\u0645 ${interval}",
 | |
|   MONTHS_STR_IVL: "\u0634\u0647\u0631/\u0623\u0634\u0647\u0631 ${interval}",
 | |
|   YEARS_STR_IVL: "\u0633\u0646\u0629/\u0633\u0646\u0648\u0627\u062A ${interval}",
 | |
|   DAYS_STR_IVL_MOBILE: "\u064A${interval}",
 | |
|   MONTHS_STR_IVL_MOBILE: "\u0634${interval}",
 | |
|   YEARS_STR_IVL_MOBILE: "\u0633${interval}",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: '.<a href="${wikiUrl}">wiki</a> \u0644\u0645\u0632\u064A\u062F \u0645\u0646 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062A \u060C \u062A\u062D\u0642\u0642 \u0645\u0646',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "\u0645\u062C\u0644\u062F\u0627\u062A \u0644\u062A\u062C\u0627\u0647\u0644\u0647\u0627",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "\u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   FLASHCARD_EASY_LABEL: "\u0646\u0635 \u0627\u0644\u0632\u0631 \u0633\u0647\u0644",
 | |
|   FLASHCARD_GOOD_LABEL: "\u0646\u0635 \u0627\u0644\u0632\u0631 \u062C\u064A\u062F",
 | |
|   FLASHCARD_HARD_LABEL: "\u0646\u0635 \u0627\u0644\u0632\u0631 \u0635\u0639\u0628",
 | |
|   FLASHCARD_EASY_DESC: '"\u062A\u062E\u0635\u064A\u0635 \u0627\u0644\u062A\u0633\u0645\u064A\u0629 \u0644\u0644\u0632\u0631 "\u0633\u0647\u0644',
 | |
|   FLASHCARD_GOOD_DESC: '"\u062A\u062E\u0635\u064A\u0635 \u0627\u0644\u062A\u0633\u0645\u064A\u0629 \u0644\u0644\u0632\u0631 "\u062C\u064A\u062F',
 | |
|   FLASHCARD_HARD_DESC: '"\u062A\u062E\u0635\u064A\u0635 \u0627\u0644\u062A\u0633\u0645\u064A\u0629 \u0644\u0644\u0632\u0631 "\u0635\u0639\u0628',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "\u0648\u064F\u0633\u0648\u0645 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   FLASHCARD_TAGS_DESC: "#2\u0623\u062F\u062E\u0644 \u0627\u0644\u0648\u064F\u0633\u0648\u0645 \u0645\u0641\u0635\u0648\u0644\u0629 \u0628\u0645\u0633\u0627\u0641\u0627\u062A \u0623\u0648 \u0623\u0633\u0637\u0631 \u062C\u062F\u064A\u062F\u0629 \u060C \u0623\u064A \u0628\u0637\u0627\u0642\u0627\u062A# \u0631\u0632\u0645\u06293# \u0631\u0632\u0645\u0629",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u062C\u0644\u062F\u0627\u062A \u0625\u0644\u0649 \u0645\u0644\u0641\u0627\u062A \u0623\u0635\u0644\u064A\u0629 \u0648 \u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0641\u0631\u0639\u064A\u0629\u061F",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: ".\u0647\u0630\u0627 \u0647\u0648 \u0628\u062F\u064A\u0644 \u0644\u062E\u064A\u0627\u0631 \u0648\u0633\u0648\u0645 \u0627\u0644\u0628\u0637\u0627\u0642\u0629 \u0623\u0639\u0644\u0627\u0647",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\u062D\u0641\u0638 \u062A\u0639\u0644\u064A\u0642 \u0627\u0644\u062C\u062F\u0648\u0644\u0629 \u0639\u0644\u0649 \u0646\u0641\u0633 \u0627\u0644\u0633\u0637\u0631 \u0645\u062B\u0644 \u0627\u0644\u0633\u0637\u0631 \u0627\u0644\u0623\u062E\u064A\u0631 \u0644\u0644\u0628\u0637\u0627\u0642\u0629 \u061F",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "\u0644\u0627 \u062A\u0643\u0633\u0631 \u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 HTML \u0633\u064A\u0624\u062F\u064A \u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0625\u0644\u0649 \u062C\u0639\u0644 \u062A\u0639\u0644\u064A\u0642\u0627\u062A",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "\u0623\u062E\u0641\u064A \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0634\u0642\u064A\u0642\u0629 \u062D\u062A\u0649 \u0627\u0644\u064A\u0648\u0645 \u0627\u0644\u062A\u0627\u0644\u064A",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "cloze deletions : \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0634\u0642\u064A\u0642\u0629 \u0647\u064A \u0628\u0637\u0627\u0642\u0627\u062A \u062A\u0645 \u0625\u0646\u0634\u0627\u0624\u0647\u0627 \u0645\u0646 \u0646\u0641\u0633 \u0646\u0635 \u0627\u0644\u0628\u0637\u0627\u0642\u0629 \u0643\u0640",
 | |
|   SHOW_CARD_CONTEXT: "\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0633\u064A\u0627\u0642 \u0641\u064A \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A\u061F",
 | |
|   SHOW_CARD_CONTEXT_DESC: "i.e. Title > Heading 1 > Subheading > ... > Subheading",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "\u0646\u0633\u0628\u0629 \u0627\u0631\u062A\u0641\u0627\u0639 \u0627\u0644\u0628\u0637\u0627\u0642\u0629",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "\u064A\u062C\u0628 \u0636\u0628\u0637\u0647\u0627 \u0639\u0644\u0649 100 \u066A \u0639\u0644\u0649 \u0627\u0644\u0647\u0627\u062A\u0641 \u0627\u0644\u0645\u062D\u0645\u0648\u0644 \u0623\u0648 \u0625\u0630\u0627 \u0643\u0627\u0646 \u0644\u062F\u064A\u0643 \u0635\u0648\u0631 \u0643\u0628\u064A\u0631\u0629 \u062C\u062F\u064B\u0627",
 | |
|   RESET_DEFAULT: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646 \u0625\u0644\u0649 \u0627\u0644\u0627\u0641\u062A\u0631\u0627\u0636\u064A",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\u0646\u0633\u0628\u0629 \u0639\u0631\u0636 \u0627\u0644\u0628\u0637\u0627\u0642\u0629",
 | |
|   RANDOMIZE_CARD_ORDER: "\u062A\u0631\u062A\u064A\u0628 \u0628\u0637\u0627\u0642\u0629 \u0639\u0634\u0648\u0627\u0626\u064A \u0623\u062B\u0646\u0627\u0621 \u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0629\u061F",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "\u061Fcloze \u062A\u0639\u0637\u064A\u0644 \u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "Convert ==highlights== to clozes",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'Add/remove the <code>${defaultPattern}</code> from your "Cloze Patterns"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "Convert **bolded text** to clozes",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'Add/remove the <code>${defaultPattern}</code> from your "Cloze Patterns"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "Convert {{curly brackets}} to clozes",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'Add/remove the <code>${defaultPattern}</code> from your "Cloze Patterns"',
 | |
|   CLOZE_PATTERNS: "Cloze Patterns",
 | |
|   CLOZE_PATTERNS_DESC: 'Enter cloze patterns separated by newlines. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "\u0641\u0627\u0635\u0644 \u0645\u0646 \u0623\u062C\u0644 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0645\u0636\u0645\u0646\u0629",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "\u0636\u0639 \u0641\u064A \u062D\u0633\u0627\u0628\u0643 \u0623\u0646\u0647 \u0628\u0639\u062F \u062A\u063A\u064A\u064A\u0631 \u0647\u0630\u0627 \u060C \u064A\u062C\u0628 \u0639\u0644\u064A\u0643 \u062A\u0639\u062F\u064A\u0644 \u0623\u064A \u0628\u0637\u0627\u0642\u0627\u062A \u0644\u062F\u064A\u0643 \u0628\u0627\u0644\u0641\u0639\u0644 \u064A\u062F\u0648\u064A\u064B\u0627",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "\u0641\u0627\u0635\u0644 \u0645\u0646 \u0623\u062C\u0644 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0639\u0643\u0633\u064A\u0629 \u0627\u0644\u0645\u0636\u0645\u0646\u0629",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\u0641\u0627\u0635\u0644 \u0645\u0646 \u0623\u062C\u0644 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0645\u062A\u0639\u062F\u062F\u0629",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\u0641\u0627\u0635\u0644 \u0645\u0646 \u0623\u062C\u0644 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0639\u0643\u0633\u064A\u0629 \u0627\u0644\u0645\u062A\u0639\u062F\u062F\u0629",
 | |
|   MULTILINE_CARDS_END_MARKER: "\u0627\u0644\u0623\u062D\u0631\u0641 \u0627\u0644\u062A\u064A \u062A\u062F\u0644 \u0639\u0644\u0649 \u0646\u0647\u0627\u064A\u0629 \u0627\u0644\u0643\u0644\u0648\u0632\u0627\u062A \u0648\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u062A\u0639\u0644\u0645 \u0627\u0644\u0645\u062A\u0639\u062F\u062F\u0629 \u0627\u0644\u0623\u0633\u0637\u0631",
 | |
|   NOTES: "\u0645\u0644\u0627\u062D\u0638\u0627\u062A",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "\u062A\u0645\u0643\u064A\u0646 \u062C\u0632\u0621 \u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0627\u062A \u0639\u0646\u062F \u0628\u062F\u0621 \u0627\u0644\u062A\u0634\u063A\u064A\u0644",
 | |
|   TAGS_TO_REVIEW: "\u0648\u0633\u0648\u0645 \u0644\u0644\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   TAGS_TO_REVIEW_DESC: "#\u0623\u062F\u062E\u0644 \u0627\u0644\u0648\u0633\u0648\u0645 \u0645\u0641\u0635\u0648\u0644\u0629 \u0628\u0645\u0633\u0627\u0641\u0627\u062A \u0623\u0648 \u062E\u0637\u0648\u0637 \u062C\u062F\u064A\u062F\u0629 \u060C \u0623\u064A : \u0645\u0631\u0627\u062C\u0639\u0629# \u0648\u0633\u06452# \u0648\u0633\u06453",
 | |
|   OPEN_RANDOM_NOTE: "\u0627\u0641\u062A\u062D \u0645\u0644\u0627\u062D\u0638\u0629 \u0639\u0634\u0648\u0627\u0626\u064A\u0629 \u0644\u0644\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   OPEN_RANDOM_NOTE_DESC: "(Pagerank) \u0639\u0646\u062F \u062A\u0639\u0637\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u062E\u064A\u0627\u0631 \u060C\u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0627\u062A \u0633\u064A\u062A\u0645 \u062A\u0631\u062A\u064A\u0628\u064F\u0647\u0627 \u062D\u0633\u0628 \u0627\u0644\u0623\u0647\u0645\u064A\u0629",
 | |
|   AUTO_NEXT_NOTE: "\u0627\u0641\u062A\u062D \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629 \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627 \u0628\u0639\u062F \u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "\u0641\u0639\u0651\u0644 \u062E\u064A\u0627\u0631\u0627\u062A \u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0629 \u0641\u064A \u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0645\u0644\u0641 (\u0645\u062B\u0627\u0644: \u0645\u0631\u0627\u062C\u0639\u0629: \u0633\u0647\u0644\u060C \u062C\u064A\u062F\u060C \u0635\u0639\u0628)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "\u0625\u0630\u0627 \u0642\u0645\u062A \u0628\u062A\u0639\u0637\u064A\u0644 \u062E\u064A\u0627\u0631\u0627\u062A \u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0629 \u0641\u064A \u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0645\u0644\u0641\u060C \u064A\u0645\u0643\u0646\u0643 \u0645\u0631\u0627\u062C\u0639\u0629 \u0645\u0644\u0627\u062D\u0638\u0627\u062A\u0643 \u0628\u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0623\u0648\u0627\u0645\u0631 \u0627\u0644\u0625\u0636\u0627\u0641\u0629 \u0648\u0625\u0630\u0627 \u0643\u0646\u062A \u0642\u062F \u062D\u062F\u062F\u062A\u0647\u0627\u060C \u0628\u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0645\u0641\u0627\u062A\u064A\u062D \u0627\u0644\u0627\u062E\u062A\u0635\u0627\u0631 \u0627\u0644\u0645\u0631\u062A\u0628\u0637\u0629.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "\u0627\u0644\u062D\u062F \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u0639\u062F\u062F \u0627\u0644\u0623\u064A\u0627\u0645 \u0627\u0644\u062A\u064A \u064A\u062C\u0628 \u0639\u0631\u0636\u0647\u0627 \u0639\u0644\u0649 \u0627\u0644\u0644\u0648\u062D\u0629 \u0627\u0644\u064A\u0645\u0646\u0649",
 | |
|   MIN_ONE_DAY: "\u064A\u062C\u0628 \u0623\u0646 \u064A\u0643\u0648\u0646 \u0639\u062F\u062F \u0627\u0644\u0623\u064A\u0627\u0645 1 \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644",
 | |
|   VALID_NUMBER_WARNING: "\u064A\u0631\u062C\u0649 \u062A\u0642\u062F\u064A\u0645 \u0631\u0642\u0645 \u0635\u0627\u0644\u062D",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\u064A\u062C\u0628 \u0623\u0646 \u064A\u0643\u0648\u0646 \u0627\u0644\u0639\u0631\u0636 \u0627\u0644\u0634\u062C\u0631\u064A \u0644\u0644\u0631\u064F\u0632\u0645 \u0645\u0648\u0633\u0639 \u0628\u062D\u064A\u062B \u062A\u0637\u0647\u0631 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0641\u0631\u0639\u064A\u0629 \u0643\u0644\u0647\u0627",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: " \u0639\u0637\u0644 \u0647\u0630\u0627 \u0627\u0644\u062E\u064A\u0627\u0631 \u0644\u0637\u064A \u0627\u0644\u0631\u064F\u0632\u0645 \u0627\u0644\u0645\u062A\u062F\u0627\u062E\u0644\u0629 \u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0628\u0637\u0627\u0642\u0629 , \u0645\u0641\u064A\u062F \u0625\u0630\u0627 \u0643\u0627\u0646 \u0644\u062F\u064A\u0643 \u0628\u0637\u0627\u0642\u0627\u062A \u062A\u0646\u062A\u0645\u064A \u0625\u0644\u0649 \u0627\u0644\u0639\u062F\u064A\u062F \u0645\u0646 \u0627\u0644\u0631\u064F\u0632\u0645 \u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0645\u0644\u0641",
 | |
|   ALGORITHM: "\u062E\u0648\u0627\u0631\u0632\u0645\u064A\u0629",
 | |
|   CHECK_ALGORITHM_WIKI: '<a href="${algoUrl}">algorithm details</a> :\u0644\u0645\u0632\u064A\u062F \u0645\u0646 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062A \u062A\u062D\u0642\u0642 \u0645\u0646',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "\u0633\u0647\u0648\u0644\u0629 \u0627\u0644\u0642\u0627\u0639\u062F\u0629",
 | |
|   BASE_EASE_DESC: "\u0627\u0644\u062D\u062F \u0627\u0644\u0623\u062F\u0646\u0649 = 130 \u060C \u0648\u064A\u0641\u0636\u0644 \u062D\u0648\u0627\u0644\u064A 250.",
 | |
|   BASE_EASE_MIN_WARNING: "\u064A\u062C\u0628 \u0623\u0646 \u062A\u0643\u0648\u0646 \u0633\u0647\u0648\u0644\u0629 \u0627\u0644\u0642\u0627\u0639\u062F\u0629 130 \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644.",
 | |
|   LAPSE_INTERVAL_CHANGE: "\u0627\u0644\u0641\u0627\u0635\u0644 \u0627\u0644\u0632\u0645\u0646\u064A \u064A\u062A\u063A\u064A\u0631 \u0639\u0646\u062F \u0645\u0631\u0627\u062C\u0639\u0629 \u0628\u0637\u0627\u0642\u0629/\u0645\u0644\u0627\u062D\u0638\u0629 \u0635\u0639\u0628\u0629",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "newInterval = oldInterval * intervalChange / 100.",
 | |
|   EASY_BONUS: "\u0645\u0643\u0627\u0641\u0623\u0629 \u0633\u0647\u0644\u0629",
 | |
|   EASY_BONUS_DESC: "\u062A\u062A\u064A\u062D \u0644\u0643 \u0627\u0644\u0645\u0643\u0627\u0641\u0623\u0629 \u0627\u0644\u0633\u0647\u0644\u0629 \u0636\u0628\u0637 \u0627\u0644\u0641\u0631\u0642 \u0641\u064A \u0627\u0644\u0641\u0648\u0627\u0635\u0644 \u0627\u0644\u0632\u0645\u0646\u064A\u0629 \u0628\u064A\u0646 \u0627\u0644\u0631\u062F \u0627\u0644\u062C\u064A\u062F \u0648\u0627\u0644\u0633\u0647\u0644 \u0639\u0644\u0649 \u0628\u0637\u0627\u0642\u0629/\u0645\u0644\u0627\u062D\u0638\u0629 (\u0627\u0644\u062D\u062F \u0627\u0644\u0623\u062F\u0646\u0649 = 100 \u066A).",
 | |
|   EASY_BONUS_MIN_WARNING: "\u064A\u062C\u0628 \u0623\u0646 \u062A\u0643\u0648\u0646 \u0627\u0644\u0645\u0643\u0627\u0641\u0623\u0629 \u0627\u0644\u0633\u0647\u0644\u0629 100 \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maximum interval in days",
 | |
|   MAX_INTERVAL_DESC: "\u064A\u062A\u064A\u062D \u0644\u0643 \u0648\u0636\u0639 \u062D\u062F \u0623\u0639\u0644\u0649  \u0644\u0644\u0641\u0627\u0635\u0644 \u0627\u0644\u0632\u0645\u0646\u064A (\u0627\u0641\u062A\u0631\u0627\u0636\u064A = 100 \u0639\u0627\u0645).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "\u064A\u062C\u0628 \u0623\u0646 \u064A\u0643\u0648\u0646 \u0627\u0644\u062D\u062F \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u0644\u0641\u0627\u0635\u0644 \u0627\u0644\u0632\u0645\u0646\u064A \u0644\u0645\u062F\u0629 \u064A\u0648\u0645 \u0648\u0627\u062D\u062F \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644.",
 | |
|   MAX_LINK_CONTRIB: "\u0623\u0642\u0635\u0649 \u0645\u0633\u0627\u0647\u0645\u0629 \u0627\u0631\u062A\u0628\u0627\u0637",
 | |
|   MAX_LINK_CONTRIB_DESC: "\u0623\u0642\u0635\u0649 \u0645\u0633\u0627\u0647\u0645\u0629 \u0644\u0644\u0633\u0647\u0648\u0644\u0629 \u0627\u0644\u0645\u0631\u062C\u062D\u0629 \u0644\u0644\u0645\u0644\u0627\u062D\u0638\u0627\u062A \u0627\u0644\u0645\u0631\u062A\u0628\u0637\u0629 \u0628\u0627\u0644\u0633\u0647\u0648\u0644\u0629 \u0627\u0644\u0623\u0648\u0644\u064A\u0629.",
 | |
|   LOGGING: "\u062A\u0633\u062C\u064A\u0644",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\u0639\u0631\u0636 \u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0627\u0644\u062A\u0635\u062D\u064A\u062D \u0639\u0644\u0649 \u0648\u062D\u062F\u0629 \u062A\u062D\u0643\u0645 \u0627\u0644\u0645\u0637\u0648\u0631",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "\u0645\u0644\u0627\u062D\u0638\u0627\u062A \u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0629",
 | |
|   CLOSE: "\u0623\u063A\u0644\u0642",
 | |
|   NEW: "\u062C\u062F\u064A\u062F",
 | |
|   YESTERDAY: "\u0627\u0644\u0628\u0627\u0631\u062D\u0629",
 | |
|   TODAY: "\u0627\u0644\u064A\u0648\u0645",
 | |
|   TOMORROW: "\u0627\u0644\u063A\u062F",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\u0625\u062D\u0635\u0627\u0626\u064A\u0627\u062A",
 | |
|   MONTH: "\u0634\u0647\u0631",
 | |
|   QUARTER: "\u0631\u0628\u0639 \u0627\u0644\u0633\u0646\u0629",
 | |
|   YEAR: "\u0633\u0646\u0629",
 | |
|   LIFETIME: "",
 | |
|   FORECAST: "",
 | |
|   FORECAST_DESC: "\u0639\u062F\u062F \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0645\u0633\u062A\u062D\u0642\u0629 \u0641\u064A \u0627\u0644\u0645\u0633\u062A\u0642\u0628\u0644",
 | |
|   SCHEDULED: "\u0627\u0644\u0645\u0642\u0631\u0631",
 | |
|   DAYS: "\u0623\u064A\u0627\u0645",
 | |
|   NUMBER_OF_CARDS: "\u0639\u062F\u062F \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   REVIEWS_PER_DAY: "\u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0627\u062A/\u0627\u0644\u064A\u0648\u0645 ${avg} :\u0645\u062A\u0648\u0633\u0637",
 | |
|   INTERVALS: "\u0641\u0648\u0627\u0635\u0644 \u0632\u0645\u0646\u064A\u0629",
 | |
|   INTERVALS_DESC: "\u0627\u0644\u062A\u0623\u062E\u064A\u0631 \u062D\u062A\u0649 \u064A\u062A\u0645 \u0639\u0631\u0636 \u0627\u0644\u0645\u0631\u0627\u062C\u0639\u0627\u062A \u0645\u0631\u0629 \u0623\u062E\u0631\u0649",
 | |
|   COUNT: "\u0639\u062F\u062F",
 | |
|   INTERVALS_SUMMARY: "${longest} : \u0623\u0637\u0648\u0644 \u0641\u0627\u0635\u0644 \u0632\u0645\u0646\u064A ,${avg} :\u0645\u062A\u0648\u0633\u0637 \u0627\u0644\u0641\u0627\u0635\u0644 \u0627\u0644\u0632\u0645\u0646\u064A",
 | |
|   EASES: "\u0627\u0644\u0633\u0647\u0648\u0644\u0629",
 | |
|   EASES_SUMMARY: "${avgEase} :\u0645\u062A\u0648\u0633\u0637 \u0627\u0644\u0633\u0647\u0648\u0644\u0629",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "\u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   CARD_TYPES_DESC: "\u0648\u0647\u0630\u0627 \u064A\u0634\u0645\u0644 \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A \u0627\u0644\u0645\u062E\u0641\u064A\u0629 \u0643\u0630\u0644\u0643 \u060C \u0625\u0646 \u0648\u062C\u062F\u062A",
 | |
|   CARD_TYPE_NEW: "\u062C\u062F\u064A\u062F\u0629",
 | |
|   CARD_TYPE_YOUNG: "\u0635\u063A\u064A\u0631\u0629",
 | |
|   CARD_TYPE_MATURE: "\u0646\u0627\u0636\u062C\u0629",
 | |
|   CARD_TYPES_SUMMARY: " ${totalCardsCount} :\u0625\u062C\u0645\u0627\u0644\u064A \u0639\u062F\u062F \u0627\u0644\u0628\u0637\u0627\u0642\u0627\u062A",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/bn.ts
 | |
| var bn_default = {};
 | |
| 
 | |
| // src/lang/locale/cz.ts
 | |
| var cz_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Bal\xED\u010Dky",
 | |
|   DUE_CARDS: "Karti\u010Dky po term\xEDnu",
 | |
|   NEW_CARDS: "Nov\xE9 karti\u010Dky",
 | |
|   TOTAL_CARDS: "Karti\u010Dek celkem",
 | |
|   BACK: "Back",
 | |
|   SKIP: "Skip",
 | |
|   EDIT_CARD: "Edit Card",
 | |
|   RESET_CARD_PROGRESS: "Vynulovat pokrok karti\u010Dky",
 | |
|   HARD: "T\u011B\u017Ek\xE9",
 | |
|   GOOD: "Dobr\xE9",
 | |
|   EASY: "Jednoduch\xE9",
 | |
|   SHOW_ANSWER: "Uk\xE1zat odpov\u011B\u010F",
 | |
|   CARD_PROGRESS_RESET: "Pokrok karti\u010Dky byl vynulov\xE1n.",
 | |
|   SAVE: "Save",
 | |
|   CANCEL: "Cancel",
 | |
|   NO_INPUT: "No input provided.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Current Ease: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Current Interval: ",
 | |
|   CARD_GENERATED_FROM: "Generated from: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Otev\u0159\xEDt pozn\xE1mku k revizi",
 | |
|   REVIEW_CARDS: "Pozn\xE1mek k revizi",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Revize: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Ozna\u010Dit pozn\xE1mku jako ${difficulty}",
 | |
|   REVIEW_ALL_CARDS: "Revidovat karti\u010Dky ve v\u0161ech pozn\xE1mk\xE1ch",
 | |
|   CRAM_ALL_CARDS: "Select a deck to cram",
 | |
|   REVIEW_CARDS_IN_NOTE: "Revidovat karti\u010Dky v t\xE9to pozn\xE1mce.",
 | |
|   CRAM_CARDS_IN_NOTE: "Cram karti\u010Dky v t\xE9to pozn\xE1mce.",
 | |
|   VIEW_STATS: "Uk\xE1zat statistiky",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "Revize: ${dueNotesCount} pozn\xE1mek, ${dueFlashcardsCount} karti\u010Dek po term\xEDnu",
 | |
|   SYNC_TIME_TAKEN: "Synchronizace trvala ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "Pozn\xE1mka je ulo\u017Eena v ignorovan\xE9 slo\u017Ece (zkontrolujte nastaven\xED).",
 | |
|   PLEASE_TAG_NOTE: "Pros\xEDm ozna\u010Dne pozn\xE1mku odpov\xEDdaj\xEDc\xEDm tagem pro revizi (v nastaven\xED).",
 | |
|   RESPONSE_RECEIVED: "Odpov\u011B\u010F p\u0159ijata.",
 | |
|   NO_DECK_EXISTS: "Neexistuje \u017E\xE1dn\xFD bal\xED\u010Dek pro ${deckName}",
 | |
|   ALL_CAUGHT_UP: "V\u0161e zrevidov\xE1no",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} den/dn\xED",
 | |
|   MONTHS_STR_IVL: "${interval} m\u011Bs\xEDc(\u016F)",
 | |
|   YEARS_STR_IVL: "${interval} rok(\u016F)",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}r",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'Pro v\xEDce informac\xED jd\u011Bte na <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Ignorovan\xE9 slo\u017Eky",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Karti\u010Dky",
 | |
|   FLASHCARD_EASY_LABEL: "Easy Button Text",
 | |
|   FLASHCARD_GOOD_LABEL: "Good Button Text",
 | |
|   FLASHCARD_HARD_LABEL: "Hard Button Text",
 | |
|   FLASHCARD_EASY_DESC: 'Customize the label for the "Easy" Button',
 | |
|   FLASHCARD_GOOD_DESC: 'Customize the label for the "Good" Button',
 | |
|   FLASHCARD_HARD_DESC: 'Customize the label for the "Hard" Button',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Tag pro karti\u010Dky",
 | |
|   FLASHCARD_TAGS_DESC: "Zadete tagy ood\u011Blen\xE9 mezerou nebo od\u0159\xE1dkov\xE1n\xEDm nap\u0159\xEDklad. #karti\u010Dky #bal\xED\u010Dke2 #bal\xED\u010Dek3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "P\u0159ev\xE9st slo\u017Eky na bal\xED\u010Dky a podbal\xED\u010Dky?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Toto je alternativa k tag\u016Fm karti\u010Dek viz nastaven\xED v\xFD\u0161e.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Ulo\u017Eit pl\xE1novac\xED koment\xE1\u0159 na stejn\xFD \u0159\xE1dek jako posledn\xED polo\u017Eka karti\u010Dky?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Zapnut\xED t\xE9to volby zp\u016Fsob\xED, \u017Ee HTML koment\xE1\u0159e nebudou rozb\xEDjet form\xE1tov\xE1n\xED list\u016F.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Odlo\u017Eit p\u0159\xEDbuzn\xE9 karti\u010Dky na dal\u0161\xED den?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "P\u0159\xEDbuzn\xE9 karti\u010Dky jsou karti\u010Dky generovan\xE9 z textu stejn\xE9 pozn\xE1mky nap\u0159\xEDklad cloze smaz\xE1n\xED",
 | |
|   SHOW_CARD_CONTEXT: "Uk\xE1zat kontext v karti\u010Dce?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "nap\u0159\xEDklad Titulek > Nadpis1 > Podnadpis > ... > Podnadpis",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "V\xFD\u0161ka karti\u010Dek v procentech",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "M\u011Blo by b\xFDt nastaveno na 100% na mobilu nebo kdy\u017E pou\u017E\xEDv\xE1te velk\xE9 obr\xE1zky",
 | |
|   RESET_DEFAULT: "Resetovat v\xFDchoz\xED nastaven\xED",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\u0160\xED\u0159ka karti\u010Dek v procentech",
 | |
|   RANDOMIZE_CARD_ORDER: "N\xE1hodn\u011B zm\u011Bnit po\u0159ad\xED karti\u010Dek b\u011Bhem revize?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "Vypnout cloze karti\u010Dky?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "P\u0159ev\xE9st ==zv\xFDrazn\u011Bn\xED== na clozes?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'P\u0159idat/odstranit <code>${defaultPattern}</code> z va\u0161ich "Cloze vzor\u016F"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "P\u0159ev\xE9st **tu\u010Dn\xFD text** na clozes?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'P\u0159idat/odstranit <code>${defaultPattern}</code> z va\u0161ich "Cloze vzor\u016F"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "P\u0159ev\xE9st {{slo\u017Een\xE9 z\xE1vorky}} na clozes?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'P\u0159idat/odstranit <code>${defaultPattern}</code> z va\u0161ich "Cloze vzor\u016F"',
 | |
|   CLOZE_PATTERNS: "Cloze vzory",
 | |
|   CLOZE_PATTERNS_DESC: 'Zadejte cloze vzory odd\u011Blen\xE9 od\u0159\xE1dkov\xE1n\xEDm. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Odd\u011Blova\u010D pro inline karti\u010Dky",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Pozor. Jakmile toto zm\u011Bn\xEDte, budete muset ru\u010Dn\u011B upravit v\u0161echny existuj\xEDc\xED karti\u010Dky.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Odd\u011Blova\u010D pro oto\u010Den\xE9 inline karti\u010Dky",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Odd\u011Blova\u010D pro v\xEDce\u0159\xE1dkov\xE9 karti\u010Dky",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Odd\u011Blova\u010D pro v\xEDce\u0159\xE1dkove oto\u010Den\xE9 karti\u010Dky",
 | |
|   MULTILINE_CARDS_END_MARKER: "Znaky ozna\u010Duj\xEDc\xED konec clozes a v\xEDce\u0159\xE1dkov\xFDch flash karet",
 | |
|   NOTES: "Pozn\xE1mky",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Enable note review pane on startup",
 | |
|   TAGS_TO_REVIEW: "Tag pro revizi",
 | |
|   TAGS_TO_REVIEW_DESC: "Zadejte tagy odd\u011Blen\xE9 mezerami nebo od\u0159\xE1dkov\xE1n\xEDm nap\u0159\xEDklad #review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "Otev\u0159\xEDt n\xE1hodnou pozn\xE1mku pro revizi",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Pokud toto vypnete, pozn\xE1mky budou \u0159azeny dle d\u016Fle\u017Eitosti (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Otev\u0159\xEDt automaticky dal\u0161\xED pozn\xE1mku po dokon\u010Den\xED revize",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Povolte mo\u017Enosti revize v nab\xEDdce souboru (nap\u0159. Revize: Jednoduch\xE9, Dobr\xE9, T\u011B\u017Ek\xE9)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "Pokud v nab\xEDdce souboru zak\xE1\u017Eete mo\u017Enosti revize, m\u016F\u017Eete sv\xE9 pozn\xE1mky revidovat pomoc\xED p\u0159\xEDkaz\u016F pluginu a, pokud jste je definovali, pomoc\xED p\u0159i\u0159azen\xFDch kl\xE1vesov\xFDch zkratek.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Maxim\xE1ln\xED po\u010Det dn\xED zobrazen\xFDch v prav\xE9m panelu",
 | |
|   MIN_ONE_DAY: "Po\u010Det dn\xED mus\xED b\xFDt minim\xE1ln\u011B 1.",
 | |
|   VALID_NUMBER_WARNING: "Pros\xEDm zadejte validn\xED \u010D\xEDslo.",
 | |
|   UI: "P\u0159edvolby u\u017Eivatelsk\xE9ho rozhran\xED",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Stromy bal\xED\u010Dky by m\u011Bly b\xFDt zpo\u010D\xE1tku zobrazeny jako rozbalen\xE9",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Vypn\u011Bte toto, chcete-li sbalit vno\u0159en\xE9 bal\xED\u010Dky na stejn\xE9 kart\u011B. To je u\u017Eite\u010Dn\xE9, pokud m\xE1te karti\u010Dky, kter\xE9 pat\u0159\xED k mnoha bal\xED\u010Dk\u016Fm ve stejn\xE9m souboru.",
 | |
|   ALGORITHM: "Algoritmus",
 | |
|   CHECK_ALGORITHM_WIKI: 'Pro v\xEDce informac\xED jd\u011Bte na <a href="${algoUrl}">popis algoritmu</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Z\xE1kladn\xED slo\u017Eitost",
 | |
|   BASE_EASE_DESC: "minimum = 130, nejl\xE9pe p\u0159ibli\u017En\u011B 250.",
 | |
|   BASE_EASE_MIN_WARNING: "Z\xE1kladn\xED slo\u017Eitost mus\xED b\xFDt minim\xE1ln\u011B 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Zm\u011Bna intervalu pokud karti\u010Dku/pozn\xE1mku ozna\u010D\xEDte jako slo\u017Eitou",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "nov\xFD_inteval = star\xFD_interval * zm\u011Bna_intevalu / 100.",
 | |
|   EASY_BONUS: "Bonus pro jednoduch\xE9",
 | |
|   EASY_BONUS_DESC: "Tento bonus umo\u017E\u0148uje nastavit rozd\xEDl intervalu mezi jednoduch\xFDmi a dobr\xFDmi karti\u010Dkami/pozn\xE1mkami (minimum = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "Bonus pro jednoduchost mus\xED b\xFDt minim\xE1ln\u011B 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maximum interval in days",
 | |
|   MAX_INTERVAL_DESC: "Umo\u017E\u0148uje nastavit horn\xED limit pro interval (defaultn\u011B = 100 let).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "Maxim\xE1ln\xED interval mus\xED b\xFDt alespo\u0148 1 den.",
 | |
|   MAX_LINK_CONTRIB: "Maxim\xE1ln\xED p\u0159\xEDsp\u011Bv\u011Bk prolinkov\xE1n\xED",
 | |
|   MAX_LINK_CONTRIB_DESC: "Maxim\xE1ln\xED p\u0159\xEDsp\u011Bvek v\xE1\u017Een\xE9 slo\u017Eitosti prolinkovan\xFDch pozn\xE1mek pou\u017Eit\xFD pro ur\u010Den\xED po\u010D\xE1te\u010Dn\xED slo\u017Eitosti.",
 | |
|   LOGGING: "Zaznamen\xE1v\xE1m",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Zobrazit informace pro lad\u011Bn\xED na v\xFDvoj\xE1\u0159sk\xE9 konzoli",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Fronta pozn\xE1mek k revizi",
 | |
|   CLOSE: "Uzav\u0159en\xE9",
 | |
|   NEW: "Nov\xE9",
 | |
|   YESTERDAY: "V\u010Dera",
 | |
|   TODAY: "Dnes",
 | |
|   TOMORROW: "Z\xEDtra",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Statistiky",
 | |
|   MONTH: "M\u011Bs\xEDc",
 | |
|   QUARTER: "\u010Ctvrtlet\xED",
 | |
|   YEAR: "Rok",
 | |
|   LIFETIME: "Celkov\u011B",
 | |
|   FORECAST: "P\u0159edpov\u011B\u010F",
 | |
|   FORECAST_DESC: "Celkov\xFD po\u010Det karti\u010Dek, kter\xFDm vypr\u0161\xED term\xEDn",
 | |
|   SCHEDULED: "Napl\xE1nov\xE1no",
 | |
|   DAYS: "Dn\xED",
 | |
|   NUMBER_OF_CARDS: "Po\u010Det karti\u010Dek",
 | |
|   REVIEWS_PER_DAY: "Pr\u016Fm\u011Br: ${avg} revize/den",
 | |
|   INTERVALS: "Intervaly",
 | |
|   INTERVALS_DESC: "Doba, za kterou bude znovu zobrazeno k revize",
 | |
|   COUNT: "Po\u010Det",
 | |
|   INTERVALS_SUMMARY: "Pr\u016Fm\u011Brn\xFD interval: ${avg}, Nejdel\u0161\xED interval: ${longest}",
 | |
|   EASES: "Slo\u017Eitost",
 | |
|   EASES_SUMMARY: "Pr\u016Fm\u011Brn\xE1 slo\u017Eitost: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Typy karti\u010Dek",
 | |
|   CARD_TYPES_DESC: "Obsahuje i odlo\u017Een\xE9 karti\u010Dky (pokud existuj\xED)",
 | |
|   CARD_TYPE_NEW: "Nov\xE1",
 | |
|   CARD_TYPE_YOUNG: "Mlad\xE1",
 | |
|   CARD_TYPE_MATURE: "Dosp\u011Bl\xE1",
 | |
|   CARD_TYPES_SUMMARY: "Karti\u010Dek celkem: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/da.ts
 | |
| var da_default = {};
 | |
| 
 | |
| // src/lang/locale/de.ts
 | |
| var de_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Stapel",
 | |
|   DUE_CARDS: "Anstehende Karten",
 | |
|   NEW_CARDS: "Neue Karten",
 | |
|   TOTAL_CARDS: "Alle Karten",
 | |
|   BACK: "Zur\xFCck",
 | |
|   SKIP: "\xDCberspringen",
 | |
|   EDIT_CARD: "Karte bearbeiten",
 | |
|   RESET_CARD_PROGRESS: "Kartenfortschritt zur\xFCcksetzten",
 | |
|   HARD: "Schwer",
 | |
|   GOOD: "Gut",
 | |
|   EASY: "Einfach",
 | |
|   SHOW_ANSWER: "Zeige Antwort",
 | |
|   CARD_PROGRESS_RESET: "Kartenfortschritt wurde zur\xFCckgesetzt.",
 | |
|   SAVE: "Speichern",
 | |
|   CANCEL: "Abbrechen",
 | |
|   NO_INPUT: "Keine Eingabe erhalten.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Aktuelle Schwierigkeit: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Aktueller Intervall: ",
 | |
|   CARD_GENERATED_FROM: "Erstellt von: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Notiz zur Wiederholung \xF6ffnen",
 | |
|   REVIEW_CARDS: "Lernkarten wiederholen",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Notizen wiederholen als: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Notizen wiederholen als: ${difficulty}",
 | |
|   REVIEW_ALL_CARDS: "Alle Lernkarten wiederholen",
 | |
|   CRAM_ALL_CARDS: "W\xE4hle ein Stapel zum pauken",
 | |
|   REVIEW_CARDS_IN_NOTE: "Lernkarten in dieser Notiz wiederholen",
 | |
|   CRAM_CARDS_IN_NOTE: "Lernkarten in dieser Notiz pauken.",
 | |
|   VIEW_STATS: "Statistiken anzeigen",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "\xD6ffne \xDCberpr\xFCfungswarteschlage in der Seitenleiste",
 | |
|   STATUS_BAR: "Wiederholung: ${dueNotesCount} Notiz(en), ${dueFlashcardsCount} Karte(n) anstehend",
 | |
|   SYNC_TIME_TAKEN: "Synchronisierung dauerte ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "Notiz befindet sich in einem ausgeschlossenen Ordner (siehe Einstellungen).",
 | |
|   PLEASE_TAG_NOTE: "Bitte die Notiz f\xFCr Wiederholungen entsprechend taggen (siehe Einstellungen).",
 | |
|   RESPONSE_RECEIVED: "Antwort erhalten.",
 | |
|   NO_DECK_EXISTS: "Kein Stapel f\xFCr ${deckName} gefunden.",
 | |
|   ALL_CAUGHT_UP: "Yuhu! Alles geschafft! :D.",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} Tag(e)",
 | |
|   MONTHS_STR_IVL: "${interval} Monat(e)",
 | |
|   YEARS_STR_IVL: "${interval} Jahr(e)",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}t",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}j",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'Weitere Informationen gibt es im <a href="${wikiUrl}">Wiki</a> (english).',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Ausgeschlossene Ordner",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Lernkarten",
 | |
|   FLASHCARD_EASY_LABEL: "Einfach Knopf Text",
 | |
|   FLASHCARD_GOOD_LABEL: "Gut Knopf Text",
 | |
|   FLASHCARD_HARD_LABEL: "Schwer Knopf Text",
 | |
|   FLASHCARD_GOOD_DESC: 'Passe die Beschriftung f\xFCr "Gut" Knopf an',
 | |
|   FLASHCARD_EASY_DESC: 'Passe die Beschriftung f\xFCr "Einfach" Knopf an',
 | |
|   FLASHCARD_HARD_DESC: 'Passe die Beschriftung f\xFCr "Schwer" Knopf an',
 | |
|   REVIEW_BUTTON_DELAY: "Druckknopfverz\xF6gerung (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "F\xFCgt den \xDCberpr\xFCfungsschaltfl\xE4chen (\u201EEinfach\u201C, \u201EGut\u201C, \u201ESchwer\u201C, \u201EAntwort anzeigen\u201C) eine Verz\xF6gerung hinzu, bevor sie erneut gedr\xFCckt werden k\xF6nnen.",
 | |
|   FLASHCARD_TAGS: "Lernkarten Tags",
 | |
|   FLASHCARD_TAGS_DESC: "Mehrere Tags mit Leerzeichen oder Zeilenumbr\xFCchen getrennt angeben. Bsp. #karte #stapel2 #stapel3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Ordner in Stapel und Substapel umwandeln?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: 'Eine Alternative zur oberen "Lernkarten Tags" Option.',
 | |
|   INLINE_SCHEDULING_COMMENTS: "Den Fortschritt in der gleichen Zeile wie die letzte Zeile einer Lernkartei speichern?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Wenn aktiviert, wird der HTML Kommentar die umgebende Liste nicht aufbrechen.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Verwandte Karten auf den n\xE4chsten Tag verlegen?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Verwandte Karten sind aus der gleichen Karte generiert worden (z.B. L\xFCckentextkarten oder beidseitige Karten).",
 | |
|   SHOW_CARD_CONTEXT: "Kontext in den Karten anzeigen?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "Bsp. Titel > \xDCberschrift 1 > Sektion > ... > Untersektion",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "H\xF6he der Lernkartei in Prozent",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Auf kleinen Bildschirmen (z.B. Smartphones) oder bei sehr grossen Bildern sollte dieser Wert auf 100% gesetzt werden.",
 | |
|   RESET_DEFAULT: "Standardeinstellung wiederherstellen",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Breite einer Lernkarte in Prozent",
 | |
|   RANDOMIZE_CARD_ORDER: "W\xE4hrend der Wiederhoung die Reihenfolge zuf\xE4llig mischen?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Reihenfolge der Karten innerhalb eines Stapels w\xE4hrend der Wiederholung",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentielle Reihenfolge innerhalb eines Stapels (Alle neuen Karten zuerst)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentielle Reihenfolge innerhalb eines Stapels (Alle f\xE4lligen Karten zuerst)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Zuf\xE4llige Reihenfolge innerhalb eines Stapels (Alle neuen Karten zuerst)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Zuf\xE4llige Reihenfolge innerhalb eines Stapels (Alle f\xE4lligen Karten zuerst)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Zuf\xE4llige Karte von zuf\xE4lligem Stapel",
 | |
|   REVIEW_DECK_ORDER: "Reihenfolge der Stapel w\xE4hrend der Wiederholung",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentielle Reihenfolge (sobald alle Karten im vorherigen Stapel wiederholt wurden)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Zuf\xE4llige Reihenfolge (sobald alle Karten im vorherigen Stapel wiederholt wurden)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Zuf\xE4llige Karte von zuf\xE4lligem Stapel",
 | |
|   DISABLE_CLOZE_CARDS: "L\xFCckentextkarten deaktivieren?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "==Hervorgehobenen== Text in L\xFCckentextkarten umwandeln?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'F\xFCge/entferne das <code>${defaultPattern}</code> zu deinen "L\xFCckentextmuster" hinzu',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "**Fettgedruckten** Text in L\xFCckentextkarten umwandeln?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'F\xFCge/entferne das <code>${defaultPattern}</code> zu deinen "L\xFCckentextmuster" hinzu',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "{{Geschweifte Klammern}} Text in L\xFCckentextkarten umwandeln?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'F\xFCge/entferne das <code>${defaultPattern}</code> zu deinen "L\xFCckentextmuster" hinzu',
 | |
|   CLOZE_PATTERNS: "L\xFCckentextmuster",
 | |
|   CLOZE_PATTERNS_DESC: 'Geben Sie L\xFCckentextmuster durch Zeilenumbr\xFCche getrennt ein. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Trennzeichen f\xFCr einzeilige Lernkarten",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Wenn diese Einstellung ge\xE4ndert wird, dann m\xFCssen die entsprechenden Lernkarten manuell angepasst werden.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Trennzeichen f\xFCr einzeilige beidseitige Lernkarten",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Trennzeichen f\xFCr mehrzeilige Lernkarten",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Trennzeichen f\xFCr mehrzeilige beidseitige Lernkarten",
 | |
|   MULTILINE_CARDS_END_MARKER: "Zeichen, die das Ende von L\xFCckentexten und mehrzeiligen Flashcards kennzeichnen",
 | |
|   NOTES: "Notizen",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "\xD6ffne \xDCberpr\xFCfungswarteschlage beim start",
 | |
|   TAGS_TO_REVIEW: "Zu wiederholende Tags",
 | |
|   TAGS_TO_REVIEW_DESC: "Mehrere Tags k\xF6nnen mit Leerzeichen oder Zeilenumbr\xFCchen getrennt angegeben werden. Bsp. #karte #tag1 #tag2.",
 | |
|   OPEN_RANDOM_NOTE: "Zuf\xE4llige Karten wiederholen",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Wenn dies deaktiviert wird, dann werden die Notizen nach Wichtigkeit wiederholt (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Nach einer Wiederholung automatisch die n\xE4chste Karte \xF6ffnen",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Aktiviere die \xDCberpr\xFCfungsoptionen im Dateimen\xFC (z. B. Notizen wiederholen als: Einfach, Gut, Schwer)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "Wenn du die \xDCberpr\xFCfungsoptionen im Dateimen\xFC deaktivierst, kannst du deine Notizen mit den Plugin-Befehlen und, falls definiert, den zugeh\xF6rigen Tastenkombinationen \xFCberpr\xFCfen.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Maximale Anzahl anstehender Notizen, die im rechten Fensterbereich angezeigt werden",
 | |
|   MIN_ONE_DAY: "Anzahl der Tage muss mindestens 1 sein.",
 | |
|   VALID_NUMBER_WARNING: "Bitte eine g\xFCltige Zahl eingeben.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "\xD6ffne im neuen Tab",
 | |
|   OPEN_IN_TAB_DESC: "Schalte dies aus, um die Notizen in einem Modalfenster zu \xF6ffnen",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Stapelverzeichnis soll beim \xF6ffnen erweitert angezeigt werden",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Deaktivieren Sie dies, um verschachtelte Stapel in derselben Karte zu reduzieren. N\xFCtzlich, wenn Sie Karten haben, die zu vielen Stapeln in derselben Datei geh\xF6ren.",
 | |
|   ALGORITHM: "Algorithmus",
 | |
|   CHECK_ALGORITHM_WIKI: 'Weiterf\xFChrende Informationen: <a href="${algoUrl}">Implementierung des Algorithmus</a> (english).',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Basis der Schwierigkeit",
 | |
|   BASE_EASE_DESC: "Minimum ist 130. Empfohlen wird ca. 250.",
 | |
|   BASE_EASE_MIN_WARNING: "Basis der Schwierigkeit muss mindestens 130 sein.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Anpassungsfaktor des Intervalls wenn eine Notiz / Karte 'Schwer' abgeschlossen wird",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "neuesIntervall = altesIntervall * anpassungsfaktor / 100.",
 | |
|   EASY_BONUS: "Einfachheit-Bonus",
 | |
|   EASY_BONUS_DESC: "Der Einfachheit-Bonus gibt an um welchen Faktor (in Prozent) das Intervall l\xE4nger sein soll, wenn eine Notiz / Karte 'Einfach' statt 'Gut' abgeschlossen wird. Minimum ist 100%.",
 | |
|   EASY_BONUS_MIN_WARNING: "Der Einfachheit-Bonus muss mindestens 100 sein.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maximale Intervall in Tagen",
 | |
|   MAX_INTERVAL_DESC: "Das maximale Intervall (in Tagen) f\xFCr Wiederholungen. Standard sind 100 Jahre.",
 | |
|   MAX_INTERVAL_MIN_WARNING: "Das maximale Interall muss mindestens ein Tag sein.",
 | |
|   MAX_LINK_CONTRIB: "Maximaler Einfluss von Links",
 | |
|   MAX_LINK_CONTRIB_DESC: "Maximaler Einfluss der Einfachheiten verlinkter Notizen zur gewichteten initialen Einfachheit einer neuen Lernkarte.",
 | |
|   LOGGING: "Protokollierung",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Informationen zum Debugging in der Entwicklerkonsole anzeigen",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Informationen zum parser Debugging in der Entwicklerkonsole anzeigen",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Anstehende Notizen zur Wiederholung",
 | |
|   CLOSE: "Schliessen",
 | |
|   NEW: "Neu",
 | |
|   YESTERDAY: "Gestern",
 | |
|   TODAY: "Heute",
 | |
|   TOMORROW: "Morgen",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Statistiken",
 | |
|   MONTH: "Monat",
 | |
|   QUARTER: "Quartal",
 | |
|   YEAR: "Jahr",
 | |
|   LIFETIME: "Lebenslang",
 | |
|   FORECAST: "Prognose",
 | |
|   FORECAST_DESC: "Anzahl der k\xFCnftig anstehenden Karten",
 | |
|   SCHEDULED: "Anstehend",
 | |
|   DAYS: "Tage",
 | |
|   NUMBER_OF_CARDS: "Anzahl der Karten",
 | |
|   REVIEWS_PER_DAY: "Durchschnitt: ${avg} Wiederholungen/Tag",
 | |
|   INTERVALS: "Intervalle",
 | |
|   INTERVALS_DESC: "Intervalle bis Wiederholungen anstehen",
 | |
|   COUNT: "Anzahl",
 | |
|   INTERVALS_SUMMARY: "Durchschnittliches Intervall: ${avg}, L\xE4ngstes Intervall: ${longest}",
 | |
|   EASES: "Schwierigkeit",
 | |
|   EASES_SUMMARY: "Durchschnittliche Schwierigkeit: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Kategorisierung",
 | |
|   CARD_TYPES_DESC: "Verlegte Karten eingeschlossen",
 | |
|   CARD_TYPE_NEW: "Neu",
 | |
|   CARD_TYPE_YOUNG: "Jung",
 | |
|   CARD_TYPE_MATURE: "Ausgereift",
 | |
|   CARD_TYPES_SUMMARY: "Insgesamt ${totalCardsCount} Karten",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/en.ts
 | |
| var en_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Decks",
 | |
|   DUE_CARDS: "Due Cards",
 | |
|   NEW_CARDS: "New Cards",
 | |
|   TOTAL_CARDS: "Total Cards",
 | |
|   BACK: "Back",
 | |
|   SKIP: "Skip",
 | |
|   EDIT_CARD: "Edit Card",
 | |
|   RESET_CARD_PROGRESS: "Reset card's progress",
 | |
|   HARD: "Hard",
 | |
|   GOOD: "Good",
 | |
|   EASY: "Easy",
 | |
|   SHOW_ANSWER: "Show Answer",
 | |
|   CARD_PROGRESS_RESET: "Card's progress has been reset.",
 | |
|   SAVE: "Save",
 | |
|   CANCEL: "Cancel",
 | |
|   NO_INPUT: "No input provided.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Current Ease: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Current Interval: ",
 | |
|   CARD_GENERATED_FROM: "Generated from: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Open a note for review",
 | |
|   REVIEW_CARDS: "Review flashcards",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Review: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Review note as ${difficulty}",
 | |
|   CRAM_ALL_CARDS: "Select a deck to cram",
 | |
|   REVIEW_ALL_CARDS: "Review flashcards from all notes",
 | |
|   REVIEW_CARDS_IN_NOTE: "Review flashcards in this note",
 | |
|   CRAM_CARDS_IN_NOTE: "Cram flashcards in this note",
 | |
|   VIEW_STATS: "View statistics",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "Review: ${dueNotesCount} note(s), ${dueFlashcardsCount} card(s) due",
 | |
|   SYNC_TIME_TAKEN: "Sync took ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "Note is saved under ignored folder (check settings).",
 | |
|   PLEASE_TAG_NOTE: "Please tag the note appropriately for reviewing (in settings).",
 | |
|   RESPONSE_RECEIVED: "Response received.",
 | |
|   NO_DECK_EXISTS: "No deck exists for ${deckName}",
 | |
|   ALL_CAUGHT_UP: "You're all caught up now :D.",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} day(s)",
 | |
|   MONTHS_STR_IVL: "${interval} month(s)",
 | |
|   YEARS_STR_IVL: "${interval} year(s)",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}y",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'For more information, check the <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Folders to ignore",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Flashcards",
 | |
|   FLASHCARD_EASY_LABEL: "Easy Button Text",
 | |
|   FLASHCARD_GOOD_LABEL: "Good Button Text",
 | |
|   FLASHCARD_HARD_LABEL: "Hard Button Text",
 | |
|   FLASHCARD_EASY_DESC: 'Customize the label for the "Easy" Button',
 | |
|   FLASHCARD_GOOD_DESC: 'Customize the label for the "Good" Button',
 | |
|   FLASHCARD_HARD_DESC: 'Customize the label for the "Hard" Button',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Flashcard tags",
 | |
|   FLASHCARD_TAGS_DESC: "Enter tags separated by spaces or newlines i.e. #flashcards #deck2 #deck3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Convert folders to decks and subdecks",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "This is an alternative to the Flashcard tags option above.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Save scheduling comment on the same line as the flashcard's last line?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Turning this on will make the HTML comments not break list formatting.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Bury sibling cards until the next day",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Siblings are cards generated from the same card text i.e. cloze deletions",
 | |
|   SHOW_CARD_CONTEXT: "Show context in cards",
 | |
|   SHOW_CARD_CONTEXT_DESC: "i.e. Title > Heading 1 > Subheading > ... > Subheading",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Flashcard Height Percentage",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Should be set to 100% on mobile or if you have very large images",
 | |
|   RESET_DEFAULT: "Reset to default",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Flashcard Width Percentage",
 | |
|   RANDOMIZE_CARD_ORDER: "Randomize card order during review?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "Disable cloze cards?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "Convert ==highlights== to clozes",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'Add/remove the <code>${defaultPattern}</code> from your "Cloze Patterns"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "Convert **bolded text** to clozes",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'Add/remove the <code>${defaultPattern}</code> from your "Cloze Patterns"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "Convert {{curly brackets}} to clozes",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'Add/remove the <code>${defaultPattern}</code> from your "Cloze Patterns"',
 | |
|   CLOZE_PATTERNS: "Cloze Patterns",
 | |
|   CLOZE_PATTERNS_DESC: 'Enter cloze patterns separated by newlines. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Separator for inline flashcards",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Note that after changing this you have to manually edit any flashcards you already have.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Separator for inline reversed flashcards",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Separator for multiline flashcards",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Separator for multiline reversed flashcards",
 | |
|   MULTILINE_CARDS_END_MARKER: "Characters denoting the end of clozes and multiline flashcards",
 | |
|   NOTES: "Notes",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Enable note review pane on startup",
 | |
|   TAGS_TO_REVIEW: "Tags to review",
 | |
|   TAGS_TO_REVIEW_DESC: "Enter tags separated by spaces or newlines i.e. #review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "Open a random note for review",
 | |
|   OPEN_RANDOM_NOTE_DESC: "When you turn this off, notes are ordered by importance (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Open next note automatically after a review",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Maximum number of days to display on note review panel",
 | |
|   MIN_ONE_DAY: "The number of days must be at least 1.",
 | |
|   VALID_NUMBER_WARNING: "Please provide a valid number.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Enable the review options in the file menu (e.g. Review: Easy, Good, Hard)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "If you disable the review options in the file menu, you can review your notes using the plugin commands and, if you defined them, the associated command hotkeys.",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Deck trees should be initially displayed as expanded",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Turn this off to collapse nested decks in the same card. Useful if you have cards which belong to many decks in the same file.",
 | |
|   ALGORITHM: "Algorithm",
 | |
|   CHECK_ALGORITHM_WIKI: 'For more information, check the <a href="${algoUrl}">algorithm details</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Base ease",
 | |
|   BASE_EASE_DESC: "minimum = 130, preferrably approximately 250.",
 | |
|   BASE_EASE_MIN_WARNING: "The base ease must be at least 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Interval change when you review a flashcard/note as hard",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "newInterval = oldInterval * intervalChange / 100.",
 | |
|   EASY_BONUS: "Easy Bonus",
 | |
|   EASY_BONUS_DESC: "The easy bonus allows you to set the difference in intervals between answering Good and Easy on a flashcard/note (minimum = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "The easy bonus must be at least 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maximum interval in days",
 | |
|   MAX_INTERVAL_DESC: "Allows you to place an upper limit on the interval (default = 100 years).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "The maximum interval must be at least 1 day.",
 | |
|   MAX_LINK_CONTRIB: "Maximum link contribution",
 | |
|   MAX_LINK_CONTRIB_DESC: "Maximum contribution of the weighted ease of linked notes to the initial ease.",
 | |
|   LOGGING: "Logging",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Show the scheduler's debugging information on the developer console",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Notes Review Queue",
 | |
|   CLOSE: "Close",
 | |
|   NEW: "New",
 | |
|   YESTERDAY: "Yesterday",
 | |
|   TODAY: "Today",
 | |
|   TOMORROW: "Tomorrow",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Statistics",
 | |
|   MONTH: "Month",
 | |
|   QUARTER: "Quarter",
 | |
|   YEAR: "Year",
 | |
|   LIFETIME: "Lifetime",
 | |
|   FORECAST: "Forecast",
 | |
|   FORECAST_DESC: "The number of cards due in the future",
 | |
|   SCHEDULED: "Scheduled",
 | |
|   DAYS: "Days",
 | |
|   NUMBER_OF_CARDS: "Number of cards",
 | |
|   REVIEWS_PER_DAY: "Average: ${avg} reviews/day",
 | |
|   INTERVALS: "Intervals",
 | |
|   INTERVALS_DESC: "Delays until reviews are shown again",
 | |
|   COUNT: "Count",
 | |
|   INTERVALS_SUMMARY: "Average interval: ${avg}, Longest interval: ${longest}",
 | |
|   EASES: "Eases",
 | |
|   EASES_SUMMARY: "Average ease: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Card Types",
 | |
|   CARD_TYPES_DESC: "This includes buried cards as well, if any",
 | |
|   CARD_TYPE_NEW: "New",
 | |
|   CARD_TYPE_YOUNG: "Young",
 | |
|   CARD_TYPE_MATURE: "Mature",
 | |
|   CARD_TYPES_SUMMARY: "Total cards: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/en-gb.ts
 | |
| var en_gb_default = {};
 | |
| 
 | |
| // src/lang/locale/es.ts
 | |
| var es_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Mazos",
 | |
|   DUE_CARDS: "Tarjetas Vencidas",
 | |
|   NEW_CARDS: "Tarjetas Nuevas",
 | |
|   TOTAL_CARDS: "Tarjetas Totales",
 | |
|   BACK: "Atr\xE1s",
 | |
|   SKIP: "Saltar",
 | |
|   EDIT_CARD: "Editar Tarjeta",
 | |
|   RESET_CARD_PROGRESS: "Reiniciar progreso de la tarjeta",
 | |
|   HARD: "Dif\xEDcil",
 | |
|   GOOD: "Bien",
 | |
|   EASY: "F\xE1cil",
 | |
|   SHOW_ANSWER: "Mostrar Respuesta",
 | |
|   CARD_PROGRESS_RESET: "El progreso de la tarjeta se ha reiniciado.",
 | |
|   SAVE: "Guardar",
 | |
|   CANCEL: "Cancelar",
 | |
|   NO_INPUT: "Se ha prove\xEDdo entrada.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Facilidad Actual: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Intervalo Actual: ",
 | |
|   CARD_GENERATED_FROM: "Generado Desde: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Abrir nota para revisi\xF3n",
 | |
|   REVIEW_CARDS: "Revisar Tarjetas",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Revisar: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Revisar nota como ${difficulty}",
 | |
|   CRAM_ALL_CARDS: "Selecciona un mazo a memorizar",
 | |
|   REVIEW_ALL_CARDS: "Revisar tarjetas de todas las notas",
 | |
|   REVIEW_CARDS_IN_NOTE: "Revisar tarjetas en esta nota",
 | |
|   CRAM_CARDS_IN_NOTE: "Memorizar tarjetas en esta nota",
 | |
|   VIEW_STATS: "Ver estad\xEDsticas",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "Revisar: ${dueNotesCount} nota(s), ${dueFlashcardsCount} tarjetas vencidas",
 | |
|   SYNC_TIME_TAKEN: "La sincronizaci\xF3n tom\xF3 ${t} milisegundos",
 | |
|   NOTE_IN_IGNORED_FOLDER: "La nota est\xE1 guardada en un directorio ignorado (revisa los ajustes).",
 | |
|   PLEASE_TAG_NOTE: "Por favor etiquete apropiadamente la nota para revisi\xF3n (en los ajustes).",
 | |
|   RESPONSE_RECEIVED: "Respuesta Recibida",
 | |
|   NO_DECK_EXISTS: "No existen mazos para: ${deckName}",
 | |
|   ALL_CAUGHT_UP: "\xA1Est\xE1s al d\xEDa! \u{1F603}",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} d\xEDa(s)",
 | |
|   MONTHS_STR_IVL: "${interval} mes(es)",
 | |
|   YEARS_STR_IVL: "${interval} a\xF1o(s)",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}a",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Extensi\xF3n de Repetici\xF3n Espaciada",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'Para m\xE1s informaci\xF3n revisa la <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Directorios a ignorar",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Tarjetas de Memorizaci\xF3n",
 | |
|   FLASHCARD_EASY_LABEL: "Texto del bot\xF3n: F\xE1cil",
 | |
|   FLASHCARD_GOOD_LABEL: "Texto del bot\xF3n: Bien",
 | |
|   FLASHCARD_HARD_LABEL: "Texto del bot\xF3n: Dif\xEDcil",
 | |
|   FLASHCARD_EASY_DESC: "Personalize la etiqueta para el bot\xF3n: F\xE1cil",
 | |
|   FLASHCARD_GOOD_DESC: "Personalize la etiqueta para el bot\xF3n: Bien",
 | |
|   FLASHCARD_HARD_DESC: "Personalize la etiqueta para el bot\xF3n: Dif\xEDcil",
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Etiquetas de las Tarjetas de Memorizaci\xF3n",
 | |
|   FLASHCARD_TAGS_DESC: "Escriba las etiquetas separadas por espacios o saltos de l\xEDnea, por ejemplo, #memorizar #mazo2 #mazo3",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\xBFConvertir directorios a mazos y submazos?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Esta es una opci\xF3n alternativa a las etiquetas de las Tarjetas de Memorizaci\xF3n.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\xBFGuardar el comentario para programaci\xF3n de las tarjetas en la \xFAltima l\xEDnea?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Activar esto har\xE1 que los comentarios HTML no rompan el formato de las listas.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "\xBFEnterrar tarjetas hermanas hasta el siguiente d\xEDa?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Los hermanos son tarjetas generadas del mismo texto de la tarjeta, por ejemplo, deletreos de huecos (cloze deletions en ingl\xE9s)",
 | |
|   SHOW_CARD_CONTEXT: "\xBFMostrar contexto en las tarjetas?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "Por Ejemplo: T\xEDtulo > Cabecera > Sub-Cabecera > ... > Sub-Cabecera",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Porcentaje de la altura de las tarjetas de memoria",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Deber\xEDa ser establecido en 100% si tienes im\xE1genes grandes",
 | |
|   RESET_DEFAULT: "Reiniciar a la configuraci\xF3n por defecto",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Porcentaje del ancho de las tarjetas de memoria",
 | |
|   RANDOMIZE_CARD_ORDER: "\xBFAleatorizar el orden de las tarjetas para revisi\xF3n?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "\xBFDeshabilitar deletreo de huecos en las tarjetas?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "\xBFConvertir ==resaltados== a deletreo de huecos?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'A\xF1adir/eliminar el <code>${defaultPattern}</code> de tus "Patrones de Deletreo de Huecos"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "\xBFConvertir **texto en negrita** a deletreo de huecos?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'A\xF1adir/eliminar el <code>${defaultPattern}</code> de tus "Patrones de Deletreo de Huecos"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "\xBFConvertir {{llaves rizadas}} a deletreo de huecos?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'A\xF1adir/eliminar el <code>${defaultPattern}</code> de tus "Patrones de Deletreo de Huecos"',
 | |
|   CLOZE_PATTERNS: "Patrones de deletreo de huecos",
 | |
|   CLOZE_PATTERNS_DESC: 'Escriba los patrones de deletreo de huecos separados por saltos de l\xEDnea. . Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Separador de tarjetas de memorizaci\xF3n en l\xEDnea",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Note que despu\xE9s de cambiar este ajuste, tendr\xE1 que cambiar manualmente todas las notas que tenga.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Separador de tarjetas de memorizaci\xF3n para tarjetas de notas invertidas",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Separador para tarjetas de memorizaci\xF3n multil\xEDnea",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Separador para tarjetas de memorizaci\xF3n multil\xEDnea invertidas",
 | |
|   MULTILINE_CARDS_END_MARKER: "Caracteres que denotan el fin de los clozes y tarjetas did\xE1cticas de varias l\xEDneas",
 | |
|   NOTES: "Notes",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Activar panel de revisi\xF3n de notas al arrancar",
 | |
|   TAGS_TO_REVIEW: "Etiquetas a revisar",
 | |
|   TAGS_TO_REVIEW_DESC: "Escriba las etiquetas separadas por espacios o saltos de l\xEDneas, por ejemplo, #revisi\xF3n #etiqueta2 #etiqueta3.",
 | |
|   OPEN_RANDOM_NOTE: "Abrir una nota al azar para revisar",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Cuando deshabilita esto, las notas son ordenadas por importancia (Algoritmo PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Abrir la siguiente nota autom\xE1ticamente despu\xE9s de una revisi\xF3n",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Habilita las opciones de revisi\xF3n en el men\xFA Archivo (por ejemplo: Revisar: F\xE1cil, Bien, Dif\xEDcil)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "Si desactivas las opciones de revisi\xF3n en el men\xFA Archivo, puedes revisar tus notas usando los comandos del plugin y, si los definiste, las teclas r\xE1pidas asociadas.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "N\xFAmero m\xE1ximo de d\xEDas a mostrar en el panel derecho.",
 | |
|   MIN_ONE_DAY: "El n\xFAmero de d\xEDas debe ser al menos uno.",
 | |
|   VALID_NUMBER_WARNING: "Por favor especifique un n\xFAmero v\xE1lido.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Los \xE1rboles de mazos deber\xEDan ser expandidos al inicio.",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Desactiva esto para contraer mazos anidados en la misma tarjeta. \xDAtil si tienes tarjetas que pertenecen a muchos mazos en el mismo archivo.",
 | |
|   ALGORITHM: "Algoritmo",
 | |
|   CHECK_ALGORITHM_WIKI: 'Para m\xE1s informaci\xF3n, revisa la <a href="${algoUrl}">implementaci\xF3n del algoritmo</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Base ease",
 | |
|   BASE_EASE_DESC: "El m\xEDnimo es 130, es preferible que est\xE9 aproximado a 250.",
 | |
|   BASE_EASE_MIN_WARNING: "La facilidad base de las tarjetas debe ser al menos 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "El intervalo cambiar\xE1 cuando se revise una tarjeta o nota como Dif\xEDcil.",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "NuevoInterval = ViejoIntervalo * CambioDeIntervalo / 100.",
 | |
|   EASY_BONUS: "Bonificaci\xF3n para F\xE1cil",
 | |
|   EASY_BONUS_DESC: "La bonificaci\xF3n para F\xE1cil te permite establecer la diferencia entre intervalos al responder Bien y F\xE1cil en las tarjetas o notas (m\xEDnimo = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "El bono de facilidad debe ser al menos 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Intervalo m\xE1ximo en d\xEDas",
 | |
|   MAX_INTERVAL_DESC: "Te permite establecer un l\xEDmite mayor en el intervalo (por defecto es de 100 a\xF1os).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "El intervalo m\xE1ximo debe ser de al menos un d\xEDa.",
 | |
|   MAX_LINK_CONTRIB: "Contribuci\xF3n m\xE1xima de las notas vinculadas.",
 | |
|   MAX_LINK_CONTRIB_DESC: "Contribuci\xF3n m\xE1xima de la facilidad ponderada de las notas vinculadas a la facilidad inicial.",
 | |
|   LOGGING: "Registro",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\xBFMostrar informaci\xF3n de depuraci\xF3n en la consola de desarrollador",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Cola de notas a revisar",
 | |
|   CLOSE: "Cerrar",
 | |
|   NEW: "Nuevo",
 | |
|   YESTERDAY: "Ayer",
 | |
|   TODAY: "Hoy",
 | |
|   TOMORROW: "Ma\xF1ana",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Estad\xEDsticas",
 | |
|   MONTH: "Mes",
 | |
|   QUARTER: "Trimestre o Cuatrimestre",
 | |
|   // En Inglés: Quarter.
 | |
|   YEAR: "A\xF1o",
 | |
|   LIFETIME: "Tiempo de Vida",
 | |
|   FORECAST: "Pron\xF3stico",
 | |
|   FORECAST_DESC: "El n\xFAmero de tarjetas vencidas en el futuro",
 | |
|   SCHEDULED: "Programado",
 | |
|   DAYS: "D\xEDas",
 | |
|   NUMBER_OF_CARDS: "N\xFAmero de tarjetas",
 | |
|   REVIEWS_PER_DAY: "Carga: ${avg} Revisiones por d\xEDa",
 | |
|   INTERVALS: "Intervalos",
 | |
|   INTERVALS_DESC: "Retrasos hasta que las revisiones se muestren de nuevo",
 | |
|   COUNT: "Conteo",
 | |
|   INTERVALS_SUMMARY: "Intervalo de carga: ${avg}, Intervalo mayor: ${longest}",
 | |
|   EASES: "Facilidad",
 | |
|   EASES_SUMMARY: "Carga de Facilidad: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Tipos de tarjetas",
 | |
|   CARD_TYPES_DESC: "Esto incluye tambi\xE9n a las tarjetas enterradas, si las hay",
 | |
|   CARD_TYPE_NEW: "Nueva",
 | |
|   CARD_TYPE_YOUNG: "Joven",
 | |
|   CARD_TYPE_MATURE: "Madura",
 | |
|   CARD_TYPES_SUMMARY: "Tarjetas Totales: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/fr.ts
 | |
| var fr_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Paquets",
 | |
|   DUE_CARDS: "Cartes dues",
 | |
|   NEW_CARDS: "Nouvelles cartes",
 | |
|   TOTAL_CARDS: "Total de cartes",
 | |
|   BACK: "Pr\xE9c\xE9dent",
 | |
|   SKIP: "Sauter",
 | |
|   EDIT_CARD: "Modifier la carte",
 | |
|   RESET_CARD_PROGRESS: "Remettre \xE0 z\xE9ro le niveau de cette carte",
 | |
|   HARD: "Difficile",
 | |
|   GOOD: "Correct",
 | |
|   EASY: "Facile",
 | |
|   SHOW_ANSWER: "Montrer la r\xE9ponse",
 | |
|   CARD_PROGRESS_RESET: "Le niveau de la carte a \xE9t\xE9 remis \xE0 z\xE9ro.",
 | |
|   SAVE: "Sauvegarder",
 | |
|   CANCEL: "Annuler",
 | |
|   NO_INPUT: "Pas de contenu.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Facilit\xE9 actuelle : ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Intervalle actuel : ",
 | |
|   CARD_GENERATED_FROM: "G\xE9n\xE9r\xE9 depuis : ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Ouvrir une note \xE0 apprendre",
 | |
|   REVIEW_CARDS: "Apprendre les flashcards",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Apprentissage : ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Difficult\xE9 de la r\xE9vision : ${difficulty}",
 | |
|   CRAM_ALL_CARDS: "Choisir un deck \xE0 r\xE9viser",
 | |
|   REVIEW_ALL_CARDS: "Apprendre les flashcards dans toutes les notes",
 | |
|   REVIEW_CARDS_IN_NOTE: "Apprendre les flashcards dans cette note",
 | |
|   CRAM_CARDS_IN_NOTE: "R\xE9viser les flashcards dans cette note",
 | |
|   VIEW_STATS: "Voir les statistiques",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Ouvrir la file d'attente des notes \xE0 apprendre dans la barre verticale",
 | |
|   STATUS_BAR: "Apprentissage : ${dueNotesCount} note(s), ${dueFlashcardsCount} carte(s) dues",
 | |
|   SYNC_TIME_TAKEN: "Synchronis\xE9 en ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "La note est dans un dossier ignor\xE9 (voir param\xE8tres).",
 | |
|   PLEASE_TAG_NOTE: "Ajoutez le bon tag \xE0 la note pour l'apprendre (dans les param\xE8tres).",
 | |
|   RESPONSE_RECEIVED: "R\xE9ponse enregistr\xE9e.",
 | |
|   NO_DECK_EXISTS: "Pas de paquet sous le nom ${deckName}",
 | |
|   ALL_CAUGHT_UP: "Bravo, vous \xEAtes \xE0 jour !",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} jour(s)",
 | |
|   MONTHS_STR_IVL: "${interval} mois(s)",
 | |
|   YEARS_STR_IVL: "${interval} an(s)",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}j",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}a",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Dossiers",
 | |
|   GROUP_FLASHCARD_REVIEW: "Apprentissage des flashcards",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "S\xE9parateurs de flashcards",
 | |
|   GROUP_DATA_STORAGE: "Stockage des informations de planification",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contribuer",
 | |
|   CHECK_WIKI: 'Pour plus d\'informations, visitez le <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visitez les <a href="${discussionsUrl}">discussions</a> pour des questions-r\xE9ponses, des retours ou une discussion g\xE9n\xE9raliste.',
 | |
|   GITHUB_ISSUES: 'Cr\xE9ez un ticket <a href="${issuesUrl}">sur GitHub</a> si vous trouvez un bug ou voulez demander une fonctionnalit\xE9.',
 | |
|   GITHUB_SOURCE_CODE: 'Code source du projet disponible sur <a href="${githubProjectUrl}">GitHub</a>',
 | |
|   CODE_CONTRIBUTION_INFO: 'Information sur les <a href="${codeContributionUrl}">contributions au code</a>',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: 'Informations sur la <a href="${translationContributionUrl}">traduction du plugin</a> dans votre langue',
 | |
|   FOLDERS_TO_IGNORE: "Dossiers \xE0 ignorer",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Flashcards",
 | |
|   FLASHCARD_EASY_LABEL: "Bouton Facile",
 | |
|   FLASHCARD_GOOD_LABEL: "Bouton Correct",
 | |
|   FLASHCARD_HARD_LABEL: "Bouton Difficile",
 | |
|   FLASHCARD_EASY_DESC: "Changez le texte du bouton Facile",
 | |
|   FLASHCARD_GOOD_DESC: "Changez le texte du bouton Correct",
 | |
|   FLASHCARD_HARD_DESC: "Changez le texte du bouton Difficile",
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Tags des flashcards",
 | |
|   FLASHCARD_TAGS_DESC: "Entrez les tags s\xE9par\xE9s par un espace ou une ligne i.e. #flashcards #paquet2 #paquet3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Convertir les dossiers en paquets et sous-paquets ?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Ceci est une alternative aux tags de flashcards pr\xE9sent\xE9s ci-dessus.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Sauvegarder le commentaire de planification dans la derni\xE8re ligne de la flashcard ?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Activer ceci emp\xEAche les commentaires HTML de casser la mise en page des listes.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Enterrer les cartes s\u0153urs jusqu'au lendemain ?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Les cartes s\u0153urs sont les cartes g\xE9n\xE9r\xE9es depuis le m\xEAme texte, par exemple pour les textes \xE0 trous",
 | |
|   SHOW_CARD_CONTEXT: "Montrer le contexte dans les cartes ?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "ex. Titre de la note > Titre 1 > Sous-titre > ... > Sous-titre",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Pourcentage de hauteur de la flashcard",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Devrait \xEAtre 100% sur mobile ou en cas de grandes images",
 | |
|   RESET_DEFAULT: "R\xE9initialiser les param\xE8tres",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Pourcentage de largeur de la flashcard",
 | |
|   RANDOMIZE_CARD_ORDER: "Apprendre les cartes dans un ordre al\xE9atoire ?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Ordre d'affichage des cartes d'un paquet pendant les r\xE9visions",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Dans l'ordre du paquet (Nouvelles cartes d'abord)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Dans l'ordre du paquet (Cartes dues d'abord)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Al\xE9atoirement dans le paquet (Nouvelles cartes d'abord)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Al\xE9atoirement dans le paquet (Cartes dues d'abord)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Carte au hasard dans un paquet au hasard",
 | |
|   REVIEW_DECK_ORDER: "Ordre d'affichage des paquets pendant les r\xE9visions",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "S\xE9quentiel (quand toutes les cartes du paquet pr\xE9c\xE9dent sont apprises)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Al\xE9atoire (quand toutes les cartes du paquet pr\xE9c\xE9dent sont apprises)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Carte au hasard dans un paquet au hasard",
 | |
|   DISABLE_CLOZE_CARDS: "D\xE9sactiver les textes \xE0 trous ?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "Convertir ==soulignages== en trous ?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'Ajouter/supprimer le <code>${defaultPattern}</code> de vos "Cloze Patterns"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "Convertir **gras** en trous ?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'Ajouter/supprimer le <code>${defaultPattern}</code> de vos "Cloze Patterns"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "Convertir {{crochets}} en trous ?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'Ajouter/supprimer le <code>${defaultPattern}</code> de vos "Cloze Patterns"',
 | |
|   CLOZE_PATTERNS: "Cloze Patterns",
 | |
|   CLOZE_PATTERNS_DESC: 'Enter cloze patterns separated by newlines. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "S\xE9parateur pour flashcards en une ligne",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Apr\xE8s avoir chang\xE9 ce r\xE9glage, vous devrez manuellement mettre \xE0 jour toutes vos flashcards.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "S\xE9parateur pour flashcards invers\xE9es en une ligne",
 | |
|   MULTILINE_CARDS_SEPARATOR: "S\xE9parateur pour flashcards en plusieurs lignes",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "S\xE9parateur pour flashcards invers\xE9es en plusieurs lignes",
 | |
|   MULTILINE_CARDS_END_MARKER: "Caract\xE8res de fin de textes \xE0 trous ou de flashcards en plusieurs lignes",
 | |
|   NOTES: "Notes",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Montrer le module d'apprentissage des notes au d\xE9marrage",
 | |
|   TAGS_TO_REVIEW: "Tags \xE0 apprendre",
 | |
|   TAGS_TO_REVIEW_DESC: "Entrez les tags s\xE9par\xE9s par un espace ou une ligne i.e. #review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "Ouvrir une note \xE0 apprendre au hasard",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Si vous d\xE9sactivez cette option, les notes sont tri\xE9es par importance (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Ouvrir la prochaine note automatiquement apr\xE8s un apprentissage",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Jours maximum affich\xE9s dans la barre de droite",
 | |
|   MIN_ONE_DAY: "Le nombre de jours doit \xEAtre au moins 1.",
 | |
|   VALID_NUMBER_WARNING: "Entrez un nombre valide.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Enable the review options in the file menu (e.g. Review: Easy, Good, Hard)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "If you disable the review options in the file menu, you can review your notes using the plugin commands and, if you defined them, the associated command hotkeys.",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Les dossiers de paquets devraient initialement tous \xEAtre ouverts",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "D\xE9sactivez pour r\xE9duire les paquets dans la m\xEAme carte. Ce r\xE9glage est utile si vous avez des cartes qui appartiennent \xE0 beaucoup de paquets \xE0 la fois.",
 | |
|   ALGORITHM: "Algorithme",
 | |
|   CHECK_ALGORITHM_WIKI: `Pour en savoir plus, lisez l'<a href="\${algoUrl}">impl\xE9mentation de l'algorithme</a>.`,
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Facilit\xE9 de base",
 | |
|   BASE_EASE_DESC: "minimum = 130, recommand\xE9 = vers 250.",
 | |
|   BASE_EASE_MIN_WARNING: "La facilit\xE9 de base doit \xEAtre sup\xE9rieure \xE0 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Changement d'intervalle quand vous indiquez qu'une flashcard/note a \xE9t\xE9 difficile",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "nouvelIntervalle = ancienIntervalle * changementIntervalle / 100.",
 | |
|   EASY_BONUS: "Bonus Facile",
 | |
|   EASY_BONUS_DESC: "Le bonus Facile vous permet d'augmenter l'intervalle entre une r\xE9ponse Correct et une r\xE9ponse Facile sur une flashcard/note (minimum = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "Le bonus Facile doit \xEAtre au moins 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Intervalle maximum (en jours)",
 | |
|   MAX_INTERVAL_DESC: "Vous permet de mettre une limite maximale sur l'intervalle (par d\xE9faut, 100 ans).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "L'intervalle maximum doit \xEAtre au moins 1 jour.",
 | |
|   MAX_LINK_CONTRIB: "Contribution maximum des liens",
 | |
|   MAX_LINK_CONTRIB_DESC: "Contribution maximum de la facilit\xE9 pond\xE9r\xE9e des notes li\xE9es \xE0 la facilit\xE9 initiale.",
 | |
|   LOGGING: "Logging",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Afficher les informations de d\xE9bogage dans la console de d\xE9veloppement",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Afficher les informations de d\xE9bogage pour le parser dans la console de d\xE9veloppement",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Cartes \xE0 apprendre",
 | |
|   CLOSE: "Fermer",
 | |
|   NEW: "Nouveau",
 | |
|   YESTERDAY: "Hier",
 | |
|   TODAY: "Aujourd'hui",
 | |
|   TOMORROW: "Demain",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Statistiques",
 | |
|   MONTH: "Mois",
 | |
|   QUARTER: "Trimestre",
 | |
|   YEAR: "Ann\xE9e",
 | |
|   LIFETIME: "Toujours",
 | |
|   FORECAST: "Pr\xE9visions",
 | |
|   FORECAST_DESC: "Le nombre de cartes dues dans le futur",
 | |
|   SCHEDULED: "Planifi\xE9",
 | |
|   DAYS: "Jours",
 | |
|   NUMBER_OF_CARDS: "Nombre de cartes",
 | |
|   REVIEWS_PER_DAY: "Moyenne : ${avg} apprentissages / jour",
 | |
|   INTERVALS: "Intervalles",
 | |
|   INTERVALS_DESC: "Dur\xE9e avant de remontrer une carte",
 | |
|   COUNT: "Total",
 | |
|   INTERVALS_SUMMARY: "Intervalle moyen : ${avg}. Intervalle maximum: ${longest}",
 | |
|   EASES: "Facilit\xE9",
 | |
|   EASES_SUMMARY: "Facilit\xE9 moyenne : ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Types de cartes",
 | |
|   CARD_TYPES_DESC: "Ceci inclut les cartes enterr\xE9es, s'il y en a",
 | |
|   CARD_TYPE_NEW: "Nouvelles",
 | |
|   CARD_TYPE_YOUNG: "En cours d'apprentissage",
 | |
|   CARD_TYPE_MATURE: "Matures",
 | |
|   CARD_TYPES_SUMMARY: "Total de cartes : ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/hi.ts
 | |
| var hi_default = {};
 | |
| 
 | |
| // src/lang/locale/id.ts
 | |
| var id_default = {};
 | |
| 
 | |
| // src/lang/locale/it.ts
 | |
| var it_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Mazzi",
 | |
|   DUE_CARDS: "Schede da fare",
 | |
|   NEW_CARDS: "Schede nuove",
 | |
|   TOTAL_CARDS: "Schede totali",
 | |
|   BACK: "Indietro",
 | |
|   SKIP: "Salta",
 | |
|   EDIT_CARD: "Modifica scheda",
 | |
|   RESET_CARD_PROGRESS: "Ripristina i progressi della scheda",
 | |
|   HARD: "Difficile",
 | |
|   GOOD: "Buono",
 | |
|   EASY: "Facile",
 | |
|   SHOW_ANSWER: "Mostra risposta",
 | |
|   CARD_PROGRESS_RESET: "I progressi della scheda sono stati ripristinati",
 | |
|   SAVE: "Salva",
 | |
|   CANCEL: "Cancella",
 | |
|   NO_INPUT: "Non \xE8 stato provvisto alcun input",
 | |
|   CURRENT_EASE_HELP_TEXT: "Difficolt\xE0 attuale: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Intervallo attuale: ",
 | |
|   CARD_GENERATED_FROM: "Generato da: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Apri una nota per rivisita",
 | |
|   REVIEW_CARDS: "Rivisita schede",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Rivisita: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Revisita note come ${difficulty}",
 | |
|   CRAM_ALL_CARDS: "Seleziona un mazzo da memorizzare",
 | |
|   REVIEW_ALL_CARDS: "Seleziona schede da rivedere",
 | |
|   REVIEW_CARDS_IN_NOTE: "Rivedi schede in questa nota",
 | |
|   CRAM_CARDS_IN_NOTE: "Memorizza schede in questa nota",
 | |
|   VIEW_STATS: "Vedi statistiche",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "Da rivedere: ${dueNotesCount} scheda/e, ${dueFlashcardsCount} schede in ritardo",
 | |
|   SYNC_TIME_TAKEN: "Sincronizzato in ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "La nota \xE8 salvata in una cartella ignorata (rivedi le impostazioni).",
 | |
|   PLEASE_TAG_NOTE: "Per favore etichetta la nota appropriatamente per la revisione (nelle impostazioni).",
 | |
|   RESPONSE_RECEIVED: "Risposta ricevuta.",
 | |
|   NO_DECK_EXISTS: "Non esistono mazzi per ${deckName}",
 | |
|   ALL_CAUGHT_UP: "Sei al passo! :D.",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} giorno/i",
 | |
|   MONTHS_STR_IVL: "${interval} mese/i",
 | |
|   YEARS_STR_IVL: "${interval} anno/i",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}y",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Plugin per ripetizione spaziata",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'Per maggiori informazioni, rivolgersi alla <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Cartelle da ignorare",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Schede",
 | |
|   FLASHCARD_EASY_LABEL: "Testo del bottone facile",
 | |
|   FLASHCARD_GOOD_LABEL: "Testo del bottone buono",
 | |
|   FLASHCARD_HARD_LABEL: "Testo del bottone difficile",
 | |
|   FLASHCARD_EASY_DESC: 'Personalizza il testo per il pulsante "Facile"',
 | |
|   FLASHCARD_GOOD_DESC: 'Personalizza il testo per il pulsante "Buono"',
 | |
|   FLASHCARD_HARD_DESC: 'Personalizza il testo per il pulsante "Difficile"',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Etichette delle schede",
 | |
|   FLASHCARD_TAGS_DESC: "Inserire etichette separate da spazi o a capi, per esempio #flashcards #deck2 #deck3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Trasformare cartelle in mazzi e sotto-mazzi?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Questa \xE8 un'alternativa all'opzione delle etichette delle schede sopra.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Salvare il commento per l'orario sulla stessa linea dell'ultimna linea della scheda?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Attivando quest'impostazione far\xF2 s\xEC che i commento HTML non rompino la formattazione delle liste.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Sotterrare schede sorelle fino al giorno dopo?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Le schede sorelle sono schede generate dallo stesso testo della scheda, per esempio i.e. cloze deletions",
 | |
|   SHOW_CARD_CONTEXT: "Mostrare contesto nelle schede?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "per esempio, Titolo > Intestazione 1 > Sottotitolo 1 > ... > Sottotitolo",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Percentuale altezza schede",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Dovrebbe essere 100% se sei su telefono o se hai immagini molto grandi",
 | |
|   RESET_DEFAULT: "Reimposta alle impostazioni iniziali",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Percentuale di larghezza delle schede",
 | |
|   RANDOMIZE_CARD_ORDER: "Rendere casuale l'ordine delle schede durante la revisione?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "L'ordine in cui le schede saranno visualizzate all'interno del mazzo",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequenzialmente dentro il mazzo (prima schede nuove)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequenzialmente dentro il mazzo (prima schede in ritardo)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "A caso dentro il mazzo (prima schede nuove)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "A caso dentro il mazzo (prima schede in ritardo)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Scheda a caso da mazzo a caso",
 | |
|   REVIEW_DECK_ORDER: "L'ordine in cui i mazzi vengono mostrati durante la revisione",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequenzialmente (quando le schede nel mazzo precedente saranno state riviste)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "A caso (quando le schede nel mazzo precedente saranno state riviste)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Scheda a caso da mazzo a caso",
 | |
|   DISABLE_CLOZE_CARDS: "Disabilita schede con spazi da riempire?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "Convertire ==testo evidenziato== in spazi da riempire?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'Aggiungi/rimuovi <code>${defaultPattern}</code> dai tuoi "Modelli per spazi da riempire"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "Convertire **testo in grassetto** in spazi da riempire",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'Aggiungi/rimuovi <code>${defaultPattern}</code> dai tuoi "Modelli per spazi da riempire"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "Convertire {{parentesi graffe}} in spazi da riempire?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'Aggiungi/rimuovi <code>${defaultPattern}</code> dai tuoi "Modelli per spazi da riempire"',
 | |
|   CLOZE_PATTERNS: "Modelli di spazi da riempire",
 | |
|   CLOZE_PATTERNS_DESC: 'Inserisci i modelli di spazi da riempire separati da a capo. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Separatore per schede sulla stessa riga",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Si avvisa che dopo aver cambiato questo dovrai manualmente modificare le schede che hai gi\xE0.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Separatore per schede all'incontrario sulla stessa riga",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Separatore per schede su pi\xF9 righe",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Separatore per schede all'incontrario su pi\xF9 righe",
 | |
|   MULTILINE_CARDS_END_MARKER: "Caratteri che denotano la fine di carte con spazi da riempiere e carte multilinea",
 | |
|   NOTES: "Note",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Abilita il pannello di revisione note all'avvio",
 | |
|   TAGS_TO_REVIEW: "Etichette da rivedere",
 | |
|   TAGS_TO_REVIEW_DESC: "Inserisci le etichette separate da spazi o a capi, tipo #review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "Apri una nota a caso per revisione",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Quando lo disabiliti, le note saranno ordinate per importanza (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Apri la prossima nota automaticamente dopo la revisione",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Abilita le opzioni di revisione nel menu File (es.: Rivisita: Facile, Buono, Difficile)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "Se disabiliti le opzioni di revisione nel menu File, puoi rivedere le tue note utilizzando i comandi del plugin e, se li hai definiti, le scorciatoie da tastiera associate.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Numero di giorni massimi da visualizzare nel pannello di destra",
 | |
|   MIN_ONE_DAY: "Il numero di giorni deve essere almeno 1.",
 | |
|   VALID_NUMBER_WARNING: "Per favore, mettere un numero valido.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Alberti di mazzi dovrebbero essere inizialmente visualizzate come espansi",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Disabilitami per collassare mazzi annidati nella stessa scheda. Utile se hai schede che appartengono a pi\xF9 mazzi nello stesso file.",
 | |
|   ALGORITHM: "Algoritmo",
 | |
|   CHECK_ALGORITHM_WIKI: "Per maggiori informazioni, visita <a href='${algoUrl}'>l'implementazione dell'algoritmo</a>.",
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Difficolt\xE0 base",
 | |
|   BASE_EASE_DESC: "mino = 130, preferibilmente circa 250.",
 | |
|   BASE_EASE_MIN_WARNING: "La difficolt\xE0 base deve essere di almeno 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "L'intervallo cambier\xE0 segnando una scheda / nota come difficile",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "Intervallo nuovo = intervallo vecchio * cambio intervallo / 100.",
 | |
|   EASY_BONUS: "Bonus facilit\xE0",
 | |
|   EASY_BONUS_DESC: "Il bonus facilit\xE0 ti permette di impostare le differenze negli intervalli tra il rispondere Buono e Facile su una scheda o nota (minimo 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "Il bonus facilit\xE0 deve essere di almeno 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Intervallo massimo in giorni",
 | |
|   MAX_INTERVAL_DESC: "Ti permette di mettere un limite massimo all'intervallo (default 100 anni).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "L'intervallo massimo deve essere di almeno 1 giorno.",
 | |
|   MAX_LINK_CONTRIB: "Contributo massimo delle note collegate",
 | |
|   MAX_LINK_CONTRIB_DESC: "Contributo massimo della difficolt\xE0 pasata delle note collegate alla difficolt\xE0 iniziale.",
 | |
|   LOGGING: "Registrando",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Visualizza informazione di debug sulla console per sviluppatori",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Visualizza informazione di debug riguardanti il parser sulla console per sviluppatori",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Coda di note da rivedere",
 | |
|   CLOSE: "Chiusi",
 | |
|   NEW: "Nuovo/a",
 | |
|   YESTERDAY: "Ieri",
 | |
|   TODAY: "Oggi",
 | |
|   TOMORROW: "Domani",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Statistiche",
 | |
|   MONTH: "Mese",
 | |
|   QUARTER: "Trimestre",
 | |
|   YEAR: "Anno",
 | |
|   LIFETIME: "Per tutta la vita",
 | |
|   FORECAST: "Previsione",
 | |
|   FORECAST_DESC: "Il numero di schede che saranno in ritardo in futuro",
 | |
|   SCHEDULED: "Programmate",
 | |
|   DAYS: "Giorni",
 | |
|   NUMBER_OF_CARDS: "Numero di schede",
 | |
|   REVIEWS_PER_DAY: "Media: ${avg} revisioni/giorno",
 | |
|   INTERVALS: "Intervalli",
 | |
|   INTERVALS_DESC: "Ritardi finch\xE9 le revisioni saranno visualizzate di nuovo",
 | |
|   COUNT: "Conta",
 | |
|   INTERVALS_SUMMARY: "Intervallo medio: ${avg}, Intervallo massimo: ${longest}",
 | |
|   EASES: "Difficolt\xE0",
 | |
|   EASES_SUMMARY: "Difficolt\xE0 media: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Tipi di schede",
 | |
|   CARD_TYPES_DESC: "Include eventuali schede sepolte",
 | |
|   CARD_TYPE_NEW: "Nuove",
 | |
|   CARD_TYPE_YOUNG: "Giovani",
 | |
|   CARD_TYPE_MATURE: "Mature",
 | |
|   CARD_TYPES_SUMMARY: "Schede tottali: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/ja.ts
 | |
| var ja_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "\u30C7\u30C3\u30AD",
 | |
|   DUE_CARDS: "\u671F\u65E5\u306E\u30AB\u30FC\u30C9",
 | |
|   NEW_CARDS: "\u65B0\u898F\u306E\u30AB\u30FC\u30C9",
 | |
|   TOTAL_CARDS: "\u30AB\u30FC\u30C9\u5408\u8A08",
 | |
|   BACK: "Back",
 | |
|   SKIP: "Skip",
 | |
|   EDIT_CARD: "Edit Card",
 | |
|   RESET_CARD_PROGRESS: "\u30AB\u30FC\u30C9\u306E\u9032\u6357\u3092\u30EA\u30BB\u30C3\u30C8",
 | |
|   HARD: "Hard",
 | |
|   GOOD: "Good",
 | |
|   EASY: "Easy",
 | |
|   SHOW_ANSWER: "\u89E3\u7B54\u3092\u8868\u793A",
 | |
|   CARD_PROGRESS_RESET: "\u30AB\u30FC\u30C9\u306E\u9032\u6357\u304C\u30EA\u30BB\u30C3\u30C8\u3055\u308C\u307E\u3057\u305F\u3002",
 | |
|   SAVE: "Save",
 | |
|   CANCEL: "Cancel",
 | |
|   NO_INPUT: "No input provided.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Current Ease: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Current Interval: ",
 | |
|   CARD_GENERATED_FROM: "Generated from: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "\u30EC\u30D3\u30E5\u30FC\u3059\u308B\u30CE\u30FC\u30C8\u3092\u958B\u304F",
 | |
|   REVIEW_CARDS: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306E\u30EC\u30D3\u30E5\u30FC",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "\u30EC\u30D3\u30E5\u30FC: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "\u30CE\u30FC\u30C8\u3092${difficulty}\u3068\u3057\u3066\u30EC\u30D3\u30E5\u30FC\u3059\u308B",
 | |
|   REVIEW_ALL_CARDS: "\u3059\u3079\u3066\u306E\u30CE\u30FC\u30C8\u304B\u3089\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u3092\u30EC\u30D3\u30E5\u30FC\u3059\u308B",
 | |
|   CRAM_ALL_CARDS: "Select a deck to cram",
 | |
|   REVIEW_CARDS_IN_NOTE: "\u3053\u306E\u30CE\u30FC\u30C8\u306E\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u3092\u30EC\u30D3\u30E5\u30FC\u3059\u308B",
 | |
|   CRAM_CARDS_IN_NOTE: "\u3053\u306E\u30CE\u30FC\u30C8\u306E\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u3092\u8A70\u3081\u8FBC\u307F\u5B66\u7FD2\u3059\u308B",
 | |
|   VIEW_STATS: "\u7D71\u8A08\u3092\u95B2\u89A7\u3059\u308B",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "\u30EC\u30D3\u30E5\u30FC: ${dueNotesCount}\u30CE\u30FC\u30C8, ${dueFlashcardsCount}\u30AB\u30FC\u30C9\u304C\u671F\u65E5",
 | |
|   SYNC_TIME_TAKEN: "\u540C\u671F\u306B${t}ms\u304B\u304B\u308A\u307E\u3057\u305F\u3002",
 | |
|   NOTE_IN_IGNORED_FOLDER: "\u30CE\u30FC\u30C8\u304C\u7121\u8996\u3059\u308B\u30D5\u30A9\u30EB\u30C0\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059(\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044)\u3002",
 | |
|   PLEASE_TAG_NOTE: "\u30EC\u30D3\u30E5\u30FC\u3092\u884C\u3046\u306B\u306F\u30CE\u30FC\u30C8\u306B\u5BFE\u3057\u3066\u6B63\u3057\u304F\u30BF\u30B0\u4ED8\u3051\u3057\u3066\u304F\u3060\u3055\u3044(\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044)\u3002",
 | |
|   RESPONSE_RECEIVED: "\u7B54\u3048\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002",
 | |
|   NO_DECK_EXISTS: "${deckName}\u306B\u306F\u30C7\u30C3\u30AD\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002",
 | |
|   ALL_CAUGHT_UP: "\u4ECA\u65E5\u306E\u8AB2\u984C\u3092\u3059\u3079\u3066\u9054\u6210\u3057\u307E\u3057\u305F :D",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval}\u65E5\u5F8C",
 | |
|   MONTHS_STR_IVL: "${interval}\u6708\u5F8C",
 | |
|   YEARS_STR_IVL: "${interval}\u5E74\u5F8C",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}y",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: '\u8A73\u7D30\u306B\u3064\u3044\u3066\u306F<a href="${wikiUrl}">wiki</a>\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "\u7121\u8996\u3059\u308B\u30D5\u30A9\u30EB\u30C0",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9",
 | |
|   FLASHCARD_EASY_LABEL: "Easy Button Text",
 | |
|   FLASHCARD_GOOD_LABEL: "Good Button Text",
 | |
|   FLASHCARD_HARD_LABEL: "Hard Button Text",
 | |
|   FLASHCARD_EASY_DESC: 'Customize the label for the "Easy" Button',
 | |
|   FLASHCARD_GOOD_DESC: 'Customize the label for the "Good" Button',
 | |
|   FLASHCARD_HARD_DESC: 'Customize the label for the "Hard" Button',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306B\u4F7F\u7528\u3059\u308B\u30BF\u30B0",
 | |
|   FLASHCARD_TAGS_DESC: '\u30BF\u30B0\u3092\u30B9\u30DA\u30FC\u30B9\u307E\u305F\u306F\u6539\u884C\u3067\u533A\u5207\u3063\u3066\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B: "#flashcards #deck2 #deck3"',
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\u30D5\u30A9\u30EB\u30C0\u3092\u30C7\u30C3\u30AD\u3068\u30B5\u30D6\u30C7\u30C3\u30AD\u3068\u3057\u3066\u4F7F\u7528\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "\u3053\u308C\u306F\u4E0A\u8A18\u306E\u30BF\u30B0\u3092\u4F7F\u7528\u3057\u305F\u30C7\u30C3\u30AD\u69CB\u7BC9\u306E\u4EE3\u66FF\u3068\u306A\u308B\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3059\u3002",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306E\u6700\u7D42\u884C\u3068\u540C\u4E00\u306E\u884C\u306B\u30B9\u30B1\u30B8\u30E5\u30FC\u30EA\u30F3\u30B0\u30B3\u30E1\u30F3\u30C8\u3092\u4FDD\u5B58\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u5316\u3059\u308B\u3068\u3001HTML\u30B3\u30E1\u30F3\u30C8\u306B\u3088\u3063\u3066Markdown\u306E\u30EA\u30B9\u30C8\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u304C\u5D29\u308C\u306A\u304F\u306A\u308A\u307E\u3059\u3002",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "\u6B21\u306E\u30EC\u30D3\u30E5\u30FC\u307E\u3067\u30B7\u30D6\u30EA\u30F3\u30B0\u3092\u5EF6\u671F\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "\u30B7\u30D6\u30EA\u30F3\u30B0\u306F\u540C\u4E00\u306E\u30AB\u30FC\u30C9\u30C6\u30AD\u30B9\u30C8\u304B\u3089\u751F\u6210\u3055\u308C\u305F\u30AB\u30FC\u30C9\u3001\u3064\u307E\u308A\u7A74\u57CB\u3081\u554F\u984C\u306E\u6D3E\u751F\u30AB\u30FC\u30C9\u3067\u3059\u3002",
 | |
|   SHOW_CARD_CONTEXT: "\u30AB\u30FC\u30C9\u306B\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3092\u8868\u793A\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   SHOW_CARD_CONTEXT_DESC: "\uFF62\u30BF\u30A4\u30C8\u30EB > \u898B\u51FA\u3057 1 > \u526F\u898B\u51FA\u3057 > ... > \u526F\u898B\u51FA\u3057\uFF63\u306E\u8868\u793A\u3092\u884C\u3046\u304B\u3069\u3046\u304B\u3092\u6C7A\u3081\u307E\u3059\u3002",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306E\u7E26\u30B5\u30A4\u30BA\u306E\u30D1\u30FC\u30BB\u30F3\u30C6\u30FC\u30B8",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "\u30E2\u30D0\u30A4\u30EB\u7248\u3001\u307E\u305F\u306F\u975E\u5E38\u306B\u5927\u304D\u306A\u30B5\u30A4\u30BA\u306E\u753B\u50CF\u304C\u3042\u308B\u5834\u5408\u306B\u306F100%\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002",
 | |
|   RESET_DEFAULT: "\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306B\u30EA\u30BB\u30C3\u30C8\u3059\u308B",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306E\u6A2A\u30B5\u30A4\u30BA\u306E\u30D1\u30FC\u30BB\u30F3\u30C6\u30FC\u30B8",
 | |
|   RANDOMIZE_CARD_ORDER: "\u30EC\u30D3\u30E5\u30FC\u4E2D\u306E\u30AB\u30FC\u30C9\u306E\u9806\u756A\u3092\u30E9\u30F3\u30C0\u30E0\u306B\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "\u7A74\u57CB\u3081\u30AB\u30FC\u30C9\u3092\u7121\u52B9\u5316\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "==\u30CF\u30A4\u30E9\u30A4\u30C8==\u3092\u7A74\u57CB\u3081\u3068\u3057\u3066\u4F7F\u7528\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: "\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u5316\u3059\u308B\u3068\u3001\u300C\u7A74\u57CB\u3081\u30D1\u30BF\u30FC\u30F3\u300D\u306B${defaultPattern}\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3059\u3002",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "**\u30DC\u30FC\u30EB\u30C9\u4F53**\u3092\u7A74\u57CB\u3081\u3068\u3057\u3066\u4F7F\u7528\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: "\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u5316\u3059\u308B\u3068\u3001\u300C\u7A74\u57CB\u3081\u30D1\u30BF\u30FC\u30F3\u300D\u306B${defaultPattern}\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3059\u3002",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "{{\u4E2D\u62EC\u5F27}}\u3092\u7A74\u57CB\u3081\u3068\u3057\u3066\u4F7F\u7528\u3057\u307E\u3059\u304B\uFF1F",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: "\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u5316\u3059\u308B\u3068\u3001\u300C\u7A74\u57CB\u3081\u30D1\u30BF\u30FC\u30F3\u300D\u306B${defaultPattern}\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3059\u3002",
 | |
|   CLOZE_PATTERNS: "\u7A74\u57CB\u3081\u30D1\u30BF\u30FC\u30F3",
 | |
|   CLOZE_PATTERNS_DESC: '\u6539\u884C\u3067\u533A\u5207\u3063\u3066\u7A74\u57CB\u3081\u30D1\u30BF\u30FC\u30F3\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "\u30A4\u30F3\u30E9\u30A4\u30F3\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306B\u4F7F\u7528\u3059\u308B\u30BB\u30D1\u30EC\u30FC\u30BF\u30FC",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u5909\u66F4\u3059\u308B\u5834\u5408\u306B\u306F\u3001\u4F5C\u6210\u6E08\u307F\u306E\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u3092\u624B\u52D5\u3067\u7DE8\u96C6\u3057\u76F4\u3059\u5FC5\u8981\u304C\u3042\u308B\u3053\u3068\u306B\u6CE8\u610F\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "\u30A4\u30F3\u30E9\u30A4\u30F3\u306E\u8868\u88CF\u53CD\u8EE2\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306B\u4F7F\u7528\u3059\u308B\u30BB\u30D1\u30EC\u30FC\u30BF\u30FC",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\u8907\u6570\u884C\u306E\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306B\u4F7F\u7528\u3059\u308B\u30BB\u30D1\u30EC\u30FC\u30BF\u30FC",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\u8907\u6570\u884C\u306E\u8868\u88CF\u53CD\u8EE2\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306B\u4F7F\u7528\u3059\u308B\u30BB\u30D1\u30EC\u30FC\u30BF\u30FC",
 | |
|   MULTILINE_CARDS_END_MARKER: "\u30AF\u30ED\u30FC\u30BA\u3068\u8907\u6570\u884C\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9\u306E\u7D42\u308F\u308A\u3092\u793A\u3059\u6587\u5B57",
 | |
|   NOTES: "\u30CE\u30FC\u30C8",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Enable note review pane on startup",
 | |
|   TAGS_TO_REVIEW: "\u30EC\u30D3\u30E5\u30FC\u306B\u4F7F\u7528\u3059\u308B\u30BF\u30B0",
 | |
|   TAGS_TO_REVIEW_DESC: '\u30BF\u30B0\u3092\u30B9\u30DA\u30FC\u30B9\u307E\u305F\u306F\u6539\u884C\u3067\u533A\u5207\u3063\u3066\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B: "#review #tag2 #tag3"',
 | |
|   OPEN_RANDOM_NOTE: "\u30E9\u30F3\u30C0\u30E0\u306B\u30CE\u30FC\u30C8\u3092\u958B\u3044\u3066\u30EC\u30D3\u30E5\u30FC\u3059\u308B",
 | |
|   OPEN_RANDOM_NOTE_DESC: "\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u308B\u72B6\u614B\u3067\u306F\u3001\u30CE\u30FC\u30C8\u306F\u91CD\u8981\u5EA6(\u30DA\u30FC\u30B8\u30E9\u30F3\u30AF)\u306B\u3088\u308B\u9806\u756A\u3067\u8868\u793A\u3055\u308C\u307E\u3059\u3002",
 | |
|   AUTO_NEXT_NOTE: "\u30EC\u30D3\u30E5\u30FC\u5F8C\u306B\u6B21\u306E\u30CE\u30FC\u30C8\u3092\u81EA\u52D5\u7684\u306B\u958B\u304F",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "\u30D5\u30A1\u30A4\u30EB\u30E1\u30CB\u30E5\u30FC\u3067\u30EC\u30D3\u30E5\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: Easy, Good, Hard\uFF09",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "\u30D5\u30A1\u30A4\u30EB\u30E1\u30CB\u30E5\u30FC\u3067\u30EC\u30D3\u30E5\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u305F\u5834\u5408\u3001\u30D7\u30E9\u30B0\u30A4\u30F3\u30B3\u30DE\u30F3\u30C9\u3084\u3001\u8A2D\u5B9A\u3057\u3066\u3044\u308B\u5834\u5408\u306F\u5BFE\u5FDC\u3059\u308B\u30DB\u30C3\u30C8\u30AD\u30FC\u3092\u4F7F\u7528\u3057\u3066\u30E1\u30E2\u3092\u30EC\u30D3\u30E5\u30FC\u3067\u304D\u307E\u3059\u3002",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "\u53F3\u30D1\u30CD\u30EB\u306B\u8868\u793A\u3059\u308B\u6700\u5927\u306E\u65E5\u6570",
 | |
|   MIN_ONE_DAY: "\u65E5\u6570\u306B\u306F1\u4EE5\u4E0A\u306E\u6570\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   VALID_NUMBER_WARNING: "\u6709\u52B9\u306A\u6570\u5B57\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\u30C7\u30C3\u30AD \u30C4\u30EA\u30FC\u306F\u6700\u521D\u306F\u5C55\u958B\u3057\u3066\u8868\u793A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "\u3053\u308C\u3092\u30AA\u30D5\u306B\u3059\u308B\u3068\u3001\u540C\u3058\u30AB\u30FC\u30C9\u5185\u306E\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30C7\u30C3\u30AD\u304C\u6298\u308A\u305F\u305F\u307E\u308C\u307E\u3059\u3002\u540C\u3058\u30D5\u30A1\u30A4\u30EB\u306B\u591A\u304F\u306E\u30C7\u30C3\u30AD\u306B\u5C5E\u3059\u308B\u30AB\u30FC\u30C9\u304C\u3042\u308B\u5834\u5408\u306B\u4FBF\u5229\u3067\u3059\u3002",
 | |
|   ALGORITHM: "\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0",
 | |
|   CHECK_ALGORITHM_WIKI: '\u8A73\u7D30\u306B\u3064\u3044\u3066\u306F<a href="${algoUrl}">\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u5B9F\u88C5</a>\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "\u30D9\u30FC\u30B9\u306E\u6613\u3057\u3055",
 | |
|   BASE_EASE_DESC: "\u6700\u5C0F\u5024\u306F130\u3067\u3059\u304C\u3001 \u9069\u6B63\u5024\u306F\u304A\u304A\u3088\u305D250\u3067\u3059\u3002",
 | |
|   BASE_EASE_MIN_WARNING: "\u30D9\u30FC\u30B9\u306E\u6613\u3057\u3055\u306B\u306F130\u4EE5\u4E0A\u306E\u6570\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   LAPSE_INTERVAL_CHANGE: "\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9/\u30CE\u30FC\u30C8\u3092Hard\u3068\u3057\u3066\u30EC\u30D3\u30E5\u30FC\u3057\u305F\u969B\u306E\u9593\u9694\u5909\u66F4",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: '"\u65B0\u3057\u3044\u9593\u9694 = \u4EE5\u524D\u306E\u9593\u9694 * \u9593\u9694\u5909\u66F4 / 100" \u3068\u3057\u3066\u8A08\u7B97\u3055\u308C\u307E\u3059\u3002',
 | |
|   EASY_BONUS: "Easy\u30DC\u30FC\u30CA\u30B9",
 | |
|   EASY_BONUS_DESC: "Easy\u30DC\u30FC\u30CA\u30B9\u306B\u3088\u3063\u3066\u30D5\u30E9\u30C3\u30B7\u30E5\u30AB\u30FC\u30C9/\u30CE\u30FC\u30C8\u306B\u304A\u3051\u308B\u9593\u9694\u306E\u5DEE\u5206\u3092\u8A2D\u5B9A\u3067\u304D\u307E\u3059(\u6700\u5C0F\u5024 = 100%)\u3002",
 | |
|   EASY_BONUS_MIN_WARNING: "Easy\u30DC\u30FC\u30CA\u30B9\u306B\u306F100\u4EE5\u4E0A\u306E\u6570\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maximum interval in days",
 | |
|   MAX_INTERVAL_DESC: "\u9593\u9694\u306B\u4E0A\u9650\u5024\u3092\u8A2D\u5B9A\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8\u5024 = 100\u5E74)\u3002",
 | |
|   MAX_INTERVAL_MIN_WARNING: "\u9593\u9694\u306E\u6700\u5927\u5024\u306B\u306F1\u4EE5\u4E0A\u306E\u6570\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   MAX_LINK_CONTRIB: "\u30EA\u30F3\u30AF\u30B3\u30F3\u30C8\u30EA\u30D3\u30E5\u30FC\u30B7\u30E7\u30F3\u306E\u6700\u5927\u5024",
 | |
|   MAX_LINK_CONTRIB_DESC: "\u6700\u521D\u306E\u6613\u3057\u3055\u306B\u5BFE\u3057\u3066\u3001\u30EA\u30F3\u30AF\u3055\u308C\u305F\u30CE\u30FC\u30C8\u306E\u91CD\u307F\u4ED8\u3051\u3055\u308C\u305F\u6613\u3057\u3055\u304C\u5BC4\u4E0E\u3059\u308B\u6700\u5927\u5024\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
 | |
|   LOGGING: "\u30ED\u30B0\u7BA1\u7406",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\u30C7\u30D9\u30ED\u30C3\u30D1\u30FC\u30B3\u30F3\u30BD\u30FC\u30EB\u306B\u3066\u30C7\u30D0\u30C3\u30B0\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\u304B",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "\u30CE\u30FC\u30C8\u30EC\u30D3\u30E5\u30FC\u306E\u30AD\u30E5\u30FC",
 | |
|   CLOSE: "\u9589\u3058\u308B",
 | |
|   NEW: "\u65B0\u898F",
 | |
|   YESTERDAY: "\u6628\u65E5",
 | |
|   TODAY: "\u4ECA\u65E5",
 | |
|   TOMORROW: "\u660E\u65E5",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\u7D71\u8A08",
 | |
|   MONTH: "Month",
 | |
|   QUARTER: "Quarter",
 | |
|   YEAR: "Year",
 | |
|   LIFETIME: "Lifetime",
 | |
|   FORECAST: "\u4E88\u6E2C",
 | |
|   FORECAST_DESC: "\u5FA9\u7FD2\u671F\u65E5\u304C\u6765\u308B\u30AB\u30FC\u30C9\u306E\u679A\u6570",
 | |
|   SCHEDULED: "\u30B9\u30B1\u30B8\u30E5\u30FC\u30EA\u30F3\u30B0\u6E08\u307F",
 | |
|   DAYS: "\u65E5",
 | |
|   NUMBER_OF_CARDS: "\u30AB\u30FC\u30C9\u6570",
 | |
|   REVIEWS_PER_DAY: "\u5E73\u5747: ${avg}\u30EC\u30D3\u30E5\u30FC/\u65E5",
 | |
|   INTERVALS: "\u9593\u9694",
 | |
|   INTERVALS_DESC: "\u6B21\u306E\u30EC\u30D3\u30E5\u30FC\u4E88\u5B9A\u65E5",
 | |
|   COUNT: "\u30AB\u30A6\u30F3\u30C8",
 | |
|   INTERVALS_SUMMARY: "\u9593\u9694\u306E\u5E73\u5747\u5024: ${avg}, \u6700\u9577\u306E\u9593\u9694: ${longest}",
 | |
|   EASES: "\u6613\u3057\u3055",
 | |
|   EASES_SUMMARY: "\u6613\u3057\u3055\u306E\u5E73\u5747\u5024: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "\u30AB\u30FC\u30C9\u30BF\u30A4\u30D7",
 | |
|   CARD_TYPES_DESC: "\u5EF6\u671F\u306E\u30AB\u30FC\u30C9\u304C\u3042\u308B\u5834\u5408\u306B\u306F\u3053\u308C\u306B\u542B\u307E\u308C\u307E\u3059",
 | |
|   CARD_TYPE_NEW: "\u65B0\u898F",
 | |
|   CARD_TYPE_YOUNG: "\u5FA9\u7FD2(\u521D\u671F)",
 | |
|   CARD_TYPE_MATURE: "\u5FA9\u7FD2(\u5F8C\u671F)",
 | |
|   CARD_TYPES_SUMMARY: "\u30AB\u30FC\u30C9\u306E\u5408\u8A08: ${totalCardsCount}\u679A",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/ko.ts
 | |
| var ko_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "\uB371",
 | |
|   DUE_CARDS: "\uB2E4\uC2DC \uBCFC \uCE74\uB4DC\uB4E4",
 | |
|   NEW_CARDS: "\uC0C8\uB85C\uC6B4 \uCE74\uB4DC\uB4E4",
 | |
|   TOTAL_CARDS: "\uC804\uCCB4 \uCE74\uB4DC\uB4E4",
 | |
|   BACK: "Back",
 | |
|   SKIP: "Skip",
 | |
|   EDIT_CARD: "Edit Card",
 | |
|   RESET_CARD_PROGRESS: "\uCE74\uB4DC\uC758 \uC9C4\uD589\uC0C1\uD669\uC744 \uCD08\uAE30\uD654\uD569\uB2C8\uB2E4.",
 | |
|   HARD: "\uC5B4\uB824\uC6C0(Hard)",
 | |
|   GOOD: "\uC88B\uC74C(Good)",
 | |
|   EASY: "\uC26C\uC6C0(Easy)",
 | |
|   SHOW_ANSWER: "\uC815\uB2F5 \uD655\uC778\uD558\uAE30",
 | |
|   CARD_PROGRESS_RESET: "\uCE74\uB4DC\uC758 \uC9C4\uD589\uC0C1\uD669\uC774 \uCD08\uAE30\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",
 | |
|   SAVE: "Save",
 | |
|   CANCEL: "Cancel",
 | |
|   NO_INPUT: "No input provided.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Current Ease: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Current Interval: ",
 | |
|   CARD_GENERATED_FROM: "Generated from: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "\uB9AC\uBDF0\uD560 \uB178\uD2B8 \uC5F4\uAE30",
 | |
|   REVIEW_CARDS: "\uD50C\uB798\uC2DC\uCE74\uB4DC \uB9AC\uBDF0",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "\uB9AC\uBDF0: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "\uB178\uD2B8\uB97C ${difficulty}\uC73C\uB85C \uB9AC\uBDF0\uD569\uB2C8\uB2E4",
 | |
|   REVIEW_ALL_CARDS: "\uBAA8\uB4E0 \uB178\uD2B8\uB4E4\uC758 \uD50C\uB798\uC2DC\uCE74\uB4DC\uB4E4\uC744 \uB9AC\uBDF0\uD569\uB2C8\uB2E4",
 | |
|   CRAM_ALL_CARDS: "Select a deck to cram",
 | |
|   REVIEW_CARDS_IN_NOTE: "\uC774 \uB178\uD2B8\uC758 \uD50C\uB798\uC2DC\uCE74\uB4DC\uB4E4\uC744 \uB9AC\uBDF0\uD569\uB2C8\uB2E4",
 | |
|   CRAM_CARDS_IN_NOTE: "\uC774 \uB178\uD2B8\uC758 \uD50C\uB798\uC2DC\uCE74\uB4DC\uB4E4\uC744 \uBCBC\uB77D\uCE58\uAE30\uD569\uB2C8\uB2E4.",
 | |
|   VIEW_STATS: "\uD1B5\uACC4 \uD655\uC778",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "--\uB9AC\uBDF0: ${dueNotesCount} \uB178\uD2B8, ${dueFlashcardsCount} \uCE74\uB4DC \uB0A8\uC558\uC2B5\uB2C8\uB2E4.",
 | |
|   SYNC_TIME_TAKEN: "\uB3D9\uAE30\uD654\uC5D0 ${t}\uBC00\uB9AC\uCD08 \uAC78\uB838\uC2B5\uB2C8\uB2E4",
 | |
|   NOTE_IN_IGNORED_FOLDER: "\uB178\uD2B8\uAC00 \uBB34\uC2DC\uB41C \uD3F4\uB354 \uC544\uB798\uC5D0 \uC800\uC7A5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. (\uC124\uC815\uC744 \uD655\uC778\uD574\uC8FC\uC138\uC694)",
 | |
|   PLEASE_TAG_NOTE: "\uB9AC\uBDF0\uB97C \uD558\uAE30\uC704\uD574 \uB178\uD2B8\uC5D0 \uC801\uC808\uD788 \uD0DC\uADF8\uD574\uC8FC\uC138\uC694. (\uC124\uC815\uC744 \uD655\uC778\uD574\uC8FC\uC138\uC694)",
 | |
|   RESPONSE_RECEIVED: "\uC694\uCCAD\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
 | |
|   NO_DECK_EXISTS: "${deckName}\uC774\uB77C\uB294 \uC774\uB984\uC758 \uB371\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
 | |
|   ALL_CAUGHT_UP: "\uBAA8\uB450 \uD655\uC778\uD588\uC2B5\uB2C8\uB2E4. :D",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} \uC77C \uD6C4",
 | |
|   MONTHS_STR_IVL: "${interval} \uAC1C\uC6D4 \uD6C4",
 | |
|   YEARS_STR_IVL: "${interval} \uB144 \uD6C4",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}y",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: '\uB354 \uB9CE\uC740 \uC815\uBCF4\uB97C \uC6D0\uD558\uC2DC\uBA74, <a href="${wikiUrl}">wiki</a>\uB97C \uD655\uC778\uD574\uC8FC\uC138\uC694.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "\uBB34\uC2DC\uD560 \uD3F4\uB354\uB4E4",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "\uD50C\uB798\uC2DC\uCE74\uB4DC",
 | |
|   FLASHCARD_EASY_LABEL: "Easy Button Text",
 | |
|   FLASHCARD_GOOD_LABEL: "Good Button Text",
 | |
|   FLASHCARD_HARD_LABEL: "Hard Button Text",
 | |
|   FLASHCARD_EASY_DESC: 'Customize the label for the "Easy" Button',
 | |
|   FLASHCARD_GOOD_DESC: 'Customize the label for the "Good" Button',
 | |
|   FLASHCARD_HARD_DESC: 'Customize the label for the "Hard" Button',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "\uD50C\uB798\uC2DC\uCE74\uB4DC \uD0DC\uADF8",
 | |
|   FLASHCARD_TAGS_DESC: "\uD0DC\uADF8\uB97C \uACF5\uBC31 \uB610\uB294 \uBE48 \uC904\uB85C \uAD6C\uBD84\uD574\uC11C \uC785\uB825\uD574\uC8FC\uC138\uC694. \uC608) '#flashcards #deck2 #deck3'",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\uD3F4\uB354\uB97C \uB371\uACFC \uC11C\uBE0C\uB371\uC73C\uB85C \uC0AC\uC6A9\uD560\uAE4C\uC694?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "\uC774 \uAE30\uB2A5\uC740 \uC704\uC758 \uD50C\uB798\uC2DC\uCE74\uB4DC \uD0DC\uADF8 \uC635\uC158\uC744 \uB300\uCCB4\uD569\uB2C8\uB2E4.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\uD50C\uB798\uC2DC\uCE74\uB4DC\uC758 \uB9C8\uC9C0\uB9C9 \uC904\uACFC \uB3D9\uC77C\uD55C \uC904\uC5D0 \uC2A4\uCF00\uC904\uB9C1 \uCF54\uBA58\uD2B8\uB97C \uC800\uC7A5\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "\uC774 \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uBA74 HTML \uC8FC\uC11D\uC774 \uBAA9\uB85D\uC758 \uD3EC\uB9E4\uD305\uC744 \uBB34\uB108\uD2B8\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Sibling \uCE74\uB4DC\uB97C \uB2E4\uC74C\uB0A0\uAE4C\uC9C0 \uBB3B\uC5B4\uB450\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Sibling \uCE74\uB4DC\uB294 \uB3D9\uC77C\uD55C \uCE74\uB4DC \uD14D\uC2A4\uD2B8\uC5D0\uC11C \uC0DD\uC131\uB41C \uCE74\uB4DC\uC785\uB2C8\uB2E4. i.e. cloze deletions",
 | |
|   SHOW_CARD_CONTEXT: "\uCE74\uB4DC\uC758 \uBB38\uB9E5(context)\uC744 \uD45C\uC2DC\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "\uCE74\uB4DC\uC5D0\uC11C 'Title > Heading 1 > Subheading > ... > Subheading' \uC758 \uD45C\uC2DC\uB97C \uD560\uC9C0 \uC124\uC815\uD569\uB2C8\uB2E4.",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "\uD50C\uB798\uC2DC\uCE74\uB4DC \uB192\uC774 \uBE44\uC728",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "\uBAA8\uBC14\uC77C \uBC84\uC804 \uD639\uC740 \uB9E4\uC6B0 \uD070 \uC774\uBBF8\uC9C0\uAC00 \uC788\uB294 \uACBD\uC6B0 100%\uB85C \uC124\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.",
 | |
|   RESET_DEFAULT: "\uAE30\uBCF8\uAC12\uC73C\uB85C \uCD08\uAE30\uD654",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\uD50C\uB798\uC2DC\uCE74\uB4DC \uB108\uBE44 \uBE44\uC728",
 | |
|   RANDOMIZE_CARD_ORDER: "\uB9AC\uBDF0\uC911\uC778 \uCE74\uB4DC\uC758 \uC21C\uC11C\uB97C \uB79C\uB364\uC73C\uB85C \uB450\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "\uBE48 \uCE78 \uCC44\uC6B0\uAE30 \uCE74\uB4DC\uB97C \uBE44\uD65C\uC131\uD654\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "==highlights== \uB97C \uBE48 \uCE78 \uCC44\uC6B0\uAE30\uB85C \uC804\uD658\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: '"\uBE48 \uCE78 \uCC44\uC6B0\uAE30 \uD328\uD134" \uC5D0\uC11C <code>${defaultPattern}</code> \uB97C \uCD94\uAC00/\uC81C\uAC70\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "**bolded text** \uB97C \uBE48 \uCE78 \uCC44\uC6B0\uAE30\uB85C \uC804\uD658\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: '"\uBE48 \uCE78 \uCC44\uC6B0\uAE30 \uD328\uD134" \uC5D0\uC11C <code>${defaultPattern}</code> \uB97C \uCD94\uAC00/\uC81C\uAC70\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "{{curly brackets}} \uB97C \uBE48 \uCE78 \uCC44\uC6B0\uAE30\uB85C \uC804\uD658\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: '"\uBE48 \uCE78 \uCC44\uC6B0\uAE30 \uD328\uD134" \uC5D0\uC11C <code>${defaultPattern}</code> \uB97C \uCD94\uAC00/\uC81C\uAC70\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?',
 | |
|   CLOZE_PATTERNS: "\uBE48 \uCE78 \uCC44\uC6B0\uAE30 \uD328\uD134",
 | |
|   CLOZE_PATTERNS_DESC: '\uBE48 \uCE78 \uCC44\uC6B0\uAE30 \uD328\uD134\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694. \uC904\uBC14\uAFC8\uC73C\uB85C \uAD6C\uBD84\uD569\uB2C8\uB2E4. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "\uC778\uB77C\uC778 \uD50C\uB798\uC2DC\uCE74\uB4DC \uAD6C\uBD84\uC790",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "\uC8FC\uC758: \uC774 \uC635\uC158\uC744 \uC218\uC815\uD55C \uD6C4\uC5D0\uB294 \uC774\uBBF8 \uC791\uC131\uB41C \uD50C\uB798\uC2DC\uCE74\uB4DC\uB97C \uC218\uB3D9\uC73C\uB85C \uC218\uC815\uD574\uC57C \uD568\uC744 \uC8FC\uC758\uD558\uC2ED\uC2DC\uC624.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "\uC778\uB77C\uC778 \uBC18\uC804 \uD50C\uB798\uC2DC\uCE74\uB4DC \uAD6C\uBD84\uC790",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\uC5EC\uB7EC \uC904 \uD50C\uB798\uC2DC\uCE74\uB4DC \uAD6C\uBD84\uC790",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\uC5EC\uB7EC \uC904 \uBC18\uC804 \uD50C\uB798\uC2DC\uCE74\uB4DC \uAD6C\uBD84\uC790",
 | |
|   MULTILINE_CARDS_END_MARKER: "\uD074\uB85C\uC988\uC640 \uB2E4\uC911 \uD589 \uD50C\uB798\uC2DC\uCE74\uB4DC\uC758 \uB05D\uC744 \uB098\uD0C0\uB0B4\uB294 \uBB38\uC790",
 | |
|   NOTES: "\uB178\uD2B8",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Enable note review pane on startup",
 | |
|   TAGS_TO_REVIEW: "\uB9AC\uBDF0\uC5D0 \uC0AC\uC6A9\uD560 \uD0DC\uADF8",
 | |
|   TAGS_TO_REVIEW_DESC: "\uD0DC\uADF8\uB97C \uACF5\uBC31 \uB610\uB294 \uBE48 \uC904\uB85C \uAD6C\uBD84\uD574\uC11C \uC785\uB825\uD574\uC8FC\uC138\uC694. \uC608) '#review #tag2 #tag3'",
 | |
|   OPEN_RANDOM_NOTE: "\uB9AC\uBDF0\uB97C \uC704\uD574 \uB79C\uB364 \uB178\uD2B8\uB97C \uC5FD\uB2C8\uB2E4.",
 | |
|   OPEN_RANDOM_NOTE_DESC: "\uC774 \uC635\uC158\uC774 \uAEBC\uC838\uC788\uC73C\uBA74, \uB178\uD2B8\uB294 \uC911\uC694\uB3C4(\uD398\uC774\uC9C0 \uB7AD\uD06C)\uC5D0 \uB530\uB77C \uC815\uB82C\uB429\uB2C8\uB2E4.",
 | |
|   AUTO_NEXT_NOTE: "\uB9AC\uBDF0 \uD6C4\uC5D0 \uB2E4\uC74C \uB178\uD2B8\uB97C \uC790\uB3D9\uC73C\uB85C \uC5FD\uB2C8\uB2E4.",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "\uD30C\uC77C \uBA54\uB274\uC5D0\uC11C \uAC80\uD1A0 \uC635\uC158\uC744 \uD65C\uC131\uD654\uD558\uC138\uC694 (\uC608: \uAC80\uD1A0: \uC26C\uC6C0, \uC88B\uC74C, \uC5B4\uB824\uC6C0)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "\uD30C\uC77C \uBA54\uB274\uC5D0\uC11C \uAC80\uD1A0 \uC635\uC158\uC744 \uBE44\uD65C\uC131\uD654\uD558\uBA74 \uD50C\uB7EC\uADF8\uC778 \uBA85\uB839\uC744 \uC0AC\uC6A9\uD574 \uB178\uD2B8\uB97C \uAC80\uD1A0\uD560 \uC218 \uC788\uC73C\uBA70, \uC815\uC758\uB41C \uACBD\uC6B0\uC5D0\uB294 \uAD00\uB828\uB41C \uB2E8\uCD95\uD0A4\uB3C4 \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "\uC624\uB978\uCABD \uD328\uB110\uC5D0 \uD45C\uC2DC\uD560 \uCD5C\uB300 \uC77C\uC218",
 | |
|   MIN_ONE_DAY: "\uC801\uC5B4\uB3C4 1\uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
 | |
|   VALID_NUMBER_WARNING: "\uC720\uD6A8\uD55C \uC22B\uC790\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\uB371 \uD2B8\uB9AC\uB294 \uCC98\uC74C\uC5D0 \uD655\uC7A5\uB41C \uAC83\uC73C\uB85C \uD45C\uC2DC\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "\uAC19\uC740 \uCE74\uB4DC\uC5D0 \uC911\uCCA9\uB41C \uB371\uC744 \uC811\uC73C\uB824\uBA74 \uC774 \uC635\uC158\uC744 \uB044\uC2ED\uC2DC\uC624. \uAC19\uC740 \uD30C\uC77C\uC5D0 \uC5EC\uB7EC \uB371\uC5D0 \uC18D\uD55C \uCE74\uB4DC\uAC00 \uC788\uB294 \uACBD\uC6B0 \uC720\uC6A9\uD569\uB2C8\uB2E4.",
 | |
|   ALGORITHM: "\uC54C\uACE0\uB9AC\uC998",
 | |
|   CHECK_ALGORITHM_WIKI: '\uB354 \uB9CE\uC740 \uC815\uBCF4\uB97C \uC6D0\uD558\uC2DC\uBA74, <a href="${algoUrl}">algorithm details</a>\uC744 \uD655\uC778\uD574\uC8FC\uC138\uC694.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "\uAE30\uBCF8 ease",
 | |
|   BASE_EASE_DESC: "\uCD5C\uC19F\uAC12 = 130, \uC801\uC815\uCE58\uB294 \uB300\uB7B5 250\uC785\uB2C8\uB2E4.",
 | |
|   BASE_EASE_MIN_WARNING: "\uAE30\uBCF8 ease\uB294 \uC801\uC5B4\uB3C4 130 \uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
 | |
|   LAPSE_INTERVAL_CHANGE: "\uD50C\uB798\uC2DC\uCE74\uB4DC/\uB178\uD2B8\uB97C \uC5B4\uB824\uC6C0(Hard)\uC73C\uB85C \uB9AC\uBDF0\uD588\uC744 \uB54C\uC758 \uAC04\uACA9 \uBCC0\uACBD",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "\uC0C8\uB85C\uC6B4 \uAC04\uACA9 = \uC774\uC804 \uAC04\uACA9 * \uAC04\uACA9\uBCC0\uACBD \uAC12 / 100.",
 | |
|   EASY_BONUS: "\uC26C\uC6C0(Easy) \uBCF4\uB108\uC2A4",
 | |
|   EASY_BONUS_DESC: "\uC26C\uC6C0(Easy) \uBCF4\uB108\uC2A4\uB294 \uD50C\uB798\uC2DC\uCE74\uB4DC/\uB178\uD2B8\uC5D0\uC11C \uC88B\uC74C(Good)\uACFC \uC26C\uC6C0(Easy) \uC0AC\uC774\uC758 \uAC04\uACA9 \uCC28\uC774\uB97C \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. (\uCD5C\uC18C = 100%)",
 | |
|   EASY_BONUS_MIN_WARNING: "\uC26C\uC6C0(Easy) \uBCF4\uB108\uC2A4\uB294 \uC801\uC5B4\uB3C4 100\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maximum interval in days",
 | |
|   MAX_INTERVAL_DESC: "\uAC04\uACA9\uC758 \uC0C1\uD55C\uC120\uC744 \uB458 \uC218 \uC788\uC2B5\uB2C8\uB2E4. (\uAE30\uBCF8\uAC12 = 100\uB144)",
 | |
|   MAX_INTERVAL_MIN_WARNING: "\uCD5C\uB300 \uAC04\uACA9\uC740 \uC801\uC5B4\uB3C4 1\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
 | |
|   MAX_LINK_CONTRIB: "\uCD5C\uB300 \uC5F0\uACB0 \uAE30\uC5EC\uB3C4",
 | |
|   MAX_LINK_CONTRIB_DESC: "\uB9C1\uD06C\uB41C \uB178\uD2B8\uC758 \uCD08\uAE30 ease\uC5D0 \uB300\uD55C \uAC00\uC911\uCE58\uAC00 \uC801\uC6A9\uB41C ease\uC758 \uCD5C\uB300 \uAE30\uC5EC\uB3C4\uC785\uB2C8\uB2E4.",
 | |
|   LOGGING: "\uB85C\uAE45",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\uB514\uBC84\uAE45 \uC815\uBCF4\uB97C \uAC1C\uBC1C\uC790 \uCF58\uC194\uC5D0 \uD45C\uC2DC\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "\uB9AC\uBDF0\uD560 \uB178\uD2B8 \uB300\uAE30\uC5F4",
 | |
|   CLOSE: "\uB2EB\uAE30",
 | |
|   NEW: "New",
 | |
|   YESTERDAY: "\uC5B4\uC81C",
 | |
|   TODAY: "\uC624\uB298",
 | |
|   TOMORROW: "\uB0B4\uC77C",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\uD1B5\uACC4",
 | |
|   MONTH: "\uC6D4",
 | |
|   QUARTER: "\uBD84\uAE30",
 | |
|   YEAR: "\uB144",
 | |
|   LIFETIME: "\uD3C9\uC0DD",
 | |
|   FORECAST: "\uC608\uCE21",
 | |
|   FORECAST_DESC: "\uC774\uD6C4\uC5D0 \uD559\uC2B5\uD560 \uCE74\uB4DC\uC758 \uC218",
 | |
|   SCHEDULED: "Scheduled",
 | |
|   DAYS: "\uC77C",
 | |
|   NUMBER_OF_CARDS: "\uCE74\uB4DC\uC758 \uC218",
 | |
|   REVIEWS_PER_DAY: "\uD3C9\uADE0: ${avg} \uB9AC\uBDF0/\uC77C",
 | |
|   INTERVALS: "\uAC04\uACA9",
 | |
|   INTERVALS_DESC: "\uB9AC\uBDF0\uB97C \uB2E4\uC2DC \uD560 \uB54C \uAE4C\uC9C0\uC758 \uAE30\uAC04",
 | |
|   COUNT: "Count",
 | |
|   INTERVALS_SUMMARY: "\uD3C9\uADE0 \uAC04\uACA9: ${avg}, \uAC00\uC7A5 \uAE34 \uAC04\uACA9: ${longest}",
 | |
|   EASES: "Eases",
 | |
|   EASES_SUMMARY: "Average ease: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "\uCE74\uB4DC \uD0C0\uC785",
 | |
|   CARD_TYPES_DESC: "\uC5EC\uAE30\uC5D0\uB294 \uBB3B\uC5B4\uB454 \uCE74\uB4DC\uB3C4 \uD3EC\uD568\uB429\uB2C8\uB2E4.",
 | |
|   CARD_TYPE_NEW: "New",
 | |
|   CARD_TYPE_YOUNG: "Young",
 | |
|   CARD_TYPE_MATURE: "Mature",
 | |
|   CARD_TYPES_SUMMARY: "\uC804\uCCB4 \uCE74\uB4DC \uC218: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/mr.ts
 | |
| var mr_default = {};
 | |
| 
 | |
| // src/lang/locale/nl.ts
 | |
| var nl_default = {};
 | |
| 
 | |
| // src/lang/locale/no.ts
 | |
| var no_default = {};
 | |
| 
 | |
| // src/lang/locale/pl.ts
 | |
| var pl_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Talie",
 | |
|   DUE_CARDS: "Fiszki z terminem",
 | |
|   NEW_CARDS: "Nowe fiszki",
 | |
|   TOTAL_CARDS: "Wszystkie karty",
 | |
|   BACK: "Wstecz",
 | |
|   SKIP: "Pomi\u0144",
 | |
|   EDIT_CARD: "Edytuj kart\u0119",
 | |
|   RESET_CARD_PROGRESS: "Zresetuj post\u0119p karty",
 | |
|   HARD: "Trudne",
 | |
|   GOOD: "\u015Arednio Trudne",
 | |
|   EASY: "\u0141atwe",
 | |
|   SHOW_ANSWER: "Poka\u017C odpowied\u017A",
 | |
|   CARD_PROGRESS_RESET: "Post\u0119p karty zosta\u0142 zresetowany.",
 | |
|   SAVE: "Zapisz",
 | |
|   CANCEL: "Anuluj",
 | |
|   NO_INPUT: "Nie wprowadzono warto\u015Bci.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Aktualna \u0142atwo\u015B\u0107: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Aktualny interwa\u0142: ",
 | |
|   CARD_GENERATED_FROM: "Wygenerowano z: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Otw\xF3rz notatk\u0119 do przegl\u0105du",
 | |
|   REVIEW_CARDS: "Przegl\u0105daj fiszki",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Przegl\u0105daj: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Przegl\u0105daj notatk\u0119 jako ${difficulty}",
 | |
|   CRAM_ALL_CARDS: "Wybierz tali\u0119 do intensywnego uczenia",
 | |
|   REVIEW_ALL_CARDS: "Przegl\u0105daj fiszki ze wszystkich notatek",
 | |
|   REVIEW_CARDS_IN_NOTE: "Przegl\u0105daj fiszki w tej notatce",
 | |
|   CRAM_CARDS_IN_NOTE: "Intensywne uczenie fiszek w tej notatce",
 | |
|   VIEW_STATS: "Wy\u015Bwietl statystyki",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "Przegl\u0105daj: ${dueNotesCount} notatek, ${dueFlashcardsCount} fiszek z terminem",
 | |
|   SYNC_TIME_TAKEN: "Synchronizacja zaj\u0119\u0142a ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "Notatka jest zapisana w folderze zignorowanym (sprawd\u017A ustawienia).",
 | |
|   PLEASE_TAG_NOTE: "Prosz\u0119 odpowiednio otagowa\u0107 notatk\u0119 do przegl\u0105du (w ustawieniach).",
 | |
|   RESPONSE_RECEIVED: "Otrzymano odpowied\u017A.",
 | |
|   NO_DECK_EXISTS: "Nie istnieje talia o nazwie ${deckName}",
 | |
|   ALL_CAUGHT_UP: "Jeste\u015B teraz na bie\u017C\u0105co :D.",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} dni",
 | |
|   MONTHS_STR_IVL: "${interval} miesi\u0119cy",
 | |
|   YEARS_STR_IVL: "${interval} lata",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}r",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'Aby uzyska\u0107 wi\u0119cej informacji, sprawd\u017A <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Foldery do zignorowania",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Fiszki",
 | |
|   FLASHCARD_EASY_LABEL: "Tekst przycisku \u0141atwe",
 | |
|   FLASHCARD_GOOD_LABEL: "Tekst przycisku \u015Arednio trudne",
 | |
|   FLASHCARD_HARD_LABEL: "Tekst przycisku Trudne",
 | |
|   FLASHCARD_EASY_DESC: 'Dostosuj etykiet\u0119 dla przycisku "\u0141atwe"',
 | |
|   FLASHCARD_GOOD_DESC: 'Dostosuj etykiet\u0119 dla przycisku "\u015Arednio trudne"',
 | |
|   FLASHCARD_HARD_DESC: 'Dostosuj etykiet\u0119 dla przycisku "Trudne"',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Tagi fiszek",
 | |
|   FLASHCARD_TAGS_DESC: "Wprowad\u017A tagi oddzielone spacj\u0105 lub nowymi liniami, np. #fiszki #talia2 #talia3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Czy konwertowa\u0107 foldery na talie i podtalie?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Jest to alternatywa dla opcji tag\xF3w fiszek powy\u017Cej.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Czy zachowa\u0107 komentarz harmonogramowania w tej samej linii co ostatnia linia fiszki?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "W\u0142\u0105czenie tej opcji sprawi, \u017Ce komentarze HTML nie b\u0119d\u0105 przerywa\u0107 formatowania listy.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Czy ukrywa\u0107 karty rodze\u0144stwa do nast\u0119pnego dnia?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Rodze\u0144stwo to karty wygenerowane z tego samego tekstu karty, np. usuni\u0119cia zamaskowane",
 | |
|   SHOW_CARD_CONTEXT: "Czy pokazywa\u0107 kontekst na kartach?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "np. Tytu\u0142 > Nag\u0142\xF3wek 1 > Podnag\u0142\xF3wek > ... > Podnag\u0142\xF3wek",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Procentowa wysoko\u015B\u0107 fiszki",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Powinno by\u0107 ustawione na 100% na urz\u0105dzeniach mobilnych lub gdy masz bardzo du\u017Ce obrazy",
 | |
|   RESET_DEFAULT: "Zresetuj do domy\u015Blnych",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Procentowa szeroko\u015B\u0107 fiszki",
 | |
|   RANDOMIZE_CARD_ORDER: "Czy losowa\u0107 kolejno\u015B\u0107 kart podczas przegl\u0105du?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Kolejno\u015B\u0107 kart w talii wy\u015Bwietlana podczas przegl\u0105dania",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Kolejno w ramach talii (Najpierw wszystkie nowe karty)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Kolejno w ramach talii (Najpierw wszystkie karty z terminem)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Losowo w ramach talii (Najpierw wszystkie nowe karty)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Losowo w ramach talii (Najpierw wszystkie karty z terminem)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Losowa karta z losowej talii",
 | |
|   REVIEW_DECK_ORDER: "Kolejno\u015B\u0107 talii wy\u015Bwietlana podczas przegl\u0105dania",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Kolejno (gdy wszystkie karty w poprzedniej talii przegl\u0105dni\u0119te)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Losowo (gdy wszystkie karty w poprzedniej talii przegl\u0105dni\u0119te)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Losowa karta z losowej talii",
 | |
|   DISABLE_CLOZE_CARDS: "Wy\u0142\u0105czy\u0107 karty zamaskowane?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "Konwertowa\u0107 ==pod\u015Bwietlenia== na karty zamaskowane?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'Dodaj/usu\u0144 <code>${defaultPattern}</code> z "Wzory kart zamaskowanych"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "Konwertowa\u0107 pogrubiony tekst na karty zamaskowane?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'Dodaj/usu\u0144 <code>${defaultPattern}</code> z "Wzory kart zamaskowanych"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "Konwertowa\u0107 {{klamry}} na karty zamaskowane?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'Dodaj/usu\u0144 <code>${defaultPattern}</code> z "Wzory kart zamaskowanych"',
 | |
|   CLOZE_PATTERNS: "Wzory kart zamaskowanych",
 | |
|   CLOZE_PATTERNS_DESC: 'Wprowad\u017A wzory kart zamaskowanych oddzielone nowymi liniami. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Separator dla kart zamaskowanych w linii",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Pami\u0119taj, \u017Ce po zmianie tego musisz r\u0119cznie edytowa\u0107 wszystkie karty zamaskowane, kt\xF3re ju\u017C masz.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Separator dla kart zamaskowanych odwr\xF3conych w linii",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Separator dla kart zamaskowanych wieloliniowych",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Separator dla kart zamaskowanych odwr\xF3conych wieloliniowych",
 | |
|   MULTILINE_CARDS_END_MARKER: "Caracteres que denotam o fim de clozes e flashcards multilineares",
 | |
|   NOTES: "Notatki",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "W\u0142\u0105czy\u0107 panel przegl\u0105du notatek przy starcie",
 | |
|   TAGS_TO_REVIEW: "Tagi do przegl\u0105du",
 | |
|   TAGS_TO_REVIEW_DESC: "Wprowad\u017A tagi oddzielone spacj\u0105 lub nowymi liniami, np. #przegl\u0105d #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "Otw\xF3rz losow\u0105 notatk\u0119 do przegl\u0105du",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Po wy\u0142\u0105czeniu tej opcji notatki s\u0105 uporz\u0105dkowane wed\u0142ug istotno\u015Bci (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Automatycznie otwiera\u0107 nast\u0119pn\u0105 notatk\u0119 po przegl\u0105dzie",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Wy\u0142\u0105czy\u0107 opcje przegl\u0105du w menu pliku, tj. Przegl\u0105daj: \u0141atwe Dobrze Trudne",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "Je\u015Bli wy\u0142\u0105czysz opcje przegl\u0105du w menu Plik, mo\u017Cesz przegl\u0105da\u0107 swoje notatki za pomoc\u0105 polece\u0144 wtyczki i, je\u015Bli je zdefiniowa\u0142e\u015B, przypisanych skr\xF3t\xF3w klawiszowych.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Maksymalna liczba dni do wy\u015Bwietlenia w panelu prawym",
 | |
|   MIN_ONE_DAY: "Liczba dni musi wynosi\u0107 co najmniej 1.",
 | |
|   VALID_NUMBER_WARNING: "Podaj prawid\u0142ow\u0105 liczb\u0119.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Podtalie powinny by\u0107 pocz\u0105tkowo wy\u015Bwietlane rozszerzone",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Wy\u0142\u0105cz to, aby zwin\u0105\u0107 zagnie\u017Cd\u017Cone talie w tej samej karcie. Przydatne, je\u015Bli karty nale\u017C\u0105 do wielu talii w tym samym pliku.",
 | |
|   ALGORITHM: "Algorytm",
 | |
|   CHECK_ALGORITHM_WIKI: 'Aby uzyska\u0107 wi\u0119cej informacji, sprawd\u017A <a href="${algoUrl}">implementacj\u0119 algorytmu</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Podstawowa \u0142atwo\u015B\u0107",
 | |
|   BASE_EASE_DESC: "minimum = 130, preferowana warto\u015B\u0107 to oko\u0142o 250.",
 | |
|   BASE_EASE_MIN_WARNING: "Podstawowa \u0142atwo\u015B\u0107 musi wynosi\u0107 co najmniej 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Zmiana interwa\u0142u podczas przegl\u0105dania fiszki/notatki jako trudne",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "nowyInterwa\u0142 = staryInterwa\u0142 * zmianaInterwa\u0142u / 100.",
 | |
|   EASY_BONUS: "Bonus za \u0142atwe",
 | |
|   EASY_BONUS_DESC: "Bonus za \u0142atwe pozwala ustawi\u0107 r\xF3\u017Cnic\u0119 w interwa\u0142ach mi\u0119dzy odpowiedziami \u015Arednio trudne i \u0141atwe na fiszce/notatce (minimum = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "Bonus za \u0142atwe musi wynosi\u0107 co najmniej 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maksymalny interwa\u0142 w dniach",
 | |
|   MAX_INTERVAL_DESC: "Pozwala na ustawienie g\xF3rnego limitu interwa\u0142u (domy\u015Blnie = 100 lat).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "Maksymalny interwa\u0142 musi wynosi\u0107 co najmniej 1 dzie\u0144.",
 | |
|   MAX_LINK_CONTRIB: "Maksymalny wk\u0142ad \u0142\u0105cza",
 | |
|   MAX_LINK_CONTRIB_DESC: "Maksymalny wk\u0142ad wa\u017Conej \u0142atwo\u015Bci po\u0142\u0105czonych notatek do pocz\u0105tkowej \u0142atwo\u015Bci.",
 | |
|   LOGGING: "Logowanie",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Wy\u015Bwietl informacje debugowania w konsoli deweloperskiej",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Kolejka przegl\u0105du notatek",
 | |
|   CLOSE: "Zamknij",
 | |
|   NEW: "Nowe",
 | |
|   YESTERDAY: "Wczoraj",
 | |
|   TODAY: "Dzisiaj",
 | |
|   TOMORROW: "Jutro",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Statystyki",
 | |
|   MONTH: "Miesi\u0105c",
 | |
|   QUARTER: "Kwarta\u0142",
 | |
|   YEAR: "Rok",
 | |
|   LIFETIME: "Ca\u0142e \u017Cycie",
 | |
|   FORECAST: "Prognoza",
 | |
|   FORECAST_DESC: "Liczba kart z terminem w przysz\u0142o\u015Bci",
 | |
|   SCHEDULED: "Zaplanowane",
 | |
|   DAYS: "Dni",
 | |
|   NUMBER_OF_CARDS: "Liczba kart",
 | |
|   REVIEWS_PER_DAY: "\u015Arednio: ${avg} przegl\u0105d\xF3w/dzie\u0144",
 | |
|   INTERVALS: "Interwa\u0142y",
 | |
|   INTERVALS_DESC: "Op\xF3\u017Anienia przed ponownym pokazaniem przegl\u0105d\xF3w",
 | |
|   COUNT: "Liczba",
 | |
|   INTERVALS_SUMMARY: "\u015Aredni interwa\u0142: ${avg}, Najd\u0142u\u017Cszy interwa\u0142: ${longest}",
 | |
|   EASES: "\u0141atwo\u015Bci",
 | |
|   EASES_SUMMARY: "\u015Arednia \u0142atwo\u015B\u0107: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Typy kart",
 | |
|   CARD_TYPES_DESC: "Obejmuje tak\u017Ce ukryte karty, je\u015Bli takie s\u0105",
 | |
|   CARD_TYPE_NEW: "Nowe",
 | |
|   CARD_TYPE_YOUNG: "M\u0142ode",
 | |
|   CARD_TYPE_MATURE: "Stare",
 | |
|   CARD_TYPES_SUMMARY: "\u0141\u0105czna liczba kart: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/pt.ts
 | |
| var pt_default = {};
 | |
| 
 | |
| // src/lang/locale/pt-br.ts
 | |
| var pt_br_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Baralhos",
 | |
|   DUE_CARDS: "Cartas para Colocar em Dia",
 | |
|   NEW_CARDS: "Novas Cartas",
 | |
|   TOTAL_CARDS: "Total de Cartas",
 | |
|   BACK: "Voltar",
 | |
|   SKIP: "Pular",
 | |
|   EDIT_CARD: "Editar Cart\xE3o",
 | |
|   RESET_CARD_PROGRESS: "Reiniciar o Progresso da Carta",
 | |
|   HARD: "Dif\xEDcil",
 | |
|   GOOD: "OK",
 | |
|   EASY: "F\xE1cil",
 | |
|   SHOW_ANSWER: "Mostrar Resposta",
 | |
|   CARD_PROGRESS_RESET: "O Progresso da Carta foi reiniciado",
 | |
|   SAVE: "Salvar",
 | |
|   CANCEL: "Cancelar",
 | |
|   NO_INPUT: "Nenhuma entrada fornecida.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Facilidade atual: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Intervalo atual: ",
 | |
|   CARD_GENERATED_FROM: "Gerada a partir de: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "Abrir uma nota para revisar",
 | |
|   REVIEW_CARDS: "Revisar flashcards",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "Revis\xE3o: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Revisar nota como ${difficulty}",
 | |
|   REVIEW_ALL_CARDS: "Revisar flashcards de todas as notas",
 | |
|   CRAM_ALL_CARDS: "Selecione um baralho para revisar",
 | |
|   REVIEW_CARDS_IN_NOTE: "Revisar flashcards nessa nota",
 | |
|   CRAM_CARDS_IN_NOTE: "Revisar todas as flashcards nessa nota",
 | |
|   VIEW_STATS: "Ver estat\xEDsticas",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "Revis\xE3o: ${dueNotesCount} nota(s), ${dueFlashcardsCount} Carta(s) para colocar em dia",
 | |
|   SYNC_TIME_TAKEN: "Sincroniza\xE7\xE3o levou ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "Nota \xE9 salva na pasta ignorada (cheque as configura\xE7\xF5es).",
 | |
|   PLEASE_TAG_NOTE: "Por favor etiquete a nota apropriadamente para revisar (nas configura\xE7\xF5es).",
 | |
|   RESPONSE_RECEIVED: "Resposta recebida.",
 | |
|   NO_DECK_EXISTS: "Nenhum baralho existe para ${deckName}",
 | |
|   ALL_CAUGHT_UP: "Voc\xEA colocou tudo em dia agora :D.",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} dia(s)",
 | |
|   MONTHS_STR_IVL: "${interval} m\xEAs(es)",
 | |
|   YEARS_STR_IVL: "${interval} ano(s)",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}d",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}m",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}a",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: 'Para mais informa\xE7\xF5es, cheque a <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "Pastas para ignorar",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Flashcards",
 | |
|   FLASHCARD_EASY_LABEL: "Texto do Bot\xE3o de F\xE1cil",
 | |
|   FLASHCARD_GOOD_LABEL: "Texto do Bot\xE3o de OK",
 | |
|   FLASHCARD_HARD_LABEL: "Texto do Bot\xE3o de Dif\xEDcil",
 | |
|   FLASHCARD_EASY_DESC: 'Customize o r\xF3tulo para o bot\xE3o de "F\xE1cil"',
 | |
|   FLASHCARD_GOOD_DESC: 'Customize o r\xF3tulo para o bot\xE3o de "OK"',
 | |
|   FLASHCARD_HARD_DESC: 'Customize o r\xF3tulo para o bot\xE3o de "Dif\xEDcil"',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Etiquetas dos Flashcards",
 | |
|   FLASHCARD_TAGS_DESC: "Insira etiquetas separadas por espa\xE7os ou quebras de linha ex: #flashcards #baralho2 #baralho3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Converter pastas para baralhos e sub-baralhos?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Isso \xE9 uma alternativa para a op\xE7\xE3o de etiqueta dos Flashcards em cima.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Salvar coment\xE1rios de agendamento na mesma linha que a \xFAltima linha do flashcard?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Ligar isso vai fazer com que os coment\xE1rios em HTML n\xE3o quebrem a formata\xE7\xE3o de listas.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Enterrar cartas irm\xE3s at\xE9 o pr\xF3ximo dia?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Cartas irm\xE3s s\xE3o geradas pelo texto da mesma carta ex: omiss\xE3o de palavras",
 | |
|   SHOW_CARD_CONTEXT: "Mostrar contexto nas cartas?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "ex: T\xEDtulo > Cabe\xE7alho 1 > Subcabe\xE7alho > ... > Subcabe\xE7alho",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Porcentagem da Altura do Flashcard",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Deveria estar configurado em 100% em dispositivos m\xF3veis ou se voc\xEA tem imagens muito grandes",
 | |
|   RESET_DEFAULT: "Reiniciar para a pr\xE9-defini\xE7\xE3o",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Porcentagem de Largura do Flashcard",
 | |
|   RANDOMIZE_CARD_ORDER: "Aleatorizar a ordem das cartas durante a revis\xE3o?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "Order cards in a deck are displayed during review",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "Sequentially within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "Sequentially within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Randomly within a deck (All new cards first)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Randomly within a deck (All due cards first)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   REVIEW_DECK_ORDER: "Order decks are displayed during review",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "Sequentially (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Randomly (once all cards in previous deck reviewed)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
 | |
|   DISABLE_CLOZE_CARDS: "Desabilitar cartas que usam omiss\xE3o de palavras?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "Converter ==marca-texto== em omiss\xF5es?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: 'Adiciona/remove o <code>${defaultPattern}</code> dos seus "Padr\xF5es de Omiss\xE3o"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "Converter **texto em negrito** em omiss\xF5es?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: 'Adiciona/remove o <code>${defaultPattern}</code> dos seus "Padr\xF5es de Omiss\xE3o"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "Converter {{chaves}} em omiss\xF5es?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: 'Adiciona/remove o <code>${defaultPattern}</code> dos seus "Padr\xF5es de Omiss\xE3o"',
 | |
|   CLOZE_PATTERNS: "Padr\xF5es de Omiss\xE3o",
 | |
|   CLOZE_PATTERNS_DESC: 'Entre os padr\xF5es de omiss\xE3o separados por quebras de linha. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Separador para flashcards inline",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Note que depois de mudar isso voc\xEA vai ter que manualmente mudar quaisquer flashcards que voc\xEA tenha.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Separador para flashcards inline reversos",
 | |
|   MULTILINE_CARDS_SEPARATOR: "Separador para flashcards de m\xFAltiplas linhas",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "Separador para flashcards de m\xFAltiplas linhas reversos",
 | |
|   MULTILINE_CARDS_END_MARKER: "Caracteres que denotam o fim de clozes e flashcards multilinha",
 | |
|   NOTES: "Notas",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Habilitar painel de revis\xE3o de notas na inicializa\xE7\xE3o",
 | |
|   TAGS_TO_REVIEW: "Etiquetas para revisar",
 | |
|   TAGS_TO_REVIEW_DESC: "Insira etiquetas separadas por espa\xE7os ou quebra de linhas ex: #revisar #etiqueta2 #etiqueta3.",
 | |
|   OPEN_RANDOM_NOTE: "Abrir uma nota aleat\xF3ria para revisar",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Quando voc\xEA desabilitar isso, as notas v\xE3o ser ordenadas por import\xE2ncia (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Abrir a pr\xF3xima nota automaticamente depois de uma revis\xE3o",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Ative as op\xE7\xF5es de revis\xE3o no menu Arquivo (ex.: Revis\xE3o: F\xE1cil, OK, Dif\xEDcil)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "Se voc\xEA desativar as op\xE7\xF5es de revis\xE3o no menu Arquivo, poder\xE1 revisar suas anota\xE7\xF5es usando os comandos do plugin e, se os tiver definido, as teclas de atalho associadas.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "N\xFAmero m\xE1ximo de dias para exibir no painel direito",
 | |
|   MIN_ONE_DAY: "O n\xFAmero de dias deve ser pelo menos 1.",
 | |
|   VALID_NUMBER_WARNING: "Por favor Insira um n\xFAmero v\xE1lido.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\xC1rvores de baralhos devem inicialmente ser exibidas como expandidas",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Desabilite isso para colapsar baralhos que est\xE3o um dentro do outro na mesma carta. \xDAtil se voc\xEA tem cartas que pertencem a muitos baralhos em um mesmo arquivo.",
 | |
|   ALGORITHM: "Algor\xEDtmo",
 | |
|   CHECK_ALGORITHM_WIKI: 'Para mais informa\xE7\xF5es, cheque a <a href="${algoUrl}">implementa\xE7\xE3o do algor\xEDtmo</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Facilidade base",
 | |
|   BASE_EASE_DESC: "m\xEDnimo = 130, preferivelmente por volta de 250.",
 | |
|   BASE_EASE_MIN_WARNING: "A facilidade base deve ser pelo menos 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Mudan\xE7a de intervalo quando voc\xEA revisa um(a) flashcard/nota como dif\xEDcil",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "novoIntervalo = velhoIntervalo * mudancaIntervalo / 100.",
 | |
|   EASY_BONUS: "B\xF4nus de F\xE1cil",
 | |
|   EASY_BONUS_DESC: "O b\xF4nus de f\xE1cil te permite mudar a difer\xEAncia entre intervalos de responder OK e F\xE1cil em um(a) flashcard/nota (m\xEDnimo = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: "O b\xF4nus de f\xE1cil deve ser pelo menos 100.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Intervalo m\xE1ximo em dias",
 | |
|   MAX_INTERVAL_DESC: "Te permite colocar um limite m\xE1ximo no intervalo (pr\xE9-defini\xE7\xE3o = 100 anos).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "O intervalo m\xE1ximo deve ser pelo menos 1 dia.",
 | |
|   MAX_LINK_CONTRIB: "Contribui\xE7\xE3o M\xE1xima de Links",
 | |
|   MAX_LINK_CONTRIB_DESC: "Contribui\xE7\xE3o m\xE1xima da facilidade ponderada das notas linkadas \xE0 facilidade inicial.",
 | |
|   LOGGING: "Logging",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Mostrar informa\xE7\xE3o de debugging no console de desenvolvimento",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Fila de Notas para Revisar",
 | |
|   CLOSE: "Fechar",
 | |
|   NEW: "Novo",
 | |
|   YESTERDAY: "Ontem",
 | |
|   TODAY: "Hoje",
 | |
|   TOMORROW: "Amanh\xE3",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "Estat\xEDsticas",
 | |
|   MONTH: "M\xEAs",
 | |
|   QUARTER: "Trimestre",
 | |
|   YEAR: "Ano",
 | |
|   LIFETIME: "Tempo Total",
 | |
|   FORECAST: "Previs\xE3o",
 | |
|   FORECAST_DESC: "O n\xFAmero de cartas a serem colocadas em dia no futuro",
 | |
|   SCHEDULED: "Agendado",
 | |
|   DAYS: "Dias",
 | |
|   NUMBER_OF_CARDS: "N\xFAmero de cartas",
 | |
|   REVIEWS_PER_DAY: "M\xE9dia: ${avg} revis\xF5es/dia",
 | |
|   INTERVALS: "Intervalos",
 | |
|   INTERVALS_DESC: "Atrasos at\xE9 que as revis\xF5es sejam exibidas de novo",
 | |
|   COUNT: "Contagem",
 | |
|   INTERVALS_SUMMARY: "Intervalo em m\xE9dia: ${avg}, Maior intervalo: ${longest}",
 | |
|   EASES: "Facilidades",
 | |
|   EASES_SUMMARY: "Facilidade em m\xE9dia: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Tipos de Cartas",
 | |
|   CARD_TYPES_DESC: "Isso tamb\xE9m inclui cartas enterradas, caso existam",
 | |
|   CARD_TYPE_NEW: "Novo",
 | |
|   CARD_TYPE_YOUNG: "Jovem",
 | |
|   CARD_TYPE_MATURE: "Amadurecido",
 | |
|   CARD_TYPES_SUMMARY: "Total de cartas: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/ro.ts
 | |
| var ro_default = {};
 | |
| 
 | |
| // src/lang/locale/ru.ts
 | |
| var ru_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "\u041A\u043E\u043B\u043E\u0434\u044B",
 | |
|   DUE_CARDS: "\u041F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u043C\u044B\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   NEW_CARDS: "\u041D\u043E\u0432\u044B\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   TOTAL_CARDS: "\u0412\u0441\u0435\u0433\u043E \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   BACK: "\u041D\u0430\u0437\u0430\u0434",
 | |
|   SKIP: "\u041F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C",
 | |
|   EDIT_CARD: "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0443",
 | |
|   RESET_CARD_PROGRESS: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   HARD: "\u0421\u043B\u043E\u0436\u043D\u043E",
 | |
|   GOOD: "\u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E",
 | |
|   EASY: "\u041B\u0435\u0433\u043A\u043E",
 | |
|   SHOW_ANSWER: "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043E\u0442\u0432\u0435\u0442",
 | |
|   CARD_PROGRESS_RESET: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441 \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   SAVE: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C",
 | |
|   CANCEL: "\u041E\u0442\u043C\u0435\u043D\u0430",
 | |
|   NO_INPUT: "\u041F\u0443\u0441\u0442\u043E\u0439 \u0432\u0432\u043E\u0434.",
 | |
|   CURRENT_EASE_HELP_TEXT: "\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B: ",
 | |
|   CARD_GENERATED_FROM: "\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E \u0438\u0437: ${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0437\u0430\u043C\u0435\u0442\u043A\u0443 \u0434\u043B\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F",
 | |
|   REVIEW_CARDS: "\u0418\u0437\u0443\u0447\u0430\u0442\u044C \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "\u0418\u0437\u0443\u0447\u0435\u043D\u0438\u0435: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "\u0418\u0437\u0443\u0447\u0430\u0442\u044C \u0437\u0430\u043C\u0435\u0442\u043A\u0443 \u043A\u0430\u043A ${difficulty}",
 | |
|   CRAM_ALL_CARDS: "\u0417\u0443\u0431\u0440\u0438\u0442\u044C \u0432\u0441\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0432 \u044D\u0442\u043E\u0439 \u043A\u043E\u043B\u043E\u0434\u0435",
 | |
|   REVIEW_ALL_CARDS: "\u0418\u0437\u0443\u0447\u0430\u0442\u044C \u0432\u0441\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0432\u043E \u0432\u0441\u0435\u0445 \u0437\u0430\u043C\u0435\u0442\u043A\u0430\u0445",
 | |
|   REVIEW_CARDS_IN_NOTE: "\u0418\u0437\u0443\u0447\u0430\u0442\u044C \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0432 \u044D\u0442\u043E\u0439 \u0437\u0430\u043C\u0435\u0442\u043A\u0435",
 | |
|   CRAM_CARDS_IN_NOTE: "\u0417\u0443\u0431\u0440\u0438\u0442\u044C \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0432 \u044D\u0442\u043E\u0439 \u0437\u0430\u043C\u0435\u0442\u043A\u0435",
 | |
|   VIEW_STATS: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u044F \u0437\u0430\u043C\u0435\u0442\u043E\u043A \u043D\u0430 \u0431\u043E\u043A\u043E\u0432\u043E\u0439 \u043F\u0430\u043D\u0435\u043B\u0438",
 | |
|   STATUS_BAR: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C: ${dueNotesCount} \u0437\u0430\u043C\u0435\u0442\u043E\u043A, ${dueFlashcardsCount} \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   SYNC_TIME_TAKEN: "\u0421\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u044F \u0437\u0430\u043D\u044F\u043B\u0430 ${t}\u043C\u0441",
 | |
|   NOTE_IN_IGNORED_FOLDER: "\u0417\u0430\u043C\u0435\u0442\u043A\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430 \u0432 \u0438\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u043C\u0443\u044E \u043F\u0430\u043F\u043A\u0443 (\u0441\u043C. \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438).",
 | |
|   PLEASE_TAG_NOTE: "\u0414\u043B\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u043F\u043E\u043C\u0435\u0442\u044C\u0442\u0435 \u0437\u0430\u043C\u0435\u0442\u043A\u0443 \u0442\u0435\u0433\u043E\u043C (\u0441\u043C. \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438).",
 | |
|   RESPONSE_RECEIVED: "\u041E\u0442\u0432\u0435\u0442 \u043F\u043E\u043B\u0443\u0447\u0435\u043D.",
 | |
|   NO_DECK_EXISTS: "\u041D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0443\u0440\u043E\u0432\u043D\u044F ${deckName}",
 | |
|   ALL_CAUGHT_UP: "\u041C\u043E\u043B\u043E\u0434\u0435\u0446! \u0422\u044B \u0441\u043F\u0440\u0430\u0432\u0438\u043B\u0441\u044F \u0438 \u0434\u043E\u0448\u0435\u043B \u0434\u043E \u043A\u043E\u043D\u0446\u0430! :D",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} \u0434\u043D\u0435\u0439",
 | |
|   MONTHS_STR_IVL: "${interval} \u043C\u0435\u0441\u044F\u0446\u0435\u0432",
 | |
|   YEARS_STR_IVL: "${interval} \u0433\u043E\u0434\u043E\u0432",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}\u0434.",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}\u043C.",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}\u0433.",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Spaced Repetition",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: '\u0414\u043B\u044F \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0439 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u043F\u043E\u0441\u0435\u0442\u0438\u0442\u0435: <a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "\u0418\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u043C\u044B\u0435 \u043F\u0430\u043F\u043A\u0438",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "\u041A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   FLASHCARD_EASY_LABEL: '\u0422\u0435\u043A\u0441\u0442 \u043A\u043D\u043E\u043F\u043A\u0438 "\u041B\u0435\u0433\u043A\u043E"',
 | |
|   FLASHCARD_GOOD_LABEL: '\u0422\u0435\u043A\u0441\u0442 \u043A\u043D\u043E\u043F\u043A\u0438 "\u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E"',
 | |
|   FLASHCARD_HARD_LABEL: '\u0422\u0435\u043A\u0441\u0442 \u043A\u043D\u043E\u043F\u043A\u0438 "\u0421\u043B\u043E\u0436\u043D\u043E"',
 | |
|   FLASHCARD_EASY_DESC: '\u041D\u0430\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u044F\u0440\u043B\u044B\u043A \u0434\u043B\u044F \u043A\u043D\u043E\u043F\u043A\u0438 "\u041B\u0435\u0433\u043A\u043E"',
 | |
|   FLASHCARD_GOOD_DESC: '\u041D\u0430\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u044F\u0440\u043B\u044B\u043A \u0434\u043B\u044F \u043A\u043D\u043E\u043F\u043A\u0438 "\u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E"',
 | |
|   FLASHCARD_HARD_DESC: '\u041D\u0430\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u044F\u0440\u043B\u044B\u043A \u0434\u043B\u044F \u043A\u043D\u043E\u043F\u043A\u0438 "\u0421\u043B\u043E\u0436\u043D\u043E"',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "\u0422\u0435\u0433\u0438 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   FLASHCARD_TAGS_DESC: "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0442\u0435\u0433\u0438 \u0440\u0430\u0437\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0435 Enter-\u043E\u043C \u0438\u043B\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u043C, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: #flashcards #deck2 #deck3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u0430\u043F\u043A\u0438 \u0432 \u0443\u0440\u043E\u0432\u043D\u0438 \u0438 \u043F\u043E\u0434\u0443\u0440\u043E\u0432\u043D\u0438?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "\u042D\u0442\u043E \u0430\u043B\u044C\u0442\u0435\u0440\u043D\u0430\u0442\u0438\u0432\u0430 \u043E\u043F\u0438\u0441\u0430\u043D\u043D\u043E\u043C\u0443 \u0432\u044B\u0448\u0435 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u0443 \u0442\u0435\u0433\u043E\u0432 \u0444\u043B\u044D\u0448-\u043A\u0430\u0440\u0442",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\u0421\u043E\u0445\u0440\u0430\u043D\u044F\u0442\u044C \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043F\u043B\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u043D\u0430 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0439 \u0441\u0442\u0440\u043E\u043A\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "\u0412\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u044D\u0442\u043E\u0439 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0441\u0434\u0435\u043B\u0430\u0435\u0442 \u0442\u0430\u043A, \u0447\u0442\u043E HTML \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 \u043D\u0435 \u0431\u0443\u0434\u0443\u0442 \u043B\u043E\u043C\u0430\u0442\u044C \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u0441\u043F\u0438\u0441\u043A\u0430.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "\u041F\u0440\u044F\u0442\u0430\u0442\u044C \u0440\u043E\u0434\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u0434\u043D\u044F?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "\u0420\u043E\u0434\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 - \u0442\u0435, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u044B \u0438\u0437 \u043E\u0434\u043D\u043E\u0433\u043E \u0442\u0435\u043A\u0441\u0442\u0430, \u043F\u0440\u0438\u043C\u0435\u0440: \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0441 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u043C\u0438 ([...])",
 | |
|   SHOW_CARD_CONTEXT: "\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442 (\u0443\u0440\u043E\u0432\u0435\u043D\u044C) \u0432 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0430\u0445 (\u0432\u043E \u0432\u0440\u0435\u043C\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u044F)?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "\u043F\u0440\u0438\u043C\u0435\u0440: Title > Heading 1 > Subheading > ... > Subheading",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "\u0412\u044B\u0441\u043E\u0442\u0430 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0432 \u043F\u0440\u043E\u0446\u0435\u043D\u0442\u0430\u0445",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "\u0415\u0441\u043B\u0438 \u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0435\u0441\u044C \u043C\u043E\u0431\u0438\u043B\u044C\u043D\u044B\u043C \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u043E\u043C, \u0432\u044B\u0441\u0442\u0430\u0432\u044C\u0442\u0435 100%. \u0418\u043D\u0430\u0447\u0435 \u0443 \u0432\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u043E\u0433\u0440\u043E\u043C\u043D\u044B\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
 | |
|   RESET_DEFAULT: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u043F\u043E-\u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\u0428\u0438\u0440\u0438\u043D\u0430 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u0432 \u043F\u0440\u043E\u0446\u0435\u043D\u0442\u0430\u0445",
 | |
|   RANDOMIZE_CARD_ORDER: "\u0421\u043B\u0443\u0447\u0430\u0439\u043D\u044B\u0439 \u043F\u043E\u0440\u044F\u0434\u043E\u043A \u043A\u0430\u0440\u0442 \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "\u041F\u043E\u0440\u044F\u0434\u043E\u043A \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \u043A\u0430\u0440\u0442 \u043A\u043E\u043B\u043E\u0434\u044B \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "\u041F\u043E\u0441\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u043D\u043E \u0432\u043D\u0443\u0442\u0440\u0438 \u043A\u043E\u043B\u043E\u0434\u044B (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 \u0432\u0441\u0435 \u043D\u043E\u0432\u044B\u0435 \u043A\u0430\u0440\u0442\u044B)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "\u041F\u043E\u0441\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u043D\u043E \u0432\u043D\u0443\u0442\u0440\u0438 \u043A\u043E\u043B\u043E\u0434\u044B (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 \u0432\u0441\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u043C\u044B\u0435 \u043A\u0430\u0440\u0442\u044B)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "\u0421\u043B\u0443\u0447\u0430\u0439\u043D\u043E \u0432\u043D\u0443\u0442\u0440\u0438 \u043A\u043E\u043B\u043E\u0434\u044B (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 \u0432\u0441\u0435 \u043D\u043E\u0432\u044B\u0435 \u043A\u0430\u0440\u0442\u044B)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "\u0421\u043B\u0443\u0447\u0430\u0439\u043D\u043E \u0432\u043D\u0443\u0442\u0440\u0438 \u043A\u043E\u043B\u043E\u0434\u044B (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 \u0432\u0441\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u043C\u044B\u0435 \u043A\u0430\u0440\u0442\u044B)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "\u0421\u043B\u0443\u0447\u0430\u0439\u043D\u0430\u044F \u043A\u0430\u0440\u0442\u0430 \u0438\u0437 \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u043E\u0439 \u043A\u043E\u043B\u043E\u0434\u044B",
 | |
|   REVIEW_DECK_ORDER: "\u041F\u043E\u0440\u044F\u0434\u043E\u043A \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u043E\u0434 \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "\u041F\u043E\u0441\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u043D\u043E  (\u043F\u043E\u0441\u043B\u0435 \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F \u0432\u0441\u0435\u0445 \u043A\u0430\u0440\u0442 \u0438\u0437 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u0439 \u043A\u043E\u043B\u043E\u0434\u044B)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "\u0421\u043B\u0443\u0447\u0430\u0439\u043D\u043E (\u043F\u043E\u0441\u043B\u0435 \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F \u0432\u0441\u0435\u0445 \u043A\u0430\u0440\u0442 \u0438\u0437 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u0439 \u043A\u043E\u043B\u043E\u0434\u044B)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "\u0421\u043B\u0443\u0447\u0430\u0439\u043D\u0430\u044F \u043A\u0430\u0440\u0442\u0430 \u0438\u0437 \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u043E\u0439 \u043A\u043E\u043B\u043E\u0434\u044B",
 | |
|   DISABLE_CLOZE_CARDS: "\u0412\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043A\u0430\u0440\u0442\u044B \u0441 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u043C\u0438 (\u043F\u0440\u0438\u043C\u0435\u0440: [...])?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C ==\u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0439 \u0442\u0435\u043A\u0441\u0442== \u0432 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0438 (\u043F\u0440\u0438\u043C\u0435\u0440: [...])?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C/\u0443\u0434\u0430\u043B\u0438\u0442\u044C <code>${defaultPattern}</code> \u0432 \u0432\u0430\u0448\u0438 "\u0428\u0430\u0431\u043B\u043E\u043D\u044B \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u043E\u0432"',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C **\u0436\u0438\u0440\u043D\u044B\u0439 \u0442\u0435\u043A\u0441\u0442** \u0432 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0438 (\u043F\u0440\u0438\u043C\u0435\u0440: [...])?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C/\u0443\u0434\u0430\u043B\u0438\u0442\u044C <code>${defaultPattern}</code> \u0432 \u0432\u0430\u0448\u0438 "\u0428\u0430\u0431\u043B\u043E\u043D\u044B \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u043E\u0432"',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C {{\u0444\u0438\u0433\u0443\u0440\u043D\u044B\u0435 \u0441\u043A\u043E\u0431\u043A\u0438}} \u0432 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0438 (\u043F\u0440\u0438\u043C\u0435\u0440: [...])?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C/\u0443\u0434\u0430\u043B\u0438\u0442\u044C <code>${defaultPattern}</code> \u0432 \u0432\u0430\u0448\u0438 "\u0428\u0430\u0431\u043B\u043E\u043D\u044B \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u043E\u0432"',
 | |
|   CLOZE_PATTERNS: "\u0428\u0430\u0431\u043B\u043E\u043D\u044B \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u043E\u0432",
 | |
|   CLOZE_PATTERNS_DESC: '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0448\u0430\u0431\u043B\u043E\u043D\u044B \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u043E\u0432, \u0440\u0430\u0437\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0435 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\u043C\u0438 \u0441\u0442\u0440\u043E\u043A. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "\u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C \u0434\u043B\u044F \u0432\u043D\u0443\u0442\u0440\u0438\u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0445 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "\u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435! \u041F\u043E\u0441\u043B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u044D\u0442\u043E\u0433\u043E \u0432\u0430\u043C \u043F\u0440\u0438\u0434\u0451\u0442\u0441\u044F \u0432\u0440\u0443\u0447\u043D\u0443\u044E \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "\u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C \u0434\u043B\u044F \u043E\u0431\u0440\u0430\u0442\u043D\u044B\u0445 \u0432\u043D\u0443\u0442\u0440\u0438\u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0445 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C \u0434\u043B\u044F \u043C\u043D\u043E\u0433\u043E\u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0445 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C \u0434\u043B\u044F \u043E\u0431\u0440\u0430\u0442\u043D\u044B\u0445 \u043C\u043D\u043E\u0433\u043E\u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0445 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   MULTILINE_CARDS_END_MARKER: "\u0421\u0438\u043C\u0432\u043E\u043B\u044B, \u043E\u0431\u043E\u0437\u043D\u0430\u0447\u0430\u044E\u0449\u0438\u0435 \u043A\u043E\u043D\u0435\u0446 \u043A\u043B\u043E\u0437\u043E\u0432 \u0438 \u043C\u043D\u043E\u0433\u043E\u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0445 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   NOTES: "\u0417\u0430\u043C\u0435\u0442\u043A\u0438",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043F\u0430\u043D\u0435\u043B\u044C \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A \u043F\u0440\u0438 \u0437\u0430\u043F\u0443\u0441\u043A\u0435 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B",
 | |
|   TAGS_TO_REVIEW: "\u0422\u0435\u0433\u0438 \u0434\u043B\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F",
 | |
|   TAGS_TO_REVIEW_DESC: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u0433\u0438, \u0440\u0430\u0437\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0435 Enter-\u0430\u043C\u0438 \u0438\u043B\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u0430\u043C\u0438, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: #review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u0443\u044E \u0437\u0430\u043C\u0435\u0442\u043A\u0443 \u0434\u043B\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F",
 | |
|   OPEN_RANDOM_NOTE_DESC: "\u0415\u0441\u043B\u0438 \u0432\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C, \u0442\u043E \u0437\u0430\u043C\u0435\u0442\u043A\u0438 \u0431\u0443\u0434\u0443\u0442 \u043E\u0442\u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u044B \u043F\u043E \u0432\u0430\u0436\u043D\u043E\u0441\u0442\u0438 (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "\u041F\u043E\u0441\u043B\u0435 \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u0437\u0430\u043C\u0435\u0442\u043A\u0443",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043E\u0431\u0437\u043E\u0440\u0430 \u0432 \u043C\u0435\u043D\u044E \u0424\u0430\u0439\u043B (\u0442.\u0435.: \u0418\u0437\u0443\u0447\u0435\u043D\u0438\u0435: \u041B\u0435\u0433\u043A\u043E, \u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E, \u0421\u043B\u043E\u0436\u043D\u043E)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "\u0415\u0441\u043B\u0438 \u0432\u044B \u043E\u0442\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043E\u0431\u0437\u043E\u0440\u0430 \u0432 \u043C\u0435\u043D\u044E \u0424\u0430\u0439\u043B, \u0432\u044B \u0441\u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0440\u043E\u0441\u043C\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044C \u0441\u0432\u043E\u0438 \u0437\u0430\u043C\u0435\u0442\u043A\u0438 \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u043A\u043E\u043C\u0430\u043D\u0434 \u043F\u043B\u0430\u0433\u0438\u043D\u0430 \u0438, \u0435\u0441\u043B\u0438 \u0432\u044B \u0438\u0445 \u0437\u0430\u0434\u0430\u043B\u0438, \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0445 \u0433\u043E\u0440\u044F\u0447\u0438\u0445 \u043A\u043B\u0430\u0432\u0438\u0448.",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "\u041D\u0430\u0438\u0431\u043E\u043B\u044C\u0448\u0435\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0434\u043D\u0435\u0439 \u0434\u043B\u044F \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0430 \u043F\u0430\u043D\u0435\u043B\u0438 \u0441\u043F\u0440\u0430\u0432\u0430",
 | |
|   MIN_ONE_DAY: "\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0434\u043D\u0435\u0439 \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 1.",
 | |
|   VALID_NUMBER_WARNING: "\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0449\u0435\u0435 \u0447\u0438\u0441\u043B\u043E.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\u0414\u0435\u0440\u0435\u0432\u044C\u044F \u043A\u043E\u043B\u043E\u0434 \u0434\u043E\u043B\u0436\u043D\u044B \u0438\u0437\u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C\u0441\u044F \u043A\u0430\u043A \u0440\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044B\u0435",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "\u041E\u0442\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u044D\u0442\u043E\u0442 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440, \u0447\u0442\u043E\u0431\u044B \u0441\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u043B\u043E\u0436\u0435\u043D\u043D\u044B\u0435 \u043A\u043E\u043B\u043E\u0434\u044B \u043D\u0430 \u043E\u0434\u043D\u043E\u0439 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0435. \u041F\u043E\u043B\u0435\u0437\u043D\u043E, \u0435\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044C \u043A\u0430\u0440\u0442\u044B, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0430\u0442 \u043C\u043D\u043E\u0433\u0438\u043C \u043A\u043E\u043B\u043E\u0434\u0430\u043C \u0432 \u043E\u0434\u043D\u043E\u043C \u0444\u0430\u0439\u043B\u0435.",
 | |
|   ALGORITHM: "\u0410\u043B\u0433\u043E\u0440\u0438\u0442\u043C",
 | |
|   CHECK_ALGORITHM_WIKI: '\u0417\u0430 \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0439 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0435\u0439 \u043E\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043A <a href="${algoUrl}">\u0440\u0435\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0430</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "\u0411\u0430\u0437\u043E\u0432\u0430\u044F \u041B\u0451\u0433\u043A\u043E\u0441\u0442\u044C",
 | |
|   BASE_EASE_DESC: "\u043C\u0438\u043D\u0438\u043C\u0443\u043C = 130, \u043F\u0440\u0435\u0434\u043F\u043E\u0447\u0442\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u043E\u043A\u043E\u043B\u043E 250.",
 | |
|   BASE_EASE_MIN_WARNING: "\u041B\u0451\u0433\u043A\u043E\u0441\u0442\u044C \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043C\u0438\u043D\u0438\u043C\u0443\u043C 130.",
 | |
|   LAPSE_INTERVAL_CHANGE: '\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B\u0430 \u043F\u0440\u0438 \u0432\u044B\u0431\u043E\u0440\u0435 "\u0421\u043B\u043E\u0436\u043D\u043E" \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438/\u0437\u0430\u043C\u0435\u0442\u043A\u0438',
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "\u043D\u043E\u0432\u044B\u0439\u041F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043E\u043A = \u0441\u0442\u0430\u0440\u044B\u0439\u041F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043E\u043A * \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435\u041F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043A\u0430 / 100.",
 | |
|   EASY_BONUS: "\u041B\u0435\u0433\u043A\u043E: \u0431\u043E\u043D\u0443\u0441",
 | |
|   EASY_BONUS_DESC: "\u0411\u043E\u043D\u0443\u0441 \u0437\u0430 \u041B\u0435\u0433\u043A\u043E \u043F\u043E\u0437\u0432\u043E\u043B\u044F\u0435\u0442 \u0432\u0430\u043C \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0440\u0430\u0437\u043D\u0438\u0446\u0443 \u0432 \u043F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043A\u0430\u0445 \u043C\u0435\u0436\u0434\u0443 \u043E\u0442\u0432\u0435\u0442\u0430\u043C\u0438 \u0425\u043E\u0440\u043E\u0448\u043E \u0438 \u041B\u0435\u0433\u043A\u043E \u043D\u0430 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0435/\u0437\u0430\u043C\u0435\u0442\u043A\u0435 (\u043C\u0438\u043D. = 100%).",
 | |
|   EASY_BONUS_MIN_WARNING: '\u0411\u043E\u043D\u0443\u0441 \u0437\u0430 "\u041B\u0435\u0433\u043A\u043E" \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 100.',
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u044F \u0432 \u0434\u043D\u044F\u0445",
 | |
|   MAX_INTERVAL_DESC: "\u041F\u043E\u0437\u0432\u043E\u043B\u044F\u0435\u0442 \u0432\u0430\u043C \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0442\u044C \u0432\u0435\u0440\u0445\u043D\u044E\u044E \u0433\u0440\u0430\u043D\u0438\u0446\u0443 \u043D\u0430 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u044F (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E = 100 \u043B\u0435\u0442).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 1.",
 | |
|   MAX_LINK_CONTRIB: "\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0432\u043A\u043B\u0430\u0434 \u0441\u0432\u044F\u0437\u0438 (\u0441\u0441\u044B\u043B\u043A\u0438)",
 | |
|   MAX_LINK_CONTRIB_DESC: '\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0432\u043A\u043B\u0430\u0434 \u0441\u0440\u0435\u0434\u043D\u0435\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F "\u041B\u0451\u0433\u043A\u043E\u0441\u0442\u0438" \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0445 \u0437\u0430\u043C\u0435\u0442\u043E\u043A \u0432 \u043D\u0430\u0447\u0430\u043B\u044C\u043D\u0443\u044E "\u041B\u0451\u0433\u043A\u043E\u0441\u0442\u044C".',
 | |
|   LOGGING: "\u0416\u0443\u0440\u043D\u0430\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C \u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u0443\u044E \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A\u0430",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "\u041E\u0447\u0435\u0440\u0435\u0434\u044C \u0437\u0430\u043C\u0435\u0442\u043E\u043A \u043D\u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u0435",
 | |
|   CLOSE: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C",
 | |
|   NEW: "\u041D\u043E\u0432\u044B\u0435",
 | |
|   YESTERDAY: "\u0412\u0447\u0435\u0440\u0430\u0448\u043D\u0438\u0435",
 | |
|   TODAY: "\u0421\u0435\u0433\u043E\u0434\u043D\u044F\u0448\u043D\u0438\u0435",
 | |
|   TOMORROW: "\u0417\u0430\u0432\u0442\u0440\u0430\u0448\u043D\u0438\u0435",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430",
 | |
|   MONTH: "\u041C\u0435\u0441\u044F\u0446",
 | |
|   QUARTER: "\u041A\u0432\u0430\u0440\u0442\u0430\u043B",
 | |
|   YEAR: "\u0413\u043E\u0434",
 | |
|   LIFETIME: "\u0412\u0441\u0451 \u0432\u0440\u0435\u043C\u044F",
 | |
|   FORECAST: "\u041F\u0440\u043E\u0433\u043D\u043E\u0437",
 | |
|   FORECAST_DESC: "\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A \u043F\u0440\u0435\u0434\u0441\u0442\u043E\u044F\u0449\u0438\u0445 \u0434\u043B\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u044F",
 | |
|   SCHEDULED: "\u0417\u0430\u043F\u043B\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043E",
 | |
|   DAYS: "\u0414\u043D\u0438",
 | |
|   NUMBER_OF_CARDS: "\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   REVIEWS_PER_DAY: "\u0421\u0440\u0435\u0434\u043D\u0435\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E: ${avg} \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u0439 \u0432 \u0434\u0435\u043D\u044C",
 | |
|   INTERVALS: "\u0418\u043D\u0442\u0435\u0440\u0432\u0430\u043B\u044B",
 | |
|   INTERVALS_DESC: "\u041F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043A\u0438 \u0432\u0440\u0435\u043C\u0435\u043D\u0438 \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u043F\u043E\u043A\u0430\u0437\u0430 \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u044F",
 | |
|   COUNT: "\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E",
 | |
|   INTERVALS_SUMMARY: "\u0421\u0440\u0435\u0434\u043D\u0438\u0439 \u043F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043E\u043A: ${avg}, \u0421\u0430\u043C\u044B\u0439 \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043E\u043A: ${longest}",
 | |
|   EASES: "\u041F\u0440\u043E\u0433\u0440\u0435\u0441\u0441 \u0438\u0437\u0443\u0447\u0435\u043D\u0438\u044F",
 | |
|   EASES_SUMMARY: "\u0421\u0440\u0435\u0434\u043D\u0435\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441\u0430: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "\u0422\u0438\u043F\u044B \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A",
 | |
|   CARD_TYPES_DESC: "\u0412\u043A\u043B\u044E\u0447\u0430\u044F \u0441\u043F\u0440\u044F\u0442\u0430\u043D\u043D\u044B\u0435 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438, \u0435\u0441\u043B\u0438 \u0442\u0430\u043A\u0438\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0442.",
 | |
|   CARD_TYPE_NEW: "\u041D\u043E\u0432\u044B\u0445",
 | |
|   CARD_TYPE_YOUNG: "\u041F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u043C\u044B\u0445",
 | |
|   CARD_TYPE_MATURE: "\u0418\u0437\u0443\u0447\u0435\u043D\u043D\u044B\u0445",
 | |
|   CARD_TYPES_SUMMARY: "\u0412\u0441\u0435\u0433\u043E \u043A\u0430\u0440\u0442\u043E\u0447\u0435\u043A: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/sw.ts
 | |
| var sw_default = {};
 | |
| 
 | |
| // src/lang/locale/ta.ts
 | |
| var ta_default = {};
 | |
| 
 | |
| // src/lang/locale/te.ts
 | |
| var te_default = {};
 | |
| 
 | |
| // src/lang/locale/th.ts
 | |
| var th_default = {};
 | |
| 
 | |
| // src/lang/locale/tr.ts
 | |
| var tr_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "Desteler",
 | |
|   DUE_CARDS: "G\xFCncel Kartlar",
 | |
|   NEW_CARDS: "Yeni Kartlar",
 | |
|   TOTAL_CARDS: "Toplam Kartlar",
 | |
|   BACK: "Geri",
 | |
|   SKIP: "Atla",
 | |
|   EDIT_CARD: "Kart\u0131 D\xFCzenle",
 | |
|   RESET_CARD_PROGRESS: "Kart\u0131n ilerlemesini s\u0131f\u0131rla",
 | |
|   HARD: "Zor",
 | |
|   GOOD: "Orta",
 | |
|   EASY: "Kolay",
 | |
|   SHOW_ANSWER: "Cevab\u0131 G\xF6ster",
 | |
|   CARD_PROGRESS_RESET: "Kart\u0131n ilerlemesi s\u0131f\u0131rland\u0131.",
 | |
|   SAVE: "Kaydet",
 | |
|   CANCEL: "\u0130ptal",
 | |
|   NO_INPUT: "Girdi sa\u011Flanmad\u0131.",
 | |
|   CURRENT_EASE_HELP_TEXT: "Mevcut Kolayl\u0131k: ",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "Mevcut Aral\u0131k: ",
 | |
|   CARD_GENERATED_FROM: "${notePath} kayna\u011F\u0131ndan olu\u015Fturuldu.",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "G\xF6zden ge\xE7irmek i\xE7in bir not a\xE7",
 | |
|   REVIEW_CARDS: "Flash kartlar\u0131 g\xF6zden ge\xE7ir",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "G\xF6zden Ge\xE7ir: ${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "Notu ${difficulty} derecesiyle g\xF6zden ge\xE7ir",
 | |
|   CRAM_ALL_CARDS: "T\xFCm destelerden yo\u011Fun tekrar yap",
 | |
|   REVIEW_ALL_CARDS: "T\xFCm notlardaki flash kartlar\u0131 g\xF6zden ge\xE7ir",
 | |
|   REVIEW_CARDS_IN_NOTE: "Bu nottaki flash kartlar\u0131 g\xF6zden ge\xE7ir",
 | |
|   CRAM_CARDS_IN_NOTE: "Bu nottaki flash kartlar\u0131 yo\u011Fun tekrar yap",
 | |
|   VIEW_STATS: "\u0130statistikleri g\xF6r\xFCnt\xFCle",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Kenar \xE7ubu\u011Funda Not G\xF6zden Ge\xE7irme S\u0131ras\u0131n\u0131 a\xE7",
 | |
|   STATUS_BAR: "G\xF6zden Ge\xE7ir: ${dueNotesCount} not, ${dueFlashcardsCount} kart g\xFCncel",
 | |
|   SYNC_TIME_TAKEN: "Senkronizasyon ${t}ms s\xFCrd\xFC",
 | |
|   NOTE_IN_IGNORED_FOLDER: "Not, d\u0131\u015Flanan klas\xF6rde kay\u0131tl\u0131 (ayarlar\u0131 kontrol edin).",
 | |
|   PLEASE_TAG_NOTE: "L\xFCtfen g\xF6zden ge\xE7irmek i\xE7in notu uygun \u015Fekilde etiketleyin (ayarlar i\xE7inde).",
 | |
|   RESPONSE_RECEIVED: "Yan\u0131t al\u0131nd\u0131.",
 | |
|   NO_DECK_EXISTS: "${deckName} ad\u0131nda bir deste yok",
 | |
|   ALL_CAUGHT_UP: "\u{1F3C6} \u015Eampiyon gibi bitirdin! \u{1F604}",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval} g\xFCn",
 | |
|   MONTHS_STR_IVL: "${interval} ay",
 | |
|   YEARS_STR_IVL: "${interval} y\u0131l",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}g",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}a",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}y",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "Aral\u0131kl\u0131 Tekrar",
 | |
|   GROUP_TAGS_FOLDERS: "Etiketler ve Klas\xF6rler",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flash Kartlar\u0131 G\xF6zden Ge\xE7irme",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flash Kart Ay\u0131r\u0131c\u0131lar\u0131",
 | |
|   GROUP_DATA_STORAGE: "Planlama Verilerinin Saklanmas\u0131",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flash Kartlar ve Notlar",
 | |
|   GROUP_CONTRIBUTING: "Katk\u0131da Bulunma",
 | |
|   CHECK_WIKI: 'Daha fazla bilgi i\xE7in <a href="${wikiUrl}">wiki</a> sayfas\u0131na g\xF6z at\u0131n.',
 | |
|   GITHUB_DISCUSSIONS: 'Soru-cevap, geri bildirim ve genel tart\u0131\u015Fmalar i\xE7in <a href="${discussionsUrl}">tart\u0131\u015Fmalar</a> b\xF6l\xFCm\xFCne g\xF6z at\u0131n.',
 | |
|   GITHUB_ISSUES: 'Bir \xF6zellik iste\u011Finiz ya da hata bildiriminiz varsa <a href="${issuesUrl}">buradan</a> bildirin.',
 | |
|   GITHUB_SOURCE_CODE: 'Proje kaynak koduna <a href="${githubProjectUrl}">GitHub</a> \xFCzerinden ula\u015Fabilirsiniz.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Kod katk\u0131lar\u0131</a> hakk\u0131nda bilgi al\u0131n.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: 'Eklentiyi kendi dilinize \xE7evirmek hakk\u0131nda bilgi i\xE7in <a href="${translationContributionUrl}">\xE7eviri katk\u0131lar\u0131</a> sayfas\u0131n\u0131 ziyaret edin.',
 | |
|   FOLDERS_TO_IGNORE: "Yoksay\u0131lan Klas\xF6rler",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "Flash Kartlar",
 | |
|   FLASHCARD_EASY_LABEL: "Kolay Butonu Metni",
 | |
|   FLASHCARD_GOOD_LABEL: "Orta Butonu Metni",
 | |
|   FLASHCARD_HARD_LABEL: "Zor Butonu Metni",
 | |
|   FLASHCARD_EASY_DESC: '"Kolay" butonunun metnini \xF6zelle\u015Ftirin',
 | |
|   FLASHCARD_GOOD_DESC: '"Orta" butonunun metnini \xF6zelle\u015Ftirin',
 | |
|   FLASHCARD_HARD_DESC: '"Zor" butonunun metnini \xF6zelle\u015Ftirin',
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "Flash Kart Etiketleri",
 | |
|   FLASHCARD_TAGS_DESC: "Etiketleri bo\u015Fluklar veya yeni sat\u0131rlarla ay\u0131rarak girin, \xF6rne\u011Fin: #flashcards #deck2 #deck3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "Klas\xF6rleri destelere ve alt destelere d\xF6n\xFC\u015Ft\xFCr?",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "Bu, yukar\u0131daki Flash Kart etiketleri se\xE7ene\u011Fine bir alternatiftir.",
 | |
|   INLINE_SCHEDULING_COMMENTS: "Planlama yorumunu flash kart\u0131n son sat\u0131r\u0131yla ayn\u0131 sat\u0131ra kaydet?",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "Bunu a\xE7mak, HTML yorumlar\u0131n\u0131n liste bi\xE7imlendirmesini bozmamas\u0131n\u0131 sa\u011Flar.",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "Karde\u015F kartlar\u0131 bir sonraki g\xFCne kadar gizle?",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "Karde\u015F kartlar, ayn\u0131 kart metninden \xFCretilen kartlard\u0131r (\xF6rne\u011Fin gizlemeler).",
 | |
|   SHOW_CARD_CONTEXT: "Kartlarda ba\u011Flam\u0131 g\xF6ster?",
 | |
|   SHOW_CARD_CONTEXT_DESC: "\xD6rne\u011Fin: Ba\u015Fl\u0131k > Ba\u015Fl\u0131k 1 > Alt Ba\u015Fl\u0131k > ... > Alt Ba\u015Fl\u0131k",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "Flash Kart Y\xFCkseklik Y\xFCzdesi",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "Mobilde veya \xE7ok b\xFCy\xFCk resimleriniz varsa %100 olarak ayarlay\u0131n.",
 | |
|   RESET_DEFAULT: "Varsay\u0131lana s\u0131f\u0131rla",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "Flash Kart Geni\u015Flik Y\xFCzdesi",
 | |
|   RANDOMIZE_CARD_ORDER: "\u0130nceleme s\u0131ras\u0131nda kart s\u0131ras\u0131n\u0131 rastgele yap?",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "\u0130nceleme s\u0131ras\u0131nda bir destede kartlar\u0131n g\xF6r\xFCnt\xFClenme s\u0131ras\u0131",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "S\u0131ral\u0131 olarak (\xF6nce t\xFCm yeni kartlar)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "S\u0131ral\u0131 olarak (\xF6nce t\xFCm g\xFCncel kartlar)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "Rastgele olarak (\xF6nce t\xFCm yeni kartlar)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "Rastgele olarak (\xF6nce t\xFCm g\xFCncel kartlar)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "Rastgele desteden rastgele kart",
 | |
|   REVIEW_DECK_ORDER: "\u0130nceleme s\u0131ras\u0131nda destelerin g\xF6r\xFCnt\xFClenme s\u0131ras\u0131",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "S\u0131ral\u0131 olarak (\xD6nceki destedeki t\xFCm kartlar g\xF6zden ge\xE7irildikten sonra)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "Rastgele olarak (\xD6nceki destedeki t\xFCm kartlar g\xF6zden ge\xE7irildikten sonra)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Rastgele desteden rastgele kart",
 | |
|   DISABLE_CLOZE_CARDS: "Gizli kartlar\u0131 devre d\u0131\u015F\u0131 b\u0131rak?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "==Vurgulanan== metni gizli kartlara d\xF6n\xFC\u015Ft\xFCr?",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: '"Cloze Patterns"den <code>${defaultPattern</code> \xF6\u011Fesini ekleyin/kald\u0131r\u0131n',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "**Kal\u0131n metni** gizli kartlara d\xF6n\xFC\u015Ft\xFCr?",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: '"Cloze Patterns"den <code>${defaultPattern</code> \xF6\u011Fesini ekleyin/kald\u0131r\u0131n',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "{{K\u0131v\u0131rc\u0131k parantezleri}} gizli kartlara d\xF6n\xFC\u015Ft\xFCr?",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: '"Cloze Patterns"den <code>${defaultPattern</code> \xF6\u011Fesini ekleyin/kald\u0131r\u0131n',
 | |
|   CLOZE_PATTERNS: "Cloze Patterns",
 | |
|   CLOZE_PATTERNS_DESC: 'Enter cloze patterns separated by newlines. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "Sat\u0131r i\xE7i flash kartlar i\xE7in ay\u0131r\u0131c\u0131",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "Bunu de\u011Fi\u015Ftirdikten sonra mevcut flash kartlar\u0131n\u0131z\u0131 manuel olarak d\xFCzenlemeniz gerekti\u011Fini unutmay\u0131n.",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "Sat\u0131r i\xE7i ters flash kartlar i\xE7in ay\u0131r\u0131c\u0131",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\xC7ok sat\u0131rl\u0131 flash kartlar i\xE7in ay\u0131r\u0131c\u0131",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\xC7ok sat\u0131rl\u0131 ters flash kartlar i\xE7in ay\u0131r\u0131c\u0131",
 | |
|   MULTILINE_CARDS_END_MARKER: "Gizli kartlar ve \xE7ok sat\u0131rl\u0131 flash kartlar\u0131n sonunu belirten karakterler",
 | |
|   NOTES: "Notlar",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "Ba\u015Flang\u0131\xE7ta not inceleme panelini etkinle\u015Ftir",
 | |
|   TAGS_TO_REVIEW: "G\xF6zden ge\xE7irilecek etiketler",
 | |
|   TAGS_TO_REVIEW_DESC: "Etiketleri bo\u015Fluklar veya yeni sat\u0131rlarla ay\u0131rarak girin, \xF6rne\u011Fin: #review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "G\xF6zden ge\xE7irmek i\xE7in rastgele bir not a\xE7",
 | |
|   OPEN_RANDOM_NOTE_DESC: "Bunu kapatt\u0131\u011F\u0131n\u0131zda, notlar \xF6nem s\u0131ras\u0131na g\xF6re s\u0131ralan\u0131r (PageRank).",
 | |
|   AUTO_NEXT_NOTE: "Bir incelemeden sonra otomatik olarak bir sonraki notu a\xE7",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "Sa\u011F panelde g\xF6sterilecek maksimum g\xFCn say\u0131s\u0131",
 | |
|   MIN_ONE_DAY: "G\xFCn say\u0131s\u0131 en az 1 olmal\u0131d\u0131r.",
 | |
|   VALID_NUMBER_WARNING: "L\xFCtfen ge\xE7erli bir say\u0131 girin.",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "Enable the review options in the file menu (e.g. Review: Easy, Good, Hard)",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "If you disable the review options in the file menu, you can review your notes using the plugin commands and, if you defined them, the associated command hotkeys.",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "Deste a\u011Fa\xE7lar\u0131 ba\u015Flang\u0131\xE7ta geni\u015Fletilmi\u015F olarak g\xF6sterilmeli mi",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "Bunu kapat\u0131n, ayn\u0131 dosyada bir\xE7ok desteye ait kartlar\u0131n\u0131z varsa i\xE7 i\xE7e desteleri daraltmak i\xE7in kullan\u0131\u015Fl\u0131d\u0131r.",
 | |
|   ALGORITHM: "Algoritma",
 | |
|   CHECK_ALGORITHM_WIKI: 'Daha fazla bilgi i\xE7in <a href="${algoUrl}">algoritma uygulamas\u0131na</a> g\xF6z at\u0131n.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "Temel kolayl\u0131k",
 | |
|   BASE_EASE_DESC: "minimum = 130, tercihen yakla\u015F\u0131k 250.",
 | |
|   BASE_EASE_MIN_WARNING: "Temel kolayl\u0131k en az 130 olmal\u0131d\u0131r.",
 | |
|   LAPSE_INTERVAL_CHANGE: "Bir flash kart\u0131/notu zor olarak inceledi\u011Finizde aral\u0131k de\u011Fi\u015Fikli\u011Fi",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "yeniAral\u0131k = eskiAral\u0131k * aral\u0131kDe\u011Fi\u015Fikli\u011Fi / 100.",
 | |
|   EASY_BONUS: "Kolayl\u0131k Bonusu",
 | |
|   EASY_BONUS_DESC: "Kolayl\u0131k bonusu, bir flash kart\u0131/notu \u0130yi ve Kolay yan\u0131tlad\u0131\u011F\u0131n\u0131zda aral\u0131klardaki fark\u0131 ayarlaman\u0131za olanak tan\u0131r (minimum = %100).",
 | |
|   EASY_BONUS_MIN_WARNING: "Kolayl\u0131k bonusu en az %100 olmal\u0131d\u0131r.",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "Maksimum aral\u0131k (g\xFCn)",
 | |
|   MAX_INTERVAL_DESC: "Aral\u0131\u011Fa bir \xFCst s\u0131n\u0131r koyman\u0131za olanak tan\u0131r (varsay\u0131lan = 100 y\u0131l).",
 | |
|   MAX_INTERVAL_MIN_WARNING: "Maksimum aral\u0131k en az 1 g\xFCn olmal\u0131d\u0131r.",
 | |
|   MAX_LINK_CONTRIB: "Maksimum ba\u011Flant\u0131 katk\u0131s\u0131",
 | |
|   MAX_LINK_CONTRIB_DESC: "Ba\u011Flant\u0131l\u0131 notlar\u0131n a\u011F\u0131rl\u0131kl\u0131 kolayl\u0131k de\u011Ferinin ba\u015Flang\u0131\xE7 kolayl\u0131\u011F\u0131na maksimum katk\u0131s\u0131.",
 | |
|   LOGGING: "Kay\u0131t tutma",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "Geli\u015Ftirici konsolunda hata ay\u0131klama bilgilerini g\xF6ster",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Ayr\u0131\u015Ft\u0131r\u0131c\u0131 i\xE7in hata ay\u0131klama bilgilerini geli\u015Ftirici konsolunda g\xF6ster",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "Not \u0130nceleme S\u0131ras\u0131",
 | |
|   CLOSE: "Kapat",
 | |
|   NEW: "Yeni",
 | |
|   YESTERDAY: "D\xFCn",
 | |
|   TODAY: "Bug\xFCn",
 | |
|   TOMORROW: "Yar\u0131n",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\u0130statistikler",
 | |
|   MONTH: "Ay",
 | |
|   QUARTER: "\xC7eyrek",
 | |
|   YEAR: "Y\u0131l",
 | |
|   LIFETIME: "\xD6m\xFCr Boyu",
 | |
|   FORECAST: "Tahmin",
 | |
|   FORECAST_DESC: "Gelecekte incelemeye al\u0131nacak kartlar\u0131n say\u0131s\u0131",
 | |
|   SCHEDULED: "Planlanm\u0131\u015F",
 | |
|   DAYS: "G\xFCnler",
 | |
|   NUMBER_OF_CARDS: "Kart Say\u0131s\u0131",
 | |
|   REVIEWS_PER_DAY: "Ortalama: ${avg} inceleme/g\xFCn",
 | |
|   INTERVALS: "Aral\u0131klar",
 | |
|   INTERVALS_DESC: "\u0130ncelemelerin tekrar g\xF6sterilme gecikmeleri",
 | |
|   COUNT: "Say\u0131",
 | |
|   INTERVALS_SUMMARY: "Ortalama aral\u0131k: ${avg}, En uzun aral\u0131k: ${longest}",
 | |
|   EASES: "Kolayl\u0131klar",
 | |
|   EASES_SUMMARY: "Ortalama kolayl\u0131k: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "Kart T\xFCrleri",
 | |
|   CARD_TYPES_DESC: "Bu, g\xF6m\xFCl\xFC kartlar\u0131 da i\xE7erir (varsa)",
 | |
|   CARD_TYPE_NEW: "Yeni",
 | |
|   CARD_TYPE_YOUNG: "Gen\xE7",
 | |
|   CARD_TYPE_MATURE: "Olgun",
 | |
|   CARD_TYPES_SUMMARY: "Toplam kart: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/uk.ts
 | |
| var uk_default = {};
 | |
| 
 | |
| // src/lang/locale/ur.ts
 | |
| var ur_default = {};
 | |
| 
 | |
| // src/lang/locale/vi.ts
 | |
| var vi_default = {};
 | |
| 
 | |
| // src/lang/locale/zh-cn.ts
 | |
| var zh_cn_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "\u5361\u7EC4",
 | |
|   DUE_CARDS: "\u5230\u671F\u5361\u7247",
 | |
|   NEW_CARDS: "\u65B0\u5361\u7247",
 | |
|   TOTAL_CARDS: "\u5168\u90E8\u5361\u7247",
 | |
|   BACK: "\u8FD4\u56DE",
 | |
|   SKIP: "\u7565\u8FC7",
 | |
|   EDIT_CARD: "\u7F16\u8F91\u5361\u7247",
 | |
|   RESET_CARD_PROGRESS: "\u91CD\u7F6E\u5361\u7247",
 | |
|   HARD: "\u8F83\u96BE",
 | |
|   GOOD: "\u8BB0\u5F97",
 | |
|   EASY: "\u7B80\u5355",
 | |
|   SHOW_ANSWER: "\u663E\u793A\u7B54\u6848",
 | |
|   CARD_PROGRESS_RESET: "\u5361\u7247\u5DF2\u88AB\u91CD\u7F6E\u3002",
 | |
|   SAVE: "\u4FDD\u5B58",
 | |
|   CANCEL: "\u53D6\u6D88",
 | |
|   NO_INPUT: "\u6CA1\u6709\u63D0\u4F9B\u8F93\u5165\u3002",
 | |
|   CURRENT_EASE_HELP_TEXT: "\u76EE\u524D\u638C\u63E1\u7A0B\u5EA6\uFF1A",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "\u76EE\u524D\u95F4\u9694\uFF1A",
 | |
|   CARD_GENERATED_FROM: "\u751F\u6210\u81EA\uFF1A${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "\u6253\u5F00\u4E00\u4E2A\u7B14\u8BB0\u5F00\u59CB\u590D\u4E60",
 | |
|   REVIEW_CARDS: "\u590D\u4E60\u5361\u7247",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "\u590D\u4E60\uFF1A${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "\u6807\u8BB0\u4E3A\u201C${difficulty}\u201D",
 | |
|   REVIEW_ALL_CARDS: "\u590D\u4E60\u6240\u6709\u7B14\u8BB0\u4E2D\u7684\u5361\u7247",
 | |
|   CRAM_ALL_CARDS: "\u9009\u62E9\u8981\u96C6\u4E2D\u590D\u4E60\u7684\u5361\u7EC4",
 | |
|   REVIEW_CARDS_IN_NOTE: "\u590D\u4E60\u6B64\u7B14\u8BB0\u4E2D\u7684\u5361\u7247",
 | |
|   CRAM_CARDS_IN_NOTE: "\u96C6\u4E2D\u590D\u4E60\u6B64\u7B14\u8BB0\u4E2D\u7684\u5361\u7247",
 | |
|   VIEW_STATS: "\u67E5\u770B\u6570\u636E",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "\u5728\u4FA7\u8FB9\u680F\u4E2D\u6253\u5F00\u7B14\u8BB0\u590D\u4E60\u961F\u5217",
 | |
|   STATUS_BAR: "\u590D\u4E60: ${dueNotesCount} \u7B14\u8BB0, ${dueFlashcardsCount} \u5361\u7247\u5DF2\u5230\u671F",
 | |
|   SYNC_TIME_TAKEN: "\u540C\u6B65\u65F6\u95F4 ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "\u7B14\u8BB0\u4FDD\u5B58\u5728\u5DF2\u88AB\u5FFD\u7565\u7684\u8DEF\u5F84\u4E2D\uFF08\u68C0\u67E5\u8BBE\u7F6E\u9009\u9879\uFF09\u3002",
 | |
|   PLEASE_TAG_NOTE: "\u8BF7\u5C06\u9700\u8981\u590D\u4E60\u7684\u7B14\u8BB0\u4E2D\u52A0\u5165\u6B63\u786E\u7684\u6807\u7B7E\uFF08\u68C0\u67E5\u8BBE\u7F6E\u9009\u9879\uFF09\u3002",
 | |
|   RESPONSE_RECEIVED: "\u53CD\u9988\u5DF2\u6536\u5230",
 | |
|   NO_DECK_EXISTS: "\u6CA1\u6709 ${deckName} \u5361\u7EC4",
 | |
|   ALL_CAUGHT_UP: "\u90FD\u590D\u4E60\u5B8C\u5566\uFF0C\u4F60\u771F\u68D2\uFF01",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval}\u5929",
 | |
|   MONTHS_STR_IVL: "${interval}\u6708",
 | |
|   YEARS_STR_IVL: "${interval}\u5E74",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}\u5929",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}\u6708",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}\u5E74",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "\u95F4\u9694\u91CD\u590D\u63D2\u4EF6",
 | |
|   GROUP_TAGS_FOLDERS: "\u6807\u7B7E\u548C\u6587\u4EF6\u5939",
 | |
|   GROUP_FLASHCARD_REVIEW: "\u95EA\u5361\u590D\u4E60",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "\u95EA\u5B58\u5361\u5206\u9694\u7B26",
 | |
|   GROUP_DATA_STORAGE: "\u5B58\u50A8\u8BA1\u5212\u6570\u636E",
 | |
|   GROUP_DATA_STORAGE_DESC: "\u9009\u62E9\u5B58\u50A8\u8BA1\u5212\u6570\u636E\u4F4D\u7F6E",
 | |
|   GROUP_FLASHCARDS_NOTES: "\u95EA\u5361\u548C\u7B14\u8BB0",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: '\u4E86\u89E3\u66F4\u591A, \u8BF7\u70B9\u51FB<a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "\u5FFD\u7565\u6B64\u6587\u4EF6\u5939",
 | |
|   FOLDERS_TO_IGNORE_DESC: "\u5728\u5355\u72EC\u4E00\u884C\u4E2D\u8F93\u5165\u6587\u4EF6\u5939\u8DEF\u5F84\u6216\u5168\u5C40\u6A21\u5F0F\uFF0C\u4F8B\u5982 Templates/Scripts \u6216 .excalidraw.md\u3002\u6B64\u8BBE\u7F6E\u5BF9\u95EA\u5B58\u5361\u548C\u7B14\u8BB0\u90FD\u901A\u7528\u3002",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "\u5361\u7247",
 | |
|   FLASHCARD_EASY_LABEL: "\u201C\u7B80\u5355\u201D\u6309\u94AE\u6587\u672C",
 | |
|   FLASHCARD_GOOD_LABEL: "\u201C\u8BB0\u5F97\u201D\u6309\u94AE\u6587\u672C",
 | |
|   FLASHCARD_HARD_LABEL: "\u201C\u8F83\u96BE\u201D\u6309\u94AE\u6587\u672C",
 | |
|   FLASHCARD_EASY_DESC: "\u81EA\u5B9A\u4E49\u201C\u7B80\u5355\u201D\u6309\u94AE\u7684\u6807\u7B7E",
 | |
|   FLASHCARD_GOOD_DESC: "\u81EA\u5B9A\u4E49\u201C\u8BB0\u5F97\u201D\u6309\u94AE\u7684\u6807\u7B7E",
 | |
|   FLASHCARD_HARD_DESC: "\u81EA\u5B9A\u4E49\u201C\u8F83\u96BE\u201D\u6309\u94AE\u7684\u6807\u7B7E",
 | |
|   REVIEW_BUTTON_DELAY: "\u6309\u94AE\u6309\u4E0B\u5EF6\u8FDF\uFF08\u6BEB\u79D2\uFF09",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "\u5728\u518D\u6B21\u6309\u4E0B\u590D\u4E60\u6309\u94AE\u524D\u589E\u52A0\u5EF6\u8FDF\u3002",
 | |
|   FLASHCARD_TAGS: "\u5361\u7247\u6807\u7B7E",
 | |
|   FLASHCARD_TAGS_DESC: "\u8F93\u5165\u6807\u7B7E\uFF0C\u7528\u7A7A\u683C\u6216\u65B0\u5EFA\u884C\u5206\u9694\uFF0C\u4F8B\u5982\uFF1A#flashcards #deck2 #deck3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\u5C06\u6587\u4EF6\u5939\u5185\u5BB9\u8F6C\u6362\u4E3A\u5361\u7247\u7EC4\u548C\u5B50\u5361\u7247\u7EC4",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "\u6B64\u9009\u9879\u4E3A\u5361\u7247\u6807\u7B7E\u9009\u9879\u7684\u66FF\u4EE3\u9009\u9879\u3002",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\u5C06\u8BA1\u5212\u91CD\u590D\u65E5\u671F\u4FDD\u5B58\u5728\u5361\u7247\u6700\u540E\u4E00\u884C\u7684\u540C\u4E00\u884C",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "HTML\u6CE8\u91CA\u4E0D\u518D\u7834\u574F\u5217\u8868\u683C\u5F0F",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "\u5C06\u5173\u8054\u5361\u7247\u9690\u85CF\u81F3\u4E0B\u4E00\u5929",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "\u5173\u8054\u5361\u7247\u662F\u6765\u81EA\u540C\u4E00\u5361\u7247\u7684\u4E0D\u540C\u5F62\u5F0F\uFF0C \u4F8B\u5982\uFF1A\u5B8C\u5F62\u586B\u7A7A\u5361\u7247",
 | |
|   SHOW_CARD_CONTEXT: "\u5728\u5361\u7247\u4E2D\u663E\u793A\u4E0A\u4E0B\u6587",
 | |
|   SHOW_CARD_CONTEXT_DESC: "\u4F8B\u5982\uFF1A\u6807\u9898 > \u526F\u6807\u9898 > \u5C0F\u6807\u9898 > ... > \u5C0F\u6807\u9898",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "\u5C06\u4E0B\u6B21\u590D\u4E60\u65F6\u95F4\u663E\u793A\u5728\u590D\u4E60\u6309\u94AE",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "\u4E86\u89E3\u4F60\u7684\u5361\u7247\u88AB\u63A8\u8FDF\u4E86\u591A\u4E45\u5BF9\u4F60\u5F88\u6709\u7528",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "\u5361\u7247\u9AD8\u5EA6\u767E\u5206\u6BD4",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "\u8BF7\u5728\u79FB\u52A8\u7AEF\u4F7F\u7528\u5E76\u9700\u8981\u6D4F\u89C8\u8F83\u5927\u56FE\u7247\u65F6\u8BBE\u4E3A100%",
 | |
|   RESET_DEFAULT: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\u5361\u7247\u5BBD\u5EA6\u767E\u5206\u6BD4",
 | |
|   RANDOMIZE_CARD_ORDER: "\u590D\u4E60\u65F6\u968F\u673A\u663E\u793A\u5361\u7247\uFF1F",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "\u590D\u4E60\u65F6\u5361\u7247\u7EC4\u5185\u7684\u5361\u7247\u6392\u5E8F",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "\u5361\u7247\u7EC4\u5185\u987A\u5E8F (\u5168\u90E8\u65B0\u5361\u7247\u4F18\u5148)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "\u5361\u7247\u7EC4\u5185\u987A\u5E8F (\u5168\u90E8\u5230\u671F\u5361\u7247\u4F18\u5148)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "\u5361\u7247\u7EC4\u5185\u4E71\u5E8F (\u5168\u90E8\u65B0\u5361\u7247\u4F18\u5148)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "\u5361\u7247\u7EC4\u5185\u4E71\u5E8F (\u5168\u90E8\u5230\u671F\u5361\u7247\u4F18\u5148)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "\u5361\u7247\u7EC4\u53CA\u5361\u7247\u90FD\u4E71\u5E8F",
 | |
|   REVIEW_DECK_ORDER: "\u590D\u4E60\u65F6\u5361\u7247\u7EC4\u7684\u6392\u5E8F",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "\u987A\u5E8F (\u5728\u524D\u4E00\u5361\u7247\u7EC4\u5185\u5361\u7247\u90FD\u590D\u4E60\u5B8C\u540E)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "\u4E71\u5E8F (\u5728\u524D\u4E00\u5361\u7247\u7EC4\u5185\u5361\u7247\u90FD\u590D\u4E60\u5B8C\u540E)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "\u5361\u7247\u7EC4\u53CA\u5361\u7247\u90FD\u4E71\u5E8F",
 | |
|   DISABLE_CLOZE_CARDS: "\u4E0D\u8FDB\u884C\u5B8C\u5F62\u586B\u7A7A",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "\u5C06 ==\u9AD8\u4EAE== \u8F6C\u6362\u4E3A\u5B8C\u5F62\u586B\u7A7A",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: '\u6DFB\u52A0/\u5220\u9664 "\u5B8C\u5F62\u586B\u7A7A\u6A21\u5F0F" \u4E2D\u7684 <code>${defaultPattern}</code>',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "\u5C06 **\u7C97\u4F53** \u8F6C\u6362\u4E3A\u5B8C\u5F62\u586B\u7A7A",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: '\u6DFB\u52A0/\u5220\u9664 "\u5B8C\u5F62\u586B\u7A7A\u6A21\u5F0F" \u4E2D\u7684 <code>${defaultPattern}</code>',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "\u5C06 {{\u5927\u62EC\u53F7}} \u8F6C\u6362\u4E3A\u5B8C\u5F62\u586B\u7A7A",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: '\u6DFB\u52A0/\u5220\u9664 "\u5B8C\u5F62\u586B\u7A7A\u6A21\u5F0F" \u4E2D\u7684 <code>${defaultPattern}</code>',
 | |
|   CLOZE_PATTERNS: "\u5B8C\u5F62\u586B\u7A7A\u6A21\u5F0F",
 | |
|   CLOZE_PATTERNS_DESC: '\u8F93\u5165\u4EE5\u6362\u884C\u7B26\u5206\u9694\u7684\u5B8C\u5F62\u586B\u7A7A\u6A21\u5F0F. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "\u5355\u884C\u5361\u7247\u7684\u5206\u9694\u7B26",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "\u6CE8\u610F\uFF1A\u66F4\u6539\u6B64\u9009\u9879\u540E\u4F60\u5C06\u9700\u8981\u81EA\u884C\u66F4\u6539\u5DF2\u5B58\u5728\u5361\u7247\u7684\u5206\u9694\u7B26\u3002",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "\u5355\u884C\u7FFB\u8F6C\u5361\u7247\u7684\u5206\u9694\u7B26",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\u591A\u884C\u5361\u7247\u7684\u5206\u9694\u7B26",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\u591A\u884C\u7FFB\u8F6C\u5361\u7247\u7684\u5206\u9694\u7B26",
 | |
|   MULTILINE_CARDS_END_MARKER: "\u8868\u793A\u586B\u7A7A\u548C\u591A\u884C\u95EA\u5361\u7ED3\u675F\u7684\u5B57\u7B26",
 | |
|   NOTES: "\u7B14\u8BB0",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "\u542F\u52A8\u65F6\u5F00\u542F\u7B14\u8BB0\u590D\u4E60\u7A97\u683C",
 | |
|   TAGS_TO_REVIEW: "\u590D\u4E60\u6807\u7B7E",
 | |
|   TAGS_TO_REVIEW_DESC: "\u8F93\u5165\u6807\u7B7E\uFF0C\u7528\u7A7A\u683C\u6216\u65B0\u5EFA\u884C\u5206\u9694\uFF0C\u4F8B\u5982\uFF1A#review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "\u590D\u4E60\u968F\u673A\u7B14\u8BB0",
 | |
|   OPEN_RANDOM_NOTE_DESC: "\u5173\u95ED\u6B64\u9009\u9879\uFF0C\u7B14\u8BB0\u5C06\u4EE5\u91CD\u8981\u5EA6(PageRank)\u6392\u5E8F\u3002",
 | |
|   AUTO_NEXT_NOTE: "\u590D\u4E60\u540E\u81EA\u52A8\u6253\u5F00\u4E0B\u4E00\u4E2A\u7B14\u8BB0",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "\u8BF7\u5728\u6587\u4EF6\u83DC\u5355\u4E2D\u542F\u7528\u590D\u4E60\u9009\u9879\uFF08\u4F8B\u5982\uFF1A\u590D\u4E60\uFF1A\u7B80\u5355\u3001\u826F\u597D\u3001\u56F0\u96BE",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "\u5982\u679C\u60A8\u5728\u6587\u4EF6\u83DC\u5355\u4E2D\u7981\u7528\u590D\u4E60\u9009\u9879\uFF0C\u60A8\u53EF\u4EE5\u4F7F\u7528\u63D2\u4EF6\u547D\u4EE4\u6765\u590D\u4E60\u7B14\u8BB0\uFF0C\u5982\u679C\u60A8\u5B9A\u4E49\u4E86\u76F8\u5173\u5FEB\u6377\u952E\uFF0C\u4E5F\u53EF\u4EE5\u4F7F\u7528\u5B83\u4EEC\u3002",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "\u53F3\u8FB9\u680F\u4E2D\u663E\u793A\u7684\u6700\u5927\u5929\u6570",
 | |
|   MIN_ONE_DAY: "\u5929\u6570\u6700\u5C0F\u503C\u4E3A1",
 | |
|   VALID_NUMBER_WARNING: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u6570\u5B57\u3002",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "\u5728\u65B0\u6807\u7B7E\u6253\u5F00",
 | |
|   OPEN_IN_TAB_DESC: "\u5173\u95ED\u6B64\u9009\u9879\u53EF\u5728\u6A21\u5F0F\u7A97\u53E3\u4E2D\u6253\u5F00\u63D2\u4EF6",
 | |
|   SHOW_STATUS_BAR: "\u663E\u793A\u5728\u72B6\u6001\u680F",
 | |
|   SHOW_STATUS_BAR_DESC: "\u5C06\u6B64\u5173\u95ED\u4EE5\u9690\u85CF Obsidian \u72B6\u6001\u680F\u4E2D\u7684\u5361\u7247\u590D\u4E60\u72B6\u6001\u3002",
 | |
|   SHOW_RIBBON_ICON: "\u5728\u529F\u80FD\u533A\u4E2D\u663E\u793A\u56FE\u6807",
 | |
|   SHOW_RIBBON_ICON_DESC: "\u5173\u95ED\u6B64\u9009\u9879\u53EF\u9690\u85CF Obsidian \u529F\u80FD\u533A\u680F\u4E2D\u7684\u63D2\u4EF6\u56FE\u6807",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\u9ED8\u8BA4\u5728\u5217\u8868\u4E2D\u5C55\u5F00\u5D4C\u5957\u5B50\u724C\u7EC4",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "\u5173\u95ED\u6B64\u9009\u9879\u53EF\u6298\u53E0\u540C\u4E00\u5F20\u5361\u7247\u4E2D\u7684\u5D4C\u5957\u724C\u7EC4\u3002\u5982\u679C\u60A8\u7684\u5361\u7247\u5C5E\u4E8E\u540C\u4E00\u6587\u4EF6\u4E2D\u7684\u8BB8\u591A\u5957\u724C\uFF0C\u5219\u5F88\u6709\u7528\u3002",
 | |
|   ALGORITHM: "\u7B97\u6CD5",
 | |
|   CHECK_ALGORITHM_WIKI: '\u4E86\u89E3\u66F4\u591A, \u8BF7\u70B9\u51FB<a href="${algoUrl}">\u7B97\u6CD5\u5B9E\u73B0</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "\u57FA\u7840\u638C\u63E1\u7A0B\u5EA6",
 | |
|   BASE_EASE_DESC: "\u6700\u5C0F\u503C130\uFF0C\u63A8\u8350\u503C\u7EA6250.",
 | |
|   BASE_EASE_MIN_WARNING: "\u57FA\u7840\u638C\u63E1\u7A0B\u5EA6\u7684\u6700\u5C0F\u503C\u4E3A130\u3002",
 | |
|   LAPSE_INTERVAL_CHANGE: "\u5C06\u590D\u4E60\u65F6\u6807\u6CE8\u4E3A\u201C\u8F83\u96BE\u201D\u7684\u5361\u7247\u6216\u7B14\u8BB0\u590D\u4E60\u95F4\u9694\u7F29\u77ED",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "\u65B0\u590D\u4E60\u95F4\u9694 = \u539F\u590D\u4E60\u95F4\u9694 * \u95F4\u9694\u6539\u53D8\u7CFB\u6570 / 100.",
 | |
|   EASY_BONUS: "\u7B80\u5355\u5956\u52B1",
 | |
|   EASY_BONUS_DESC: "\u7B80\u5355\u5956\u52B1\u8BBE\u5B9A\u201C\u8BB0\u5F97\u201D\u548C\u201C\u7B80\u5355\u201D\u5361\u7247\u6216\u7B14\u8BB0\u7684\u590D\u4E60\u95F4\u9694\u5DEE\u8DDD\uFF08\u6700\u5C0F\u503C100%\uFF09\u3002",
 | |
|   EASY_BONUS_MIN_WARNING: "\u7B80\u5355\u5956\u52B1\u81F3\u5C11\u4E3A100\u3002",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "\u6700\u5927\u95F4\u9694\uFF08\u5929\uFF09",
 | |
|   MAX_INTERVAL_DESC: "\u8BBE\u5B9A\u590D\u4E60\u7684\u6700\u5927\u95F4\u9694\u65F6\u95F4\uFF08\u9ED8\u8BA4\u503C100\u5E74\uFF09\u3002",
 | |
|   MAX_INTERVAL_MIN_WARNING: "\u6700\u5927\u95F4\u9694\u81F3\u5C11\u4E3A1\u5929",
 | |
|   MAX_LINK_CONTRIB: "\u6700\u5927\u94FE\u63A5\u6536\u76CA",
 | |
|   MAX_LINK_CONTRIB_DESC: "\u94FE\u63A5\u7B14\u8BB0\u7684\u52A0\u6743\u638C\u63E1\u7A0B\u5EA6\u5BF9\u539F\u59CB\u638C\u63E1\u7A0B\u5EA6\u7684\u6700\u5927\u8D21\u732E\u3002",
 | |
|   LOGGING: "\u8BB0\u5F55\u4E2D",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\u5728\u5F00\u53D1\u8005\u63A7\u5236\u53F0\u4E2D\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "\u7B14\u8BB0\u590D\u4E60\u5E8F\u5217",
 | |
|   CLOSE: "\u4E34\u8FD1",
 | |
|   NEW: "\u65B0",
 | |
|   YESTERDAY: "\u6628\u5929",
 | |
|   TODAY: "\u4ECA\u5929",
 | |
|   TOMORROW: "\u660E\u5929",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\u6570\u636E",
 | |
|   MONTH: "\u6708",
 | |
|   QUARTER: "\u5B63",
 | |
|   YEAR: "\u5E74",
 | |
|   LIFETIME: "\u5168\u90E8",
 | |
|   FORECAST: "\u9884\u671F",
 | |
|   FORECAST_DESC: "\u5C06\u8981\u5230\u671F\u7684\u5361\u7247\u6570\u91CF",
 | |
|   SCHEDULED: "\u5DF2\u6392\u671F",
 | |
|   DAYS: "\u5929",
 | |
|   NUMBER_OF_CARDS: "\u5361\u7247\u6570\u91CF",
 | |
|   REVIEWS_PER_DAY: "\u5E73\u5747: \u590D\u4E60${avg} /\u5929",
 | |
|   INTERVALS: "\u95F4\u9694",
 | |
|   INTERVALS_DESC: "\u5230\u4E0B\u4E00\u6B21\u590D\u4E60\u7684\u65F6\u95F4\u95F4\u9694",
 | |
|   COUNT: "\u8BA1\u6570",
 | |
|   INTERVALS_SUMMARY: "\u5E73\u5747\u95F4\u9694\u65F6\u95F4: ${avg}, \u6700\u957F\u95F4\u9694\u65F6\u95F4: ${longest}",
 | |
|   EASES: "\u638C\u63E1\u7A0B\u5EA6",
 | |
|   EASES_SUMMARY: "\u5E73\u5747\u638C\u63E1\u7A0B\u5EA6: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "\u5361\u7247\u7C7B\u578B",
 | |
|   CARD_TYPES_DESC: "\u5982\u6709\uFF0C\u5C06\u663E\u793A\u9690\u85CF\u7684\u5361\u7247",
 | |
|   CARD_TYPE_NEW: "\u65B0",
 | |
|   CARD_TYPE_YOUNG: "\u8F83\u65B0",
 | |
|   CARD_TYPE_MATURE: "\u719F\u6089",
 | |
|   CARD_TYPES_SUMMARY: "\u603B\u5361\u7247\u6570: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/locale/zh-tw.ts
 | |
| var zh_tw_default = {
 | |
|   // flashcard-modal.tsx
 | |
|   DECKS: "\u724C\u7D44",
 | |
|   DUE_CARDS: "\u5230\u671F\u5361\u7247",
 | |
|   NEW_CARDS: "\u65B0\u5361\u7247",
 | |
|   TOTAL_CARDS: "\u5168\u90E8\u5361\u7247",
 | |
|   BACK: "\u8FD4\u56DE",
 | |
|   SKIP: "\u7565\u904E",
 | |
|   EDIT_CARD: "\u7DE8\u8F2F\u5361\u7247",
 | |
|   RESET_CARD_PROGRESS: "\u91CD\u7F6E\u5361\u7247",
 | |
|   HARD: "\u8F03\u96E3",
 | |
|   GOOD: "\u8A18\u5F97",
 | |
|   EASY: "\u7C21\u55AE",
 | |
|   SHOW_ANSWER: "\u986F\u793A\u7B54\u6848",
 | |
|   CARD_PROGRESS_RESET: "\u5361\u7247\u5DF2\u88AB\u91CD\u7F6E\u3002",
 | |
|   SAVE: "\u5132\u5B58",
 | |
|   CANCEL: "\u53D6\u6D88",
 | |
|   NO_INPUT: "\u6C92\u6709\u63D0\u4F9B\u8F38\u5165\u3002",
 | |
|   CURRENT_EASE_HELP_TEXT: "\u76EE\u524D\u638C\u63E1\u7A0B\u5EA6\uFF1A",
 | |
|   CURRENT_INTERVAL_HELP_TEXT: "\u76EE\u524D\u9593\u9694\u6642\u9593\uFF1A",
 | |
|   CARD_GENERATED_FROM: "\u751F\u6210\u81EA\uFF1A${notePath}",
 | |
|   // main.ts
 | |
|   OPEN_NOTE_FOR_REVIEW: "\u6253\u958B\u4E00\u500B\u7B46\u8A18\u958B\u59CB\u5FA9\u7FD2",
 | |
|   REVIEW_CARDS: "\u5FA9\u7FD2\u5361\u7247",
 | |
|   REVIEW_DIFFICULTY_FILE_MENU: "\u5FA9\u7FD2\uFF1A${difficulty}",
 | |
|   REVIEW_NOTE_DIFFICULTY_CMD: "\u6A19\u8A18\u70BA\u300C${difficulty}\u300D",
 | |
|   REVIEW_CARDS_IN_NOTE: "\u5FA9\u7FD2\u6B64\u7B46\u8A18\u4E2D\u7684\u5361\u7247",
 | |
|   CRAM_ALL_CARDS: "\u9078\u64C7\u8981\u4E0D\u8A08\u96E3\u6613\u5EA6\u5FA9\u7FD2\u7684\u724C\u7D44",
 | |
|   REVIEW_ALL_CARDS: "\u5FA9\u7FD2\u6240\u6709\u7B46\u8A18\u4E2D\u7684\u5361\u7247",
 | |
|   CRAM_CARDS_IN_NOTE: "\u4E0D\u8A08\u96E3\u6613\u5EA6\u5FA9\u7FD2\u6B64\u7B46\u8A18\u4E2D\u7684\u5361\u7247",
 | |
|   VIEW_STATS: "\u6AA2\u8996\u6578\u64DA",
 | |
|   OPEN_REVIEW_QUEUE_VIEW: "Open Notes Review Queue in sidebar",
 | |
|   STATUS_BAR: "\u5FA9\u7FD2: ${dueNotesCount} \u7B46\u8A18, ${dueFlashcardsCount} \u5361\u7247\u5DF2\u5230\u671F",
 | |
|   SYNC_TIME_TAKEN: "\u540C\u6B65\u6642\u9593 ${t}ms",
 | |
|   NOTE_IN_IGNORED_FOLDER: "\u7B46\u8A18\u5132\u5B58\u5728\u5DF2\u88AB\u5FFD\u7565\u7684\u8DEF\u5F91\u4E2D\uFF08\u6AA2\u67E5\u8A2D\u5B9A\u9078\u9805\uFF09\u3002",
 | |
|   PLEASE_TAG_NOTE: "\u8ACB\u5C07\u9700\u8981\u5FA9\u7FD2\u7684\u7B46\u8A18\u4E2D\u52A0\u5165\u6B63\u78BA\u7684\u6A19\u7C64\uFF08\u6AA2\u67E5\u8A2D\u5B9A\u9078\u9805\uFF09\u3002",
 | |
|   RESPONSE_RECEIVED: "\u56DE\u994B\u5DF2\u6536\u5230",
 | |
|   NO_DECK_EXISTS: "\u6C92\u6709 ${deckName} \u724C\u7D44",
 | |
|   ALL_CAUGHT_UP: "\u90FD\u5FA9\u7FD2\u5B8C\u5566\uFF0C\u4F60\u771F\u68D2\uFF01",
 | |
|   // scheduling.ts
 | |
|   DAYS_STR_IVL: "${interval}\u5929",
 | |
|   MONTHS_STR_IVL: "${interval}\u6708",
 | |
|   YEARS_STR_IVL: "${interval}\u5E74",
 | |
|   DAYS_STR_IVL_MOBILE: "${interval}\u5929",
 | |
|   MONTHS_STR_IVL_MOBILE: "${interval}\u6708",
 | |
|   YEARS_STR_IVL_MOBILE: "${interval}\u5E74",
 | |
|   // settings.ts
 | |
|   SETTINGS_HEADER: "\u9593\u9694\u91CD\u8907\u5916\u639B",
 | |
|   GROUP_TAGS_FOLDERS: "Tags & Folders",
 | |
|   GROUP_FLASHCARD_REVIEW: "Flashcard Review",
 | |
|   GROUP_FLASHCARD_SEPARATORS: "Flashcard Separators",
 | |
|   GROUP_DATA_STORAGE: "Storage of Scheduling Data",
 | |
|   GROUP_DATA_STORAGE_DESC: "Choose where to store the scheduling data",
 | |
|   GROUP_FLASHCARDS_NOTES: "Flashcards & Notes",
 | |
|   GROUP_CONTRIBUTING: "Contributing",
 | |
|   CHECK_WIKI: '\u77AD\u89E3\u66F4\u591A, \u8ACB\u9EDE\u9078<a href="${wikiUrl}">wiki</a>.',
 | |
|   GITHUB_DISCUSSIONS: 'Visit the <a href="${discussionsUrl}">discussions</a> section for Q&A help, feedback, and general discussion.',
 | |
|   GITHUB_ISSUES: 'Raise an issue <a href="${issuesUrl}">here</a> if you have a feature request or a bug report.',
 | |
|   GITHUB_SOURCE_CODE: 'The project\'s source code is available on <a href="${githubProjectUrl}">GitHub</a>.',
 | |
|   CODE_CONTRIBUTION_INFO: '<a href="${codeContributionUrl}">Here\'s</a> how to contribute code to the plugin.',
 | |
|   TRANSLATION_CONTRIBUTION_INFO: '<a href="${translationContributionUrl}">Here\'s</a> how to translate the plugin to another language.',
 | |
|   FOLDERS_TO_IGNORE: "\u5FFD\u7565\u6B64\u8CC7\u6599\u593E",
 | |
|   FOLDERS_TO_IGNORE_DESC: "Enter folder paths or glob patterns on separate lines e.g. Templates/Scripts or **/*.excalidraw.md. This setting is common to both flashcards and notes.",
 | |
|   OBSIDIAN_INTEGRATION: "Integration into Obsidian",
 | |
|   FLASHCARDS: "\u5361\u7247",
 | |
|   FLASHCARD_EASY_LABEL: "\u7C21\u55AE\u6309\u9215\u6587\u5B57",
 | |
|   FLASHCARD_GOOD_LABEL: "\u8A18\u5F97\u6309\u9215\u6587\u5B57",
 | |
|   FLASHCARD_HARD_LABEL: "\u8F03\u96E3\u6309\u9215\u6587\u5B57",
 | |
|   FLASHCARD_EASY_DESC: "\u81EA\u8A02\u300C\u7C21\u55AE\u300D\u6309\u9215\u7684\u6A19\u7C64",
 | |
|   FLASHCARD_GOOD_DESC: "\u81EA\u8A02\u300C\u8A18\u5F97\u300D\u6309\u9215\u7684\u6A19\u7C64",
 | |
|   FLASHCARD_HARD_DESC: "\u81EA\u8A02\u300C\u8F03\u96E3\u300D\u6309\u9215\u7684\u6A19\u7C64",
 | |
|   REVIEW_BUTTON_DELAY: "Button Press Delay (ms)",
 | |
|   REVIEW_BUTTON_DELAY_DESC: "Add a delay to the review buttons before they can be pressed again.",
 | |
|   FLASHCARD_TAGS: "\u5361\u7247\u6A19\u7C64",
 | |
|   FLASHCARD_TAGS_DESC: "\u8F38\u5165\u6A19\u7C64\uFF08\u7528\u7A7A\u767D\u6216\u63DB\u884C\u5B57\u5143\u5206\u9694\uFF09\uFF0C\u4F8B\u5982\uFF1A#flashcards #deck2 #deck3.",
 | |
|   CONVERT_FOLDERS_TO_DECKS: "\u662F\u5426\u5C07\u8CC7\u6599\u593E\u5167\u5BB9\u8F49\u63DB\u70BA\u724C\u7D44\u548C\u5B50\u724C\u7D44\uFF1F",
 | |
|   CONVERT_FOLDERS_TO_DECKS_DESC: "\u6B64\u9078\u9805\u70BA\u5361\u7247\u6A19\u7C64\u9078\u9805\u7684\u66FF\u4EE3\u9078\u9805\u3002",
 | |
|   INLINE_SCHEDULING_COMMENTS: "\u662F\u5426\u5C07\u8A08\u5283\u91CD\u8907\u6642\u9593\u5132\u5B58\u5728\u5361\u7247\u6700\u5F8C\u4E00\u884C\u7684\u540C\u4E00\u884C\uFF1F",
 | |
|   INLINE_SCHEDULING_COMMENTS_DESC: "\u52FE\u9078\u5F8CHTML\u8A3B\u89E3\u4E0D\u6703\u7834\u58DE\u5217\u8868\u683C\u5F0F\u554F\u984C\u3002",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY: "\u5C07\u53CD\u8F49\u5361\u7247\u96B1\u85CF\u81F3\u4E0B\u4E00\u5929\uFF1F",
 | |
|   BURY_SIBLINGS_TILL_NEXT_DAY_DESC: "\u53CD\u8F49\u5361\u7247\u7531\u540C\u4E00\u5361\u7247\u6587\u5B57\u7522\u751F\uFF0C\u4F8B\u5982\uFF1A\u586B\u7A7A\u514B\u6F0F\u5B57",
 | |
|   SHOW_CARD_CONTEXT: "\u5728\u5361\u7247\u4E2D\u986F\u793A\u4E0A\u4E0B\u6587\uFF1F",
 | |
|   SHOW_CARD_CONTEXT_DESC: "\u4F8B\u5982\uFF1A\u6A19\u984C > \u526F\u6A19\u984C > \u5C0F\u6A19\u984C > ... > \u5C0F\u6A19\u984C",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS: "Show next review time in the review buttons",
 | |
|   SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC: "Useful to know how far in the future your cards are being pushed.",
 | |
|   CARD_MODAL_HEIGHT_PERCENT: "\u5361\u7247\u9AD8\u5EA6\u767E\u5206\u6BD4",
 | |
|   CARD_MODAL_SIZE_PERCENT_DESC: "\u5728\u79FB\u52D5\u7AEF\u6216\u9700\u8981\u8F03\u5927\u5716\u7247\u6642\u61C9\u8A2D\u5B9A\u70BA100%",
 | |
|   RESET_DEFAULT: "\u91CD\u7F6E\u70BA\u9810\u8A2D\u503C",
 | |
|   CARD_MODAL_WIDTH_PERCENT: "\u5361\u7247\u5BEC\u5EA6\u767E\u5206\u6BD4",
 | |
|   RANDOMIZE_CARD_ORDER: "\u5FA9\u7FD2\u6642\u96A8\u6A5F\u986F\u793A\u5361\u7247\uFF1F",
 | |
|   REVIEW_CARD_ORDER_WITHIN_DECK: "\u5FA9\u7FD2\u6642\u724C\u7D44\u5167\u7684\u5361\u7247\u6392\u5E8F",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL: "\u724C\u7D44\u5167\u9806\u5E8F (\u5168\u90E8\u65B0\u5361\u7247\u512A\u5148)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL: "\u724C\u7D44\u5167\u9806\u5E8F (\u5168\u90E8\u5230\u671F\u5361\u7247\u512A\u5148)",
 | |
|   REVIEW_CARD_ORDER_NEW_FIRST_RANDOM: "\u724C\u7D44\u5167\u4E82\u5E8F (\u5168\u90E8\u65B0\u5361\u7247\u512A\u5148)",
 | |
|   REVIEW_CARD_ORDER_DUE_FIRST_RANDOM: "\u724C\u7D44\u5167\u4E82\u5E8F (\u5168\u90E8\u5230\u671F\u5361\u7247\u512A\u5148)",
 | |
|   REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD: "\u724C\u7D44\u53CA\u5361\u7247\u90FD\u4E82\u5E8F",
 | |
|   REVIEW_DECK_ORDER: "\u5FA9\u7FD2\u6642\u724C\u7D44\u7684\u6392\u5E8F",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "\u9806\u5E8F (\u5728\u524D\u4E00\u724C\u7D44\u5167\u5361\u7247\u90FD\u5FA9\u7FD2\u5B8C\u5F8C)",
 | |
|   REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "\u4E82\u5E8F (\u5728\u524D\u4E00\u724C\u7D44\u5167\u5361\u7247\u90FD\u5FA9\u7FD2\u5B8C\u5F8C)",
 | |
|   REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "\u724C\u7D44\u53CA\u5361\u7247\u90FD\u4E82\u5E8F",
 | |
|   DISABLE_CLOZE_CARDS: "\u505C\u7528\u586B\u7A7A\u514B\u6F0F\u5B57\u5361\u7247\uFF1F",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES: "\u5C07 ==\u9AD8\u4EAE== \u8F49\u63DB\u70BA\u586B\u7A7A\u514B\u6F0F\u5B57\uFF1F",
 | |
|   CONVERT_HIGHLIGHTS_TO_CLOZES_DESC: '\u5728 "\u586B\u7A7A\u514B\u6F0F\u5B57\u6A21\u5F0F" \u4E2D\u52A0\u5165/\u79FB\u9664 <code>${defaultPattern}</code>',
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES: "\u5C07 **\u7C97\u9AD4** \u8F49\u63DB\u70BA\u586B\u7A7A\u514B\u6F0F\u5B57\uFF1F",
 | |
|   CONVERT_BOLD_TEXT_TO_CLOZES_DESC: '\u5728 "\u586B\u7A7A\u514B\u6F0F\u5B57\u6A21\u5F0F" \u4E2D\u52A0\u5165/\u79FB\u9664 <code>${defaultPattern}</code>',
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES: "\u5C07 {{\u5927\u62EC\u865F}} \u8F49\u63DB\u70BA\u586B\u7A7A\u514B\u6F0F\u5B57\uFF1F",
 | |
|   CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC: '\u5728 "\u586B\u7A7A\u514B\u6F0F\u5B57\u6A21\u5F0F" \u4E2D\u52A0\u5165/\u79FB\u9664 <code>${defaultPattern}</code>',
 | |
|   CLOZE_PATTERNS: "\u586B\u7A7A\u514B\u6F0F\u5B57\u6A21\u5F0F",
 | |
|   CLOZE_PATTERNS_DESC: '\u8F38\u5165\u4EE5\u63DB\u884C\u7B26\u5206\u9694\u7684\u586B\u7A7A\u514B\u6F0F\u5B57\u6A21\u5F0F. Check the <a href="${docsUrl}">wiki</a> for guidance.',
 | |
|   INLINE_CARDS_SEPARATOR: "\u55AE\u884C\u5361\u7247\u7684\u5206\u9694\u5B57\u5143",
 | |
|   FIX_SEPARATORS_MANUALLY_WARNING: "\u6CE8\u610F\uFF1A\u66F4\u6539\u6B64\u9078\u9805\u5F8C\u4F60\u5C07\u9700\u8981\u81EA\u884C\u66F4\u6539\u5DF2\u5B58\u5728\u5361\u7247\u7684\u5206\u9694\u5B57\u5143\u3002",
 | |
|   INLINE_REVERSED_CARDS_SEPARATOR: "\u55AE\u884C\u53CD\u8F49\u5361\u7247\u7684\u5206\u9694\u5B57\u5143",
 | |
|   MULTILINE_CARDS_SEPARATOR: "\u591A\u884C\u5361\u7247\u7684\u5206\u9694\u5B57\u5143",
 | |
|   MULTILINE_REVERSED_CARDS_SEPARATOR: "\u591A\u884C\u7FFB\u8F49\u5361\u7247\u7684\u5206\u9694\u5B57\u5143",
 | |
|   MULTILINE_CARDS_END_MARKER: "\u8868\u793A\u586B\u7A7A\u548C\u591A\u884C\u95EA\u5361\u7ED3\u675F\u7684\u5B57\u7B26",
 | |
|   NOTES: "\u7B46\u8A18",
 | |
|   NOTE: "Note",
 | |
|   REVIEW_PANE_ON_STARTUP: "\u555F\u52D5\u6642\u958B\u555F\u7B46\u8A18\u5FA9\u7FD2\u7A97\u683C",
 | |
|   TAGS_TO_REVIEW: "\u5FA9\u7FD2\u6A19\u7C64",
 | |
|   TAGS_TO_REVIEW_DESC: "\u8F38\u5165\u6A19\u7C64\uFF0C\u7528\u7A7A\u683C\u6216\u63DB\u884C\u5B57\u5143\u5206\u9694\uFF0C\u4F8B\u5982\uFF1A#review #tag2 #tag3.",
 | |
|   OPEN_RANDOM_NOTE: "\u5FA9\u7FD2\u96A8\u6A5F\u7B46\u8A18",
 | |
|   OPEN_RANDOM_NOTE_DESC: "\u95DC\u9589\u6B64\u9078\u9805\uFF0C\u7B46\u8A18\u5C07\u4EE5\u91CD\u8981\u5EA6(PageRank)\u6392\u5E8F\u3002",
 | |
|   AUTO_NEXT_NOTE: "\u5FA9\u7FD2\u5F8C\u81EA\u52D5\u6253\u958B\u4E0B\u4E00\u500B\u7B46\u8A18",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS: "\u8ACB\u5728\u6A94\u6848\u9078\u55AE\u4E2D\u555F\u7528\u6AA2\u8996\u9078\u9805\uFF08\u4F8B\u5982\uFF1A\u6AA2\u8996\uFF1A\u7C21\u55AE\u3001\u8A18\u5F97\u3001\u8F03\u96E3\uFF09",
 | |
|   ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC: "\u5982\u679C\u60A8\u5728\u6A94\u6848\u9078\u55AE\u4E2D\u505C\u7528\u6AA2\u8996\u9078\u9805\uFF0C\u60A8\u53EF\u4EE5\u4F7F\u7528\u63D2\u4EF6\u6307\u4EE4\u6AA2\u8996\u7B46\u8A18\uFF0C\u5982\u679C\u6709\u8A2D\u5B9A\uFF0C\u4E5F\u53EF\u4EE5\u4F7F\u7528\u76F8\u95DC\u7684\u5FEB\u6377\u9375\u3002",
 | |
|   MAX_N_DAYS_REVIEW_QUEUE: "\u53F3\u908A\u9762\u677F\u986F\u793A\u7684\u6700\u5927\u5929\u6578",
 | |
|   MIN_ONE_DAY: "\u5929\u6578\u6700\u5C0F\u503C\u70BA1",
 | |
|   VALID_NUMBER_WARNING: "\u8ACB\u8F38\u5165\u6709\u6548\u7684\u6578\u5B57\u3002",
 | |
|   UI: "User Interface",
 | |
|   OPEN_IN_TAB: "Open in new tab",
 | |
|   OPEN_IN_TAB_DESC: "Turn this off to open the plugin in a modal window",
 | |
|   SHOW_STATUS_BAR: "Show status bar",
 | |
|   SHOW_STATUS_BAR_DESC: "Turn this off to hide the flashcard's review status in Obsidian's status bar",
 | |
|   SHOW_RIBBON_ICON: "Show icon in the ribbon bar",
 | |
|   SHOW_RIBBON_ICON_DESC: "Turn this off to hide the plugin icon from Obsidian's ribbon bar",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE: "\u724C\u7D44\u6A39\u6700\u521D\u61C9\u986F\u793A\u70BA\u5C55\u958B",
 | |
|   INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC: "\u95DC\u9589\u6B64\u9078\u9805\u53EF\u647A\u758A\u540C\u4E00\u5F35\u5361\u7247\u4E2D\u7684\u5DE2\u72C0\u724C\u7D44\u3002\u5982\u679C\u60A8\u7684\u5361\u7247\u5C6C\u65BC\u540C\u4E00\u6A94\u6848\u4E2D\u7684\u8A31\u591A\u5957\u724C\uFF0C\u5247\u5F88\u6709\u7528\u3002",
 | |
|   ALGORITHM: "\u6F14\u7B97\u6CD5",
 | |
|   CHECK_ALGORITHM_WIKI: '\u77AD\u89E3\u66F4\u591A, \u8ACB\u9EDE\u9078<a href="${algoUrl}">\u7B97\u6CD5\u5BE6\u73FE</a>.',
 | |
|   SM2_OSR_VARIANT: "OSR's variant of SM-2",
 | |
|   BASE_EASE: "\u57FA\u790E\u638C\u63E1\u7A0B\u5EA6",
 | |
|   BASE_EASE_DESC: "\u6700\u5C0F\u503C130\uFF0C\u63A8\u85A6\u503C\u7D04250.",
 | |
|   BASE_EASE_MIN_WARNING: "\u57FA\u790E\u638C\u63E1\u7A0B\u5EA6\u7684\u6700\u5C0F\u503C\u70BA130\u3002",
 | |
|   LAPSE_INTERVAL_CHANGE: "\u5C07\u5FA9\u7FD2\u6642\u6A19\u8A3B\u70BA\u300C\u8F03\u96E3\u300D\u7684\u5361\u7247\u6216\u7B46\u8A18\u5FA9\u7FD2\u9593\u9694\u7E2E\u77ED",
 | |
|   LAPSE_INTERVAL_CHANGE_DESC: "\u65B0\u5FA9\u7FD2\u9593\u9694 = \u539F\u5FA9\u7FD2\u9593\u9694 * \u9593\u9694\u6539\u8B8A\u4FC2\u6578 / 100.",
 | |
|   EASY_BONUS: "\u7C21\u55AE\u734E\u52F5",
 | |
|   EASY_BONUS_DESC: "\u7C21\u55AE\u734E\u52F5\u8A2D\u5B9A\u300C\u8A18\u5F97\u300D\u548C\u300C\u7C21\u55AE\u300D\u5361\u7247\u6216\u7B46\u8A18\u7684\u5FA9\u7FD2\u9593\u9694\u5DEE\u8DDD\uFF08\u6700\u5C0F\u503C100%\uFF09\u3002",
 | |
|   EASY_BONUS_MIN_WARNING: "\u7C21\u55AE\u734E\u52F5\u81F3\u5C11\u70BA100\u3002",
 | |
|   LOAD_BALANCE: "Enable load balancer",
 | |
|   LOAD_BALANCE_DESC: `Slightly tweaks the interval so that the number of reviews per day is more consistent.
 | |
|         It's like Anki's fuzz but instead of being random, it picks the day with the least amount of reviews.
 | |
|         It's turned off for small intervals.`,
 | |
|   MAX_INTERVAL: "\u6700\u5927\u9593\u9694\uFF08\u5929\uFF09",
 | |
|   MAX_INTERVAL_DESC: "\u8A2D\u5B9A\u5FA9\u7FD2\u7684\u6700\u5927\u9593\u9694\u6642\u9593\uFF08\u9810\u8A2D\u503C100\u5E74\uFF09\u3002",
 | |
|   MAX_INTERVAL_MIN_WARNING: "\u6700\u5927\u9593\u9694\u81F3\u5C11\u70BA1\u5929",
 | |
|   MAX_LINK_CONTRIB: "\u6700\u5927\u93C8\u63A5\u8CA2\u737B",
 | |
|   MAX_LINK_CONTRIB_DESC: "\u93C8\u63A5\u7B46\u8A18\u7684\u52A0\u6B0A\u638C\u63E1\u7A0B\u5EA6\u5C0D\u539F\u59CB\u638C\u63E1\u7A0B\u5EA6\u7684\u6700\u5927\u8CA2\u737B\u3002",
 | |
|   LOGGING: "\u8A18\u9304\u4E2D",
 | |
|   DISPLAY_SCHEDULING_DEBUG_INFO: "\u5728\u958B\u767C\u8005\u63A7\u5236\u53F0\u4E2D\u986F\u793A\u9664\u932F\u8CC7\u8A0A",
 | |
|   DISPLAY_PARSER_DEBUG_INFO: "Show the parser's debugging information on the developer console",
 | |
|   SCHEDULING: "Scheduling",
 | |
|   EXPERIMENTAL: "Experimental",
 | |
|   HELP: "Help",
 | |
|   STORE_IN_NOTES: "In the notes",
 | |
|   // sidebar.ts
 | |
|   NOTES_REVIEW_QUEUE: "\u7B46\u8A18\u5FA9\u7FD2\u5E8F\u5217",
 | |
|   CLOSE: "\u81E8\u8FD1",
 | |
|   NEW: "\u65B0",
 | |
|   YESTERDAY: "\u6628\u5929",
 | |
|   TODAY: "\u4ECA\u5929",
 | |
|   TOMORROW: "\u660E\u5929",
 | |
|   // stats-modal.tsx
 | |
|   STATS_TITLE: "\u7D71\u8A08",
 | |
|   MONTH: "\u6708",
 | |
|   QUARTER: "\u5B63",
 | |
|   YEAR: "\u5E74",
 | |
|   LIFETIME: "\u5168\u90E8",
 | |
|   FORECAST: "\u9810\u6E2C",
 | |
|   FORECAST_DESC: "\u5C07\u8981\u5230\u671F\u7684\u5361\u7247\u6578\u91CF",
 | |
|   SCHEDULED: "\u5DF2\u6392\u7A0B",
 | |
|   DAYS: "\u5929",
 | |
|   NUMBER_OF_CARDS: "\u5361\u7247\u6578\u91CF",
 | |
|   REVIEWS_PER_DAY: "\u5E73\u5747: \u5FA9\u7FD2${avg} /\u5929",
 | |
|   INTERVALS: "\u9593\u9694",
 | |
|   INTERVALS_DESC: "\u5230\u4E0B\u4E00\u6B21\u5FA9\u7FD2\u7684\u6642\u9593\u9593\u9694",
 | |
|   COUNT: "\u8A08\u6578",
 | |
|   INTERVALS_SUMMARY: "\u5E73\u5747\u9593\u9694\u6642\u9593: ${avg}, \u6700\u9577\u9593\u9694\u6642\u9593: ${longest}",
 | |
|   EASES: "\u638C\u63E1\u7A0B\u5EA6",
 | |
|   EASES_SUMMARY: "\u5E73\u5747\u638C\u63E1\u7A0B\u5EA6: ${avgEase}",
 | |
|   EASE: "Ease",
 | |
|   CARD_TYPES: "\u5361\u7247\u578B\u5225",
 | |
|   CARD_TYPES_DESC: "\u5982\u6709\uFF0C\u5C07\u986F\u793A\u96B1\u85CF\u7684\u5361\u7247",
 | |
|   CARD_TYPE_NEW: "\u65B0",
 | |
|   CARD_TYPE_YOUNG: "\u8F03\u65B0",
 | |
|   CARD_TYPE_MATURE: "\u719F\u6089",
 | |
|   CARD_TYPES_SUMMARY: "\u7E3D\u5361\u7247\u6578: ${totalCardsCount}",
 | |
|   SEARCH: "Search",
 | |
|   PREVIOUS: "Previous",
 | |
|   NEXT: "Next"
 | |
| };
 | |
| 
 | |
| // src/lang/helpers.ts
 | |
| var localeMap = {
 | |
|   af: af_default,
 | |
|   ar: ar_default,
 | |
|   bn: bn_default,
 | |
|   cs: cz_default,
 | |
|   da: da_default,
 | |
|   de: de_default,
 | |
|   en: en_default,
 | |
|   "en-gb": en_gb_default,
 | |
|   es: es_default,
 | |
|   fr: fr_default,
 | |
|   hi: hi_default,
 | |
|   id: id_default,
 | |
|   it: it_default,
 | |
|   ja: ja_default,
 | |
|   ko: ko_default,
 | |
|   mr: mr_default,
 | |
|   nl: nl_default,
 | |
|   nn: no_default,
 | |
|   pl: pl_default,
 | |
|   pt: pt_default,
 | |
|   "pt-br": pt_br_default,
 | |
|   ro: ro_default,
 | |
|   ru: ru_default,
 | |
|   sw: sw_default,
 | |
|   ta: ta_default,
 | |
|   te: te_default,
 | |
|   th: th_default,
 | |
|   tr: tr_default,
 | |
|   uk: uk_default,
 | |
|   ur: ur_default,
 | |
|   vi: vi_default,
 | |
|   "zh-cn": zh_cn_default,
 | |
|   "zh-tw": zh_tw_default
 | |
| };
 | |
| var locale = localeMap[import_obsidian.moment.locale()];
 | |
| function interpolate(str, params) {
 | |
|   const names2 = Object.keys(params);
 | |
|   const vals = Object.values(params);
 | |
|   return new Function(...names2, `return \`${str}\`;`)(...vals);
 | |
| }
 | |
| function t(str, params) {
 | |
|   if (!locale) {
 | |
|     console.error(`SRS error: Locale ${import_obsidian.moment.locale()} not found.`);
 | |
|   }
 | |
|   const result = locale && locale[str] || en_default[str];
 | |
|   if (params) {
 | |
|     return interpolate(result, params);
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| // src/algorithms/osr/note-scheduling.ts
 | |
| function osrSchedule(response, originalInterval, ease, delayedBeforeReview, settings, dueDateHistogram) {
 | |
|   const delayedBeforeReviewDays = Math.max(0, Math.floor(delayedBeforeReview / TICKS_PER_DAY));
 | |
|   let interval = originalInterval;
 | |
|   if (response === 0 /* Easy */) {
 | |
|     ease += 20;
 | |
|     interval = (interval + delayedBeforeReviewDays) * ease / 100;
 | |
|     interval *= settings.easyBonus;
 | |
|   } else if (response === 1 /* Good */) {
 | |
|     interval = (interval + delayedBeforeReviewDays / 2) * ease / 100;
 | |
|   } else if (response === 2 /* Hard */) {
 | |
|     ease = Math.max(130, ease - 20);
 | |
|     interval = Math.max(
 | |
|       1,
 | |
|       (interval + delayedBeforeReviewDays / 4) * settings.lapsesIntervalChange
 | |
|     );
 | |
|   }
 | |
|   if (settings.loadBalance && dueDateHistogram !== void 0) {
 | |
|     interval = Math.round(interval);
 | |
|     if (interval > 7) {
 | |
|       let fuzz;
 | |
|       if (interval <= 21) fuzz = 1;
 | |
|       else if (interval <= 180) fuzz = Math.min(3, Math.floor(interval * 0.05));
 | |
|       else fuzz = Math.min(7, Math.floor(interval * 0.025));
 | |
|       interval = dueDateHistogram.findLeastUsedIntervalOverRange(interval, fuzz);
 | |
|     }
 | |
|   }
 | |
|   interval = Math.min(interval, settings.maximumInterval);
 | |
|   interval = Math.round(interval * 10) / 10;
 | |
|   return { interval, ease };
 | |
| }
 | |
| function textInterval(interval, isMobile) {
 | |
|   if (interval === void 0) {
 | |
|     return t("NEW");
 | |
|   }
 | |
|   const m2 = Math.round(interval / 3.04375) / 10, y2 = Math.round(interval / 36.525) / 10;
 | |
|   if (isMobile) {
 | |
|     if (m2 < 1) return t("DAYS_STR_IVL_MOBILE", { interval });
 | |
|     else if (y2 < 1) return t("MONTHS_STR_IVL_MOBILE", { interval: m2 });
 | |
|     else return t("YEARS_STR_IVL_MOBILE", { interval: y2 });
 | |
|   } else {
 | |
|     if (m2 < 1) return t("DAYS_STR_IVL", { interval });
 | |
|     else if (y2 < 1) return t("MONTHS_STR_IVL", { interval: m2 });
 | |
|     else return t("YEARS_STR_IVL", { interval: y2 });
 | |
|   }
 | |
| }
 | |
| 
 | |
| // src/utils/dates.ts
 | |
| var import_moment = __toESM(require_moment());
 | |
| function formatDateYYYYMMDD(ticks) {
 | |
|   return ticks.format(PREFERRED_DATE_FORMAT);
 | |
| }
 | |
| var LiveDateProvider = class {
 | |
|   get now() {
 | |
|     return (0, import_moment.default)();
 | |
|   }
 | |
|   get today() {
 | |
|     return (0, import_moment.default)().startOf("day");
 | |
|   }
 | |
| };
 | |
| var DateUtil = class {
 | |
|   static dateStrToMoment(str) {
 | |
|     return (0, import_moment.default)(str, ALLOWED_DATE_FORMATS);
 | |
|   }
 | |
| };
 | |
| var globalDateProvider = new LiveDateProvider();
 | |
| 
 | |
| // src/algorithms/base/rep-item-schedule-info.ts
 | |
| var RepItemScheduleInfo = class {
 | |
|   get dueDateAsUnix() {
 | |
|     return this.dueDate.valueOf();
 | |
|   }
 | |
|   isDue() {
 | |
|     return this.dueDate && this.dueDate.isSameOrBefore(globalDateProvider.today);
 | |
|   }
 | |
|   formatDueDate() {
 | |
|     return formatDateYYYYMMDD(this.dueDate);
 | |
|   }
 | |
|   delayedBeforeReviewDaysInt() {
 | |
|     return Math.max(0, Math.floor(this.delayedBeforeReviewTicks / TICKS_PER_DAY));
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/algorithms/osr/rep-item-schedule-info-osr.ts
 | |
| var _RepItemScheduleInfoOsr = class _RepItemScheduleInfoOsr extends RepItemScheduleInfo {
 | |
|   constructor(dueDate, interval, latestEase, delayedBeforeReviewTicks = null) {
 | |
|     super();
 | |
|     this.dueDate = dueDate;
 | |
|     this.interval = Math.round(interval);
 | |
|     this.latestEase = latestEase;
 | |
|     this.delayedBeforeReviewTicks = delayedBeforeReviewTicks;
 | |
|     if (dueDate && delayedBeforeReviewTicks == null) {
 | |
|       this.delayedBeforeReviewTicks = globalDateProvider.today.valueOf() - dueDate.valueOf();
 | |
|     }
 | |
|   }
 | |
|   formatCardScheduleForHtmlComment() {
 | |
|     const dateStr = this.dueDate ? this.formatDueDate() : _RepItemScheduleInfoOsr.dummyDueDateForNewCard;
 | |
|     return `!${dateStr},${this.interval},${this.latestEase}`;
 | |
|   }
 | |
|   static get initialInterval() {
 | |
|     return 1;
 | |
|   }
 | |
|   static getDummyScheduleForNewCard(settings) {
 | |
|     return _RepItemScheduleInfoOsr.fromDueDateStr(
 | |
|       _RepItemScheduleInfoOsr.dummyDueDateForNewCard,
 | |
|       _RepItemScheduleInfoOsr.initialInterval,
 | |
|       settings.baseEase
 | |
|     );
 | |
|   }
 | |
|   static fromDueDateStr(dueDateStr, interval, ease, delayedBeforeReviewTicks = null) {
 | |
|     const dueDate = DateUtil.dateStrToMoment(dueDateStr);
 | |
|     return new _RepItemScheduleInfoOsr(dueDate, interval, ease, delayedBeforeReviewTicks);
 | |
|   }
 | |
| };
 | |
| // A question can have multiple cards. The schedule info for all sibling cards are formatted together
 | |
| // in a single <!--SR: --> comment, such as:
 | |
| // <!--SR:!2023-09-02,4,270!2023-09-02,5,270!2023-09-02,6,270!2023-09-02,7,270-->
 | |
| //
 | |
| // However, not all sibling cards may have been reviewed. Therefore we need a method of indicating that a particular card
 | |
| // has not been reviewed, and should be considered "new"
 | |
| // This is done by using this magic value for the date
 | |
| _RepItemScheduleInfoOsr.dummyDueDateForNewCard = "2000-01-01";
 | |
| var RepItemScheduleInfoOsr = _RepItemScheduleInfoOsr;
 | |
| 
 | |
| // src/note-ease-list.ts
 | |
| var NoteEaseList = class {
 | |
|   constructor(settings) {
 | |
|     this.dict = {};
 | |
|     this.settings = settings;
 | |
|   }
 | |
|   get baseEase() {
 | |
|     return this.settings.baseEase;
 | |
|   }
 | |
|   hasEaseForPath(path3) {
 | |
|     return Object.prototype.hasOwnProperty.call(this.dict, path3);
 | |
|   }
 | |
|   getEaseByPath(path3) {
 | |
|     let ease = null;
 | |
|     if (this.hasEaseForPath(path3)) {
 | |
|       ease = Math.round(this.dict[path3]);
 | |
|     }
 | |
|     return ease;
 | |
|   }
 | |
|   setEaseForPath(path3, ease) {
 | |
|     this.dict[path3] = ease;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/algorithms/osr/srs-algorithm-osr.ts
 | |
| var SrsAlgorithmOsr = class _SrsAlgorithmOsr {
 | |
|   constructor(settings) {
 | |
|     this.settings = settings;
 | |
|     this.noteEaseList = new NoteEaseList(settings);
 | |
|   }
 | |
|   static get initialInterval() {
 | |
|     return 1;
 | |
|   }
 | |
|   noteCalcNewSchedule(notePath, osrNoteGraph, response, dueDateNoteHistogram) {
 | |
|     const noteLinkStat = osrNoteGraph.calcNoteLinkStat(
 | |
|       notePath,
 | |
|       this.noteEaseList
 | |
|     );
 | |
|     const linkContribution = this.settings.maxLinkFactor * Math.min(1, Math.log(noteLinkStat.totalLinkCount + 0.5) / Math.log(64));
 | |
|     let ease = (1 - linkContribution) * this.settings.baseEase + (noteLinkStat.totalLinkCount > 0 ? linkContribution * noteLinkStat.linkTotal / noteLinkStat.linkPGTotal : linkContribution * this.settings.baseEase);
 | |
|     if (this.noteEaseList.hasEaseForPath(notePath)) {
 | |
|       ease = (ease + this.noteEaseList.getEaseByPath(notePath)) / 2;
 | |
|     }
 | |
|     const dueDate = null;
 | |
|     const interval = _SrsAlgorithmOsr.initialInterval;
 | |
|     ease = Math.round(ease);
 | |
|     const temp = new RepItemScheduleInfoOsr(dueDate, interval, ease);
 | |
|     const result = this.calcSchedule(
 | |
|       temp,
 | |
|       response,
 | |
|       dueDateNoteHistogram
 | |
|     );
 | |
|     result.dueDate = (0, import_moment2.default)(globalDateProvider.today.add(result.interval, "d"));
 | |
|     return result;
 | |
|   }
 | |
|   noteOnLoadedNote(path3, note, noteEase) {
 | |
|     let flashcardsInNoteAvgEase = null;
 | |
|     if (note) {
 | |
|       flashcardsInNoteAvgEase = _SrsAlgorithmOsr.calculateFlashcardAvgEase(
 | |
|         note.questionList,
 | |
|         this.settings
 | |
|       );
 | |
|     }
 | |
|     let ease = null;
 | |
|     if (flashcardsInNoteAvgEase && noteEase) {
 | |
|       ease = (flashcardsInNoteAvgEase + noteEase) / 2;
 | |
|     } else {
 | |
|       ease = flashcardsInNoteAvgEase ? flashcardsInNoteAvgEase : noteEase;
 | |
|     }
 | |
|     if (ease) {
 | |
|       this.noteEaseList.setEaseForPath(path3, ease);
 | |
|     }
 | |
|   }
 | |
|   static calculateFlashcardAvgEase(questionList, settings) {
 | |
|     let totalEase = 0;
 | |
|     let scheduledCount = 0;
 | |
|     questionList.forEach((question) => {
 | |
|       question.cards.filter((card) => card.hasSchedule).forEach((card) => {
 | |
|         totalEase += card.scheduleInfo.latestEase;
 | |
|         scheduledCount++;
 | |
|       });
 | |
|     });
 | |
|     let result = 0;
 | |
|     if (scheduledCount > 0) {
 | |
|       const flashcardsInNoteAvgEase = totalEase / scheduledCount;
 | |
|       const flashcardContribution = Math.min(
 | |
|         1,
 | |
|         Math.log(scheduledCount + 0.5) / Math.log(64)
 | |
|       );
 | |
|       result = flashcardsInNoteAvgEase * flashcardContribution + settings.baseEase * (1 - flashcardContribution);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   noteCalcUpdatedSchedule(notePath, noteSchedule, response, dueDateNoteHistogram) {
 | |
|     const noteScheduleOsr = noteSchedule;
 | |
|     const temp = this.calcSchedule(
 | |
|       noteScheduleOsr,
 | |
|       response,
 | |
|       dueDateNoteHistogram
 | |
|     );
 | |
|     const interval = temp.interval;
 | |
|     const ease = temp.latestEase;
 | |
|     const dueDate = (0, import_moment2.default)(globalDateProvider.today.add(interval, "d"));
 | |
|     this.noteEaseList.setEaseForPath(notePath, ease);
 | |
|     return new RepItemScheduleInfoOsr(dueDate, interval, ease);
 | |
|   }
 | |
|   calcSchedule(schedule, response, dueDateHistogram) {
 | |
|     const temp = osrSchedule(
 | |
|       response,
 | |
|       schedule.interval,
 | |
|       schedule.latestEase,
 | |
|       schedule.delayedBeforeReviewTicks,
 | |
|       this.settings,
 | |
|       dueDateHistogram
 | |
|     );
 | |
|     return new RepItemScheduleInfoOsr(globalDateProvider.today, temp.interval, temp.ease);
 | |
|   }
 | |
|   cardGetResetSchedule() {
 | |
|     const interval = _SrsAlgorithmOsr.initialInterval;
 | |
|     const ease = this.settings.baseEase;
 | |
|     const dueDate = globalDateProvider.today.add(interval, "d");
 | |
|     return new RepItemScheduleInfoOsr(dueDate, interval, ease);
 | |
|   }
 | |
|   cardGetNewSchedule(response, notePath, dueDateFlashcardHistogram) {
 | |
|     let initialEase = this.settings.baseEase;
 | |
|     if (this.noteEaseList.hasEaseForPath(notePath)) {
 | |
|       initialEase = Math.round(this.noteEaseList.getEaseByPath(notePath));
 | |
|     }
 | |
|     const delayBeforeReview = 0;
 | |
|     const schedObj = osrSchedule(
 | |
|       response,
 | |
|       _SrsAlgorithmOsr.initialInterval,
 | |
|       initialEase,
 | |
|       delayBeforeReview,
 | |
|       this.settings,
 | |
|       dueDateFlashcardHistogram
 | |
|     );
 | |
|     const interval = schedObj.interval;
 | |
|     const ease = schedObj.ease;
 | |
|     const dueDate = globalDateProvider.today.add(interval, "d");
 | |
|     return new RepItemScheduleInfoOsr(dueDate, interval, ease, delayBeforeReview);
 | |
|   }
 | |
|   cardCalcUpdatedSchedule(response, cardSchedule, dueDateFlashcardHistogram) {
 | |
|     const cardScheduleOsr = cardSchedule;
 | |
|     const schedObj = osrSchedule(
 | |
|       response,
 | |
|       cardScheduleOsr.interval,
 | |
|       cardSchedule.latestEase,
 | |
|       cardSchedule.delayedBeforeReviewTicks,
 | |
|       this.settings,
 | |
|       dueDateFlashcardHistogram
 | |
|     );
 | |
|     const interval = schedObj.interval;
 | |
|     const ease = schedObj.ease;
 | |
|     const dueDate = globalDateProvider.today.add(interval, "d");
 | |
|     const delayBeforeReview = 0;
 | |
|     return new RepItemScheduleInfoOsr(dueDate, interval, ease, delayBeforeReview);
 | |
|   }
 | |
|   noteStats() {
 | |
|     return this.noteEaseList;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/algorithms/osr/osr-note-graph.ts
 | |
| var graph = __toESM(require_lib());
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/index.js
 | |
| var import_brace_expansion = __toESM(require_brace_expansion(), 1);
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/assert-valid-pattern.js
 | |
| var MAX_PATTERN_LENGTH = 1024 * 64;
 | |
| var assertValidPattern = (pattern) => {
 | |
|   if (typeof pattern !== "string") {
 | |
|     throw new TypeError("invalid pattern");
 | |
|   }
 | |
|   if (pattern.length > MAX_PATTERN_LENGTH) {
 | |
|     throw new TypeError("pattern is too long");
 | |
|   }
 | |
| };
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/brace-expressions.js
 | |
| var posixClasses = {
 | |
|   "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
 | |
|   "[:alpha:]": ["\\p{L}\\p{Nl}", true],
 | |
|   "[:ascii:]": ["\\x00-\\x7f", false],
 | |
|   "[:blank:]": ["\\p{Zs}\\t", true],
 | |
|   "[:cntrl:]": ["\\p{Cc}", true],
 | |
|   "[:digit:]": ["\\p{Nd}", true],
 | |
|   "[:graph:]": ["\\p{Z}\\p{C}", true, true],
 | |
|   "[:lower:]": ["\\p{Ll}", true],
 | |
|   "[:print:]": ["\\p{C}", true],
 | |
|   "[:punct:]": ["\\p{P}", true],
 | |
|   "[:space:]": ["\\p{Z}\\t\\r\\n\\v\\f", true],
 | |
|   "[:upper:]": ["\\p{Lu}", true],
 | |
|   "[:word:]": ["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}", true],
 | |
|   "[:xdigit:]": ["A-Fa-f0-9", false]
 | |
| };
 | |
| var braceEscape = (s2) => s2.replace(/[[\]\\-]/g, "\\$&");
 | |
| var regexpEscape = (s2) => s2.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
 | |
| var rangesToString = (ranges) => ranges.join("");
 | |
| var parseClass = (glob, position) => {
 | |
|   const pos = position;
 | |
|   if (glob.charAt(pos) !== "[") {
 | |
|     throw new Error("not in a brace expression");
 | |
|   }
 | |
|   const ranges = [];
 | |
|   const negs = [];
 | |
|   let i2 = pos + 1;
 | |
|   let sawStart = false;
 | |
|   let uflag = false;
 | |
|   let escaping = false;
 | |
|   let negate = false;
 | |
|   let endPos = pos;
 | |
|   let rangeStart = "";
 | |
|   WHILE: while (i2 < glob.length) {
 | |
|     const c2 = glob.charAt(i2);
 | |
|     if ((c2 === "!" || c2 === "^") && i2 === pos + 1) {
 | |
|       negate = true;
 | |
|       i2++;
 | |
|       continue;
 | |
|     }
 | |
|     if (c2 === "]" && sawStart && !escaping) {
 | |
|       endPos = i2 + 1;
 | |
|       break;
 | |
|     }
 | |
|     sawStart = true;
 | |
|     if (c2 === "\\") {
 | |
|       if (!escaping) {
 | |
|         escaping = true;
 | |
|         i2++;
 | |
|         continue;
 | |
|       }
 | |
|     }
 | |
|     if (c2 === "[" && !escaping) {
 | |
|       for (const [cls, [unip, u2, neg]] of Object.entries(posixClasses)) {
 | |
|         if (glob.startsWith(cls, i2)) {
 | |
|           if (rangeStart) {
 | |
|             return ["$.", false, glob.length - pos, true];
 | |
|           }
 | |
|           i2 += cls.length;
 | |
|           if (neg)
 | |
|             negs.push(unip);
 | |
|           else
 | |
|             ranges.push(unip);
 | |
|           uflag = uflag || u2;
 | |
|           continue WHILE;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     escaping = false;
 | |
|     if (rangeStart) {
 | |
|       if (c2 > rangeStart) {
 | |
|         ranges.push(braceEscape(rangeStart) + "-" + braceEscape(c2));
 | |
|       } else if (c2 === rangeStart) {
 | |
|         ranges.push(braceEscape(c2));
 | |
|       }
 | |
|       rangeStart = "";
 | |
|       i2++;
 | |
|       continue;
 | |
|     }
 | |
|     if (glob.startsWith("-]", i2 + 1)) {
 | |
|       ranges.push(braceEscape(c2 + "-"));
 | |
|       i2 += 2;
 | |
|       continue;
 | |
|     }
 | |
|     if (glob.startsWith("-", i2 + 1)) {
 | |
|       rangeStart = c2;
 | |
|       i2 += 2;
 | |
|       continue;
 | |
|     }
 | |
|     ranges.push(braceEscape(c2));
 | |
|     i2++;
 | |
|   }
 | |
|   if (endPos < i2) {
 | |
|     return ["", false, 0, false];
 | |
|   }
 | |
|   if (!ranges.length && !negs.length) {
 | |
|     return ["$.", false, glob.length - pos, true];
 | |
|   }
 | |
|   if (negs.length === 0 && ranges.length === 1 && /^\\?.$/.test(ranges[0]) && !negate) {
 | |
|     const r2 = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
 | |
|     return [regexpEscape(r2), false, endPos - pos, false];
 | |
|   }
 | |
|   const sranges = "[" + (negate ? "^" : "") + rangesToString(ranges) + "]";
 | |
|   const snegs = "[" + (negate ? "" : "^") + rangesToString(negs) + "]";
 | |
|   const comb = ranges.length && negs.length ? "(" + sranges + "|" + snegs + ")" : ranges.length ? sranges : snegs;
 | |
|   return [comb, uflag, endPos - pos, true];
 | |
| };
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/unescape.js
 | |
| var unescape = (s2, { windowsPathsNoEscape = false } = {}) => {
 | |
|   return windowsPathsNoEscape ? s2.replace(/\[([^\/\\])\]/g, "$1") : s2.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1");
 | |
| };
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/ast.js
 | |
| var types = /* @__PURE__ */ new Set(["!", "?", "+", "*", "@"]);
 | |
| var isExtglobType = (c2) => types.has(c2);
 | |
| var startNoTraversal = "(?!(?:^|/)\\.\\.?(?:$|/))";
 | |
| var startNoDot = "(?!\\.)";
 | |
| var addPatternStart = /* @__PURE__ */ new Set(["[", "."]);
 | |
| var justDots = /* @__PURE__ */ new Set(["..", "."]);
 | |
| var reSpecials = new Set("().*{}+?[]^$\\!");
 | |
| var regExpEscape = (s2) => s2.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
 | |
| var qmark = "[^/]";
 | |
| var star = qmark + "*?";
 | |
| var starNoEmpty = qmark + "+?";
 | |
| var _root, _hasMagic, _uflag, _parts, _parent, _parentIndex, _negs, _filledNegs, _options, _toString, _emptyExt, _AST_instances, fillNegs_fn, _AST_static, parseAST_fn, partsToRegExp_fn, parseGlob_fn;
 | |
| var _AST = class _AST {
 | |
|   constructor(type, parent, options = {}) {
 | |
|     __privateAdd(this, _AST_instances);
 | |
|     __publicField(this, "type");
 | |
|     __privateAdd(this, _root);
 | |
|     __privateAdd(this, _hasMagic);
 | |
|     __privateAdd(this, _uflag, false);
 | |
|     __privateAdd(this, _parts, []);
 | |
|     __privateAdd(this, _parent);
 | |
|     __privateAdd(this, _parentIndex);
 | |
|     __privateAdd(this, _negs);
 | |
|     __privateAdd(this, _filledNegs, false);
 | |
|     __privateAdd(this, _options);
 | |
|     __privateAdd(this, _toString);
 | |
|     // set to true if it's an extglob with no children
 | |
|     // (which really means one child of '')
 | |
|     __privateAdd(this, _emptyExt, false);
 | |
|     this.type = type;
 | |
|     if (type)
 | |
|       __privateSet(this, _hasMagic, true);
 | |
|     __privateSet(this, _parent, parent);
 | |
|     __privateSet(this, _root, __privateGet(this, _parent) ? __privateGet(__privateGet(this, _parent), _root) : this);
 | |
|     __privateSet(this, _options, __privateGet(this, _root) === this ? options : __privateGet(__privateGet(this, _root), _options));
 | |
|     __privateSet(this, _negs, __privateGet(this, _root) === this ? [] : __privateGet(__privateGet(this, _root), _negs));
 | |
|     if (type === "!" && !__privateGet(__privateGet(this, _root), _filledNegs))
 | |
|       __privateGet(this, _negs).push(this);
 | |
|     __privateSet(this, _parentIndex, __privateGet(this, _parent) ? __privateGet(__privateGet(this, _parent), _parts).length : 0);
 | |
|   }
 | |
|   get hasMagic() {
 | |
|     if (__privateGet(this, _hasMagic) !== void 0)
 | |
|       return __privateGet(this, _hasMagic);
 | |
|     for (const p2 of __privateGet(this, _parts)) {
 | |
|       if (typeof p2 === "string")
 | |
|         continue;
 | |
|       if (p2.type || p2.hasMagic)
 | |
|         return __privateSet(this, _hasMagic, true);
 | |
|     }
 | |
|     return __privateGet(this, _hasMagic);
 | |
|   }
 | |
|   // reconstructs the pattern
 | |
|   toString() {
 | |
|     if (__privateGet(this, _toString) !== void 0)
 | |
|       return __privateGet(this, _toString);
 | |
|     if (!this.type) {
 | |
|       return __privateSet(this, _toString, __privateGet(this, _parts).map((p2) => String(p2)).join(""));
 | |
|     } else {
 | |
|       return __privateSet(this, _toString, this.type + "(" + __privateGet(this, _parts).map((p2) => String(p2)).join("|") + ")");
 | |
|     }
 | |
|   }
 | |
|   push(...parts) {
 | |
|     for (const p2 of parts) {
 | |
|       if (p2 === "")
 | |
|         continue;
 | |
|       if (typeof p2 !== "string" && !(p2 instanceof _AST && __privateGet(p2, _parent) === this)) {
 | |
|         throw new Error("invalid part: " + p2);
 | |
|       }
 | |
|       __privateGet(this, _parts).push(p2);
 | |
|     }
 | |
|   }
 | |
|   toJSON() {
 | |
|     var _a;
 | |
|     const ret = this.type === null ? __privateGet(this, _parts).slice().map((p2) => typeof p2 === "string" ? p2 : p2.toJSON()) : [this.type, ...__privateGet(this, _parts).map((p2) => p2.toJSON())];
 | |
|     if (this.isStart() && !this.type)
 | |
|       ret.unshift([]);
 | |
|     if (this.isEnd() && (this === __privateGet(this, _root) || __privateGet(__privateGet(this, _root), _filledNegs) && ((_a = __privateGet(this, _parent)) == null ? void 0 : _a.type) === "!")) {
 | |
|       ret.push({});
 | |
|     }
 | |
|     return ret;
 | |
|   }
 | |
|   isStart() {
 | |
|     var _a;
 | |
|     if (__privateGet(this, _root) === this)
 | |
|       return true;
 | |
|     if (!((_a = __privateGet(this, _parent)) == null ? void 0 : _a.isStart()))
 | |
|       return false;
 | |
|     if (__privateGet(this, _parentIndex) === 0)
 | |
|       return true;
 | |
|     const p2 = __privateGet(this, _parent);
 | |
|     for (let i2 = 0; i2 < __privateGet(this, _parentIndex); i2++) {
 | |
|       const pp = __privateGet(p2, _parts)[i2];
 | |
|       if (!(pp instanceof _AST && pp.type === "!")) {
 | |
|         return false;
 | |
|       }
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
|   isEnd() {
 | |
|     var _a, _b, _c;
 | |
|     if (__privateGet(this, _root) === this)
 | |
|       return true;
 | |
|     if (((_a = __privateGet(this, _parent)) == null ? void 0 : _a.type) === "!")
 | |
|       return true;
 | |
|     if (!((_b = __privateGet(this, _parent)) == null ? void 0 : _b.isEnd()))
 | |
|       return false;
 | |
|     if (!this.type)
 | |
|       return (_c = __privateGet(this, _parent)) == null ? void 0 : _c.isEnd();
 | |
|     const pl = __privateGet(this, _parent) ? __privateGet(__privateGet(this, _parent), _parts).length : 0;
 | |
|     return __privateGet(this, _parentIndex) === pl - 1;
 | |
|   }
 | |
|   copyIn(part) {
 | |
|     if (typeof part === "string")
 | |
|       this.push(part);
 | |
|     else
 | |
|       this.push(part.clone(this));
 | |
|   }
 | |
|   clone(parent) {
 | |
|     const c2 = new _AST(this.type, parent);
 | |
|     for (const p2 of __privateGet(this, _parts)) {
 | |
|       c2.copyIn(p2);
 | |
|     }
 | |
|     return c2;
 | |
|   }
 | |
|   static fromGlob(pattern, options = {}) {
 | |
|     var _a;
 | |
|     const ast = new _AST(null, void 0, options);
 | |
|     __privateMethod(_a = _AST, _AST_static, parseAST_fn).call(_a, pattern, ast, 0, options);
 | |
|     return ast;
 | |
|   }
 | |
|   // returns the regular expression if there's magic, or the unescaped
 | |
|   // string if not.
 | |
|   toMMPattern() {
 | |
|     if (this !== __privateGet(this, _root))
 | |
|       return __privateGet(this, _root).toMMPattern();
 | |
|     const glob = this.toString();
 | |
|     const [re, body, hasMagic, uflag] = this.toRegExpSource();
 | |
|     const anyMagic = hasMagic || __privateGet(this, _hasMagic) || __privateGet(this, _options).nocase && !__privateGet(this, _options).nocaseMagicOnly && glob.toUpperCase() !== glob.toLowerCase();
 | |
|     if (!anyMagic) {
 | |
|       return body;
 | |
|     }
 | |
|     const flags = (__privateGet(this, _options).nocase ? "i" : "") + (uflag ? "u" : "");
 | |
|     return Object.assign(new RegExp(`^${re}$`, flags), {
 | |
|       _src: re,
 | |
|       _glob: glob
 | |
|     });
 | |
|   }
 | |
|   get options() {
 | |
|     return __privateGet(this, _options);
 | |
|   }
 | |
|   // returns the string match, the regexp source, whether there's magic
 | |
|   // in the regexp (so a regular expression is required) and whether or
 | |
|   // not the uflag is needed for the regular expression (for posix classes)
 | |
|   // TODO: instead of injecting the start/end at this point, just return
 | |
|   // the BODY of the regexp, along with the start/end portions suitable
 | |
|   // for binding the start/end in either a joined full-path makeRe context
 | |
|   // (where we bind to (^|/), or a standalone matchPart context (where
 | |
|   // we bind to ^, and not /).  Otherwise slashes get duped!
 | |
|   //
 | |
|   // In part-matching mode, the start is:
 | |
|   // - if not isStart: nothing
 | |
|   // - if traversal possible, but not allowed: ^(?!\.\.?$)
 | |
|   // - if dots allowed or not possible: ^
 | |
|   // - if dots possible and not allowed: ^(?!\.)
 | |
|   // end is:
 | |
|   // - if not isEnd(): nothing
 | |
|   // - else: $
 | |
|   //
 | |
|   // In full-path matching mode, we put the slash at the START of the
 | |
|   // pattern, so start is:
 | |
|   // - if first pattern: same as part-matching mode
 | |
|   // - if not isStart(): nothing
 | |
|   // - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
 | |
|   // - if dots allowed or not possible: /
 | |
|   // - if dots possible and not allowed: /(?!\.)
 | |
|   // end is:
 | |
|   // - if last pattern, same as part-matching mode
 | |
|   // - else nothing
 | |
|   //
 | |
|   // Always put the (?:$|/) on negated tails, though, because that has to be
 | |
|   // there to bind the end of the negated pattern portion, and it's easier to
 | |
|   // just stick it in now rather than try to inject it later in the middle of
 | |
|   // the pattern.
 | |
|   //
 | |
|   // We can just always return the same end, and leave it up to the caller
 | |
|   // to know whether it's going to be used joined or in parts.
 | |
|   // And, if the start is adjusted slightly, can do the same there:
 | |
|   // - if not isStart: nothing
 | |
|   // - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
 | |
|   // - if dots allowed or not possible: (?:/|^)
 | |
|   // - if dots possible and not allowed: (?:/|^)(?!\.)
 | |
|   //
 | |
|   // But it's better to have a simpler binding without a conditional, for
 | |
|   // performance, so probably better to return both start options.
 | |
|   //
 | |
|   // Then the caller just ignores the end if it's not the first pattern,
 | |
|   // and the start always gets applied.
 | |
|   //
 | |
|   // But that's always going to be $ if it's the ending pattern, or nothing,
 | |
|   // so the caller can just attach $ at the end of the pattern when building.
 | |
|   //
 | |
|   // So the todo is:
 | |
|   // - better detect what kind of start is needed
 | |
|   // - return both flavors of starting pattern
 | |
|   // - attach $ at the end of the pattern when creating the actual RegExp
 | |
|   //
 | |
|   // Ah, but wait, no, that all only applies to the root when the first pattern
 | |
|   // is not an extglob. If the first pattern IS an extglob, then we need all
 | |
|   // that dot prevention biz to live in the extglob portions, because eg
 | |
|   // +(*|.x*) can match .xy but not .yx.
 | |
|   //
 | |
|   // So, return the two flavors if it's #root and the first child is not an
 | |
|   // AST, otherwise leave it to the child AST to handle it, and there,
 | |
|   // use the (?:^|/) style of start binding.
 | |
|   //
 | |
|   // Even simplified further:
 | |
|   // - Since the start for a join is eg /(?!\.) and the start for a part
 | |
|   // is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
 | |
|   // or start or whatever) and prepend ^ or / at the Regexp construction.
 | |
|   toRegExpSource(allowDot) {
 | |
|     var _a;
 | |
|     const dot = allowDot != null ? allowDot : !!__privateGet(this, _options).dot;
 | |
|     if (__privateGet(this, _root) === this)
 | |
|       __privateMethod(this, _AST_instances, fillNegs_fn).call(this);
 | |
|     if (!this.type) {
 | |
|       const noEmpty = this.isStart() && this.isEnd();
 | |
|       const src = __privateGet(this, _parts).map((p2) => {
 | |
|         var _a2;
 | |
|         const [re, _2, hasMagic, uflag] = typeof p2 === "string" ? __privateMethod(_a2 = _AST, _AST_static, parseGlob_fn).call(_a2, p2, __privateGet(this, _hasMagic), noEmpty) : p2.toRegExpSource(allowDot);
 | |
|         __privateSet(this, _hasMagic, __privateGet(this, _hasMagic) || hasMagic);
 | |
|         __privateSet(this, _uflag, __privateGet(this, _uflag) || uflag);
 | |
|         return re;
 | |
|       }).join("");
 | |
|       let start2 = "";
 | |
|       if (this.isStart()) {
 | |
|         if (typeof __privateGet(this, _parts)[0] === "string") {
 | |
|           const dotTravAllowed = __privateGet(this, _parts).length === 1 && justDots.has(__privateGet(this, _parts)[0]);
 | |
|           if (!dotTravAllowed) {
 | |
|             const aps = addPatternStart;
 | |
|             const needNoTrav = (
 | |
|               // dots are allowed, and the pattern starts with [ or .
 | |
|               dot && aps.has(src.charAt(0)) || // the pattern starts with \., and then [ or .
 | |
|               src.startsWith("\\.") && aps.has(src.charAt(2)) || // the pattern starts with \.\., and then [ or .
 | |
|               src.startsWith("\\.\\.") && aps.has(src.charAt(4))
 | |
|             );
 | |
|             const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
 | |
|             start2 = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : "";
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       let end = "";
 | |
|       if (this.isEnd() && __privateGet(__privateGet(this, _root), _filledNegs) && ((_a = __privateGet(this, _parent)) == null ? void 0 : _a.type) === "!") {
 | |
|         end = "(?:$|\\/)";
 | |
|       }
 | |
|       const final2 = start2 + src + end;
 | |
|       return [
 | |
|         final2,
 | |
|         unescape(src),
 | |
|         __privateSet(this, _hasMagic, !!__privateGet(this, _hasMagic)),
 | |
|         __privateGet(this, _uflag)
 | |
|       ];
 | |
|     }
 | |
|     const repeated = this.type === "*" || this.type === "+";
 | |
|     const start = this.type === "!" ? "(?:(?!(?:" : "(?:";
 | |
|     let body = __privateMethod(this, _AST_instances, partsToRegExp_fn).call(this, dot);
 | |
|     if (this.isStart() && this.isEnd() && !body && this.type !== "!") {
 | |
|       const s2 = this.toString();
 | |
|       __privateSet(this, _parts, [s2]);
 | |
|       this.type = null;
 | |
|       __privateSet(this, _hasMagic, void 0);
 | |
|       return [s2, unescape(this.toString()), false, false];
 | |
|     }
 | |
|     let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot ? "" : __privateMethod(this, _AST_instances, partsToRegExp_fn).call(this, true);
 | |
|     if (bodyDotAllowed === body) {
 | |
|       bodyDotAllowed = "";
 | |
|     }
 | |
|     if (bodyDotAllowed) {
 | |
|       body = `(?:${body})(?:${bodyDotAllowed})*?`;
 | |
|     }
 | |
|     let final = "";
 | |
|     if (this.type === "!" && __privateGet(this, _emptyExt)) {
 | |
|       final = (this.isStart() && !dot ? startNoDot : "") + starNoEmpty;
 | |
|     } else {
 | |
|       const close = this.type === "!" ? (
 | |
|         // !() must match something,but !(x) can match ''
 | |
|         "))" + (this.isStart() && !dot && !allowDot ? startNoDot : "") + star + ")"
 | |
|       ) : this.type === "@" ? ")" : this.type === "?" ? ")?" : this.type === "+" && bodyDotAllowed ? ")" : this.type === "*" && bodyDotAllowed ? `)?` : `)${this.type}`;
 | |
|       final = start + body + close;
 | |
|     }
 | |
|     return [
 | |
|       final,
 | |
|       unescape(body),
 | |
|       __privateSet(this, _hasMagic, !!__privateGet(this, _hasMagic)),
 | |
|       __privateGet(this, _uflag)
 | |
|     ];
 | |
|   }
 | |
| };
 | |
| _root = new WeakMap();
 | |
| _hasMagic = new WeakMap();
 | |
| _uflag = new WeakMap();
 | |
| _parts = new WeakMap();
 | |
| _parent = new WeakMap();
 | |
| _parentIndex = new WeakMap();
 | |
| _negs = new WeakMap();
 | |
| _filledNegs = new WeakMap();
 | |
| _options = new WeakMap();
 | |
| _toString = new WeakMap();
 | |
| _emptyExt = new WeakMap();
 | |
| _AST_instances = new WeakSet();
 | |
| fillNegs_fn = function() {
 | |
|   if (this !== __privateGet(this, _root))
 | |
|     throw new Error("should only call on root");
 | |
|   if (__privateGet(this, _filledNegs))
 | |
|     return this;
 | |
|   this.toString();
 | |
|   __privateSet(this, _filledNegs, true);
 | |
|   let n2;
 | |
|   while (n2 = __privateGet(this, _negs).pop()) {
 | |
|     if (n2.type !== "!")
 | |
|       continue;
 | |
|     let p2 = n2;
 | |
|     let pp = __privateGet(p2, _parent);
 | |
|     while (pp) {
 | |
|       for (let i2 = __privateGet(p2, _parentIndex) + 1; !pp.type && i2 < __privateGet(pp, _parts).length; i2++) {
 | |
|         for (const part of __privateGet(n2, _parts)) {
 | |
|           if (typeof part === "string") {
 | |
|             throw new Error("string part in extglob AST??");
 | |
|           }
 | |
|           part.copyIn(__privateGet(pp, _parts)[i2]);
 | |
|         }
 | |
|       }
 | |
|       p2 = pp;
 | |
|       pp = __privateGet(p2, _parent);
 | |
|     }
 | |
|   }
 | |
|   return this;
 | |
| };
 | |
| _AST_static = new WeakSet();
 | |
| parseAST_fn = function(str, ast, pos, opt) {
 | |
|   var _a, _b;
 | |
|   let escaping = false;
 | |
|   let inBrace = false;
 | |
|   let braceStart = -1;
 | |
|   let braceNeg = false;
 | |
|   if (ast.type === null) {
 | |
|     let i3 = pos;
 | |
|     let acc2 = "";
 | |
|     while (i3 < str.length) {
 | |
|       const c2 = str.charAt(i3++);
 | |
|       if (escaping || c2 === "\\") {
 | |
|         escaping = !escaping;
 | |
|         acc2 += c2;
 | |
|         continue;
 | |
|       }
 | |
|       if (inBrace) {
 | |
|         if (i3 === braceStart + 1) {
 | |
|           if (c2 === "^" || c2 === "!") {
 | |
|             braceNeg = true;
 | |
|           }
 | |
|         } else if (c2 === "]" && !(i3 === braceStart + 2 && braceNeg)) {
 | |
|           inBrace = false;
 | |
|         }
 | |
|         acc2 += c2;
 | |
|         continue;
 | |
|       } else if (c2 === "[") {
 | |
|         inBrace = true;
 | |
|         braceStart = i3;
 | |
|         braceNeg = false;
 | |
|         acc2 += c2;
 | |
|         continue;
 | |
|       }
 | |
|       if (!opt.noext && isExtglobType(c2) && str.charAt(i3) === "(") {
 | |
|         ast.push(acc2);
 | |
|         acc2 = "";
 | |
|         const ext2 = new _AST(c2, ast);
 | |
|         i3 = __privateMethod(_a = _AST, _AST_static, parseAST_fn).call(_a, str, ext2, i3, opt);
 | |
|         ast.push(ext2);
 | |
|         continue;
 | |
|       }
 | |
|       acc2 += c2;
 | |
|     }
 | |
|     ast.push(acc2);
 | |
|     return i3;
 | |
|   }
 | |
|   let i2 = pos + 1;
 | |
|   let part = new _AST(null, ast);
 | |
|   const parts = [];
 | |
|   let acc = "";
 | |
|   while (i2 < str.length) {
 | |
|     const c2 = str.charAt(i2++);
 | |
|     if (escaping || c2 === "\\") {
 | |
|       escaping = !escaping;
 | |
|       acc += c2;
 | |
|       continue;
 | |
|     }
 | |
|     if (inBrace) {
 | |
|       if (i2 === braceStart + 1) {
 | |
|         if (c2 === "^" || c2 === "!") {
 | |
|           braceNeg = true;
 | |
|         }
 | |
|       } else if (c2 === "]" && !(i2 === braceStart + 2 && braceNeg)) {
 | |
|         inBrace = false;
 | |
|       }
 | |
|       acc += c2;
 | |
|       continue;
 | |
|     } else if (c2 === "[") {
 | |
|       inBrace = true;
 | |
|       braceStart = i2;
 | |
|       braceNeg = false;
 | |
|       acc += c2;
 | |
|       continue;
 | |
|     }
 | |
|     if (isExtglobType(c2) && str.charAt(i2) === "(") {
 | |
|       part.push(acc);
 | |
|       acc = "";
 | |
|       const ext2 = new _AST(c2, part);
 | |
|       part.push(ext2);
 | |
|       i2 = __privateMethod(_b = _AST, _AST_static, parseAST_fn).call(_b, str, ext2, i2, opt);
 | |
|       continue;
 | |
|     }
 | |
|     if (c2 === "|") {
 | |
|       part.push(acc);
 | |
|       acc = "";
 | |
|       parts.push(part);
 | |
|       part = new _AST(null, ast);
 | |
|       continue;
 | |
|     }
 | |
|     if (c2 === ")") {
 | |
|       if (acc === "" && __privateGet(ast, _parts).length === 0) {
 | |
|         __privateSet(ast, _emptyExt, true);
 | |
|       }
 | |
|       part.push(acc);
 | |
|       acc = "";
 | |
|       ast.push(...parts, part);
 | |
|       return i2;
 | |
|     }
 | |
|     acc += c2;
 | |
|   }
 | |
|   ast.type = null;
 | |
|   __privateSet(ast, _hasMagic, void 0);
 | |
|   __privateSet(ast, _parts, [str.substring(pos - 1)]);
 | |
|   return i2;
 | |
| };
 | |
| partsToRegExp_fn = function(dot) {
 | |
|   return __privateGet(this, _parts).map((p2) => {
 | |
|     if (typeof p2 === "string") {
 | |
|       throw new Error("string type in extglob ast??");
 | |
|     }
 | |
|     const [re, _2, _hasMagic2, uflag] = p2.toRegExpSource(dot);
 | |
|     __privateSet(this, _uflag, __privateGet(this, _uflag) || uflag);
 | |
|     return re;
 | |
|   }).filter((p2) => !(this.isStart() && this.isEnd()) || !!p2).join("|");
 | |
| };
 | |
| parseGlob_fn = function(glob, hasMagic, noEmpty = false) {
 | |
|   let escaping = false;
 | |
|   let re = "";
 | |
|   let uflag = false;
 | |
|   for (let i2 = 0; i2 < glob.length; i2++) {
 | |
|     const c2 = glob.charAt(i2);
 | |
|     if (escaping) {
 | |
|       escaping = false;
 | |
|       re += (reSpecials.has(c2) ? "\\" : "") + c2;
 | |
|       continue;
 | |
|     }
 | |
|     if (c2 === "\\") {
 | |
|       if (i2 === glob.length - 1) {
 | |
|         re += "\\\\";
 | |
|       } else {
 | |
|         escaping = true;
 | |
|       }
 | |
|       continue;
 | |
|     }
 | |
|     if (c2 === "[") {
 | |
|       const [src, needUflag, consumed, magic] = parseClass(glob, i2);
 | |
|       if (consumed) {
 | |
|         re += src;
 | |
|         uflag = uflag || needUflag;
 | |
|         i2 += consumed - 1;
 | |
|         hasMagic = hasMagic || magic;
 | |
|         continue;
 | |
|       }
 | |
|     }
 | |
|     if (c2 === "*") {
 | |
|       if (noEmpty && glob === "*")
 | |
|         re += starNoEmpty;
 | |
|       else
 | |
|         re += star;
 | |
|       hasMagic = true;
 | |
|       continue;
 | |
|     }
 | |
|     if (c2 === "?") {
 | |
|       re += qmark;
 | |
|       hasMagic = true;
 | |
|       continue;
 | |
|     }
 | |
|     re += regExpEscape(c2);
 | |
|   }
 | |
|   return [re, unescape(glob), !!hasMagic, uflag];
 | |
| };
 | |
| __privateAdd(_AST, _AST_static);
 | |
| var AST = _AST;
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/escape.js
 | |
| var escape = (s2, { windowsPathsNoEscape = false } = {}) => {
 | |
|   return windowsPathsNoEscape ? s2.replace(/[?*()[\]]/g, "[$&]") : s2.replace(/[?*()[\]\\]/g, "\\$&");
 | |
| };
 | |
| 
 | |
| // node_modules/.pnpm/minimatch@10.0.1/node_modules/minimatch/dist/esm/index.js
 | |
| var minimatch = (p2, pattern, options = {}) => {
 | |
|   assertValidPattern(pattern);
 | |
|   if (!options.nocomment && pattern.charAt(0) === "#") {
 | |
|     return false;
 | |
|   }
 | |
|   return new Minimatch(pattern, options).match(p2);
 | |
| };
 | |
| var starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
 | |
| var starDotExtTest = (ext2) => (f2) => !f2.startsWith(".") && f2.endsWith(ext2);
 | |
| var starDotExtTestDot = (ext2) => (f2) => f2.endsWith(ext2);
 | |
| var starDotExtTestNocase = (ext2) => {
 | |
|   ext2 = ext2.toLowerCase();
 | |
|   return (f2) => !f2.startsWith(".") && f2.toLowerCase().endsWith(ext2);
 | |
| };
 | |
| var starDotExtTestNocaseDot = (ext2) => {
 | |
|   ext2 = ext2.toLowerCase();
 | |
|   return (f2) => f2.toLowerCase().endsWith(ext2);
 | |
| };
 | |
| var starDotStarRE = /^\*+\.\*+$/;
 | |
| var starDotStarTest = (f2) => !f2.startsWith(".") && f2.includes(".");
 | |
| var starDotStarTestDot = (f2) => f2 !== "." && f2 !== ".." && f2.includes(".");
 | |
| var dotStarRE = /^\.\*+$/;
 | |
| var dotStarTest = (f2) => f2 !== "." && f2 !== ".." && f2.startsWith(".");
 | |
| var starRE = /^\*+$/;
 | |
| var starTest = (f2) => f2.length !== 0 && !f2.startsWith(".");
 | |
| var starTestDot = (f2) => f2.length !== 0 && f2 !== "." && f2 !== "..";
 | |
| var qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
 | |
| var qmarksTestNocase = ([$0, ext2 = ""]) => {
 | |
|   const noext = qmarksTestNoExt([$0]);
 | |
|   if (!ext2)
 | |
|     return noext;
 | |
|   ext2 = ext2.toLowerCase();
 | |
|   return (f2) => noext(f2) && f2.toLowerCase().endsWith(ext2);
 | |
| };
 | |
| var qmarksTestNocaseDot = ([$0, ext2 = ""]) => {
 | |
|   const noext = qmarksTestNoExtDot([$0]);
 | |
|   if (!ext2)
 | |
|     return noext;
 | |
|   ext2 = ext2.toLowerCase();
 | |
|   return (f2) => noext(f2) && f2.toLowerCase().endsWith(ext2);
 | |
| };
 | |
| var qmarksTestDot = ([$0, ext2 = ""]) => {
 | |
|   const noext = qmarksTestNoExtDot([$0]);
 | |
|   return !ext2 ? noext : (f2) => noext(f2) && f2.endsWith(ext2);
 | |
| };
 | |
| var qmarksTest = ([$0, ext2 = ""]) => {
 | |
|   const noext = qmarksTestNoExt([$0]);
 | |
|   return !ext2 ? noext : (f2) => noext(f2) && f2.endsWith(ext2);
 | |
| };
 | |
| var qmarksTestNoExt = ([$0]) => {
 | |
|   const len = $0.length;
 | |
|   return (f2) => f2.length === len && !f2.startsWith(".");
 | |
| };
 | |
| var qmarksTestNoExtDot = ([$0]) => {
 | |
|   const len = $0.length;
 | |
|   return (f2) => f2.length === len && f2 !== "." && f2 !== "..";
 | |
| };
 | |
| var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
 | |
| var path = {
 | |
|   win32: { sep: "\\" },
 | |
|   posix: { sep: "/" }
 | |
| };
 | |
| var sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep;
 | |
| minimatch.sep = sep;
 | |
| var GLOBSTAR = Symbol("globstar **");
 | |
| minimatch.GLOBSTAR = GLOBSTAR;
 | |
| var qmark2 = "[^/]";
 | |
| var star2 = qmark2 + "*?";
 | |
| var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?";
 | |
| var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?";
 | |
| var filter = (pattern, options = {}) => (p2) => minimatch(p2, pattern, options);
 | |
| minimatch.filter = filter;
 | |
| var ext = (a2, b2 = {}) => Object.assign({}, a2, b2);
 | |
| var defaults = (def) => {
 | |
|   if (!def || typeof def !== "object" || !Object.keys(def).length) {
 | |
|     return minimatch;
 | |
|   }
 | |
|   const orig = minimatch;
 | |
|   const m2 = (p2, pattern, options = {}) => orig(p2, pattern, ext(def, options));
 | |
|   return Object.assign(m2, {
 | |
|     Minimatch: class Minimatch extends orig.Minimatch {
 | |
|       constructor(pattern, options = {}) {
 | |
|         super(pattern, ext(def, options));
 | |
|       }
 | |
|       static defaults(options) {
 | |
|         return orig.defaults(ext(def, options)).Minimatch;
 | |
|       }
 | |
|     },
 | |
|     AST: class AST extends orig.AST {
 | |
|       /* c8 ignore start */
 | |
|       constructor(type, parent, options = {}) {
 | |
|         super(type, parent, ext(def, options));
 | |
|       }
 | |
|       /* c8 ignore stop */
 | |
|       static fromGlob(pattern, options = {}) {
 | |
|         return orig.AST.fromGlob(pattern, ext(def, options));
 | |
|       }
 | |
|     },
 | |
|     unescape: (s2, options = {}) => orig.unescape(s2, ext(def, options)),
 | |
|     escape: (s2, options = {}) => orig.escape(s2, ext(def, options)),
 | |
|     filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
 | |
|     defaults: (options) => orig.defaults(ext(def, options)),
 | |
|     makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
 | |
|     braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
 | |
|     match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
 | |
|     sep: orig.sep,
 | |
|     GLOBSTAR
 | |
|   });
 | |
| };
 | |
| minimatch.defaults = defaults;
 | |
| var braceExpand = (pattern, options = {}) => {
 | |
|   assertValidPattern(pattern);
 | |
|   if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
 | |
|     return [pattern];
 | |
|   }
 | |
|   return (0, import_brace_expansion.default)(pattern);
 | |
| };
 | |
| minimatch.braceExpand = braceExpand;
 | |
| var makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
 | |
| minimatch.makeRe = makeRe;
 | |
| var match = (list, pattern, options = {}) => {
 | |
|   const mm = new Minimatch(pattern, options);
 | |
|   list = list.filter((f2) => mm.match(f2));
 | |
|   if (mm.options.nonull && !list.length) {
 | |
|     list.push(pattern);
 | |
|   }
 | |
|   return list;
 | |
| };
 | |
| minimatch.match = match;
 | |
| var globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
 | |
| var regExpEscape2 = (s2) => s2.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
 | |
| var Minimatch = class {
 | |
|   constructor(pattern, options = {}) {
 | |
|     __publicField(this, "options");
 | |
|     __publicField(this, "set");
 | |
|     __publicField(this, "pattern");
 | |
|     __publicField(this, "windowsPathsNoEscape");
 | |
|     __publicField(this, "nonegate");
 | |
|     __publicField(this, "negate");
 | |
|     __publicField(this, "comment");
 | |
|     __publicField(this, "empty");
 | |
|     __publicField(this, "preserveMultipleSlashes");
 | |
|     __publicField(this, "partial");
 | |
|     __publicField(this, "globSet");
 | |
|     __publicField(this, "globParts");
 | |
|     __publicField(this, "nocase");
 | |
|     __publicField(this, "isWindows");
 | |
|     __publicField(this, "platform");
 | |
|     __publicField(this, "windowsNoMagicRoot");
 | |
|     __publicField(this, "regexp");
 | |
|     assertValidPattern(pattern);
 | |
|     options = options || {};
 | |
|     this.options = options;
 | |
|     this.pattern = pattern;
 | |
|     this.platform = options.platform || defaultPlatform;
 | |
|     this.isWindows = this.platform === "win32";
 | |
|     this.windowsPathsNoEscape = !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
 | |
|     if (this.windowsPathsNoEscape) {
 | |
|       this.pattern = this.pattern.replace(/\\/g, "/");
 | |
|     }
 | |
|     this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
 | |
|     this.regexp = null;
 | |
|     this.negate = false;
 | |
|     this.nonegate = !!options.nonegate;
 | |
|     this.comment = false;
 | |
|     this.empty = false;
 | |
|     this.partial = !!options.partial;
 | |
|     this.nocase = !!this.options.nocase;
 | |
|     this.windowsNoMagicRoot = options.windowsNoMagicRoot !== void 0 ? options.windowsNoMagicRoot : !!(this.isWindows && this.nocase);
 | |
|     this.globSet = [];
 | |
|     this.globParts = [];
 | |
|     this.set = [];
 | |
|     this.make();
 | |
|   }
 | |
|   hasMagic() {
 | |
|     if (this.options.magicalBraces && this.set.length > 1) {
 | |
|       return true;
 | |
|     }
 | |
|     for (const pattern of this.set) {
 | |
|       for (const part of pattern) {
 | |
|         if (typeof part !== "string")
 | |
|           return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
|   debug(..._2) {
 | |
|   }
 | |
|   make() {
 | |
|     const pattern = this.pattern;
 | |
|     const options = this.options;
 | |
|     if (!options.nocomment && pattern.charAt(0) === "#") {
 | |
|       this.comment = true;
 | |
|       return;
 | |
|     }
 | |
|     if (!pattern) {
 | |
|       this.empty = true;
 | |
|       return;
 | |
|     }
 | |
|     this.parseNegate();
 | |
|     this.globSet = [...new Set(this.braceExpand())];
 | |
|     if (options.debug) {
 | |
|       this.debug = (...args) => console.error(...args);
 | |
|     }
 | |
|     this.debug(this.pattern, this.globSet);
 | |
|     const rawGlobParts = this.globSet.map((s2) => this.slashSplit(s2));
 | |
|     this.globParts = this.preprocess(rawGlobParts);
 | |
|     this.debug(this.pattern, this.globParts);
 | |
|     let set2 = this.globParts.map((s2, _2, __) => {
 | |
|       if (this.isWindows && this.windowsNoMagicRoot) {
 | |
|         const isUNC = s2[0] === "" && s2[1] === "" && (s2[2] === "?" || !globMagic.test(s2[2])) && !globMagic.test(s2[3]);
 | |
|         const isDrive = /^[a-z]:/i.test(s2[0]);
 | |
|         if (isUNC) {
 | |
|           return [...s2.slice(0, 4), ...s2.slice(4).map((ss) => this.parse(ss))];
 | |
|         } else if (isDrive) {
 | |
|           return [s2[0], ...s2.slice(1).map((ss) => this.parse(ss))];
 | |
|         }
 | |
|       }
 | |
|       return s2.map((ss) => this.parse(ss));
 | |
|     });
 | |
|     this.debug(this.pattern, set2);
 | |
|     this.set = set2.filter((s2) => s2.indexOf(false) === -1);
 | |
|     if (this.isWindows) {
 | |
|       for (let i2 = 0; i2 < this.set.length; i2++) {
 | |
|         const p2 = this.set[i2];
 | |
|         if (p2[0] === "" && p2[1] === "" && this.globParts[i2][2] === "?" && typeof p2[3] === "string" && /^[a-z]:$/i.test(p2[3])) {
 | |
|           p2[2] = "?";
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     this.debug(this.pattern, this.set);
 | |
|   }
 | |
|   // various transforms to equivalent pattern sets that are
 | |
|   // faster to process in a filesystem walk.  The goal is to
 | |
|   // eliminate what we can, and push all ** patterns as far
 | |
|   // to the right as possible, even if it increases the number
 | |
|   // of patterns that we have to process.
 | |
|   preprocess(globParts) {
 | |
|     if (this.options.noglobstar) {
 | |
|       for (let i2 = 0; i2 < globParts.length; i2++) {
 | |
|         for (let j2 = 0; j2 < globParts[i2].length; j2++) {
 | |
|           if (globParts[i2][j2] === "**") {
 | |
|             globParts[i2][j2] = "*";
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     const { optimizationLevel = 1 } = this.options;
 | |
|     if (optimizationLevel >= 2) {
 | |
|       globParts = this.firstPhasePreProcess(globParts);
 | |
|       globParts = this.secondPhasePreProcess(globParts);
 | |
|     } else if (optimizationLevel >= 1) {
 | |
|       globParts = this.levelOneOptimize(globParts);
 | |
|     } else {
 | |
|       globParts = this.adjascentGlobstarOptimize(globParts);
 | |
|     }
 | |
|     return globParts;
 | |
|   }
 | |
|   // just get rid of adjascent ** portions
 | |
|   adjascentGlobstarOptimize(globParts) {
 | |
|     return globParts.map((parts) => {
 | |
|       let gs = -1;
 | |
|       while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
 | |
|         let i2 = gs;
 | |
|         while (parts[i2 + 1] === "**") {
 | |
|           i2++;
 | |
|         }
 | |
|         if (i2 !== gs) {
 | |
|           parts.splice(gs, i2 - gs);
 | |
|         }
 | |
|       }
 | |
|       return parts;
 | |
|     });
 | |
|   }
 | |
|   // get rid of adjascent ** and resolve .. portions
 | |
|   levelOneOptimize(globParts) {
 | |
|     return globParts.map((parts) => {
 | |
|       parts = parts.reduce((set2, part) => {
 | |
|         const prev = set2[set2.length - 1];
 | |
|         if (part === "**" && prev === "**") {
 | |
|           return set2;
 | |
|         }
 | |
|         if (part === "..") {
 | |
|           if (prev && prev !== ".." && prev !== "." && prev !== "**") {
 | |
|             set2.pop();
 | |
|             return set2;
 | |
|           }
 | |
|         }
 | |
|         set2.push(part);
 | |
|         return set2;
 | |
|       }, []);
 | |
|       return parts.length === 0 ? [""] : parts;
 | |
|     });
 | |
|   }
 | |
|   levelTwoFileOptimize(parts) {
 | |
|     if (!Array.isArray(parts)) {
 | |
|       parts = this.slashSplit(parts);
 | |
|     }
 | |
|     let didSomething = false;
 | |
|     do {
 | |
|       didSomething = false;
 | |
|       if (!this.preserveMultipleSlashes) {
 | |
|         for (let i2 = 1; i2 < parts.length - 1; i2++) {
 | |
|           const p2 = parts[i2];
 | |
|           if (i2 === 1 && p2 === "" && parts[0] === "")
 | |
|             continue;
 | |
|           if (p2 === "." || p2 === "") {
 | |
|             didSomething = true;
 | |
|             parts.splice(i2, 1);
 | |
|             i2--;
 | |
|           }
 | |
|         }
 | |
|         if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
 | |
|           didSomething = true;
 | |
|           parts.pop();
 | |
|         }
 | |
|       }
 | |
|       let dd = 0;
 | |
|       while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
 | |
|         const p2 = parts[dd - 1];
 | |
|         if (p2 && p2 !== "." && p2 !== ".." && p2 !== "**") {
 | |
|           didSomething = true;
 | |
|           parts.splice(dd - 1, 2);
 | |
|           dd -= 2;
 | |
|         }
 | |
|       }
 | |
|     } while (didSomething);
 | |
|     return parts.length === 0 ? [""] : parts;
 | |
|   }
 | |
|   // First phase: single-pattern processing
 | |
|   // <pre> is 1 or more portions
 | |
|   // <rest> is 1 or more portions
 | |
|   // <p> is any portion other than ., .., '', or **
 | |
|   // <e> is . or ''
 | |
|   //
 | |
|   // **/.. is *brutal* for filesystem walking performance, because
 | |
|   // it effectively resets the recursive walk each time it occurs,
 | |
|   // and ** cannot be reduced out by a .. pattern part like a regexp
 | |
|   // or most strings (other than .., ., and '') can be.
 | |
|   //
 | |
|   // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
 | |
|   // <pre>/<e>/<rest> -> <pre>/<rest>
 | |
|   // <pre>/<p>/../<rest> -> <pre>/<rest>
 | |
|   // **/**/<rest> -> **/<rest>
 | |
|   //
 | |
|   // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
 | |
|   // this WOULD be allowed if ** did follow symlinks, or * didn't
 | |
|   firstPhasePreProcess(globParts) {
 | |
|     let didSomething = false;
 | |
|     do {
 | |
|       didSomething = false;
 | |
|       for (let parts of globParts) {
 | |
|         let gs = -1;
 | |
|         while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
 | |
|           let gss = gs;
 | |
|           while (parts[gss + 1] === "**") {
 | |
|             gss++;
 | |
|           }
 | |
|           if (gss > gs) {
 | |
|             parts.splice(gs + 1, gss - gs);
 | |
|           }
 | |
|           let next = parts[gs + 1];
 | |
|           const p2 = parts[gs + 2];
 | |
|           const p22 = parts[gs + 3];
 | |
|           if (next !== "..")
 | |
|             continue;
 | |
|           if (!p2 || p2 === "." || p2 === ".." || !p22 || p22 === "." || p22 === "..") {
 | |
|             continue;
 | |
|           }
 | |
|           didSomething = true;
 | |
|           parts.splice(gs, 1);
 | |
|           const other = parts.slice(0);
 | |
|           other[gs] = "**";
 | |
|           globParts.push(other);
 | |
|           gs--;
 | |
|         }
 | |
|         if (!this.preserveMultipleSlashes) {
 | |
|           for (let i2 = 1; i2 < parts.length - 1; i2++) {
 | |
|             const p2 = parts[i2];
 | |
|             if (i2 === 1 && p2 === "" && parts[0] === "")
 | |
|               continue;
 | |
|             if (p2 === "." || p2 === "") {
 | |
|               didSomething = true;
 | |
|               parts.splice(i2, 1);
 | |
|               i2--;
 | |
|             }
 | |
|           }
 | |
|           if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
 | |
|             didSomething = true;
 | |
|             parts.pop();
 | |
|           }
 | |
|         }
 | |
|         let dd = 0;
 | |
|         while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
 | |
|           const p2 = parts[dd - 1];
 | |
|           if (p2 && p2 !== "." && p2 !== ".." && p2 !== "**") {
 | |
|             didSomething = true;
 | |
|             const needDot = dd === 1 && parts[dd + 1] === "**";
 | |
|             const splin = needDot ? ["."] : [];
 | |
|             parts.splice(dd - 1, 2, ...splin);
 | |
|             if (parts.length === 0)
 | |
|               parts.push("");
 | |
|             dd -= 2;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     } while (didSomething);
 | |
|     return globParts;
 | |
|   }
 | |
|   // second phase: multi-pattern dedupes
 | |
|   // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
 | |
|   // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
 | |
|   // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
 | |
|   //
 | |
|   // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
 | |
|   // ^-- not valid because ** doens't follow symlinks
 | |
|   secondPhasePreProcess(globParts) {
 | |
|     for (let i2 = 0; i2 < globParts.length - 1; i2++) {
 | |
|       for (let j2 = i2 + 1; j2 < globParts.length; j2++) {
 | |
|         const matched = this.partsMatch(globParts[i2], globParts[j2], !this.preserveMultipleSlashes);
 | |
|         if (matched) {
 | |
|           globParts[i2] = [];
 | |
|           globParts[j2] = matched;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return globParts.filter((gs) => gs.length);
 | |
|   }
 | |
|   partsMatch(a2, b2, emptyGSMatch = false) {
 | |
|     let ai = 0;
 | |
|     let bi = 0;
 | |
|     let result = [];
 | |
|     let which = "";
 | |
|     while (ai < a2.length && bi < b2.length) {
 | |
|       if (a2[ai] === b2[bi]) {
 | |
|         result.push(which === "b" ? b2[bi] : a2[ai]);
 | |
|         ai++;
 | |
|         bi++;
 | |
|       } else if (emptyGSMatch && a2[ai] === "**" && b2[bi] === a2[ai + 1]) {
 | |
|         result.push(a2[ai]);
 | |
|         ai++;
 | |
|       } else if (emptyGSMatch && b2[bi] === "**" && a2[ai] === b2[bi + 1]) {
 | |
|         result.push(b2[bi]);
 | |
|         bi++;
 | |
|       } else if (a2[ai] === "*" && b2[bi] && (this.options.dot || !b2[bi].startsWith(".")) && b2[bi] !== "**") {
 | |
|         if (which === "b")
 | |
|           return false;
 | |
|         which = "a";
 | |
|         result.push(a2[ai]);
 | |
|         ai++;
 | |
|         bi++;
 | |
|       } else if (b2[bi] === "*" && a2[ai] && (this.options.dot || !a2[ai].startsWith(".")) && a2[ai] !== "**") {
 | |
|         if (which === "a")
 | |
|           return false;
 | |
|         which = "b";
 | |
|         result.push(b2[bi]);
 | |
|         ai++;
 | |
|         bi++;
 | |
|       } else {
 | |
|         return false;
 | |
|       }
 | |
|     }
 | |
|     return a2.length === b2.length && result;
 | |
|   }
 | |
|   parseNegate() {
 | |
|     if (this.nonegate)
 | |
|       return;
 | |
|     const pattern = this.pattern;
 | |
|     let negate = false;
 | |
|     let negateOffset = 0;
 | |
|     for (let i2 = 0; i2 < pattern.length && pattern.charAt(i2) === "!"; i2++) {
 | |
|       negate = !negate;
 | |
|       negateOffset++;
 | |
|     }
 | |
|     if (negateOffset)
 | |
|       this.pattern = pattern.slice(negateOffset);
 | |
|     this.negate = negate;
 | |
|   }
 | |
|   // set partial to true to test if, for example,
 | |
|   // "/a/b" matches the start of "/*/b/*/d"
 | |
|   // Partial means, if you run out of file before you run
 | |
|   // out of pattern, then that's fine, as long as all
 | |
|   // the parts match.
 | |
|   matchOne(file, pattern, partial = false) {
 | |
|     const options = this.options;
 | |
|     if (this.isWindows) {
 | |
|       const fileDrive = typeof file[0] === "string" && /^[a-z]:$/i.test(file[0]);
 | |
|       const fileUNC = !fileDrive && file[0] === "" && file[1] === "" && file[2] === "?" && /^[a-z]:$/i.test(file[3]);
 | |
|       const patternDrive = typeof pattern[0] === "string" && /^[a-z]:$/i.test(pattern[0]);
 | |
|       const patternUNC = !patternDrive && pattern[0] === "" && pattern[1] === "" && pattern[2] === "?" && typeof pattern[3] === "string" && /^[a-z]:$/i.test(pattern[3]);
 | |
|       const fdi = fileUNC ? 3 : fileDrive ? 0 : void 0;
 | |
|       const pdi = patternUNC ? 3 : patternDrive ? 0 : void 0;
 | |
|       if (typeof fdi === "number" && typeof pdi === "number") {
 | |
|         const [fd, pd] = [file[fdi], pattern[pdi]];
 | |
|         if (fd.toLowerCase() === pd.toLowerCase()) {
 | |
|           pattern[pdi] = fd;
 | |
|           if (pdi > fdi) {
 | |
|             pattern = pattern.slice(pdi);
 | |
|           } else if (fdi > pdi) {
 | |
|             file = file.slice(fdi);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     const { optimizationLevel = 1 } = this.options;
 | |
|     if (optimizationLevel >= 2) {
 | |
|       file = this.levelTwoFileOptimize(file);
 | |
|     }
 | |
|     this.debug("matchOne", this, { file, pattern });
 | |
|     this.debug("matchOne", file.length, pattern.length);
 | |
|     for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
 | |
|       this.debug("matchOne loop");
 | |
|       var p2 = pattern[pi];
 | |
|       var f2 = file[fi];
 | |
|       this.debug(pattern, p2, f2);
 | |
|       if (p2 === false) {
 | |
|         return false;
 | |
|       }
 | |
|       if (p2 === GLOBSTAR) {
 | |
|         this.debug("GLOBSTAR", [pattern, p2, f2]);
 | |
|         var fr = fi;
 | |
|         var pr = pi + 1;
 | |
|         if (pr === pl) {
 | |
|           this.debug("** at the end");
 | |
|           for (; fi < fl; fi++) {
 | |
|             if (file[fi] === "." || file[fi] === ".." || !options.dot && file[fi].charAt(0) === ".")
 | |
|               return false;
 | |
|           }
 | |
|           return true;
 | |
|         }
 | |
|         while (fr < fl) {
 | |
|           var swallowee = file[fr];
 | |
|           this.debug("\nglobstar while", file, fr, pattern, pr, swallowee);
 | |
|           if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
 | |
|             this.debug("globstar found match!", fr, fl, swallowee);
 | |
|             return true;
 | |
|           } else {
 | |
|             if (swallowee === "." || swallowee === ".." || !options.dot && swallowee.charAt(0) === ".") {
 | |
|               this.debug("dot detected!", file, fr, pattern, pr);
 | |
|               break;
 | |
|             }
 | |
|             this.debug("globstar swallow a segment, and continue");
 | |
|             fr++;
 | |
|           }
 | |
|         }
 | |
|         if (partial) {
 | |
|           this.debug("\n>>> no match, partial?", file, fr, pattern, pr);
 | |
|           if (fr === fl) {
 | |
|             return true;
 | |
|           }
 | |
|         }
 | |
|         return false;
 | |
|       }
 | |
|       let hit;
 | |
|       if (typeof p2 === "string") {
 | |
|         hit = f2 === p2;
 | |
|         this.debug("string match", p2, f2, hit);
 | |
|       } else {
 | |
|         hit = p2.test(f2);
 | |
|         this.debug("pattern match", p2, f2, hit);
 | |
|       }
 | |
|       if (!hit)
 | |
|         return false;
 | |
|     }
 | |
|     if (fi === fl && pi === pl) {
 | |
|       return true;
 | |
|     } else if (fi === fl) {
 | |
|       return partial;
 | |
|     } else if (pi === pl) {
 | |
|       return fi === fl - 1 && file[fi] === "";
 | |
|     } else {
 | |
|       throw new Error("wtf?");
 | |
|     }
 | |
|   }
 | |
|   braceExpand() {
 | |
|     return braceExpand(this.pattern, this.options);
 | |
|   }
 | |
|   parse(pattern) {
 | |
|     assertValidPattern(pattern);
 | |
|     const options = this.options;
 | |
|     if (pattern === "**")
 | |
|       return GLOBSTAR;
 | |
|     if (pattern === "")
 | |
|       return "";
 | |
|     let m2;
 | |
|     let fastTest = null;
 | |
|     if (m2 = pattern.match(starRE)) {
 | |
|       fastTest = options.dot ? starTestDot : starTest;
 | |
|     } else if (m2 = pattern.match(starDotExtRE)) {
 | |
|       fastTest = (options.nocase ? options.dot ? starDotExtTestNocaseDot : starDotExtTestNocase : options.dot ? starDotExtTestDot : starDotExtTest)(m2[1]);
 | |
|     } else if (m2 = pattern.match(qmarksRE)) {
 | |
|       fastTest = (options.nocase ? options.dot ? qmarksTestNocaseDot : qmarksTestNocase : options.dot ? qmarksTestDot : qmarksTest)(m2);
 | |
|     } else if (m2 = pattern.match(starDotStarRE)) {
 | |
|       fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
 | |
|     } else if (m2 = pattern.match(dotStarRE)) {
 | |
|       fastTest = dotStarTest;
 | |
|     }
 | |
|     const re = AST.fromGlob(pattern, this.options).toMMPattern();
 | |
|     if (fastTest && typeof re === "object") {
 | |
|       Reflect.defineProperty(re, "test", { value: fastTest });
 | |
|     }
 | |
|     return re;
 | |
|   }
 | |
|   makeRe() {
 | |
|     if (this.regexp || this.regexp === false)
 | |
|       return this.regexp;
 | |
|     const set2 = this.set;
 | |
|     if (!set2.length) {
 | |
|       this.regexp = false;
 | |
|       return this.regexp;
 | |
|     }
 | |
|     const options = this.options;
 | |
|     const twoStar = options.noglobstar ? star2 : options.dot ? twoStarDot : twoStarNoDot;
 | |
|     const flags = new Set(options.nocase ? ["i"] : []);
 | |
|     let re = set2.map((pattern) => {
 | |
|       const pp = pattern.map((p2) => {
 | |
|         if (p2 instanceof RegExp) {
 | |
|           for (const f2 of p2.flags.split(""))
 | |
|             flags.add(f2);
 | |
|         }
 | |
|         return typeof p2 === "string" ? regExpEscape2(p2) : p2 === GLOBSTAR ? GLOBSTAR : p2._src;
 | |
|       });
 | |
|       pp.forEach((p2, i2) => {
 | |
|         const next = pp[i2 + 1];
 | |
|         const prev = pp[i2 - 1];
 | |
|         if (p2 !== GLOBSTAR || prev === GLOBSTAR) {
 | |
|           return;
 | |
|         }
 | |
|         if (prev === void 0) {
 | |
|           if (next !== void 0 && next !== GLOBSTAR) {
 | |
|             pp[i2 + 1] = "(?:\\/|" + twoStar + "\\/)?" + next;
 | |
|           } else {
 | |
|             pp[i2] = twoStar;
 | |
|           }
 | |
|         } else if (next === void 0) {
 | |
|           pp[i2 - 1] = prev + "(?:\\/|" + twoStar + ")?";
 | |
|         } else if (next !== GLOBSTAR) {
 | |
|           pp[i2 - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next;
 | |
|           pp[i2 + 1] = GLOBSTAR;
 | |
|         }
 | |
|       });
 | |
|       return pp.filter((p2) => p2 !== GLOBSTAR).join("/");
 | |
|     }).join("|");
 | |
|     const [open, close] = set2.length > 1 ? ["(?:", ")"] : ["", ""];
 | |
|     re = "^" + open + re + close + "$";
 | |
|     if (this.negate)
 | |
|       re = "^(?!" + re + ").+$";
 | |
|     try {
 | |
|       this.regexp = new RegExp(re, [...flags].join(""));
 | |
|     } catch (ex) {
 | |
|       this.regexp = false;
 | |
|     }
 | |
|     return this.regexp;
 | |
|   }
 | |
|   slashSplit(p2) {
 | |
|     if (this.preserveMultipleSlashes) {
 | |
|       return p2.split("/");
 | |
|     } else if (this.isWindows && /^\/\/[^\/]+/.test(p2)) {
 | |
|       return ["", ...p2.split(/\/+/)];
 | |
|     } else {
 | |
|       return p2.split(/\/+/);
 | |
|     }
 | |
|   }
 | |
|   match(f2, partial = this.partial) {
 | |
|     this.debug("match", f2, this.pattern);
 | |
|     if (this.comment) {
 | |
|       return false;
 | |
|     }
 | |
|     if (this.empty) {
 | |
|       return f2 === "";
 | |
|     }
 | |
|     if (f2 === "/" && partial) {
 | |
|       return true;
 | |
|     }
 | |
|     const options = this.options;
 | |
|     if (this.isWindows) {
 | |
|       f2 = f2.split("\\").join("/");
 | |
|     }
 | |
|     const ff = this.slashSplit(f2);
 | |
|     this.debug(this.pattern, "split", ff);
 | |
|     const set2 = this.set;
 | |
|     this.debug(this.pattern, "set", set2);
 | |
|     let filename = ff[ff.length - 1];
 | |
|     if (!filename) {
 | |
|       for (let i2 = ff.length - 2; !filename && i2 >= 0; i2--) {
 | |
|         filename = ff[i2];
 | |
|       }
 | |
|     }
 | |
|     for (let i2 = 0; i2 < set2.length; i2++) {
 | |
|       const pattern = set2[i2];
 | |
|       let file = ff;
 | |
|       if (options.matchBase && pattern.length === 1) {
 | |
|         file = [filename];
 | |
|       }
 | |
|       const hit = this.matchOne(file, pattern, partial);
 | |
|       if (hit) {
 | |
|         if (options.flipNegate) {
 | |
|           return true;
 | |
|         }
 | |
|         return !this.negate;
 | |
|       }
 | |
|     }
 | |
|     if (options.flipNegate) {
 | |
|       return false;
 | |
|     }
 | |
|     return this.negate;
 | |
|   }
 | |
|   static defaults(def) {
 | |
|     return minimatch.defaults(def).Minimatch;
 | |
|   }
 | |
| };
 | |
| minimatch.AST = AST;
 | |
| minimatch.Minimatch = Minimatch;
 | |
| minimatch.escape = escape;
 | |
| minimatch.unescape = unescape;
 | |
| 
 | |
| // src/utils/fs.ts
 | |
| function isSupportedFileType(path3) {
 | |
|   return path3.split(".").pop().toLowerCase() === "md";
 | |
| }
 | |
| function pathMatchesPattern(path3, pattern) {
 | |
|   return path3.startsWith(pattern) || minimatch(path3, pattern);
 | |
| }
 | |
| 
 | |
| // src/algorithms/osr/osr-note-graph.ts
 | |
| var OsrNoteGraph = class {
 | |
|   constructor(vaultNoteLinkInfoFinder) {
 | |
|     // Key: targetFilename
 | |
|     // Value: Map<sourceFilename, linkCount>
 | |
|     // This is the number of links from sourceFilename to targetFilename
 | |
|     // For simplicity, we just store the filename without the directory or filename extension
 | |
|     this.incomingLinks = {};
 | |
|     this.pageranks = {};
 | |
|     this.vaultNoteLinkInfoFinder = vaultNoteLinkInfoFinder;
 | |
|     this.reset();
 | |
|   }
 | |
|   reset() {
 | |
|     this.incomingLinks = {};
 | |
|     this.pageranks = {};
 | |
|     graph.reset();
 | |
|   }
 | |
|   processLinks(path3) {
 | |
|     if (this.incomingLinks[path3] === void 0) {
 | |
|       this.incomingLinks[path3] = [];
 | |
|     }
 | |
|     const targetLinks = this.vaultNoteLinkInfoFinder.getResolvedTargetLinksForNotePath(path3) || {};
 | |
|     for (const targetPath in targetLinks) {
 | |
|       if (this.incomingLinks[targetPath] === void 0) this.incomingLinks[targetPath] = [];
 | |
|       if (isSupportedFileType(targetPath)) {
 | |
|         const linkCount = targetLinks[targetPath];
 | |
|         this.incomingLinks[targetPath].push({
 | |
|           sourcePath: path3,
 | |
|           linkCount
 | |
|         });
 | |
|         graph.link(path3, targetPath, linkCount);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   calcNoteLinkStat(notePath, noteEaseList) {
 | |
|     let linkTotal = 0, linkPGTotal = 0, totalLinkCount = 0;
 | |
|     for (const statObj of this.incomingLinks[notePath] || []) {
 | |
|       const ease = noteEaseList.getEaseByPath(statObj.sourcePath);
 | |
|       if (ease) {
 | |
|         linkTotal += statObj.linkCount * this.pageranks[statObj.sourcePath] * ease;
 | |
|         linkPGTotal += this.pageranks[statObj.sourcePath] * statObj.linkCount;
 | |
|         totalLinkCount += statObj.linkCount;
 | |
|       }
 | |
|     }
 | |
|     const outgoingLinks = this.vaultNoteLinkInfoFinder.getResolvedTargetLinksForNotePath(notePath) || {};
 | |
|     for (const outgoingLink in outgoingLinks) {
 | |
|       const ease = noteEaseList.getEaseByPath(outgoingLink);
 | |
|       const linkCount = outgoingLinks[outgoingLink];
 | |
|       const pageRank = this.pageranks[outgoingLink];
 | |
|       if (ease) {
 | |
|         linkTotal += linkCount * pageRank * ease;
 | |
|         linkPGTotal += pageRank * linkCount;
 | |
|         totalLinkCount += linkCount;
 | |
|       }
 | |
|     }
 | |
|     return { linkTotal, linkPGTotal, totalLinkCount };
 | |
|   }
 | |
|   generatePageRanks() {
 | |
|     graph.rank(0.85, 1e-6, (node, rank2) => {
 | |
|       this.pageranks[node] = rank2 * 1e4;
 | |
|     });
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/data-store-algorithm/data-store-algorithm.ts
 | |
| var DataStoreAlgorithm = class _DataStoreAlgorithm {
 | |
|   static getInstance() {
 | |
|     if (!_DataStoreAlgorithm.instance) {
 | |
|       throw new Error("there is no DataStoreAlgorithm instance.");
 | |
|     }
 | |
|     return _DataStoreAlgorithm.instance;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/data-stores/base/data-store.ts
 | |
| var DataStore = class _DataStore {
 | |
|   static getInstance() {
 | |
|     if (!_DataStore.instance) {
 | |
|       throw new Error("there is no DataStore instance.");
 | |
|     }
 | |
|     return _DataStore.instance;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/topic-path.ts
 | |
| var TopicPath = class _TopicPath {
 | |
|   constructor(path3) {
 | |
|     if (path3 == null) throw "null path";
 | |
|     if (path3.some((str) => str.includes("/"))) throw "path entries must not contain '/'";
 | |
|     this.path = path3;
 | |
|   }
 | |
|   get hasPath() {
 | |
|     return this.path.length > 0;
 | |
|   }
 | |
|   get isEmptyPath() {
 | |
|     return !this.hasPath;
 | |
|   }
 | |
|   static get emptyPath() {
 | |
|     return new _TopicPath([]);
 | |
|   }
 | |
|   shift() {
 | |
|     if (this.isEmptyPath) throw "can't shift an empty path";
 | |
|     return this.path.shift();
 | |
|   }
 | |
|   clone() {
 | |
|     return new _TopicPath([...this.path]);
 | |
|   }
 | |
|   formatAsTag() {
 | |
|     if (this.isEmptyPath) throw "Empty path";
 | |
|     const result = "#" + this.path.join("/");
 | |
|     return result;
 | |
|   }
 | |
|   static getTopicPathOfFile(noteFile, settings) {
 | |
|     let deckPath = [];
 | |
|     let result = _TopicPath.emptyPath;
 | |
|     if (settings.convertFoldersToDecks) {
 | |
|       deckPath = noteFile.path.split("/");
 | |
|       deckPath.pop();
 | |
|       if (deckPath.length != 0) {
 | |
|         result = new _TopicPath(deckPath);
 | |
|       }
 | |
|     } else {
 | |
|       const tagList = this.getTopicPathsFromTagList(
 | |
|         noteFile.getAllTagsFromCache()
 | |
|       );
 | |
|       outer: for (const tagToReview of this.getTopicPathsFromTagList(
 | |
|         settings.flashcardTags
 | |
|       )) {
 | |
|         for (const tag of tagList) {
 | |
|           if (tagToReview.isSameOrAncestorOf(tag)) {
 | |
|             result = tag;
 | |
|             break outer;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   isSameOrAncestorOf(topicPath) {
 | |
|     if (this.isEmptyPath) return topicPath.isEmptyPath;
 | |
|     if (this.path.length > topicPath.path.length) return false;
 | |
|     for (let i2 = 0; i2 < this.path.length; i2++) {
 | |
|       if (this.path[i2] != topicPath.path[i2]) return false;
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
|   static getTopicPathFromCardText(cardText) {
 | |
|     var _a;
 | |
|     const path3 = (_a = cardText.trimStart().match(OBSIDIAN_TAG_AT_STARTOFLINE_REGEX)) == null ? void 0 : _a.slice(-1)[0];
 | |
|     return (path3 == null ? void 0 : path3.length) > 0 ? _TopicPath.getTopicPathFromTag(path3) : null;
 | |
|   }
 | |
|   static getTopicPathsFromTagList(tagList) {
 | |
|     const result = [];
 | |
|     for (const tag of tagList) {
 | |
|       if (this.isValidTag(tag)) result.push(_TopicPath.getTopicPathFromTag(tag));
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   static isValidTag(tag) {
 | |
|     if (tag == null || tag.length == 0) return false;
 | |
|     if (tag[0] != "#") return false;
 | |
|     if (tag.length == 1) return false;
 | |
|     return true;
 | |
|   }
 | |
|   static getTopicPathFromTag(tag) {
 | |
|     if (tag == null || tag.length == 0) throw "Null/empty tag";
 | |
|     if (tag[0] != "#") throw "Tag must start with #";
 | |
|     if (tag.length == 1) throw "Invalid tag";
 | |
|     const path3 = tag.replace("#", "").split("/").filter((str) => str);
 | |
|     return new _TopicPath(path3);
 | |
|   }
 | |
|   static getFolderPathFromFilename(noteFile, settings) {
 | |
|     let result = _TopicPath.emptyPath;
 | |
|     if (settings.convertFoldersToDecks) {
 | |
|       const deckPath = noteFile.path.split("/");
 | |
|       deckPath.pop();
 | |
|       if (deckPath.length != 0) {
 | |
|         result = new _TopicPath(deckPath);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var TopicPathList = class _TopicPathList {
 | |
|   constructor(list, lineNum = null) {
 | |
|     if (list == null) throw "TopicPathList null";
 | |
|     this.list = list;
 | |
|     this.lineNum = lineNum;
 | |
|   }
 | |
|   get length() {
 | |
|     return this.list.length;
 | |
|   }
 | |
|   isAnyElementSameOrAncestorOf(topicPath) {
 | |
|     return this.list.some((item) => item.isSameOrAncestorOf(topicPath));
 | |
|   }
 | |
|   formatPsv() {
 | |
|     return this.format("|");
 | |
|   }
 | |
|   format(sep2) {
 | |
|     return this.list.map((topicPath) => topicPath.formatAsTag()).join(sep2);
 | |
|   }
 | |
|   static empty() {
 | |
|     return new _TopicPathList([]);
 | |
|   }
 | |
|   static fromPsv(str, lineNum) {
 | |
|     const result = _TopicPathList.convertTagListToTopicPathList(str.split("|"));
 | |
|     result.lineNum = lineNum;
 | |
|     return result;
 | |
|   }
 | |
|   //
 | |
|   // tagList is a list of tags such as:
 | |
|   //      ["#flashcards/computing", "#boring-stuff", "#news-worthy"]
 | |
|   // validTopicPathList is a list of valid tags, such as those from settings.flashcardTags,E.g.
 | |
|   //      ["#flashcards"]
 | |
|   //
 | |
|   // This returns a filtered version of tagList, containing only topic paths that are considered valid.
 | |
|   // Validity is defined as "isAnyElementSameOrAncestorOf", and "#flashcards" is considered the ancestor of
 | |
|   // "#flashcards/computing".
 | |
|   //
 | |
|   // Therefore this would return:
 | |
|   //      "#flashcards/computing" (but not "#boring-stuff" or "#news-worthy")
 | |
|   //
 | |
|   static filterValidTopicPathsFromTagList(list, validTopicPathList, lineNum = null) {
 | |
|     const result = [];
 | |
|     for (const tag of list.list) {
 | |
|       if (validTopicPathList.isAnyElementSameOrAncestorOf(tag)) result.push(tag);
 | |
|     }
 | |
|     return new _TopicPathList(result, lineNum);
 | |
|   }
 | |
|   static convertTagListToTopicPathList(tagList) {
 | |
|     const result = [];
 | |
|     for (const tag of tagList) {
 | |
|       if (TopicPath.isValidTag(tag)) result.push(TopicPath.getTopicPathFromTag(tag));
 | |
|     }
 | |
|     return new _TopicPathList(result);
 | |
|   }
 | |
| };
 | |
| var TopicPathWithWs = class {
 | |
|   constructor(topicPath, preWhitespace, postWhitespace) {
 | |
|     if (!topicPath || topicPath.isEmptyPath) throw "topicPath null";
 | |
|     this.topicPath = topicPath;
 | |
|     this.preWhitespace = preWhitespace;
 | |
|     this.postWhitespace = postWhitespace;
 | |
|   }
 | |
|   formatWithWs() {
 | |
|     return `${this.preWhitespace}${this.topicPath.formatAsTag()}${this.postWhitespace}`;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/flashcard-review-sequencer.ts
 | |
| var DeckStats = class {
 | |
|   constructor(totalCount, dueCount, newCount, cardsInQueueCount, dueCardsInQueueOfThisDeckCount, newCardsInQueueOfThisDeckCount, cardsInQueueOfThisDeckCount, subDecksInQueueOfThisDeckCount, decksInQueueOfThisDeckCount) {
 | |
|     this.dueCount = dueCount;
 | |
|     this.newCount = newCount;
 | |
|     this.totalCount = totalCount;
 | |
|     this.cardsInQueueCount = cardsInQueueCount;
 | |
|     this.dueCardsInQueueOfThisDeckCount = dueCardsInQueueOfThisDeckCount;
 | |
|     this.newCardsInQueueOfThisDeckCount = newCardsInQueueOfThisDeckCount;
 | |
|     this.cardsInQueueOfThisDeckCount = cardsInQueueOfThisDeckCount;
 | |
|     this.subDecksInQueueOfThisDeckCount = subDecksInQueueOfThisDeckCount;
 | |
|     this.decksInQueueOfThisDeckCount = decksInQueueOfThisDeckCount;
 | |
|   }
 | |
| };
 | |
| var FlashcardReviewSequencer = class {
 | |
|   constructor(reviewMode, cardSequencer, settings, srsAlgorithm, questionPostponementList, dueDateFlashcardHistogram) {
 | |
|     this.reviewMode = reviewMode;
 | |
|     this.cardSequencer = cardSequencer;
 | |
|     this.settings = settings;
 | |
|     this.srsAlgorithm = srsAlgorithm;
 | |
|     this.questionPostponementList = questionPostponementList;
 | |
|     this.dueDateFlashcardHistogram = dueDateFlashcardHistogram;
 | |
|   }
 | |
|   get hasCurrentCard() {
 | |
|     return this.cardSequencer.currentCard != null;
 | |
|   }
 | |
|   get currentCard() {
 | |
|     return this.cardSequencer.currentCard;
 | |
|   }
 | |
|   get currentQuestion() {
 | |
|     var _a;
 | |
|     return (_a = this.currentCard) == null ? void 0 : _a.question;
 | |
|   }
 | |
|   get currentDeck() {
 | |
|     return this.cardSequencer.currentDeck;
 | |
|   }
 | |
|   get currentNote() {
 | |
|     return this.currentQuestion.note;
 | |
|   }
 | |
|   // originalDeckTree isn't modified by the review process
 | |
|   // Only remainingDeckTree
 | |
|   setDeckTree(originalDeckTree, remainingDeckTree) {
 | |
|     this.cardSequencer.setBaseDeck(remainingDeckTree);
 | |
|     this._originalDeckTree = originalDeckTree;
 | |
|     this.remainingDeckTree = remainingDeckTree;
 | |
|     this.setCurrentDeck(TopicPath.emptyPath);
 | |
|   }
 | |
|   setCurrentDeck(topicPath) {
 | |
|     this.cardSequencer.setIteratorTopicPath(topicPath);
 | |
|     this.cardSequencer.nextCard();
 | |
|   }
 | |
|   get originalDeckTree() {
 | |
|     return this._originalDeckTree;
 | |
|   }
 | |
|   getDeckStats(topicPath) {
 | |
|     const totalCount = this._originalDeckTree.getDeck(topicPath).getDistinctCardCount(2 /* All */, true);
 | |
|     const remainingDeck = this.remainingDeckTree.getDeck(topicPath);
 | |
|     const newCount = remainingDeck.getDistinctCardCount(0 /* NewCard */, true);
 | |
|     const dueCount = remainingDeck.getDistinctCardCount(1 /* DueCard */, true);
 | |
|     const newCardsInQueueOfThisDeckCount = remainingDeck.getDistinctCardCount(
 | |
|       0 /* NewCard */,
 | |
|       false
 | |
|     );
 | |
|     const dueCardsInQueueOfThisDeckCount = remainingDeck.getDistinctCardCount(
 | |
|       1 /* DueCard */,
 | |
|       false
 | |
|     );
 | |
|     const cardsInQueueOfThisDeckCount = newCardsInQueueOfThisDeckCount + dueCardsInQueueOfThisDeckCount;
 | |
|     const subDecksInQueueOfThisDeckCount = this.getSubDecksWithCardsInQueue(remainingDeck).length;
 | |
|     const decksInQueueOfThisDeckCount = cardsInQueueOfThisDeckCount > 0 ? subDecksInQueueOfThisDeckCount + 1 : subDecksInQueueOfThisDeckCount;
 | |
|     return new DeckStats(
 | |
|       totalCount,
 | |
|       dueCount,
 | |
|       newCount,
 | |
|       dueCount + newCount,
 | |
|       dueCardsInQueueOfThisDeckCount,
 | |
|       newCardsInQueueOfThisDeckCount,
 | |
|       cardsInQueueOfThisDeckCount,
 | |
|       subDecksInQueueOfThisDeckCount,
 | |
|       decksInQueueOfThisDeckCount
 | |
|     );
 | |
|   }
 | |
|   getSubDecksWithCardsInQueue(deck) {
 | |
|     let subDecksWithCardsInQueue = [];
 | |
|     deck.subdecks.forEach((subDeck) => {
 | |
|       subDecksWithCardsInQueue = subDecksWithCardsInQueue.concat(
 | |
|         this.getSubDecksWithCardsInQueue(subDeck)
 | |
|       );
 | |
|       const newCount = subDeck.getDistinctCardCount(0 /* NewCard */, false);
 | |
|       const dueCount = subDeck.getDistinctCardCount(1 /* DueCard */, false);
 | |
|       if (newCount + dueCount > 0) subDecksWithCardsInQueue.push(subDeck);
 | |
|     });
 | |
|     return subDecksWithCardsInQueue;
 | |
|   }
 | |
|   skipCurrentCard() {
 | |
|     this.cardSequencer.deleteCurrentQuestionFromAllDecks();
 | |
|   }
 | |
|   deleteCurrentCard() {
 | |
|     this.cardSequencer.deleteCurrentCardFromAllDecks();
 | |
|   }
 | |
|   async processReview(response) {
 | |
|     switch (this.reviewMode) {
 | |
|       case 1 /* Review */:
 | |
|         await this.processReviewReviewMode(response);
 | |
|         break;
 | |
|       case 0 /* Cram */:
 | |
|         await this.processReviewCramMode(response);
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
|   async processReviewReviewMode(response) {
 | |
|     if (response != 3 /* Reset */ || this.currentCard.hasSchedule) {
 | |
|       const oldSchedule = this.currentCard.scheduleInfo;
 | |
|       this.currentCard.scheduleInfo = this.determineCardSchedule(response, this.currentCard);
 | |
|       await DataStore.getInstance().questionWriteSchedule(this.currentQuestion);
 | |
|       if (oldSchedule) {
 | |
|         const today = globalDateProvider.today.valueOf();
 | |
|         const nDays = Math.ceil(
 | |
|           (oldSchedule.dueDateAsUnix - today) / TICKS_PER_DAY
 | |
|         );
 | |
|         this.dueDateFlashcardHistogram.decrement(nDays);
 | |
|       }
 | |
|       this.dueDateFlashcardHistogram.increment(this.currentCard.scheduleInfo.interval);
 | |
|     }
 | |
|     if (response == 3 /* Reset */) {
 | |
|       this.cardSequencer.moveCurrentCardToEndOfList();
 | |
|       this.cardSequencer.nextCard();
 | |
|     } else {
 | |
|       if (this.settings.burySiblingCards) {
 | |
|         await this.burySiblingCards();
 | |
|         this.cardSequencer.deleteCurrentQuestionFromAllDecks();
 | |
|       } else {
 | |
|         this.deleteCurrentCard();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   async burySiblingCards() {
 | |
|     const remaining = this.currentDeck.getQuestionCardCount(this.currentQuestion);
 | |
|     if (remaining > 1) {
 | |
|       this.questionPostponementList.add(this.currentQuestion);
 | |
|       await this.questionPostponementList.write();
 | |
|     }
 | |
|   }
 | |
|   async processReviewCramMode(response) {
 | |
|     if (response == 0 /* Easy */) this.deleteCurrentCard();
 | |
|     else {
 | |
|       this.cardSequencer.moveCurrentCardToEndOfList();
 | |
|       this.cardSequencer.nextCard();
 | |
|     }
 | |
|   }
 | |
|   determineCardSchedule(response, card) {
 | |
|     let result;
 | |
|     if (response == 3 /* Reset */) {
 | |
|       result = this.srsAlgorithm.cardGetResetSchedule();
 | |
|     } else {
 | |
|       if (card.hasSchedule) {
 | |
|         result = this.srsAlgorithm.cardCalcUpdatedSchedule(
 | |
|           response,
 | |
|           card.scheduleInfo,
 | |
|           this.dueDateFlashcardHistogram
 | |
|         );
 | |
|       } else {
 | |
|         const currentNote = card.question.note;
 | |
|         result = this.srsAlgorithm.cardGetNewSchedule(
 | |
|           response,
 | |
|           currentNote.filePath,
 | |
|           this.dueDateFlashcardHistogram
 | |
|         );
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   async updateCurrentQuestionText(text) {
 | |
|     const q2 = this.currentQuestion.questionText;
 | |
|     q2.actualQuestion = text;
 | |
|     await DataStore.getInstance().questionWrite(this.currentQuestion);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/deck.ts
 | |
| var Deck2 = class _Deck {
 | |
|   constructor(deckName, parent) {
 | |
|     this.deckName = deckName;
 | |
|     this.newFlashcards = [];
 | |
|     this.dueFlashcards = [];
 | |
|     this.subdecks = [];
 | |
|     this.parent = parent;
 | |
|   }
 | |
|   getCardCount(cardListType, includeSubdeckCounts) {
 | |
|     let result = 0;
 | |
|     if (cardListType == 0 /* NewCard */ || cardListType == 2 /* All */)
 | |
|       result += this.newFlashcards.length;
 | |
|     if (cardListType == 1 /* DueCard */ || cardListType == 2 /* All */)
 | |
|       result += this.dueFlashcards.length;
 | |
|     if (includeSubdeckCounts) {
 | |
|       for (const deck of this.subdecks) {
 | |
|         result += deck.getCardCount(cardListType, includeSubdeckCounts);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   getDistinctCardCount(cardListType, includeSubdeckCounts) {
 | |
|     const cardList = this.getFlattenedCardArray(cardListType, includeSubdeckCounts);
 | |
|     const distinctCardSet = new Set(cardList);
 | |
|     return distinctCardSet.size;
 | |
|   }
 | |
|   getFlattenedCardArray(cardListType, includeSubdeckCounts) {
 | |
|     let result = [];
 | |
|     switch (cardListType) {
 | |
|       case 0 /* NewCard */:
 | |
|         result = this.newFlashcards;
 | |
|         break;
 | |
|       case 1 /* DueCard */:
 | |
|         result = this.dueFlashcards;
 | |
|         break;
 | |
|       case 2 /* All */:
 | |
|         result = this.newFlashcards.concat(this.dueFlashcards);
 | |
|     }
 | |
|     if (includeSubdeckCounts) {
 | |
|       for (const subdeck of this.subdecks) {
 | |
|         result = result.concat(
 | |
|           subdeck.getFlattenedCardArray(cardListType, includeSubdeckCounts)
 | |
|         );
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   // Returns a count of the number of this question's cards are present in this deck.
 | |
|   // (The returned value would be <= question.cards.length)
 | |
|   getQuestionCardCount(question) {
 | |
|     let result = 0;
 | |
|     result += this.getQuestionCardCountForCardListType(question, this.newFlashcards);
 | |
|     result += this.getQuestionCardCountForCardListType(question, this.dueFlashcards);
 | |
|     return result;
 | |
|   }
 | |
|   getQuestionCardCountForCardListType(question, cards) {
 | |
|     let result = 0;
 | |
|     for (let i2 = 0; i2 < cards.length; i2++) {
 | |
|       if (Object.is(question, cards[i2].question)) result++;
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   static get emptyDeck() {
 | |
|     return new _Deck("Root", null);
 | |
|   }
 | |
|   get isRootDeck() {
 | |
|     return this.parent == null;
 | |
|   }
 | |
|   getDeckByTopicTag(tag) {
 | |
|     return this.getDeck(TopicPath.getTopicPathFromTag(tag));
 | |
|   }
 | |
|   getDeck(topicPath) {
 | |
|     return this._getOrCreateDeck(topicPath, false);
 | |
|   }
 | |
|   getOrCreateDeck(topicPath) {
 | |
|     return this._getOrCreateDeck(topicPath, true);
 | |
|   }
 | |
|   _getOrCreateDeck(topicPath, createAllowed) {
 | |
|     if (!topicPath.hasPath) {
 | |
|       return this;
 | |
|     }
 | |
|     const t3 = topicPath.clone();
 | |
|     const deckName = t3.shift();
 | |
|     for (const subdeck of this.subdecks) {
 | |
|       if (deckName === subdeck.deckName) {
 | |
|         return subdeck._getOrCreateDeck(t3, createAllowed);
 | |
|       }
 | |
|     }
 | |
|     let result = null;
 | |
|     if (createAllowed) {
 | |
|       const subdeck = new _Deck(
 | |
|         deckName,
 | |
|         this
 | |
|         /* parent */
 | |
|       );
 | |
|       this.subdecks.push(subdeck);
 | |
|       result = subdeck._getOrCreateDeck(t3, createAllowed);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   getTopicPath() {
 | |
|     const list = [];
 | |
|     let deck = this;
 | |
|     while (!deck.isRootDeck) {
 | |
|       list.push(deck.deckName);
 | |
|       deck = deck.parent;
 | |
|     }
 | |
|     return new TopicPath(list.reverse());
 | |
|   }
 | |
|   getRootDeck() {
 | |
|     let deck = this;
 | |
|     while (!deck.isRootDeck) {
 | |
|       deck = deck.parent;
 | |
|     }
 | |
|     return deck;
 | |
|   }
 | |
|   getCard(index, cardListType) {
 | |
|     const cardList = this.getCardListForCardType(cardListType);
 | |
|     return cardList[index];
 | |
|   }
 | |
|   getCardListForCardType(cardListType) {
 | |
|     return cardListType == 1 /* DueCard */ ? this.dueFlashcards : this.newFlashcards;
 | |
|   }
 | |
|   appendCard(topicPathList, cardObj) {
 | |
|     if (topicPathList.list.length == 0) {
 | |
|       this.appendCardToRootDeck(cardObj);
 | |
|     } else {
 | |
|       for (const topicPath of topicPathList.list) {
 | |
|         this.appendCardSingleTopic(topicPath, cardObj);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   appendCardToRootDeck(cardObj) {
 | |
|     this.appendCardSingleTopic(TopicPath.emptyPath, cardObj);
 | |
|   }
 | |
|   appendCardSingleTopic(topicPath, cardObj) {
 | |
|     const deck = this.getOrCreateDeck(topicPath);
 | |
|     const cardList = deck.getCardListForCardType(cardObj.cardListType);
 | |
|     cardList.push(cardObj);
 | |
|   }
 | |
|   // The question lists all the topics in which this card is included.
 | |
|   // The topics are relative to the base deck, and this method must be called on that deck
 | |
|   deleteQuestionFromAllDecks(question, exceptionIfMissing) {
 | |
|     for (const card of question.cards) {
 | |
|       this.deleteCardFromAllDecks(card, exceptionIfMissing);
 | |
|     }
 | |
|   }
 | |
|   deleteQuestion(question, exceptionIfMissing) {
 | |
|     for (const card of question.cards) {
 | |
|       this.deleteCardFromThisDeck(card, exceptionIfMissing);
 | |
|     }
 | |
|   }
 | |
|   // The card's question lists all the topics in which this card is included.
 | |
|   // The topics are relative to the base deck, and this method must be called on that deck
 | |
|   deleteCardFromAllDecks(card, exceptionIfMissing) {
 | |
|     for (const topicPath of card.question.topicPathList.list) {
 | |
|       const deck = this.getDeck(topicPath);
 | |
|       deck.deleteCardFromThisDeck(card, exceptionIfMissing);
 | |
|     }
 | |
|   }
 | |
|   deleteCardFromThisDeck(card, exceptionIfMissing) {
 | |
|     const newIdx = this.newFlashcards.indexOf(card);
 | |
|     if (newIdx != -1) this.newFlashcards.splice(newIdx, 1);
 | |
|     const dueIdx = this.dueFlashcards.indexOf(card);
 | |
|     if (dueIdx != -1) this.dueFlashcards.splice(dueIdx, 1);
 | |
|     if (newIdx == -1 && dueIdx == -1 && exceptionIfMissing) {
 | |
|       throw `deleteCardFromThisDeck: Card: ${card.front} not found in deck: ${this.deckName}`;
 | |
|     }
 | |
|   }
 | |
|   deleteCardAtIndex(index, cardListType) {
 | |
|     const cardList = this.getCardListForCardType(cardListType);
 | |
|     cardList.splice(index, 1);
 | |
|   }
 | |
|   toDeckArray() {
 | |
|     const result = [];
 | |
|     result.push(this);
 | |
|     for (const subdeck of this.subdecks) {
 | |
|       result.push(...subdeck.toDeckArray());
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   sortSubdecksList() {
 | |
|     this.subdecks.sort((a2, b2) => {
 | |
|       if (a2.deckName < b2.deckName) {
 | |
|         return -1;
 | |
|       } else if (a2.deckName > b2.deckName) {
 | |
|         return 1;
 | |
|       }
 | |
|       return 0;
 | |
|     });
 | |
|     for (const deck of this.subdecks) {
 | |
|       deck.sortSubdecksList();
 | |
|     }
 | |
|   }
 | |
|   debugLogToConsole(desc = null, indent = 0) {
 | |
|     let str = desc != null ? `${desc}: ` : "";
 | |
|     console.log(str += this.toString(indent));
 | |
|   }
 | |
|   toString(indent = 0) {
 | |
|     let result = "";
 | |
|     let indentStr = " ".repeat(indent * 4);
 | |
|     result += `${indentStr}${this.deckName}\r
 | |
| `;
 | |
|     indentStr += "  ";
 | |
|     for (let i2 = 0; i2 < this.newFlashcards.length; i2++) {
 | |
|       const card = this.newFlashcards[i2];
 | |
|       result += `${indentStr}New: ${i2}: ${card.front}::${card.back}\r
 | |
| `;
 | |
|     }
 | |
|     for (let i2 = 0; i2 < this.dueFlashcards.length; i2++) {
 | |
|       const card = this.dueFlashcards[i2];
 | |
|       const s2 = card.isDue ? "Due" : "Not due";
 | |
|       result += `${indentStr}${s2}: ${i2}: ${card.front}::${card.back}\r
 | |
| `;
 | |
|     }
 | |
|     for (const subdeck of this.subdecks) {
 | |
|       result += subdeck.toString(indent + 1);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   clone() {
 | |
|     return this.copyWithCardFilter(() => true);
 | |
|   }
 | |
|   copyWithCardFilter(predicate, parent = null) {
 | |
|     const result = new _Deck(this.deckName, parent);
 | |
|     result.newFlashcards = [...this.newFlashcards.filter((card) => predicate(card))];
 | |
|     result.dueFlashcards = [...this.dueFlashcards.filter((card) => predicate(card))];
 | |
|     for (const s2 of this.subdecks) {
 | |
|       const newParent = result;
 | |
|       const newDeck = s2.copyWithCardFilter(predicate, newParent);
 | |
|       result.subdecks.push(newDeck);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   static otherListType(cardListType) {
 | |
|     let result;
 | |
|     if (cardListType == 0 /* NewCard */) result = 1 /* DueCard */;
 | |
|     else if (cardListType == 1 /* DueCard */) result = 0 /* NewCard */;
 | |
|     else throw "Invalid cardListType";
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var DeckTreeFilter = class {
 | |
|   static filterForReviewableCards(reviewableDeckTree) {
 | |
|     return reviewableDeckTree.copyWithCardFilter((card) => !card.question.hasEditLaterTag);
 | |
|   }
 | |
|   static filterForRemainingCards(questionPostponementList, deckTree, reviewMode) {
 | |
|     return deckTree.copyWithCardFilter(
 | |
|       (card) => (reviewMode == 0 /* Cram */ || card.isNew || card.isDue) && !questionPostponementList.includes(card.question)
 | |
|     );
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/utils/types.ts
 | |
| function getTypedObjectEntries(obj) {
 | |
|   return Object.entries(obj);
 | |
| }
 | |
| var getKeysPreserveType = Object.keys;
 | |
| function mapRecord(record, transform) {
 | |
|   return Object.fromEntries(
 | |
|     Object.entries(record).map(([key, value]) => transform(key, value))
 | |
|   );
 | |
| }
 | |
| 
 | |
| // src/utils/numbers.ts
 | |
| var ValueCountDict = class {
 | |
|   constructor() {
 | |
|     this.dict = {};
 | |
|   }
 | |
|   // Record<value, count>
 | |
|   clearCountIfMissing(value) {
 | |
|     if (!this.hasValue(value)) this.dict[value] = 0;
 | |
|   }
 | |
|   hasValue(value) {
 | |
|     return Object.prototype.hasOwnProperty.call(this.dict, value);
 | |
|   }
 | |
|   incrementCount(value) {
 | |
|     this.clearCountIfMissing(value);
 | |
|     this.dict[value]++;
 | |
|   }
 | |
|   getMaxValue() {
 | |
|     return Math.max(...getKeysPreserveType(this.dict)) || 0;
 | |
|   }
 | |
|   getTotalOfValueMultiplyCount() {
 | |
|     const v2 = getTypedObjectEntries(this.dict).map(([value, count]) => value * count).reduce((a2, b2) => a2 + b2, 0) || 0;
 | |
|     return v2;
 | |
|   }
 | |
| };
 | |
| var RandomNumberProvider = class {
 | |
|   getInteger(lowerBound, upperBound) {
 | |
|     const range = upperBound - lowerBound + 1;
 | |
|     return Math.floor(Math.random() * range) + lowerBound;
 | |
|   }
 | |
| };
 | |
| var StaticRandomNumberProvider = class {
 | |
|   getInteger(lowerBound, upperBound) {
 | |
|     if (lowerBound != this.expectedLowerBound || upperBound != this.expectedUpperBound)
 | |
|       throw `lowerBound: A${lowerBound}/E${this.expectedLowerBound}, upperBound: A${upperBound}/E${this.expectedUpperBound}`;
 | |
|     return this.next;
 | |
|   }
 | |
| };
 | |
| var WeightedRandomNumber = class _WeightedRandomNumber {
 | |
|   constructor(provider) {
 | |
|     this.provider = provider;
 | |
|   }
 | |
|   static create() {
 | |
|     return new _WeightedRandomNumber(globalRandomNumberProvider);
 | |
|   }
 | |
|   // weights is a dictionary:
 | |
|   //      first number - a key that can be returned
 | |
|   //      second number - the "bucket size" - this is a weight that influences the probability of the
 | |
|   //          first number being returned
 | |
|   //
 | |
|   // returns:
 | |
|   //      first number - one of the keys from the weights parameter
 | |
|   //      second number - an "index" value; 0 <= index < bucketSize
 | |
|   getRandomValues(weights) {
 | |
|     const total = _WeightedRandomNumber.calcTotalOfCount(weights);
 | |
|     if (Object.values(weights).some((i2) => !Number.isInteger(i2) || i2 < 0))
 | |
|       throw "All weights must be positive integers";
 | |
|     const v2 = this.provider.getInteger(0, total - 1);
 | |
|     let x2 = 0;
 | |
|     for (const kvp in weights) {
 | |
|       const [value, count] = [Number(kvp), weights[kvp]];
 | |
|       if (v2 < x2 + count) {
 | |
|         const index = v2 - x2;
 | |
|         return [value, index];
 | |
|       }
 | |
|       x2 += count;
 | |
|     }
 | |
|     throw "";
 | |
|   }
 | |
|   static calcTotalOfCount(weights) {
 | |
|     const total = getTypedObjectEntries(weights).map(([_2, count]) => count).reduce((a2, b2) => a2 + b2, 0) || 0;
 | |
|     return total;
 | |
|   }
 | |
| };
 | |
| var globalRandomNumberProvider = new RandomNumberProvider();
 | |
| var staticRandomNumberProvider = new StaticRandomNumberProvider();
 | |
| 
 | |
| // src/deck-tree-iterator.ts
 | |
| var CardOrder = /* @__PURE__ */ ((CardOrder2) => {
 | |
|   CardOrder2[CardOrder2["NewFirstSequential"] = 0] = "NewFirstSequential";
 | |
|   CardOrder2[CardOrder2["NewFirstRandom"] = 1] = "NewFirstRandom";
 | |
|   CardOrder2[CardOrder2["DueFirstSequential"] = 2] = "DueFirstSequential";
 | |
|   CardOrder2[CardOrder2["DueFirstRandom"] = 3] = "DueFirstRandom";
 | |
|   CardOrder2[CardOrder2["EveryCardRandomDeckAndCard"] = 4] = "EveryCardRandomDeckAndCard";
 | |
|   return CardOrder2;
 | |
| })(CardOrder || {});
 | |
| var DeckOrder = /* @__PURE__ */ ((DeckOrder2) => {
 | |
|   DeckOrder2[DeckOrder2["PrevDeckComplete_Sequential"] = 0] = "PrevDeckComplete_Sequential";
 | |
|   DeckOrder2[DeckOrder2["PrevDeckComplete_Random"] = 1] = "PrevDeckComplete_Random";
 | |
|   return DeckOrder2;
 | |
| })(DeckOrder || {});
 | |
| var SingleDeckIterator = class _SingleDeckIterator {
 | |
|   get hasCurrentCard() {
 | |
|     return this.cardIdx != null;
 | |
|   }
 | |
|   get currentCard() {
 | |
|     let result = null;
 | |
|     if (this.cardIdx != null) result = this.deck.getCard(this.cardIdx, this.cardListType);
 | |
|     return result;
 | |
|   }
 | |
|   constructor(iteratorOrder) {
 | |
|     this.iteratorOrder = iteratorOrder;
 | |
|     this.preferredCardListType = _SingleDeckIterator.getCardListTypeForIterator(
 | |
|       this.iteratorOrder
 | |
|     );
 | |
|     this.weightedRandomNumber = WeightedRandomNumber.create();
 | |
|   }
 | |
|   setDeck(deck) {
 | |
|     this.deck = deck;
 | |
|     this.setCardListType(null);
 | |
|   }
 | |
|   //
 | |
|   // 0 <= cardIndex < newFlashcards.length + dueFlashcards.length
 | |
|   //
 | |
|   setNewOrDueCardIdx(cardIndex) {
 | |
|     let cardListType = 0 /* NewCard */;
 | |
|     let index = cardIndex;
 | |
|     if (cardIndex >= this.deck.newFlashcards.length) {
 | |
|       cardListType = 1 /* DueCard */;
 | |
|       index = cardIndex - this.deck.newFlashcards.length;
 | |
|     }
 | |
|     this.setCardListType(cardListType, index);
 | |
|   }
 | |
|   setCardListType(cardListType, cardIdx = null) {
 | |
|     this.cardListType = cardListType;
 | |
|     this.cardIdx = cardIdx;
 | |
|   }
 | |
|   nextCard() {
 | |
|     if (this.iteratorOrder.cardOrder == 4 /* EveryCardRandomDeckAndCard */) {
 | |
|       this.nextRandomCard();
 | |
|     } else {
 | |
|       if (this.cardListType == null) {
 | |
|         this.setCardListType(this.preferredCardListType);
 | |
|       }
 | |
|       if (!this.nextCardWithinCurrentList()) {
 | |
|         if (this.cardListType == this.preferredCardListType) {
 | |
|           this.setCardListType(Deck2.otherListType(this.cardListType));
 | |
|           if (!this.nextCardWithinCurrentList()) {
 | |
|             this.setCardListType(null);
 | |
|           }
 | |
|         } else {
 | |
|           this.cardIdx = null;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return this.cardIdx != null;
 | |
|   }
 | |
|   nextRandomCard() {
 | |
|     const newCount = this.deck.newFlashcards.length;
 | |
|     const dueCount = this.deck.dueFlashcards.length;
 | |
|     if (newCount + dueCount > 0) {
 | |
|       const weights = {};
 | |
|       if (newCount > 0) weights[0 /* NewCard */] = newCount;
 | |
|       if (dueCount > 0) weights[1 /* DueCard */] = dueCount;
 | |
|       const [cardListType, index] = this.weightedRandomNumber.getRandomValues(weights);
 | |
|       this.setCardListType(cardListType, index);
 | |
|     } else {
 | |
|       this.setCardListType(null);
 | |
|     }
 | |
|   }
 | |
|   nextCardWithinCurrentList() {
 | |
|     const cardList = this.deck.getCardListForCardType(this.cardListType);
 | |
|     const result = cardList.length > 0;
 | |
|     if (result) {
 | |
|       switch (this.iteratorOrder.cardOrder) {
 | |
|         case 2 /* DueFirstSequential */:
 | |
|         case 0 /* NewFirstSequential */:
 | |
|           this.cardIdx = 0;
 | |
|           break;
 | |
|         case 3 /* DueFirstRandom */:
 | |
|         case 1 /* NewFirstRandom */:
 | |
|           this.cardIdx = globalRandomNumberProvider.getInteger(0, cardList.length - 1);
 | |
|           break;
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   moveCurrentCardToEndOfList() {
 | |
|     this.ensureCurrentCard();
 | |
|     const cardList = this.deck.getCardListForCardType(this.cardListType);
 | |
|     if (cardList.length <= 1) return;
 | |
|     const card = this.currentCard;
 | |
|     this.deck.deleteCardAtIndex(this.cardIdx, this.cardListType);
 | |
|     this.deck.appendCardToRootDeck(card);
 | |
|     this.setNoCurrentCard();
 | |
|   }
 | |
|   setNoCurrentCard() {
 | |
|     this.cardIdx = null;
 | |
|   }
 | |
|   ensureCurrentCard() {
 | |
|     if (this.cardIdx == null || this.cardListType == null) throw "no current card";
 | |
|   }
 | |
|   static getCardListTypeForIterator(iteratorOrder) {
 | |
|     let result = null;
 | |
|     switch (iteratorOrder.cardOrder) {
 | |
|       case 3 /* DueFirstRandom */:
 | |
|       case 2 /* DueFirstSequential */:
 | |
|         result = 1 /* DueCard */;
 | |
|         break;
 | |
|       case 1 /* NewFirstRandom */:
 | |
|       case 0 /* NewFirstSequential */:
 | |
|         result = 0 /* NewCard */;
 | |
|         break;
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var DeckTreeIterator = class _DeckTreeIterator {
 | |
|   get hasCurrentCard() {
 | |
|     return this.deckIdx != null && this.singleDeckIterator.hasCurrentCard;
 | |
|   }
 | |
|   get currentTopicPath() {
 | |
|     var _a;
 | |
|     return (_a = this.currentDeck) == null ? void 0 : _a.getTopicPath();
 | |
|   }
 | |
|   get currentDeck() {
 | |
|     if (this.deckIdx == null) return null;
 | |
|     return this.deckArray[this.deckIdx];
 | |
|   }
 | |
|   get currentCard() {
 | |
|     let result = null;
 | |
|     if (this.deckIdx != null && this.singleDeckIterator.hasCurrentCard)
 | |
|       result = this.singleDeckIterator.currentCard;
 | |
|     return result;
 | |
|   }
 | |
|   get currentQuestion() {
 | |
|     var _a;
 | |
|     return (_a = this.currentCard) == null ? void 0 : _a.question;
 | |
|   }
 | |
|   constructor(iteratorOrder, baseDeckTree) {
 | |
|     this.singleDeckIterator = new SingleDeckIterator(iteratorOrder);
 | |
|     this.iteratorOrder = iteratorOrder;
 | |
|     this.weightedRandomNumber = WeightedRandomNumber.create();
 | |
|     this.setBaseDeck(baseDeckTree);
 | |
|   }
 | |
|   setBaseDeck(baseDeck) {
 | |
|     this.baseDeckTree = baseDeck;
 | |
|     this.singleDeckIterator.setNoCurrentCard();
 | |
|   }
 | |
|   setIteratorTopicPath(topicPath) {
 | |
|     const iteratorDeck = this.baseDeckTree.getDeck(topicPath);
 | |
|     this.deckArray = _DeckTreeIterator.filterForDecksWithCards(iteratorDeck.toDeckArray());
 | |
|     this.setDeckIdx(null);
 | |
|   }
 | |
|   static filterForDecksWithCards(sourceArray) {
 | |
|     const result = [];
 | |
|     for (let idx = 0; idx < sourceArray.length; idx++) {
 | |
|       const deck = sourceArray[idx];
 | |
|       const hasAnyCards = deck.getCardCount(2 /* All */, false) > 0;
 | |
|       if (hasAnyCards) {
 | |
|         result.push(deck);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   setDeckIdx(deckIdx) {
 | |
|     this.deckIdx = deckIdx;
 | |
|     if (deckIdx != null) this.singleDeckIterator.setDeck(this.deckArray[deckIdx]);
 | |
|   }
 | |
|   nextCard() {
 | |
|     let result = false;
 | |
|     if (this.hasCurrentCard) {
 | |
|       this.baseDeckTree.deleteCardFromAllDecks(this.currentCard, true);
 | |
|     }
 | |
|     if (this.iteratorOrder.cardOrder == 4 /* EveryCardRandomDeckAndCard */) {
 | |
|       result = this.nextCardEveryCardRandomDeck();
 | |
|     } else {
 | |
|       if (this.deckIdx == null) {
 | |
|         this.chooseNextDeck(true);
 | |
|       }
 | |
|       while (this.deckIdx < this.deckArray.length) {
 | |
|         if (this.singleDeckIterator.nextCard()) {
 | |
|           result = true;
 | |
|           break;
 | |
|         }
 | |
|         this.chooseNextDeck(false);
 | |
|       }
 | |
|     }
 | |
|     if (!result) this.deckIdx = null;
 | |
|     return result;
 | |
|   }
 | |
|   chooseNextDeck(firstTime) {
 | |
|     switch (this.iteratorOrder.deckOrder) {
 | |
|       case 0 /* PrevDeckComplete_Sequential */:
 | |
|         this.deckIdx = firstTime ? 0 : this.deckIdx + 1;
 | |
|         break;
 | |
|       case 1 /* PrevDeckComplete_Random */: {
 | |
|         const weights = {};
 | |
|         let hasDeck = false;
 | |
|         for (let i2 = 0; i2 < this.deckArray.length; i2++) {
 | |
|           if (this.deckArray[i2].getCardCount(2 /* All */, false)) {
 | |
|             weights[i2] = 1;
 | |
|             hasDeck = true;
 | |
|           }
 | |
|         }
 | |
|         if (hasDeck) {
 | |
|           const [deckIdx, _2] = this.weightedRandomNumber.getRandomValues(weights);
 | |
|           this.deckIdx = deckIdx;
 | |
|         } else {
 | |
|           this.deckIdx = this.deckArray.length;
 | |
|         }
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (this.deckIdx < this.deckArray.length) {
 | |
|       this.singleDeckIterator.setDeck(this.deckArray[this.deckIdx]);
 | |
|     }
 | |
|   }
 | |
|   nextCardEveryCardRandomDeck() {
 | |
|     const weights = {};
 | |
|     for (let i2 = 0; i2 < this.deckArray.length; i2++) {
 | |
|       const cardCount = this.deckArray[i2].getCardCount(2 /* All */, false);
 | |
|       if (cardCount) {
 | |
|         weights[i2] = cardCount;
 | |
|       }
 | |
|     }
 | |
|     if (Object.keys(weights).length == 0) return false;
 | |
|     const [deckIdx, cardIdx] = this.weightedRandomNumber.getRandomValues(weights);
 | |
|     this.setDeckIdx(deckIdx);
 | |
|     this.singleDeckIterator.setNewOrDueCardIdx(cardIdx);
 | |
|     return true;
 | |
|   }
 | |
|   deleteCurrentQuestionFromAllDecks() {
 | |
|     this.singleDeckIterator.ensureCurrentCard();
 | |
|     this.baseDeckTree.deleteQuestionFromAllDecks(this.currentQuestion, false);
 | |
|     this.singleDeckIterator.setNoCurrentCard();
 | |
|     return this.nextCard();
 | |
|   }
 | |
|   deleteCurrentCardFromAllDecks() {
 | |
|     this.singleDeckIterator.ensureCurrentCard();
 | |
|     this.baseDeckTree.deleteCardFromAllDecks(this.currentCard, true);
 | |
|     this.singleDeckIterator.setNoCurrentCard();
 | |
|     return this.nextCard();
 | |
|   }
 | |
|   moveCurrentCardToEndOfList() {
 | |
|     this.singleDeckIterator.moveCurrentCardToEndOfList();
 | |
|   }
 | |
|   removeCurrentDeckIfEmpty() {
 | |
|     if (this.currentDeck.getCardCount(2 /* All */, false) == 0) {
 | |
|       this.deckArray.splice(this.deckIdx, 1);
 | |
|       if (this.deckIdx < this.deckArray.length) this.setDeckIdx(this.deckIdx);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/stats.ts
 | |
| var Stats = class {
 | |
|   constructor() {
 | |
|     this.eases = new ValueCountDict();
 | |
|     this.intervals = new ValueCountDict();
 | |
|     this.delayedDays = new ValueCountDict();
 | |
|     this.newCount = 0;
 | |
|     this.youngCount = 0;
 | |
|     this.matureCount = 0;
 | |
|   }
 | |
|   get totalCount() {
 | |
|     return this.youngCount + this.matureCount;
 | |
|   }
 | |
|   incrementNew() {
 | |
|     this.newCount++;
 | |
|   }
 | |
|   update(delayedDays, interval, ease) {
 | |
|     this.intervals.incrementCount(interval);
 | |
|     this.eases.incrementCount(ease);
 | |
|     this.delayedDays.incrementCount(delayedDays);
 | |
|     if (interval >= 32) {
 | |
|       this.matureCount++;
 | |
|     } else {
 | |
|       this.youngCount++;
 | |
|     }
 | |
|   }
 | |
|   getMaxInterval() {
 | |
|     return this.intervals.getMaxValue();
 | |
|   }
 | |
|   getAverageInterval() {
 | |
|     return this.intervals.getTotalOfValueMultiplyCount() / this.totalCount;
 | |
|   }
 | |
|   getAverageEases() {
 | |
|     return this.eases.getTotalOfValueMultiplyCount() / this.totalCount;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/deck-tree-stats-calculator.ts
 | |
| var DeckTreeStatsCalculator = class {
 | |
|   calculate(deckTree) {
 | |
|     const iteratorOrder = {
 | |
|       deckOrder: 0 /* PrevDeckComplete_Sequential */,
 | |
|       cardOrder: 2 /* DueFirstSequential */
 | |
|     };
 | |
|     const iterator = new DeckTreeIterator(iteratorOrder, deckTree.clone());
 | |
|     const result = new Stats();
 | |
|     iterator.setIteratorTopicPath(TopicPath.emptyPath);
 | |
|     while (iterator.nextCard()) {
 | |
|       const card = iterator.currentCard;
 | |
|       if (card.hasSchedule) {
 | |
|         const schedule = card.scheduleInfo;
 | |
|         result.update(
 | |
|           schedule.delayedBeforeReviewDaysInt(),
 | |
|           schedule.interval,
 | |
|           schedule.latestEase
 | |
|         );
 | |
|       } else {
 | |
|         result.incrementNew();
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/due-date-histogram.ts
 | |
| var _DueDateHistogram = class _DueDateHistogram {
 | |
|   constructor(rec = null) {
 | |
|     // Key - # of days in future
 | |
|     // Value - Count of notes due
 | |
|     this.dueDatesMap = /* @__PURE__ */ new Map();
 | |
|     this.dueDatesMap = /* @__PURE__ */ new Map();
 | |
|     if (rec != null) {
 | |
|       Object.entries(rec).forEach(([key, value]) => {
 | |
|         this.dueDatesMap.set(Number(key), value);
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   get dueNotesCount() {
 | |
|     let result = 0;
 | |
|     if (this.dueDatesMap.has(_DueDateHistogram.dueNowNDays))
 | |
|       result = this.dueDatesMap.get(_DueDateHistogram.dueNowNDays);
 | |
|     return result;
 | |
|   }
 | |
|   hasEntryForDays(days) {
 | |
|     return this.dueDatesMap.has(days);
 | |
|   }
 | |
|   set(days, value) {
 | |
|     this.dueDatesMap.set(days, value);
 | |
|   }
 | |
|   get(days) {
 | |
|     return this.dueDatesMap.get(days);
 | |
|   }
 | |
|   increment(days) {
 | |
|     let value = 0;
 | |
|     if (this.dueDatesMap.has(days)) {
 | |
|       value = this.dueDatesMap.get(days);
 | |
|     }
 | |
|     this.dueDatesMap.set(days, value + 1);
 | |
|   }
 | |
|   decrement(days) {
 | |
|     let value = 0;
 | |
|     if (this.dueDatesMap.has(days)) value = this.dueDatesMap.get(days);
 | |
|     if (value > 0) {
 | |
|       this.dueDatesMap.set(days, value - 1);
 | |
|     }
 | |
|   }
 | |
|   findLeastUsedIntervalOverRange(originalInterval, fuzz) {
 | |
|     if (!this.hasEntryForDays(originalInterval)) {
 | |
|       return originalInterval;
 | |
|     }
 | |
|     let interval = originalInterval;
 | |
|     outer: for (let i2 = 1; i2 <= fuzz; i2++) {
 | |
|       for (const ivl of [originalInterval - i2, originalInterval + i2]) {
 | |
|         if (!this.hasEntryForDays(ivl)) {
 | |
|           interval = ivl;
 | |
|           break outer;
 | |
|         }
 | |
|         if (this.dueDatesMap.get(ivl) < this.dueDatesMap.get(interval)) interval = ivl;
 | |
|       }
 | |
|     }
 | |
|     return interval;
 | |
|   }
 | |
| };
 | |
| // The key for dueDatesNotes is the number of days after today
 | |
| // therefore the key to lookup how many cards are due today is 0
 | |
| _DueDateHistogram.dueNowNDays = 0;
 | |
| var DueDateHistogram = _DueDateHistogram;
 | |
| var NoteDueDateHistogram = class extends DueDateHistogram {
 | |
|   calculateFromReviewDecksAndSort(reviewDecks, osrNoteGraph) {
 | |
|     this.dueDatesMap = /* @__PURE__ */ new Map();
 | |
|     const today = globalDateProvider.today.valueOf();
 | |
|     reviewDecks.forEach((reviewDeck) => {
 | |
|       reviewDeck.scheduledNotes.forEach((scheduledNote) => {
 | |
|         const nDays = Math.ceil((scheduledNote.dueUnix - today) / TICKS_PER_DAY);
 | |
|         this.increment(nDays);
 | |
|       });
 | |
|       reviewDeck.sortNotesByDateAndImportance(osrNoteGraph.pageranks);
 | |
|     });
 | |
|   }
 | |
| };
 | |
| var CardDueDateHistogram = class extends DueDateHistogram {
 | |
|   calculateFromDeckTree(deckTree) {
 | |
|     this.dueDatesMap = /* @__PURE__ */ new Map();
 | |
|     const iteratorOrder = {
 | |
|       deckOrder: 0 /* PrevDeckComplete_Sequential */,
 | |
|       cardOrder: 2 /* DueFirstSequential */
 | |
|     };
 | |
|     const today = globalDateProvider.today.valueOf();
 | |
|     const iterator = new DeckTreeIterator(iteratorOrder, deckTree.clone());
 | |
|     iterator.setIteratorTopicPath(TopicPath.emptyPath);
 | |
|     while (iterator.nextCard()) {
 | |
|       const card = iterator.currentCard;
 | |
|       if (card.hasSchedule) {
 | |
|         const scheduledCard = card.scheduleInfo;
 | |
|         const nDays = Math.ceil(
 | |
|           (scheduledCard.dueDateAsUnix - today) / TICKS_PER_DAY
 | |
|         );
 | |
|         this.increment(nDays);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/file.ts
 | |
| var import_obsidian2 = require("obsidian");
 | |
| 
 | |
| // src/utils/strings.ts
 | |
| function literalStringReplace(text, searchStr, replacementStr) {
 | |
|   let result = text;
 | |
|   const startIdx = text.indexOf(searchStr);
 | |
|   if (startIdx >= 0) {
 | |
|     const startStr = text.substring(0, startIdx);
 | |
|     const endIdx = startIdx + searchStr.length;
 | |
|     const endStr = text.substring(endIdx);
 | |
|     result = startStr + replacementStr + endStr;
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function cyrb53(str, seed = 0) {
 | |
|   let h12 = 3735928559 ^ seed, h22 = 1103547991 ^ seed;
 | |
|   for (let i2 = 0, ch; i2 < str.length; i2++) {
 | |
|     ch = str.charCodeAt(i2);
 | |
|     h12 = Math.imul(h12 ^ ch, 2654435761);
 | |
|     h22 = Math.imul(h22 ^ ch, 1597334677);
 | |
|   }
 | |
|   h12 = Math.imul(h12 ^ h12 >>> 16, 2246822507) ^ Math.imul(h22 ^ h22 >>> 13, 3266489909);
 | |
|   h22 = Math.imul(h22 ^ h22 >>> 16, 2246822507) ^ Math.imul(h12 ^ h12 >>> 13, 3266489909);
 | |
|   return (4294967296 * (2097151 & h22) + (h12 >>> 0)).toString(16);
 | |
| }
 | |
| function convertToStringOrEmpty(v2) {
 | |
|   let result = "";
 | |
|   if (v2 != null && v2 != void 0) {
 | |
|     result = v2 + "";
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function splitTextIntoLineArray(text) {
 | |
|   return text.replaceAll(/\r\n|\r/g, "\n").split("\n");
 | |
| }
 | |
| function stringTrimStart(str) {
 | |
|   if (!str) {
 | |
|     return ["", ""];
 | |
|   }
 | |
|   const trimmed = str.trimStart();
 | |
|   const wsCount = str.length - trimmed.length;
 | |
|   const ws = str.substring(0, wsCount);
 | |
|   return [ws, trimmed];
 | |
| }
 | |
| function splitNoteIntoFrontmatterAndContent(str) {
 | |
|   const lines = splitTextIntoLineArray(str);
 | |
|   let lineIndex = 0;
 | |
|   let hasFrontmatter = false;
 | |
|   do {
 | |
|     if (lineIndex === 0 && lines[lineIndex] === "---") {
 | |
|       hasFrontmatter = true;
 | |
|     } else if (hasFrontmatter && lines[lineIndex] === "---") {
 | |
|       hasFrontmatter = false;
 | |
|       lineIndex++;
 | |
|     }
 | |
|     if (hasFrontmatter) {
 | |
|       lineIndex++;
 | |
|     }
 | |
|   } while (hasFrontmatter && lineIndex < lines.length);
 | |
|   if (hasFrontmatter) {
 | |
|     lineIndex = 0;
 | |
|   }
 | |
|   const frontmatter = lines.slice(0, lineIndex).join("\n");
 | |
|   const emptyLines = lineIndex > 0 ? Array(lineIndex).join(".").split(".") : [];
 | |
|   const content = emptyLines.concat(lines.slice(lineIndex)).join("\n");
 | |
|   return [frontmatter, content];
 | |
| }
 | |
| function findLineIndexOfSearchStringIgnoringWs(lines, searchString) {
 | |
|   let result = -1;
 | |
|   for (let i2 = 0; i2 < lines.length; i2++) {
 | |
|     if (lines[i2].trim() == searchString) {
 | |
|       result = i2;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function parseObsidianFrontmatterTag(tagStr) {
 | |
|   const result = [];
 | |
|   if (tagStr) {
 | |
|     const tagStrList = tagStr.split(",");
 | |
|     for (const tag of tagStrList) {
 | |
|       if (tag !== "") {
 | |
|         result.push(tag.startsWith("#") ? tag : "#" + tag);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| var MultiLineTextFinder = class _MultiLineTextFinder {
 | |
|   static findAndReplace(sourceText, searchText, replacementText) {
 | |
|     let result = null;
 | |
|     if (sourceText.includes(searchText)) {
 | |
|       result = literalStringReplace(sourceText, searchText, replacementText);
 | |
|     } else {
 | |
|       const sourceTextArray = splitTextIntoLineArray(sourceText);
 | |
|       const searchTextArray = splitTextIntoLineArray(searchText);
 | |
|       const lineNo = _MultiLineTextFinder.find(
 | |
|         sourceTextArray,
 | |
|         searchTextArray
 | |
|       );
 | |
|       if (lineNo !== null) {
 | |
|         const replacementTextArray = splitTextIntoLineArray(replacementText);
 | |
|         const linesToRemove = searchTextArray.length;
 | |
|         sourceTextArray.splice(lineNo, linesToRemove, ...replacementTextArray);
 | |
|         result = sourceTextArray.join("\n");
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   static find(sourceText, searchText) {
 | |
|     let result = null;
 | |
|     let searchIdx = 0;
 | |
|     const maxSearchIdx = searchText.length - 1;
 | |
|     for (let sourceIdx = 0; sourceIdx < sourceText.length; sourceIdx++) {
 | |
|       const sourceLine = sourceText[sourceIdx].trim();
 | |
|       const searchLine = searchText[searchIdx].trim();
 | |
|       if (searchLine == sourceLine) {
 | |
|         if (searchIdx == maxSearchIdx) {
 | |
|           result = sourceIdx - searchIdx;
 | |
|           break;
 | |
|         }
 | |
|         searchIdx++;
 | |
|       } else {
 | |
|         searchIdx = 0;
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/file.ts
 | |
| var frontmatterTagPseudoLineNum = -1;
 | |
| var SrTFile = class {
 | |
|   constructor(vault, metadataCache, file) {
 | |
|     this.vault = vault;
 | |
|     this.metadataCache = metadataCache;
 | |
|     this.file = file;
 | |
|   }
 | |
|   get path() {
 | |
|     return this.file.path;
 | |
|   }
 | |
|   get basename() {
 | |
|     return this.file.basename;
 | |
|   }
 | |
|   get tfile() {
 | |
|     return this.file;
 | |
|   }
 | |
|   async getFrontmatter() {
 | |
|     const fileCachedData = this.metadataCache.getFileCache(this.file) || {};
 | |
|     const frontmatter = fileCachedData.frontmatter || {};
 | |
|     const result = /* @__PURE__ */ new Map();
 | |
|     for (const [key, value] of Object.entries(frontmatter)) {
 | |
|       const v2 = Array.isArray(value) && value.length > 0 ? value[0] : value;
 | |
|       const vStr = v2 + "";
 | |
|       result.set(key, vStr);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   getAllTagsFromCache() {
 | |
|     const fileCachedData = this.metadataCache.getFileCache(this.file) || {};
 | |
|     const result = (0, import_obsidian2.getAllTags)(fileCachedData) || [];
 | |
|     return result;
 | |
|   }
 | |
|   getAllTagsFromText() {
 | |
|     var _a;
 | |
|     const result = [];
 | |
|     const fileCachedData = this.metadataCache.getFileCache(this.file) || {};
 | |
|     if (((_a = fileCachedData.tags) == null ? void 0 : _a.length) > 0) {
 | |
|       result.push(...fileCachedData.tags);
 | |
|     }
 | |
|     result.push(...this.getFrontmatterTags(fileCachedData.frontmatter));
 | |
|     return result;
 | |
|   }
 | |
|   getFrontmatterTags(frontmatter) {
 | |
|     const result = [];
 | |
|     const frontmatterTags = frontmatter != null ? frontmatter["tags"] + "" : null;
 | |
|     if (frontmatterTags) {
 | |
|       const tagStrList = parseObsidianFrontmatterTag(frontmatterTags);
 | |
|       for (const str of tagStrList) {
 | |
|         const tag = {
 | |
|           tag: str,
 | |
|           position: {
 | |
|             start: {
 | |
|               line: frontmatterTagPseudoLineNum,
 | |
|               col: null,
 | |
|               offset: null
 | |
|             },
 | |
|             end: {
 | |
|               line: frontmatterTagPseudoLineNum,
 | |
|               col: null,
 | |
|               offset: null
 | |
|             }
 | |
|           }
 | |
|         };
 | |
|         result.push(tag);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   getQuestionContext(cardLine) {
 | |
|     const fileCachedData = this.metadataCache.getFileCache(this.file) || {};
 | |
|     const headings = fileCachedData.headings || [];
 | |
|     const stack = [];
 | |
|     for (const heading of headings) {
 | |
|       if (heading.position.start.line > cardLine) {
 | |
|         break;
 | |
|       }
 | |
|       while (stack.length > 0 && stack[stack.length - 1].level >= heading.level) {
 | |
|         stack.pop();
 | |
|       }
 | |
|       stack.push(heading);
 | |
|     }
 | |
|     const result = [];
 | |
|     for (const headingObj of stack) {
 | |
|       headingObj.heading = headingObj.heading.replace(/\[\^\d+\]/gm, "").trim();
 | |
|       result.push(headingObj.heading);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   getTextDirection() {
 | |
|     let result = 0 /* Unspecified */;
 | |
|     const fileCache = this.metadataCache.getFileCache(this.file);
 | |
|     const frontMatter = fileCache == null ? void 0 : fileCache.frontmatter;
 | |
|     if (frontMatter && (frontMatter == null ? void 0 : frontMatter.direction)) {
 | |
|       const str = (frontMatter.direction + "").toLowerCase();
 | |
|       result = str == "rtl" ? 2 /* Rtl */ : 1 /* Ltr */;
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   async read() {
 | |
|     return await this.vault.read(this.file);
 | |
|   }
 | |
|   async write(content) {
 | |
|     await this.vault.modify(this.file, content);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/note.ts
 | |
| var Note = class {
 | |
|   get hasChanged() {
 | |
|     return this.questionList.some((question) => question.hasChanged);
 | |
|   }
 | |
|   get filePath() {
 | |
|     return this.file.path;
 | |
|   }
 | |
|   constructor(file, questionList) {
 | |
|     this.file = file;
 | |
|     this.questionList = questionList;
 | |
|     questionList.forEach((question) => question.note = this);
 | |
|   }
 | |
|   appendCardsToDeck(deck) {
 | |
|     for (const question of this.questionList) {
 | |
|       for (const card of question.cards) {
 | |
|         deck.appendCard(question.topicPathList, card);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   debugLogToConsole(desc = "") {
 | |
|     var _a;
 | |
|     let str = `Note: ${desc}: ${this.questionList.length} questions\r
 | |
| `;
 | |
|     for (let i2 = 0; i2 < this.questionList.length; i2++) {
 | |
|       const q2 = this.questionList[i2];
 | |
|       str += `[${i2}]: ${q2.questionType}: ${q2.lineNo}: ${(_a = q2.topicPathList) == null ? void 0 : _a.format("|")}: ${q2.questionText.original}\r
 | |
| `;
 | |
|     }
 | |
|     console.debug(str);
 | |
|   }
 | |
|   async writeNoteFile(settings) {
 | |
|     let fileText = await this.file.read();
 | |
|     for (const question of this.questionList) {
 | |
|       if (question.hasChanged) {
 | |
|         fileText = question.updateQuestionWithinNoteText(fileText, settings);
 | |
|       }
 | |
|     }
 | |
|     await this.file.write(fileText);
 | |
|     this.questionList.forEach((question) => question.hasChanged = false);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/card.ts
 | |
| var Card = class extends RepetitionItem {
 | |
|   constructor(init) {
 | |
|     super();
 | |
|     Object.assign(this, init);
 | |
|   }
 | |
|   get cardListType() {
 | |
|     return this.isNew ? 0 /* NewCard */ : 1 /* DueCard */;
 | |
|   }
 | |
|   formatSchedule() {
 | |
|     let result = "";
 | |
|     if (this.hasSchedule) result = this.scheduleInfo.formatCardScheduleForHtmlComment();
 | |
|     else result = "New";
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/parser.ts
 | |
| var import_clozecraft = __toESM(require_dist());
 | |
| 
 | |
| // src/question.ts
 | |
| var QuestionText = class _QuestionText {
 | |
|   constructor(original, topicPathWithWs, actualQuestion, textDirection, blockId) {
 | |
|     this.original = original;
 | |
|     this.topicPathWithWs = topicPathWithWs;
 | |
|     this.actualQuestion = actualQuestion;
 | |
|     this.textDirection = textDirection;
 | |
|     this.obsidianBlockId = blockId;
 | |
|     this.textHash = cyrb53(this.formatTopicAndQuestion());
 | |
|   }
 | |
|   endsWithCodeBlock() {
 | |
|     return this.actualQuestion.endsWith("```");
 | |
|   }
 | |
|   static create(original, textDirection, settings) {
 | |
|     const [topicPathWithWs, actualQuestion, blockId] = this.splitText(original, settings);
 | |
|     return new _QuestionText(original, topicPathWithWs, actualQuestion, textDirection, blockId);
 | |
|   }
 | |
|   static splitText(original, settings) {
 | |
|     const originalWithoutSR = DataStore.getInstance().questionRemoveScheduleInfo(original);
 | |
|     let actualQuestion = originalWithoutSR.trimEnd();
 | |
|     let topicPathWithWs = null;
 | |
|     let blockId = null;
 | |
|     const topicPath = TopicPath.getTopicPathFromCardText(originalWithoutSR);
 | |
|     if (topicPath == null ? void 0 : topicPath.hasPath) {
 | |
|       const [preTopicPathWs, cardText2] = stringTrimStart(originalWithoutSR);
 | |
|       const cardText3 = cardText2.replaceAll(OBSIDIAN_TAG_AT_STARTOFLINE_REGEX, "");
 | |
|       let postTopicPathWs = null;
 | |
|       [postTopicPathWs, actualQuestion] = stringTrimStart(cardText3);
 | |
|       if (!settings.convertFoldersToDecks) {
 | |
|         topicPathWithWs = new TopicPathWithWs(topicPath, preTopicPathWs, postTopicPathWs);
 | |
|       }
 | |
|     }
 | |
|     [actualQuestion, blockId] = this.extractObsidianBlockId(actualQuestion);
 | |
|     return [topicPathWithWs, actualQuestion, blockId];
 | |
|   }
 | |
|   static extractObsidianBlockId(text) {
 | |
|     let question = text;
 | |
|     let blockId = null;
 | |
|     const match2 = text.match(OBSIDIAN_BLOCK_ID_ENDOFLINE_REGEX);
 | |
|     if (match2) {
 | |
|       blockId = match2[0].trim();
 | |
|       const newLength = question.length - blockId.length;
 | |
|       question = question.substring(0, newLength).trimEnd();
 | |
|     }
 | |
|     return [question, blockId];
 | |
|   }
 | |
|   formatTopicAndQuestion() {
 | |
|     let result = "";
 | |
|     if (this.topicPathWithWs) {
 | |
|       result += this.topicPathWithWs.formatWithWs();
 | |
|     }
 | |
|     result += this.actualQuestion;
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var Question = class _Question {
 | |
|   get questionType() {
 | |
|     return this.parsedQuestionInfo.cardType;
 | |
|   }
 | |
|   get lineNo() {
 | |
|     return this.parsedQuestionInfo.firstLineNum;
 | |
|   }
 | |
|   constructor(init) {
 | |
|     Object.assign(this, init);
 | |
|   }
 | |
|   getHtmlCommentSeparator(settings) {
 | |
|     const sep2 = this.isCardCommentsOnSameLine(settings) ? " " : "\n";
 | |
|     return sep2;
 | |
|   }
 | |
|   isCardCommentsOnSameLine(settings) {
 | |
|     let result = settings.cardCommentOnSameLine;
 | |
|     if (this.questionText.endsWithCodeBlock()) {
 | |
|       result = false;
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   setCardList(cards) {
 | |
|     this.cards = cards;
 | |
|     this.cards.forEach((card) => card.question = this);
 | |
|   }
 | |
|   formatForNote(settings) {
 | |
|     let result = this.questionText.formatTopicAndQuestion();
 | |
|     const blockId = this.questionText.obsidianBlockId;
 | |
|     const hasSchedule = this.cards.some((card) => card.hasSchedule);
 | |
|     if (hasSchedule) {
 | |
|       result = result.trimEnd();
 | |
|       const scheduleHtml = DataStoreAlgorithm.getInstance().questionFormatScheduleAsHtmlComment(this);
 | |
|       if (blockId) {
 | |
|         if (this.isCardCommentsOnSameLine(settings))
 | |
|           result += ` ${scheduleHtml} ${blockId}`;
 | |
|         else result += ` ${blockId}
 | |
| ${scheduleHtml}`;
 | |
|       } else {
 | |
|         result += this.getHtmlCommentSeparator(settings) + scheduleHtml;
 | |
|       }
 | |
|     } else {
 | |
|       if (blockId) result += ` ${blockId}`;
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   updateQuestionWithinNoteText(noteText, settings) {
 | |
|     const originalText = this.questionText.original;
 | |
|     const replacementText = this.formatForNote(settings);
 | |
|     let newText = MultiLineTextFinder.findAndReplace(noteText, originalText, replacementText);
 | |
|     if (newText) {
 | |
|       this.questionText = QuestionText.create(
 | |
|         replacementText,
 | |
|         this.questionText.textDirection,
 | |
|         settings
 | |
|       );
 | |
|     } else {
 | |
|       console.error(
 | |
|         `updateQuestionText: Text not found: ${originalText.substring(
 | |
|           0,
 | |
|           100
 | |
|         )} in note: ${noteText.substring(0, 100)}`
 | |
|       );
 | |
|       newText = noteText;
 | |
|     }
 | |
|     return newText;
 | |
|   }
 | |
|   async writeQuestion(settings) {
 | |
|     const fileText = await this.note.file.read();
 | |
|     const newText = this.updateQuestionWithinNoteText(fileText, settings);
 | |
|     await this.note.file.write(newText);
 | |
|     this.hasChanged = false;
 | |
|   }
 | |
|   formatTopicPathList() {
 | |
|     return this.topicPathList.format("|");
 | |
|   }
 | |
|   static Create(settings, parsedQuestionInfo, noteTopicPathList, textDirection, context) {
 | |
|     const hasEditLaterTag = parsedQuestionInfo.text.includes(settings.editLaterTag);
 | |
|     const questionText = QuestionText.create(
 | |
|       parsedQuestionInfo.text,
 | |
|       textDirection,
 | |
|       settings
 | |
|     );
 | |
|     let topicPathList = noteTopicPathList;
 | |
|     if (questionText.topicPathWithWs) {
 | |
|       topicPathList = new TopicPathList([questionText.topicPathWithWs.topicPath]);
 | |
|     }
 | |
|     const result = new _Question({
 | |
|       parsedQuestionInfo,
 | |
|       topicPathList,
 | |
|       questionText,
 | |
|       hasEditLaterTag,
 | |
|       questionContext: context,
 | |
|       cards: null,
 | |
|       hasChanged: false
 | |
|     });
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/parser.ts
 | |
| var debugParser = false;
 | |
| function setDebugParser(value) {
 | |
|   debugParser = value;
 | |
| }
 | |
| var ParsedQuestionInfo = class {
 | |
|   constructor(cardType, text, firstLineNum, lastLineNum) {
 | |
|     this.cardType = cardType;
 | |
|     this.text = text;
 | |
|     this.firstLineNum = firstLineNum;
 | |
|     this.lastLineNum = lastLineNum;
 | |
|   }
 | |
|   isQuestionLineNum(lineNum) {
 | |
|     return lineNum >= this.firstLineNum && lineNum <= this.lastLineNum;
 | |
|   }
 | |
| };
 | |
| function markerInsideCodeBlock(text, marker, markerIndex) {
 | |
|   let goingBack = markerIndex - 1, goingForward = markerIndex + marker.length;
 | |
|   let backTicksBefore = 0, backTicksAfter = 0;
 | |
|   while (goingBack >= 0) {
 | |
|     if (text[goingBack] === "`") backTicksBefore++;
 | |
|     goingBack--;
 | |
|   }
 | |
|   while (goingForward < text.length) {
 | |
|     if (text[goingForward] === "`") backTicksAfter++;
 | |
|     goingForward++;
 | |
|   }
 | |
|   return backTicksBefore % 2 === 1 && backTicksAfter % 2 === 1;
 | |
| }
 | |
| function hasInlineMarker(text, marker) {
 | |
|   if (marker.length == 0) return false;
 | |
|   const markerIdx = text.indexOf(marker);
 | |
|   if (markerIdx === -1) return false;
 | |
|   return !markerInsideCodeBlock(text, marker, markerIdx);
 | |
| }
 | |
| function parse(text, options) {
 | |
|   if (debugParser) {
 | |
|     console.log("Text to parse:\n<<<" + text + ">>>");
 | |
|   }
 | |
|   const inlineSeparators = [
 | |
|     { separator: options.singleLineCardSeparator, type: 0 /* SingleLineBasic */ },
 | |
|     { separator: options.singleLineReversedCardSeparator, type: 1 /* SingleLineReversed */ }
 | |
|   ];
 | |
|   inlineSeparators.sort((a2, b2) => b2.separator.length - a2.separator.length);
 | |
|   const cards = [];
 | |
|   let cardText = "";
 | |
|   let cardType = null;
 | |
|   let firstLineNo = 0, lastLineNo = 0;
 | |
|   const clozecrafter = new import_clozecraft.ClozeCrafter(options.clozePatterns);
 | |
|   const lines = text.replaceAll("\r\n", "\n").split("\n");
 | |
|   for (let i2 = 0; i2 < lines.length; i2++) {
 | |
|     const currentLine = lines[i2], currentTrimmed = lines[i2].trim();
 | |
|     if (currentLine.startsWith("<!--") && !currentLine.startsWith("<!--SR:")) {
 | |
|       while (i2 + 1 < lines.length && !currentLine.includes("-->")) i2++;
 | |
|       i2++;
 | |
|       continue;
 | |
|     }
 | |
|     const isEmptyLine = currentTrimmed.length == 0;
 | |
|     const hasMultilineCardEndMarker = options.multilineCardEndMarker && currentTrimmed == options.multilineCardEndMarker;
 | |
|     if (
 | |
|       // We've probably reached the end of a card
 | |
|       isEmptyLine && !options.multilineCardEndMarker || // Empty line & we're not picking up any card
 | |
|       isEmptyLine && cardType == null || // We've reached the end of a multi line card &
 | |
|       //  we're using custom end markers
 | |
|       hasMultilineCardEndMarker
 | |
|     ) {
 | |
|       if (cardType) {
 | |
|         lastLineNo = i2 - 1;
 | |
|         cards.push(
 | |
|           new ParsedQuestionInfo(cardType, cardText.trimEnd(), firstLineNo, lastLineNo)
 | |
|         );
 | |
|         cardType = null;
 | |
|       }
 | |
|       cardText = "";
 | |
|       firstLineNo = i2 + 1;
 | |
|       continue;
 | |
|     }
 | |
|     if (cardText.length > 0) {
 | |
|       cardText += "\n";
 | |
|     }
 | |
|     cardText += currentLine.trimEnd();
 | |
|     for (const { separator, type } of inlineSeparators) {
 | |
|       if (hasInlineMarker(currentLine, separator)) {
 | |
|         cardType = type;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (cardType == 0 /* SingleLineBasic */ || cardType == 1 /* SingleLineReversed */) {
 | |
|       cardText = currentLine;
 | |
|       firstLineNo = i2;
 | |
|       if (i2 + 1 < lines.length && lines[i2 + 1].startsWith("<!--SR:")) {
 | |
|         cardText += "\n" + lines[i2 + 1];
 | |
|         i2++;
 | |
|       }
 | |
|       lastLineNo = i2;
 | |
|       cards.push(new ParsedQuestionInfo(cardType, cardText, firstLineNo, lastLineNo));
 | |
|       cardType = null;
 | |
|       cardText = "";
 | |
|     } else if (currentTrimmed === options.multilineCardSeparator) {
 | |
|       if (cardText.length > 1) {
 | |
|         cardType = 2 /* MultiLineBasic */;
 | |
|       }
 | |
|     } else if (currentTrimmed === options.multilineReversedCardSeparator) {
 | |
|       if (cardText.length > 1) {
 | |
|         cardType = 3 /* MultiLineReversed */;
 | |
|       }
 | |
|     } else if (currentLine.startsWith("```") || currentLine.startsWith("~~~")) {
 | |
|       const codeBlockClose = currentLine.match(/`+|~+/)[0];
 | |
|       while (i2 + 1 < lines.length && !lines[i2 + 1].startsWith(codeBlockClose)) {
 | |
|         i2++;
 | |
|         cardText += "\n" + lines[i2];
 | |
|       }
 | |
|       cardText += "\n" + codeBlockClose;
 | |
|       i2++;
 | |
|     } else if (cardType === null && clozecrafter.isClozeNote(currentLine)) {
 | |
|       cardType = 4 /* Cloze */;
 | |
|     }
 | |
|   }
 | |
|   if (cardType && cardText) {
 | |
|     lastLineNo = lines.length - 1;
 | |
|     cards.push(new ParsedQuestionInfo(cardType, cardText.trimEnd(), firstLineNo, lastLineNo));
 | |
|   }
 | |
|   if (debugParser) {
 | |
|     console.log("Parsed cards:\n", cards);
 | |
|   }
 | |
|   return cards;
 | |
| }
 | |
| 
 | |
| // src/question-type.ts
 | |
| var import_clozecraft2 = __toESM(require_dist());
 | |
| var CardFrontBack = class {
 | |
|   // The caller is responsible for any required trimming of leading/trailing spaces
 | |
|   constructor(front, back) {
 | |
|     this.front = front;
 | |
|     this.back = back;
 | |
|   }
 | |
| };
 | |
| var CardFrontBackUtil = class {
 | |
|   static expand(questionType, questionText, settings) {
 | |
|     const handler = QuestionTypeFactory.create(questionType);
 | |
|     return handler.expand(questionText, settings);
 | |
|   }
 | |
| };
 | |
| var QuestionTypeSingleLineBasic = class {
 | |
|   expand(questionText, settings) {
 | |
|     const idx = questionText.indexOf(settings.singleLineCardSeparator);
 | |
|     const item = new CardFrontBack(
 | |
|       questionText.substring(0, idx),
 | |
|       questionText.substring(idx + settings.singleLineCardSeparator.length)
 | |
|     );
 | |
|     const result = [item];
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var QuestionTypeSingleLineReversed = class {
 | |
|   expand(questionText, settings) {
 | |
|     const idx = questionText.indexOf(settings.singleLineReversedCardSeparator);
 | |
|     const side1 = questionText.substring(0, idx), side2 = questionText.substring(
 | |
|       idx + settings.singleLineReversedCardSeparator.length
 | |
|     );
 | |
|     const result = [
 | |
|       new CardFrontBack(side1, side2),
 | |
|       new CardFrontBack(side2, side1)
 | |
|     ];
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var QuestionTypeMultiLineBasic = class {
 | |
|   expand(questionText, settings) {
 | |
|     const questionLines = questionText.split("\n");
 | |
|     const lineIdx = findLineIndexOfSearchStringIgnoringWs(
 | |
|       questionLines,
 | |
|       settings.multilineCardSeparator
 | |
|     );
 | |
|     const side1 = questionLines.slice(0, lineIdx).join("\n");
 | |
|     const side2 = questionLines.slice(lineIdx + 1).join("\n");
 | |
|     const result = [new CardFrontBack(side1, side2)];
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var QuestionTypeMultiLineReversed = class {
 | |
|   expand(questionText, settings) {
 | |
|     const questionLines = questionText.split("\n");
 | |
|     const lineIdx = findLineIndexOfSearchStringIgnoringWs(
 | |
|       questionLines,
 | |
|       settings.multilineReversedCardSeparator
 | |
|     );
 | |
|     const side1 = questionLines.slice(0, lineIdx).join("\n");
 | |
|     const side2 = questionLines.slice(lineIdx + 1).join("\n");
 | |
|     const result = [
 | |
|       new CardFrontBack(side1, side2),
 | |
|       new CardFrontBack(side2, side1)
 | |
|     ];
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var QuestionTypeCloze = class {
 | |
|   expand(questionText, settings) {
 | |
|     const clozecrafter = new import_clozecraft2.ClozeCrafter(settings.clozePatterns);
 | |
|     const clozeNote = clozecrafter.createClozeNote(questionText);
 | |
|     const clozeFormatter = new QuestionTypeClozeFormatter();
 | |
|     let front, back;
 | |
|     const result = [];
 | |
|     for (let i2 = 0; i2 < clozeNote.numCards; i2++) {
 | |
|       front = clozeNote.getCardFront(i2, clozeFormatter);
 | |
|       back = clozeNote.getCardBack(i2, clozeFormatter);
 | |
|       result.push(new CardFrontBack(front, back));
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| var QuestionTypeClozeFormatter = class {
 | |
|   asking(answer, hint) {
 | |
|     return `<span style='color:#2196f3'>${!hint ? "[...]" : `[${hint}]`}</span>`;
 | |
|   }
 | |
|   showingAnswer(answer, _hint) {
 | |
|     return `<span style='color:#2196f3'>${answer}</span>`;
 | |
|   }
 | |
|   hiding(answer, hint) {
 | |
|     return `<span style='color:var(--code-comment)'>${!hint ? "[...]" : `[${hint}]`}</span>`;
 | |
|   }
 | |
| };
 | |
| var QuestionTypeFactory = class {
 | |
|   static create(questionType) {
 | |
|     let handler;
 | |
|     switch (questionType) {
 | |
|       case 0 /* SingleLineBasic */:
 | |
|         handler = new QuestionTypeSingleLineBasic();
 | |
|         break;
 | |
|       case 1 /* SingleLineReversed */:
 | |
|         handler = new QuestionTypeSingleLineReversed();
 | |
|         break;
 | |
|       case 2 /* MultiLineBasic */:
 | |
|         handler = new QuestionTypeMultiLineBasic();
 | |
|         break;
 | |
|       case 3 /* MultiLineReversed */:
 | |
|         handler = new QuestionTypeMultiLineReversed();
 | |
|         break;
 | |
|       case 4 /* Cloze */:
 | |
|         handler = new QuestionTypeCloze();
 | |
|         break;
 | |
|     }
 | |
|     return handler;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/settings.ts
 | |
| var import_obsidian3 = require("obsidian");
 | |
| var DEFAULT_SETTINGS = {
 | |
|   // flashcards
 | |
|   flashcardTags: ["#flashcards"],
 | |
|   convertFoldersToDecks: false,
 | |
|   burySiblingCards: false,
 | |
|   randomizeCardOrder: null,
 | |
|   flashcardCardOrder: "DueFirstRandom",
 | |
|   flashcardDeckOrder: "PrevDeckComplete_Sequential",
 | |
|   convertHighlightsToClozes: true,
 | |
|   convertBoldTextToClozes: false,
 | |
|   convertCurlyBracketsToClozes: false,
 | |
|   clozePatterns: ["==[123;;]answer[;;hint]=="],
 | |
|   singleLineCardSeparator: "::",
 | |
|   singleLineReversedCardSeparator: ":::",
 | |
|   multilineCardSeparator: "?",
 | |
|   multilineReversedCardSeparator: "??",
 | |
|   multilineCardEndMarker: "",
 | |
|   editLaterTag: "#edit-later",
 | |
|   // notes
 | |
|   enableNoteReviewPaneOnStartup: true,
 | |
|   tagsToReview: ["#review"],
 | |
|   noteFoldersToIgnore: ["**/*.excalidraw.md"],
 | |
|   openRandomNote: false,
 | |
|   autoNextNote: false,
 | |
|   disableFileMenuReviewOptions: false,
 | |
|   maxNDaysNotesReviewQueue: 365,
 | |
|   // UI settings
 | |
|   showRibbonIcon: true,
 | |
|   showStatusBar: true,
 | |
|   initiallyExpandAllSubdecksInTree: false,
 | |
|   showContextInCards: true,
 | |
|   showIntervalInReviewButtons: true,
 | |
|   flashcardHeightPercentage: import_obsidian3.Platform.isMobile ? 100 : 80,
 | |
|   flashcardWidthPercentage: import_obsidian3.Platform.isMobile ? 100 : 40,
 | |
|   flashcardEasyText: t("EASY"),
 | |
|   flashcardGoodText: t("GOOD"),
 | |
|   flashcardHardText: t("HARD"),
 | |
|   reviewButtonDelay: 0,
 | |
|   openViewInNewTab: false,
 | |
|   // algorithm
 | |
|   algorithm: "SM-2-OSR" /* SM_2_OSR */,
 | |
|   baseEase: 250,
 | |
|   lapsesIntervalChange: 0.5,
 | |
|   easyBonus: 1.3,
 | |
|   loadBalance: true,
 | |
|   maximumInterval: 36525,
 | |
|   maxLinkFactor: 1,
 | |
|   // storage
 | |
|   dataStore: "NOTES" /* NOTES */,
 | |
|   cardCommentOnSameLine: false,
 | |
|   // logging
 | |
|   showSchedulingDebugMessages: false,
 | |
|   showParserDebugMessages: false
 | |
| };
 | |
| function upgradeSettings(settings) {
 | |
|   if (settings.randomizeCardOrder != null && settings.flashcardCardOrder == null && settings.flashcardDeckOrder == null) {
 | |
|     settings.flashcardCardOrder = settings.randomizeCardOrder ? "DueFirstRandom" : "DueFirstSequential";
 | |
|     settings.flashcardDeckOrder = "PrevDeckComplete_Sequential";
 | |
|     settings.randomizeCardOrder = null;
 | |
|   }
 | |
|   if (settings.clozePatterns == null) {
 | |
|     settings.clozePatterns = [];
 | |
|     if (settings.convertHighlightsToClozes)
 | |
|       settings.clozePatterns.push("==[123;;]answer[;;hint]==");
 | |
|     if (settings.convertBoldTextToClozes)
 | |
|       settings.clozePatterns.push("**[123;;]answer[;;hint]**");
 | |
|     if (settings.convertCurlyBracketsToClozes)
 | |
|       settings.clozePatterns.push("{{[123;;]answer[;;hint]}}");
 | |
|   }
 | |
| }
 | |
| var SettingsUtil = class _SettingsUtil {
 | |
|   static isFlashcardTag(settings, tag) {
 | |
|     return _SettingsUtil.isTagInList(settings.flashcardTags, tag);
 | |
|   }
 | |
|   static isPathInNoteIgnoreFolder(settings, path3) {
 | |
|     return settings.noteFoldersToIgnore.some((folder) => pathMatchesPattern(path3, folder));
 | |
|   }
 | |
|   static isAnyTagANoteReviewTag(settings, tags) {
 | |
|     for (const tag of tags) {
 | |
|       if (settings.tagsToReview.some(
 | |
|         (tagToReview) => tag === tagToReview || tag.startsWith(tagToReview + "/")
 | |
|       )) {
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
|   // Given a list of tags, return the subset that is in settings.tagsToReview
 | |
|   static filterForNoteReviewTag(settings, tags) {
 | |
|     const result = [];
 | |
|     for (const tagToReview of settings.tagsToReview) {
 | |
|       if (tags.some((tag) => tag === tagToReview || tag.startsWith(tagToReview + "/"))) {
 | |
|         result.push(tagToReview);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   static isTagInList(tagList, tag) {
 | |
|     for (const tagFromList of tagList) {
 | |
|       if (tag === tagFromList || tag.startsWith(tagFromList + "/")) {
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/note-question-parser.ts
 | |
| var NoteQuestionParser = class {
 | |
|   constructor(settings) {
 | |
|     this.settings = settings;
 | |
|   }
 | |
|   async createQuestionList(noteFile, defaultTextDirection, folderTopicPath, onlyKeepQuestionsWithTopicPath) {
 | |
|     this.noteFile = noteFile;
 | |
|     const tagCacheList = noteFile.getAllTagsFromCache();
 | |
|     const hasTopicPaths = tagCacheList.some((item) => SettingsUtil.isFlashcardTag(this.settings, item)) || folderTopicPath.hasPath;
 | |
|     if (hasTopicPaths) {
 | |
|       const noteText = await noteFile.read();
 | |
|       const tagCompleteList = noteFile.getAllTagsFromText();
 | |
|       [this.frontmatterText, this.contentText] = splitNoteIntoFrontmatterAndContent(noteText);
 | |
|       let textDirection = noteFile.getTextDirection();
 | |
|       if (textDirection == 0 /* Unspecified */) textDirection = defaultTextDirection;
 | |
|       this.questionList = this.doCreateQuestionList(
 | |
|         noteText,
 | |
|         textDirection,
 | |
|         folderTopicPath,
 | |
|         this.tagCacheList
 | |
|       );
 | |
|       [this.frontmatterTopicPathList, this.contentTopicPathInfo] = this.analyseTagCacheList(tagCompleteList);
 | |
|       for (const question of this.questionList) {
 | |
|         question.topicPathList = this.determineQuestionTopicPathList(question);
 | |
|       }
 | |
|       if (onlyKeepQuestionsWithTopicPath) {
 | |
|         this.questionList = this.questionList.filter((q2) => q2.topicPathList);
 | |
|       }
 | |
|     } else {
 | |
|       this.questionList = [];
 | |
|     }
 | |
|     return this.questionList;
 | |
|   }
 | |
|   doCreateQuestionList(noteText, textDirection, folderTopicPath, tagCacheList) {
 | |
|     this.noteText = noteText;
 | |
|     this.noteLines = splitTextIntoLineArray(noteText);
 | |
|     this.folderTopicPath = folderTopicPath;
 | |
|     this.tagCacheList = tagCacheList;
 | |
|     const result = [];
 | |
|     const parsedQuestionInfoList = this.parseQuestions();
 | |
|     for (const parsedQuestionInfo of parsedQuestionInfoList) {
 | |
|       const question = this.createQuestionObject(parsedQuestionInfo, textDirection);
 | |
|       const cardFrontBackList = CardFrontBackUtil.expand(
 | |
|         question.questionType,
 | |
|         question.questionText.actualQuestion,
 | |
|         this.settings
 | |
|       );
 | |
|       let cardScheduleInfoList = DataStore.getInstance().questionCreateSchedule(
 | |
|         question.questionText.original,
 | |
|         null
 | |
|       );
 | |
|       const correctLength = cardFrontBackList.length;
 | |
|       if (cardScheduleInfoList.length > correctLength) {
 | |
|         question.hasChanged = true;
 | |
|         cardScheduleInfoList = cardScheduleInfoList.slice(0, correctLength);
 | |
|       }
 | |
|       const cardList = this.createCardList(cardFrontBackList, cardScheduleInfoList);
 | |
|       question.setCardList(cardList);
 | |
|       result.push(question);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   parseQuestions() {
 | |
|     const settings = this.settings;
 | |
|     const parserOptions = {
 | |
|       singleLineCardSeparator: settings.singleLineCardSeparator,
 | |
|       singleLineReversedCardSeparator: settings.singleLineReversedCardSeparator,
 | |
|       multilineCardSeparator: settings.multilineCardSeparator,
 | |
|       multilineReversedCardSeparator: settings.multilineReversedCardSeparator,
 | |
|       multilineCardEndMarker: settings.multilineCardEndMarker,
 | |
|       clozePatterns: settings.clozePatterns
 | |
|     };
 | |
|     return parse(this.contentText, parserOptions);
 | |
|   }
 | |
|   createQuestionObject(parsedQuestionInfo, textDirection) {
 | |
|     const questionContext = this.noteFile.getQuestionContext(
 | |
|       parsedQuestionInfo.firstLineNum
 | |
|     );
 | |
|     const result = Question.Create(
 | |
|       this.settings,
 | |
|       parsedQuestionInfo,
 | |
|       null,
 | |
|       // We haven't worked out the TopicPathList yet
 | |
|       textDirection,
 | |
|       questionContext
 | |
|     );
 | |
|     return result;
 | |
|   }
 | |
|   createCardList(cardFrontBackList, cardScheduleInfoList) {
 | |
|     const siblings = [];
 | |
|     for (let i2 = 0; i2 < cardFrontBackList.length; i2++) {
 | |
|       const { front, back } = cardFrontBackList[i2];
 | |
|       const hasScheduleInfo = i2 < cardScheduleInfoList.length;
 | |
|       const schedule = cardScheduleInfoList[i2];
 | |
|       const cardObj = new Card({
 | |
|         front,
 | |
|         back,
 | |
|         cardIdx: i2
 | |
|       });
 | |
|       cardObj.scheduleInfo = hasScheduleInfo ? schedule : null;
 | |
|       siblings.push(cardObj);
 | |
|     }
 | |
|     return siblings;
 | |
|   }
 | |
|   //
 | |
|   // Given the complete list of tags within a note:
 | |
|   // 1.   Only keep tags that are specified in the user settings as flashcardTags
 | |
|   // 2.   Filter out tags that are question specific
 | |
|   //      (these will be parsed separately by class QuestionText)
 | |
|   // 3.   Combine all tags present logically grouped together into a single entry
 | |
|   //      - All tags present on the same line grouped together
 | |
|   //      - All tags within frontmatter grouped together (note that multiple tags
 | |
|   //      within frontmatter appear on separate lines)
 | |
|   //
 | |
|   analyseTagCacheList(tagCacheList) {
 | |
|     this.flashcardTagList = tagCacheList.filter(
 | |
|       (item) => SettingsUtil.isFlashcardTag(this.settings, item.tag)
 | |
|     );
 | |
|     if (this.flashcardTagList.length > 0) {
 | |
|       this.flashcardTagList.sort((a2, b2) => a2.position.start.line - b2.position.start.line);
 | |
|     }
 | |
|     let frontmatterLineCount = 0;
 | |
|     if (this.frontmatterText) {
 | |
|       frontmatterLineCount = splitTextIntoLineArray(this.frontmatterText).length;
 | |
|     }
 | |
|     const frontmatterTopicPathList = this.determineFrontmatterTopicPathList(
 | |
|       this.flashcardTagList,
 | |
|       frontmatterLineCount
 | |
|     );
 | |
|     const contentTopicPathList = this.determineContentTopicPathList(
 | |
|       this.flashcardTagList,
 | |
|       frontmatterLineCount
 | |
|     );
 | |
|     return [frontmatterTopicPathList, contentTopicPathList];
 | |
|   }
 | |
|   determineFrontmatterTopicPathList(flashcardTagList, frontmatterLineCount) {
 | |
|     let result = null;
 | |
|     const noteLevelTagList = flashcardTagList.filter(
 | |
|       (item) => item.position.start.line == frontmatterTagPseudoLineNum && this.isNoteLevelFlashcardTag(item)
 | |
|     );
 | |
|     if (noteLevelTagList.length > 0) {
 | |
|       if (this.frontmatterText) {
 | |
|         const frontmatterTagCacheList = noteLevelTagList.filter(
 | |
|           (item) => item.position.start.line < frontmatterLineCount
 | |
|         );
 | |
|         if (frontmatterTagCacheList.length > 0)
 | |
|           result = this.createTopicPathList(
 | |
|             frontmatterTagCacheList,
 | |
|             frontmatterTagPseudoLineNum
 | |
|           );
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   determineContentTopicPathList(flashcardTagList, frontmatterLineCount) {
 | |
|     const result = [];
 | |
|     const contentStartLineNum = frontmatterLineCount;
 | |
|     const contentTagCacheList = flashcardTagList.filter(
 | |
|       (item) => item.position.start.line >= contentStartLineNum && this.isNoteLevelFlashcardTag(item)
 | |
|     );
 | |
|     let list = [];
 | |
|     for (const tag of contentTagCacheList) {
 | |
|       if (list.length != 0) {
 | |
|         const startLineNum = list[0].position.start.line;
 | |
|         if (startLineNum != tag.position.start.line) {
 | |
|           result.push(this.createTopicPathList(list, startLineNum));
 | |
|           list = [];
 | |
|         }
 | |
|       }
 | |
|       list.push(tag);
 | |
|     }
 | |
|     if (list.length > 0) {
 | |
|       const startLineNum = list[0].position.start.line;
 | |
|       result.push(this.createTopicPathList(list, startLineNum));
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   isNoteLevelFlashcardTag(tagItem) {
 | |
|     const tagLineNum = tagItem.position.start.line;
 | |
|     const isQuestionSpecific = this.questionList.some(
 | |
|       (q2) => q2.parsedQuestionInfo.isQuestionLineNum(tagLineNum)
 | |
|     );
 | |
|     return !isQuestionSpecific;
 | |
|   }
 | |
|   createTopicPathList(tagCacheList, lineNum) {
 | |
|     const list = [];
 | |
|     for (const tagCache of tagCacheList) {
 | |
|       list.push(TopicPath.getTopicPathFromTag(tagCache.tag));
 | |
|     }
 | |
|     return new TopicPathList(list, lineNum);
 | |
|   }
 | |
|   createTopicPathListFromSingleTag(tagCache) {
 | |
|     const list = [TopicPath.getTopicPathFromTag(tagCache.tag)];
 | |
|     return new TopicPathList(list, tagCache.position.start.line);
 | |
|   }
 | |
|   // A question can be associated with multiple topics (hence returning TopicPathList and not just TopicPath).
 | |
|   //
 | |
|   // If the question has an associated question specific TopicPath, then that is returned.
 | |
|   //
 | |
|   // Else the first TopicPathList prior to the question (in the order present in the file) is returned.
 | |
|   // That could be either the tags within the note's frontmatter, or tags on lines within the note's content.
 | |
|   determineQuestionTopicPathList(question) {
 | |
|     let result;
 | |
|     if (this.settings.convertFoldersToDecks) {
 | |
|       result = new TopicPathList([this.folderTopicPath]);
 | |
|     } else {
 | |
|       const questionText = question.questionText;
 | |
|       if (questionText.topicPathWithWs)
 | |
|         result = new TopicPathList(
 | |
|           [questionText.topicPathWithWs.topicPath],
 | |
|           question.parsedQuestionInfo.firstLineNum
 | |
|         );
 | |
|       else {
 | |
|         result = this.frontmatterTopicPathList;
 | |
|         for (let i2 = this.contentTopicPathInfo.length - 1; i2 >= 0; i2--) {
 | |
|           const topicPathList = this.contentTopicPathInfo[i2];
 | |
|           if (topicPathList.lineNum < question.parsedQuestionInfo.firstLineNum) {
 | |
|             result = topicPathList;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|         if (!result && this.flashcardTagList.length > 0) {
 | |
|           result = this.createTopicPathListFromSingleTag(this.flashcardTagList[0]);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/note-file-loader.ts
 | |
| var NoteFileLoader = class {
 | |
|   constructor(settings) {
 | |
|     this.settings = settings;
 | |
|   }
 | |
|   async load(noteFile, defaultTextDirection, folderTopicPath) {
 | |
|     this.noteFile = noteFile;
 | |
|     const questionParser = new NoteQuestionParser(this.settings);
 | |
|     const onlyKeepQuestionsWithTopicPath = true;
 | |
|     const questionList = await questionParser.createQuestionList(
 | |
|       noteFile,
 | |
|       defaultTextDirection,
 | |
|       folderTopicPath,
 | |
|       onlyKeepQuestionsWithTopicPath
 | |
|     );
 | |
|     const result = new Note(noteFile, questionList);
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/core.ts
 | |
| var OsrCore = class {
 | |
|   constructor() {
 | |
|     this._reviewableDeckTree = new Deck2("root", null);
 | |
|   }
 | |
|   get noteReviewQueue() {
 | |
|     return this._noteReviewQueue;
 | |
|   }
 | |
|   get remainingDeckTree() {
 | |
|     return this._remainingDeckTree;
 | |
|   }
 | |
|   get reviewableDeckTree() {
 | |
|     return this._reviewableDeckTree;
 | |
|   }
 | |
|   get questionPostponementList() {
 | |
|     return this._questionPostponementList;
 | |
|   }
 | |
|   get dueDateFlashcardHistogram() {
 | |
|     return this._dueDateFlashcardHistogram;
 | |
|   }
 | |
|   get dueDateNoteHistogram() {
 | |
|     return this._dueDateNoteHistogram;
 | |
|   }
 | |
|   get cardStats() {
 | |
|     return this._cardStats;
 | |
|   }
 | |
|   init(questionPostponementList, osrNoteLinkInfoFinder, settings, dataChangedHandler, noteReviewQueue) {
 | |
|     this.settings = settings;
 | |
|     this.osrNoteLinkInfoFinder = osrNoteLinkInfoFinder;
 | |
|     this.dataChangedHandler = dataChangedHandler;
 | |
|     this._noteReviewQueue = noteReviewQueue;
 | |
|     this._questionPostponementList = questionPostponementList;
 | |
|     this._dueDateFlashcardHistogram = new CardDueDateHistogram();
 | |
|     this._dueDateNoteHistogram = new NoteDueDateHistogram();
 | |
|   }
 | |
|   loadInit() {
 | |
|     this.osrNoteGraph = new OsrNoteGraph(this.osrNoteLinkInfoFinder);
 | |
|     this._noteReviewQueue.init();
 | |
|     this.fullDeckTree = new Deck2("root", null);
 | |
|   }
 | |
|   async processFile(noteFile) {
 | |
|     const schedule = await DataStoreAlgorithm.getInstance().noteGetSchedule(noteFile);
 | |
|     let note = null;
 | |
|     this.osrNoteGraph.processLinks(noteFile.path);
 | |
|     const topicPath = this.findTopicPath(noteFile);
 | |
|     if (topicPath.hasPath) {
 | |
|       note = await this.loadNote(noteFile, topicPath);
 | |
|       note.appendCardsToDeck(this.fullDeckTree);
 | |
|     }
 | |
|     SrsAlgorithm.getInstance().noteOnLoadedNote(noteFile.path, note, schedule == null ? void 0 : schedule.latestEase);
 | |
|     const tags = noteFile.getAllTagsFromCache();
 | |
|     const matchedNoteTags = SettingsUtil.filterForNoteReviewTag(this.settings, tags);
 | |
|     if (matchedNoteTags.length == 0) {
 | |
|       return;
 | |
|     }
 | |
|     const noteSchedule = await DataStoreAlgorithm.getInstance().noteGetSchedule(noteFile);
 | |
|     this._noteReviewQueue.addNoteToQueue(noteFile, noteSchedule, matchedNoteTags);
 | |
|   }
 | |
|   finaliseLoad() {
 | |
|     this.osrNoteGraph.generatePageRanks();
 | |
|     this._reviewableDeckTree = DeckTreeFilter.filterForReviewableCards(this.fullDeckTree);
 | |
|     this._reviewableDeckTree.sortSubdecksList();
 | |
|     this._remainingDeckTree = DeckTreeFilter.filterForRemainingCards(
 | |
|       this._questionPostponementList,
 | |
|       this._reviewableDeckTree,
 | |
|       1 /* Review */
 | |
|     );
 | |
|     const calc = new DeckTreeStatsCalculator();
 | |
|     this._cardStats = calc.calculate(this._reviewableDeckTree);
 | |
|     this.calculateDerivedInfo();
 | |
|     this._dueDateFlashcardHistogram.calculateFromDeckTree(this._reviewableDeckTree);
 | |
|     if (this.dataChangedHandler) this.dataChangedHandler();
 | |
|   }
 | |
|   async saveNoteReviewResponse(noteFile, response, settings) {
 | |
|     const originalNoteSchedule = await DataStoreAlgorithm.getInstance().noteGetSchedule(noteFile);
 | |
|     let noteSchedule;
 | |
|     if (originalNoteSchedule == null) {
 | |
|       noteSchedule = SrsAlgorithm.getInstance().noteCalcNewSchedule(
 | |
|         noteFile.path,
 | |
|         this.osrNoteGraph,
 | |
|         response,
 | |
|         this._dueDateNoteHistogram
 | |
|       );
 | |
|     } else {
 | |
|       noteSchedule = SrsAlgorithm.getInstance().noteCalcUpdatedSchedule(
 | |
|         noteFile.path,
 | |
|         originalNoteSchedule,
 | |
|         response,
 | |
|         this._dueDateNoteHistogram
 | |
|       );
 | |
|     }
 | |
|     await DataStoreAlgorithm.getInstance().noteSetSchedule(noteFile, noteSchedule);
 | |
|     this._noteReviewQueue.updateScheduleInfo(noteFile, noteSchedule);
 | |
|     this.calculateDerivedInfo();
 | |
|     await this.buryAllCardsInNote(settings, noteFile);
 | |
|     if (this.dataChangedHandler) this.dataChangedHandler();
 | |
|   }
 | |
|   calculateDerivedInfo() {
 | |
|     const todayUnix = globalDateProvider.today.valueOf();
 | |
|     this.noteReviewQueue.calcDueNotesCount(todayUnix);
 | |
|     this._dueDateNoteHistogram.calculateFromReviewDecksAndSort(
 | |
|       this.noteReviewQueue.reviewDecks,
 | |
|       this.osrNoteGraph
 | |
|     );
 | |
|   }
 | |
|   async buryAllCardsInNote(settings, noteFile) {
 | |
|     if (settings.burySiblingCards) {
 | |
|       const topicPath = this.findTopicPath(noteFile);
 | |
|       const noteX = await this.loadNote(noteFile, topicPath);
 | |
|       if (noteX.questionList.length > 0) {
 | |
|         for (const question of noteX.questionList) {
 | |
|           this._questionPostponementList.add(question);
 | |
|         }
 | |
|         await this._questionPostponementList.write();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   async loadNote(noteFile, topicPath) {
 | |
|     const loader = new NoteFileLoader(this.settings);
 | |
|     const note = await loader.load(noteFile, this.defaultTextDirection, topicPath);
 | |
|     if (note.hasChanged) {
 | |
|       await note.writeNoteFile(this.settings);
 | |
|     }
 | |
|     return note;
 | |
|   }
 | |
|   findTopicPath(note) {
 | |
|     return TopicPath.getTopicPathOfFile(note, this.settings);
 | |
|   }
 | |
| };
 | |
| var OsrAppCore = class extends OsrCore {
 | |
|   constructor(app) {
 | |
|     super();
 | |
|     this._syncLock = false;
 | |
|     this.app = app;
 | |
|   }
 | |
|   get syncLock() {
 | |
|     return this._syncLock;
 | |
|   }
 | |
|   async loadVault() {
 | |
|     if (this._syncLock) {
 | |
|       return;
 | |
|     }
 | |
|     this._syncLock = true;
 | |
|     try {
 | |
|       this.loadInit();
 | |
|       const notes = this.app.vault.getMarkdownFiles();
 | |
|       for (const noteFile of notes) {
 | |
|         if (SettingsUtil.isPathInNoteIgnoreFolder(this.settings, noteFile.path)) {
 | |
|           continue;
 | |
|         }
 | |
|         const file = this.createSrTFile(noteFile);
 | |
|         await this.processFile(file);
 | |
|       }
 | |
|       this.finaliseLoad();
 | |
|     } finally {
 | |
|       this._syncLock = false;
 | |
|     }
 | |
|   }
 | |
|   createSrTFile(note) {
 | |
|     return new SrTFile(this.app.vault, this.app.metadataCache, note);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/data-store-algorithm/data-store-in-note-algorithm-osr.ts
 | |
| var import_moment3 = __toESM(require_moment());
 | |
| var DataStoreInNoteAlgorithmOsr = class {
 | |
|   constructor(settings) {
 | |
|     this.settings = settings;
 | |
|   }
 | |
|   async noteGetSchedule(note) {
 | |
|     let result = null;
 | |
|     const frontmatter = await note.getFrontmatter();
 | |
|     if (frontmatter && frontmatter.has("sr-due") && frontmatter.has("sr-interval") && frontmatter.has("sr-ease")) {
 | |
|       const dueDate = (0, import_moment3.default)(frontmatter.get("sr-due"), ALLOWED_DATE_FORMATS);
 | |
|       const interval = parseFloat(frontmatter.get("sr-interval"));
 | |
|       const ease = parseFloat(frontmatter.get("sr-ease"));
 | |
|       result = new RepItemScheduleInfoOsr(dueDate, interval, ease);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   async noteSetSchedule(note, repItemScheduleInfo) {
 | |
|     let fileText = await note.read();
 | |
|     const schedInfo = repItemScheduleInfo;
 | |
|     const dueString = formatDateYYYYMMDD(schedInfo.dueDate);
 | |
|     const interval = schedInfo.interval;
 | |
|     const ease = schedInfo.latestEase;
 | |
|     if (SCHEDULING_INFO_REGEX.test(fileText)) {
 | |
|       const schedulingInfo = SCHEDULING_INFO_REGEX.exec(fileText);
 | |
|       fileText = fileText.replace(
 | |
|         SCHEDULING_INFO_REGEX,
 | |
|         `---
 | |
| ${schedulingInfo[1]}sr-due: ${dueString}
 | |
| sr-interval: ${interval}
 | |
| sr-ease: ${ease}
 | |
| ${schedulingInfo[5]}---`
 | |
|       );
 | |
|     } else if (YAML_FRONT_MATTER_REGEX.test(fileText)) {
 | |
|       const existingYaml = YAML_FRONT_MATTER_REGEX.exec(fileText);
 | |
|       fileText = fileText.replace(
 | |
|         YAML_FRONT_MATTER_REGEX,
 | |
|         `---
 | |
| ${existingYaml[1]}sr-due: ${dueString}
 | |
| sr-interval: ${interval}
 | |
| sr-ease: ${ease}
 | |
| ---`
 | |
|       );
 | |
|     } else {
 | |
|       fileText = `---
 | |
| sr-due: ${dueString}
 | |
| sr-interval: ${interval}
 | |
| sr-ease: ${ease}
 | |
| ---
 | |
| 
 | |
| ${fileText}`;
 | |
|     }
 | |
|     await note.write(fileText);
 | |
|   }
 | |
|   questionFormatScheduleAsHtmlComment(question) {
 | |
|     let result = SR_HTML_COMMENT_BEGIN;
 | |
|     for (let i2 = 0; i2 < question.cards.length; i2++) {
 | |
|       const card = question.cards[i2];
 | |
|       result += this.formatCardSchedule(card);
 | |
|     }
 | |
|     result += SR_HTML_COMMENT_END;
 | |
|     return result;
 | |
|   }
 | |
|   formatCardSchedule(card) {
 | |
|     let result;
 | |
|     if (card.hasSchedule) {
 | |
|       const schedule = card.scheduleInfo;
 | |
|       const dateStr = schedule.dueDate ? formatDateYYYYMMDD(schedule.dueDate) : RepItemScheduleInfoOsr.dummyDueDateForNewCard;
 | |
|       result = `!${dateStr},${schedule.interval},${schedule.latestEase}`;
 | |
|     } else {
 | |
|       result = `!${RepItemScheduleInfoOsr.dummyDueDateForNewCard},${RepItemScheduleInfoOsr.initialInterval},${this.settings.baseEase}`;
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/data-stores/notes/notes.ts
 | |
| var StoreInNotes = class {
 | |
|   constructor(settings) {
 | |
|     this.settings = settings;
 | |
|   }
 | |
|   questionCreateSchedule(originalQuestionText, _2) {
 | |
|     let scheduling = [
 | |
|       ...originalQuestionText.matchAll(MULTI_SCHEDULING_EXTRACTOR)
 | |
|     ];
 | |
|     if (scheduling.length === 0)
 | |
|       scheduling = [...originalQuestionText.matchAll(LEGACY_SCHEDULING_EXTRACTOR)];
 | |
|     const result = [];
 | |
|     for (let i2 = 0; i2 < scheduling.length; i2++) {
 | |
|       const match2 = scheduling[i2];
 | |
|       const dueDateStr = match2[1];
 | |
|       const interval = parseInt(match2[2]);
 | |
|       const ease = parseInt(match2[3]);
 | |
|       const dueDate = DateUtil.dateStrToMoment(dueDateStr);
 | |
|       let info;
 | |
|       if (dueDate == null || formatDateYYYYMMDD(dueDate) == RepItemScheduleInfoOsr.dummyDueDateForNewCard) {
 | |
|         info = null;
 | |
|       } else {
 | |
|         const delayBeforeReviewTicks = dueDate.valueOf() - globalDateProvider.today.valueOf();
 | |
|         info = new RepItemScheduleInfoOsr(dueDate, interval, ease, delayBeforeReviewTicks);
 | |
|       }
 | |
|       result.push(info);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   questionRemoveScheduleInfo(questionText) {
 | |
|     return questionText.replace(/<!--SR:.+-->/gm, "");
 | |
|   }
 | |
|   async questionWriteSchedule(question) {
 | |
|     await this.questionWrite(question);
 | |
|   }
 | |
|   async questionWrite(question) {
 | |
|     const fileText = await question.note.file.read();
 | |
|     const newText = question.updateQuestionWithinNoteText(fileText, this.settings);
 | |
|     await question.note.file.write(newText);
 | |
|     question.hasChanged = false;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/review-queue-list-view.tsx
 | |
| var import_obsidian4 = require("obsidian");
 | |
| var REVIEW_QUEUE_VIEW_TYPE = "review-queue-list-view";
 | |
| var ReviewQueueListView = class extends import_obsidian4.ItemView {
 | |
|   get noteReviewQueue() {
 | |
|     return this.nextNoteReviewHandler.noteReviewQueue;
 | |
|   }
 | |
|   constructor(leaf, nextNoteReviewHandler, settings) {
 | |
|     super(leaf);
 | |
|     this.nextNoteReviewHandler = nextNoteReviewHandler;
 | |
|     this.settings = settings;
 | |
|     if (this.settings.enableNoteReviewPaneOnStartup) {
 | |
|       this.registerEvent(this.app.workspace.on("file-open", () => this.redraw()));
 | |
|       this.registerEvent(this.app.vault.on("rename", () => this.redraw()));
 | |
|     }
 | |
|   }
 | |
|   getViewType() {
 | |
|     return REVIEW_QUEUE_VIEW_TYPE;
 | |
|   }
 | |
|   getDisplayText() {
 | |
|     return t("NOTES_REVIEW_QUEUE");
 | |
|   }
 | |
|   getIcon() {
 | |
|     return "SpacedRepIcon";
 | |
|   }
 | |
|   onHeaderMenu(menu) {
 | |
|     menu.addItem((item) => {
 | |
|       item.setTitle(t("CLOSE")).setIcon("cross").onClick(() => {
 | |
|         this.app.workspace.detachLeavesOfType(REVIEW_QUEUE_VIEW_TYPE);
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   redraw() {
 | |
|     if (!this.noteReviewQueue.reviewDecks) return;
 | |
|     const activeFile = this.app.workspace.getActiveFile();
 | |
|     const rootEl = createDiv("tree-item nav-folder mod-root");
 | |
|     const childrenEl = rootEl.createDiv("tree-item-children nav-folder-children");
 | |
|     for (const [deckKey, deck] of this.noteReviewQueue.reviewDecks) {
 | |
|       const deckCollapsed = !deck.activeFolders.has(deck.deckName);
 | |
|       const deckFolderEl = this.createRightPaneFolder(
 | |
|         childrenEl,
 | |
|         deckKey,
 | |
|         deckCollapsed,
 | |
|         false,
 | |
|         deck
 | |
|       ).getElementsByClassName("tree-item-children nav-folder-children")[0];
 | |
|       if (deck.newNotes.length > 0) {
 | |
|         const newNotesFolderEl = this.createRightPaneFolder(
 | |
|           deckFolderEl,
 | |
|           t("NEW"),
 | |
|           !deck.activeFolders.has(t("NEW")),
 | |
|           deckCollapsed,
 | |
|           deck
 | |
|         );
 | |
|         for (const newFile of deck.newNotes) {
 | |
|           const fileIsOpen = activeFile && newFile.path === activeFile.path;
 | |
|           if (fileIsOpen) {
 | |
|             deck.activeFolders.add(deck.deckName);
 | |
|             deck.activeFolders.add(t("NEW"));
 | |
|             this.changeFolderFolding(newNotesFolderEl);
 | |
|             this.changeFolderFolding(deckFolderEl);
 | |
|           }
 | |
|           this.createRightPaneFile(
 | |
|             newNotesFolderEl,
 | |
|             newFile.tfile,
 | |
|             fileIsOpen,
 | |
|             !deck.activeFolders.has(t("NEW")),
 | |
|             deck
 | |
|           );
 | |
|         }
 | |
|       }
 | |
|       if (deck.scheduledNotes.length > 0) {
 | |
|         const now2 = Date.now();
 | |
|         let currUnix = -1;
 | |
|         let schedFolderEl = null, folderTitle = "";
 | |
|         const maxDaysToRender = this.settings.maxNDaysNotesReviewQueue;
 | |
|         for (const sNote of deck.scheduledNotes) {
 | |
|           if (sNote.dueUnix != currUnix) {
 | |
|             const nDays = Math.ceil((sNote.dueUnix - now2) / TICKS_PER_DAY);
 | |
|             if (nDays > maxDaysToRender) {
 | |
|               break;
 | |
|             }
 | |
|             if (nDays === -1) {
 | |
|               folderTitle = t("YESTERDAY");
 | |
|             } else if (nDays === 0) {
 | |
|               folderTitle = t("TODAY");
 | |
|             } else if (nDays === 1) {
 | |
|               folderTitle = t("TOMORROW");
 | |
|             } else {
 | |
|               folderTitle = new Date(sNote.dueUnix).toDateString();
 | |
|             }
 | |
|             schedFolderEl = this.createRightPaneFolder(
 | |
|               deckFolderEl,
 | |
|               folderTitle,
 | |
|               !deck.activeFolders.has(folderTitle),
 | |
|               deckCollapsed,
 | |
|               deck
 | |
|             );
 | |
|             currUnix = sNote.dueUnix;
 | |
|           }
 | |
|           const fileIsOpen = activeFile && sNote.note.path === activeFile.path;
 | |
|           if (fileIsOpen) {
 | |
|             deck.activeFolders.add(deck.deckName);
 | |
|             deck.activeFolders.add(folderTitle);
 | |
|             this.changeFolderFolding(schedFolderEl);
 | |
|             this.changeFolderFolding(deckFolderEl);
 | |
|           }
 | |
|           this.createRightPaneFile(
 | |
|             schedFolderEl,
 | |
|             sNote.note.tfile,
 | |
|             fileIsOpen,
 | |
|             !deck.activeFolders.has(folderTitle),
 | |
|             deck
 | |
|           );
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     const contentEl = this.containerEl.children[1];
 | |
|     contentEl.empty();
 | |
|     contentEl.appendChild(rootEl);
 | |
|   }
 | |
|   createRightPaneFolder(parentEl, folderTitle, collapsed, hidden, deck) {
 | |
|     const folderEl = parentEl.createDiv("tree-item nav-folder");
 | |
|     const folderTitleEl = folderEl.createDiv("tree-item-self nav-folder-title");
 | |
|     const childrenEl = folderEl.createDiv(
 | |
|       "tree-item-children nav-folder-children"
 | |
|     );
 | |
|     const collapseIconEl = folderTitleEl.createDiv(
 | |
|       "tree-item-icon collapse-icon nav-folder-collapse-indicator"
 | |
|     );
 | |
|     collapseIconEl.innerHTML = COLLAPSE_ICON;
 | |
|     this.changeFolderFolding(folderEl, collapsed);
 | |
|     folderTitleEl.createDiv("tree-item-inner nav-folder-title-content").setText(folderTitle);
 | |
|     if (hidden) {
 | |
|       folderEl.style.display = "none";
 | |
|     }
 | |
|     folderTitleEl.onClickEvent(() => {
 | |
|       this.changeFolderFolding(folderEl, !folderEl.hasClass("is-collapsed"));
 | |
|       childrenEl.style.display = !folderEl.hasClass("is-collapsed") ? "block" : "none";
 | |
|       if (!folderEl.hasClass("is-collapsed")) {
 | |
|         deck.activeFolders.delete(folderTitle);
 | |
|       } else {
 | |
|         deck.activeFolders.add(folderTitle);
 | |
|       }
 | |
|     });
 | |
|     return folderEl;
 | |
|   }
 | |
|   createRightPaneFile(folderEl, file, fileElActive, hidden, deck) {
 | |
|     const childrenEl = folderEl.getElementsByClassName(
 | |
|       "tree-item-children nav-folder-children"
 | |
|     )[0];
 | |
|     const navFileEl = childrenEl.createDiv("nav-file");
 | |
|     if (hidden) {
 | |
|       childrenEl.style.display = "none";
 | |
|     }
 | |
|     const navFileTitle = navFileEl.createDiv("tree-item-self nav-file-title");
 | |
|     if (fileElActive) {
 | |
|       navFileTitle.addClass("is-active");
 | |
|     }
 | |
|     navFileTitle.createDiv("tree-item-inner nav-file-title-content").setText(file.basename);
 | |
|     navFileTitle.addEventListener(
 | |
|       "click",
 | |
|       async (event) => {
 | |
|         event.preventDefault();
 | |
|         await this.nextNoteReviewHandler.openNote(deck.deckName, file);
 | |
|         return false;
 | |
|       },
 | |
|       false
 | |
|     );
 | |
|     navFileTitle.addEventListener(
 | |
|       "contextmenu",
 | |
|       (event) => {
 | |
|         event.preventDefault();
 | |
|         const fileMenu = new import_obsidian4.Menu();
 | |
|         this.app.workspace.trigger("file-menu", fileMenu, file, "my-context-menu", null);
 | |
|         fileMenu.showAtPosition({
 | |
|           x: event.pageX,
 | |
|           y: event.pageY
 | |
|         });
 | |
|         return false;
 | |
|       },
 | |
|       false
 | |
|     );
 | |
|   }
 | |
|   changeFolderFolding(folderEl, collapsed = false) {
 | |
|     if (collapsed) {
 | |
|       folderEl.addClass("is-collapsed");
 | |
|       const collapseIconEl = folderEl.find("div.nav-folder-collapse-indicator");
 | |
|       collapseIconEl.addClass("is-collapsed");
 | |
|     } else {
 | |
|       folderEl.removeClass("is-collapsed");
 | |
|       const collapseIconEl = folderEl.find("div.nav-folder-collapse-indicator");
 | |
|       collapseIconEl.removeClass("is-collapsed");
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/settings.tsx
 | |
| var import_obsidian6 = require("obsidian");
 | |
| 
 | |
| // node_modules/.pnpm/@kurkle+color@0.3.4/node_modules/@kurkle/color/dist/color.esm.js
 | |
| function round(v2) {
 | |
|   return v2 + 0.5 | 0;
 | |
| }
 | |
| var lim = (v2, l2, h6) => Math.max(Math.min(v2, h6), l2);
 | |
| function p2b(v2) {
 | |
|   return lim(round(v2 * 2.55), 0, 255);
 | |
| }
 | |
| function n2b(v2) {
 | |
|   return lim(round(v2 * 255), 0, 255);
 | |
| }
 | |
| function b2n(v2) {
 | |
|   return lim(round(v2 / 2.55) / 100, 0, 1);
 | |
| }
 | |
| function n2p(v2) {
 | |
|   return lim(round(v2 * 100), 0, 100);
 | |
| }
 | |
| var map$1 = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15 };
 | |
| var hex = [..."0123456789ABCDEF"];
 | |
| var h1 = (b2) => hex[b2 & 15];
 | |
| var h2 = (b2) => hex[(b2 & 240) >> 4] + hex[b2 & 15];
 | |
| var eq = (b2) => (b2 & 240) >> 4 === (b2 & 15);
 | |
| var isShort = (v2) => eq(v2.r) && eq(v2.g) && eq(v2.b) && eq(v2.a);
 | |
| function hexParse(str) {
 | |
|   var len = str.length;
 | |
|   var ret;
 | |
|   if (str[0] === "#") {
 | |
|     if (len === 4 || len === 5) {
 | |
|       ret = {
 | |
|         r: 255 & map$1[str[1]] * 17,
 | |
|         g: 255 & map$1[str[2]] * 17,
 | |
|         b: 255 & map$1[str[3]] * 17,
 | |
|         a: len === 5 ? map$1[str[4]] * 17 : 255
 | |
|       };
 | |
|     } else if (len === 7 || len === 9) {
 | |
|       ret = {
 | |
|         r: map$1[str[1]] << 4 | map$1[str[2]],
 | |
|         g: map$1[str[3]] << 4 | map$1[str[4]],
 | |
|         b: map$1[str[5]] << 4 | map$1[str[6]],
 | |
|         a: len === 9 ? map$1[str[7]] << 4 | map$1[str[8]] : 255
 | |
|       };
 | |
|     }
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| var alpha = (a2, f2) => a2 < 255 ? f2(a2) : "";
 | |
| function hexString(v2) {
 | |
|   var f2 = isShort(v2) ? h1 : h2;
 | |
|   return v2 ? "#" + f2(v2.r) + f2(v2.g) + f2(v2.b) + alpha(v2.a, f2) : void 0;
 | |
| }
 | |
| var HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;
 | |
| function hsl2rgbn(h6, s2, l2) {
 | |
|   const a2 = s2 * Math.min(l2, 1 - l2);
 | |
|   const f2 = (n2, k = (n2 + h6 / 30) % 12) => l2 - a2 * Math.max(Math.min(k - 3, 9 - k, 1), -1);
 | |
|   return [f2(0), f2(8), f2(4)];
 | |
| }
 | |
| function hsv2rgbn(h6, s2, v2) {
 | |
|   const f2 = (n2, k = (n2 + h6 / 60) % 6) => v2 - v2 * s2 * Math.max(Math.min(k, 4 - k, 1), 0);
 | |
|   return [f2(5), f2(3), f2(1)];
 | |
| }
 | |
| function hwb2rgbn(h6, w2, b2) {
 | |
|   const rgb = hsl2rgbn(h6, 1, 0.5);
 | |
|   let i2;
 | |
|   if (w2 + b2 > 1) {
 | |
|     i2 = 1 / (w2 + b2);
 | |
|     w2 *= i2;
 | |
|     b2 *= i2;
 | |
|   }
 | |
|   for (i2 = 0; i2 < 3; i2++) {
 | |
|     rgb[i2] *= 1 - w2 - b2;
 | |
|     rgb[i2] += w2;
 | |
|   }
 | |
|   return rgb;
 | |
| }
 | |
| function hueValue(r2, g2, b2, d2, max) {
 | |
|   if (r2 === max) {
 | |
|     return (g2 - b2) / d2 + (g2 < b2 ? 6 : 0);
 | |
|   }
 | |
|   if (g2 === max) {
 | |
|     return (b2 - r2) / d2 + 2;
 | |
|   }
 | |
|   return (r2 - g2) / d2 + 4;
 | |
| }
 | |
| function rgb2hsl(v2) {
 | |
|   const range = 255;
 | |
|   const r2 = v2.r / range;
 | |
|   const g2 = v2.g / range;
 | |
|   const b2 = v2.b / range;
 | |
|   const max = Math.max(r2, g2, b2);
 | |
|   const min = Math.min(r2, g2, b2);
 | |
|   const l2 = (max + min) / 2;
 | |
|   let h6, s2, d2;
 | |
|   if (max !== min) {
 | |
|     d2 = max - min;
 | |
|     s2 = l2 > 0.5 ? d2 / (2 - max - min) : d2 / (max + min);
 | |
|     h6 = hueValue(r2, g2, b2, d2, max);
 | |
|     h6 = h6 * 60 + 0.5;
 | |
|   }
 | |
|   return [h6 | 0, s2 || 0, l2];
 | |
| }
 | |
| function calln(f2, a2, b2, c2) {
 | |
|   return (Array.isArray(a2) ? f2(a2[0], a2[1], a2[2]) : f2(a2, b2, c2)).map(n2b);
 | |
| }
 | |
| function hsl2rgb(h6, s2, l2) {
 | |
|   return calln(hsl2rgbn, h6, s2, l2);
 | |
| }
 | |
| function hwb2rgb(h6, w2, b2) {
 | |
|   return calln(hwb2rgbn, h6, w2, b2);
 | |
| }
 | |
| function hsv2rgb(h6, s2, v2) {
 | |
|   return calln(hsv2rgbn, h6, s2, v2);
 | |
| }
 | |
| function hue(h6) {
 | |
|   return (h6 % 360 + 360) % 360;
 | |
| }
 | |
| function hueParse(str) {
 | |
|   const m2 = HUE_RE.exec(str);
 | |
|   let a2 = 255;
 | |
|   let v2;
 | |
|   if (!m2) {
 | |
|     return;
 | |
|   }
 | |
|   if (m2[5] !== v2) {
 | |
|     a2 = m2[6] ? p2b(+m2[5]) : n2b(+m2[5]);
 | |
|   }
 | |
|   const h6 = hue(+m2[2]);
 | |
|   const p1 = +m2[3] / 100;
 | |
|   const p2 = +m2[4] / 100;
 | |
|   if (m2[1] === "hwb") {
 | |
|     v2 = hwb2rgb(h6, p1, p2);
 | |
|   } else if (m2[1] === "hsv") {
 | |
|     v2 = hsv2rgb(h6, p1, p2);
 | |
|   } else {
 | |
|     v2 = hsl2rgb(h6, p1, p2);
 | |
|   }
 | |
|   return {
 | |
|     r: v2[0],
 | |
|     g: v2[1],
 | |
|     b: v2[2],
 | |
|     a: a2
 | |
|   };
 | |
| }
 | |
| function rotate(v2, deg) {
 | |
|   var h6 = rgb2hsl(v2);
 | |
|   h6[0] = hue(h6[0] + deg);
 | |
|   h6 = hsl2rgb(h6);
 | |
|   v2.r = h6[0];
 | |
|   v2.g = h6[1];
 | |
|   v2.b = h6[2];
 | |
| }
 | |
| function hslString(v2) {
 | |
|   if (!v2) {
 | |
|     return;
 | |
|   }
 | |
|   const a2 = rgb2hsl(v2);
 | |
|   const h6 = a2[0];
 | |
|   const s2 = n2p(a2[1]);
 | |
|   const l2 = n2p(a2[2]);
 | |
|   return v2.a < 255 ? `hsla(${h6}, ${s2}%, ${l2}%, ${b2n(v2.a)})` : `hsl(${h6}, ${s2}%, ${l2}%)`;
 | |
| }
 | |
| var map = {
 | |
|   x: "dark",
 | |
|   Z: "light",
 | |
|   Y: "re",
 | |
|   X: "blu",
 | |
|   W: "gr",
 | |
|   V: "medium",
 | |
|   U: "slate",
 | |
|   A: "ee",
 | |
|   T: "ol",
 | |
|   S: "or",
 | |
|   B: "ra",
 | |
|   C: "lateg",
 | |
|   D: "ights",
 | |
|   R: "in",
 | |
|   Q: "turquois",
 | |
|   E: "hi",
 | |
|   P: "ro",
 | |
|   O: "al",
 | |
|   N: "le",
 | |
|   M: "de",
 | |
|   L: "yello",
 | |
|   F: "en",
 | |
|   K: "ch",
 | |
|   G: "arks",
 | |
|   H: "ea",
 | |
|   I: "ightg",
 | |
|   J: "wh"
 | |
| };
 | |
| var names$1 = {
 | |
|   OiceXe: "f0f8ff",
 | |
|   antiquewEte: "faebd7",
 | |
|   aqua: "ffff",
 | |
|   aquamarRe: "7fffd4",
 | |
|   azuY: "f0ffff",
 | |
|   beige: "f5f5dc",
 | |
|   bisque: "ffe4c4",
 | |
|   black: "0",
 | |
|   blanKedOmond: "ffebcd",
 | |
|   Xe: "ff",
 | |
|   XeviTet: "8a2be2",
 | |
|   bPwn: "a52a2a",
 | |
|   burlywood: "deb887",
 | |
|   caMtXe: "5f9ea0",
 | |
|   KartYuse: "7fff00",
 | |
|   KocTate: "d2691e",
 | |
|   cSO: "ff7f50",
 | |
|   cSnflowerXe: "6495ed",
 | |
|   cSnsilk: "fff8dc",
 | |
|   crimson: "dc143c",
 | |
|   cyan: "ffff",
 | |
|   xXe: "8b",
 | |
|   xcyan: "8b8b",
 | |
|   xgTMnPd: "b8860b",
 | |
|   xWay: "a9a9a9",
 | |
|   xgYF: "6400",
 | |
|   xgYy: "a9a9a9",
 | |
|   xkhaki: "bdb76b",
 | |
|   xmagFta: "8b008b",
 | |
|   xTivegYF: "556b2f",
 | |
|   xSange: "ff8c00",
 | |
|   xScEd: "9932cc",
 | |
|   xYd: "8b0000",
 | |
|   xsOmon: "e9967a",
 | |
|   xsHgYF: "8fbc8f",
 | |
|   xUXe: "483d8b",
 | |
|   xUWay: "2f4f4f",
 | |
|   xUgYy: "2f4f4f",
 | |
|   xQe: "ced1",
 | |
|   xviTet: "9400d3",
 | |
|   dAppRk: "ff1493",
 | |
|   dApskyXe: "bfff",
 | |
|   dimWay: "696969",
 | |
|   dimgYy: "696969",
 | |
|   dodgerXe: "1e90ff",
 | |
|   fiYbrick: "b22222",
 | |
|   flSOwEte: "fffaf0",
 | |
|   foYstWAn: "228b22",
 | |
|   fuKsia: "ff00ff",
 | |
|   gaRsbSo: "dcdcdc",
 | |
|   ghostwEte: "f8f8ff",
 | |
|   gTd: "ffd700",
 | |
|   gTMnPd: "daa520",
 | |
|   Way: "808080",
 | |
|   gYF: "8000",
 | |
|   gYFLw: "adff2f",
 | |
|   gYy: "808080",
 | |
|   honeyMw: "f0fff0",
 | |
|   hotpRk: "ff69b4",
 | |
|   RdianYd: "cd5c5c",
 | |
|   Rdigo: "4b0082",
 | |
|   ivSy: "fffff0",
 | |
|   khaki: "f0e68c",
 | |
|   lavFMr: "e6e6fa",
 | |
|   lavFMrXsh: "fff0f5",
 | |
|   lawngYF: "7cfc00",
 | |
|   NmoncEffon: "fffacd",
 | |
|   ZXe: "add8e6",
 | |
|   ZcSO: "f08080",
 | |
|   Zcyan: "e0ffff",
 | |
|   ZgTMnPdLw: "fafad2",
 | |
|   ZWay: "d3d3d3",
 | |
|   ZgYF: "90ee90",
 | |
|   ZgYy: "d3d3d3",
 | |
|   ZpRk: "ffb6c1",
 | |
|   ZsOmon: "ffa07a",
 | |
|   ZsHgYF: "20b2aa",
 | |
|   ZskyXe: "87cefa",
 | |
|   ZUWay: "778899",
 | |
|   ZUgYy: "778899",
 | |
|   ZstAlXe: "b0c4de",
 | |
|   ZLw: "ffffe0",
 | |
|   lime: "ff00",
 | |
|   limegYF: "32cd32",
 | |
|   lRF: "faf0e6",
 | |
|   magFta: "ff00ff",
 | |
|   maPon: "800000",
 | |
|   VaquamarRe: "66cdaa",
 | |
|   VXe: "cd",
 | |
|   VScEd: "ba55d3",
 | |
|   VpurpN: "9370db",
 | |
|   VsHgYF: "3cb371",
 | |
|   VUXe: "7b68ee",
 | |
|   VsprRggYF: "fa9a",
 | |
|   VQe: "48d1cc",
 | |
|   VviTetYd: "c71585",
 | |
|   midnightXe: "191970",
 | |
|   mRtcYam: "f5fffa",
 | |
|   mistyPse: "ffe4e1",
 | |
|   moccasR: "ffe4b5",
 | |
|   navajowEte: "ffdead",
 | |
|   navy: "80",
 | |
|   Tdlace: "fdf5e6",
 | |
|   Tive: "808000",
 | |
|   TivedBb: "6b8e23",
 | |
|   Sange: "ffa500",
 | |
|   SangeYd: "ff4500",
 | |
|   ScEd: "da70d6",
 | |
|   pOegTMnPd: "eee8aa",
 | |
|   pOegYF: "98fb98",
 | |
|   pOeQe: "afeeee",
 | |
|   pOeviTetYd: "db7093",
 | |
|   papayawEp: "ffefd5",
 | |
|   pHKpuff: "ffdab9",
 | |
|   peru: "cd853f",
 | |
|   pRk: "ffc0cb",
 | |
|   plum: "dda0dd",
 | |
|   powMrXe: "b0e0e6",
 | |
|   purpN: "800080",
 | |
|   YbeccapurpN: "663399",
 | |
|   Yd: "ff0000",
 | |
|   Psybrown: "bc8f8f",
 | |
|   PyOXe: "4169e1",
 | |
|   saddNbPwn: "8b4513",
 | |
|   sOmon: "fa8072",
 | |
|   sandybPwn: "f4a460",
 | |
|   sHgYF: "2e8b57",
 | |
|   sHshell: "fff5ee",
 | |
|   siFna: "a0522d",
 | |
|   silver: "c0c0c0",
 | |
|   skyXe: "87ceeb",
 | |
|   UXe: "6a5acd",
 | |
|   UWay: "708090",
 | |
|   UgYy: "708090",
 | |
|   snow: "fffafa",
 | |
|   sprRggYF: "ff7f",
 | |
|   stAlXe: "4682b4",
 | |
|   tan: "d2b48c",
 | |
|   teO: "8080",
 | |
|   tEstN: "d8bfd8",
 | |
|   tomato: "ff6347",
 | |
|   Qe: "40e0d0",
 | |
|   viTet: "ee82ee",
 | |
|   JHt: "f5deb3",
 | |
|   wEte: "ffffff",
 | |
|   wEtesmoke: "f5f5f5",
 | |
|   Lw: "ffff00",
 | |
|   LwgYF: "9acd32"
 | |
| };
 | |
| function unpack() {
 | |
|   const unpacked = {};
 | |
|   const keys = Object.keys(names$1);
 | |
|   const tkeys = Object.keys(map);
 | |
|   let i2, j2, k, ok, nk;
 | |
|   for (i2 = 0; i2 < keys.length; i2++) {
 | |
|     ok = nk = keys[i2];
 | |
|     for (j2 = 0; j2 < tkeys.length; j2++) {
 | |
|       k = tkeys[j2];
 | |
|       nk = nk.replace(k, map[k]);
 | |
|     }
 | |
|     k = parseInt(names$1[ok], 16);
 | |
|     unpacked[nk] = [k >> 16 & 255, k >> 8 & 255, k & 255];
 | |
|   }
 | |
|   return unpacked;
 | |
| }
 | |
| var names;
 | |
| function nameParse(str) {
 | |
|   if (!names) {
 | |
|     names = unpack();
 | |
|     names.transparent = [0, 0, 0, 0];
 | |
|   }
 | |
|   const a2 = names[str.toLowerCase()];
 | |
|   return a2 && {
 | |
|     r: a2[0],
 | |
|     g: a2[1],
 | |
|     b: a2[2],
 | |
|     a: a2.length === 4 ? a2[3] : 255
 | |
|   };
 | |
| }
 | |
| var RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;
 | |
| function rgbParse(str) {
 | |
|   const m2 = RGB_RE.exec(str);
 | |
|   let a2 = 255;
 | |
|   let r2, g2, b2;
 | |
|   if (!m2) {
 | |
|     return;
 | |
|   }
 | |
|   if (m2[7] !== r2) {
 | |
|     const v2 = +m2[7];
 | |
|     a2 = m2[8] ? p2b(v2) : lim(v2 * 255, 0, 255);
 | |
|   }
 | |
|   r2 = +m2[1];
 | |
|   g2 = +m2[3];
 | |
|   b2 = +m2[5];
 | |
|   r2 = 255 & (m2[2] ? p2b(r2) : lim(r2, 0, 255));
 | |
|   g2 = 255 & (m2[4] ? p2b(g2) : lim(g2, 0, 255));
 | |
|   b2 = 255 & (m2[6] ? p2b(b2) : lim(b2, 0, 255));
 | |
|   return {
 | |
|     r: r2,
 | |
|     g: g2,
 | |
|     b: b2,
 | |
|     a: a2
 | |
|   };
 | |
| }
 | |
| function rgbString(v2) {
 | |
|   return v2 && (v2.a < 255 ? `rgba(${v2.r}, ${v2.g}, ${v2.b}, ${b2n(v2.a)})` : `rgb(${v2.r}, ${v2.g}, ${v2.b})`);
 | |
| }
 | |
| var to = (v2) => v2 <= 31308e-7 ? v2 * 12.92 : Math.pow(v2, 1 / 2.4) * 1.055 - 0.055;
 | |
| var from = (v2) => v2 <= 0.04045 ? v2 / 12.92 : Math.pow((v2 + 0.055) / 1.055, 2.4);
 | |
| function interpolate2(rgb1, rgb2, t3) {
 | |
|   const r2 = from(b2n(rgb1.r));
 | |
|   const g2 = from(b2n(rgb1.g));
 | |
|   const b2 = from(b2n(rgb1.b));
 | |
|   return {
 | |
|     r: n2b(to(r2 + t3 * (from(b2n(rgb2.r)) - r2))),
 | |
|     g: n2b(to(g2 + t3 * (from(b2n(rgb2.g)) - g2))),
 | |
|     b: n2b(to(b2 + t3 * (from(b2n(rgb2.b)) - b2))),
 | |
|     a: rgb1.a + t3 * (rgb2.a - rgb1.a)
 | |
|   };
 | |
| }
 | |
| function modHSL(v2, i2, ratio) {
 | |
|   if (v2) {
 | |
|     let tmp = rgb2hsl(v2);
 | |
|     tmp[i2] = Math.max(0, Math.min(tmp[i2] + tmp[i2] * ratio, i2 === 0 ? 360 : 1));
 | |
|     tmp = hsl2rgb(tmp);
 | |
|     v2.r = tmp[0];
 | |
|     v2.g = tmp[1];
 | |
|     v2.b = tmp[2];
 | |
|   }
 | |
| }
 | |
| function clone(v2, proto) {
 | |
|   return v2 ? Object.assign(proto || {}, v2) : v2;
 | |
| }
 | |
| function fromObject(input) {
 | |
|   var v2 = { r: 0, g: 0, b: 0, a: 255 };
 | |
|   if (Array.isArray(input)) {
 | |
|     if (input.length >= 3) {
 | |
|       v2 = { r: input[0], g: input[1], b: input[2], a: 255 };
 | |
|       if (input.length > 3) {
 | |
|         v2.a = n2b(input[3]);
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     v2 = clone(input, { r: 0, g: 0, b: 0, a: 1 });
 | |
|     v2.a = n2b(v2.a);
 | |
|   }
 | |
|   return v2;
 | |
| }
 | |
| function functionParse(str) {
 | |
|   if (str.charAt(0) === "r") {
 | |
|     return rgbParse(str);
 | |
|   }
 | |
|   return hueParse(str);
 | |
| }
 | |
| var Color = class _Color {
 | |
|   constructor(input) {
 | |
|     if (input instanceof _Color) {
 | |
|       return input;
 | |
|     }
 | |
|     const type = typeof input;
 | |
|     let v2;
 | |
|     if (type === "object") {
 | |
|       v2 = fromObject(input);
 | |
|     } else if (type === "string") {
 | |
|       v2 = hexParse(input) || nameParse(input) || functionParse(input);
 | |
|     }
 | |
|     this._rgb = v2;
 | |
|     this._valid = !!v2;
 | |
|   }
 | |
|   get valid() {
 | |
|     return this._valid;
 | |
|   }
 | |
|   get rgb() {
 | |
|     var v2 = clone(this._rgb);
 | |
|     if (v2) {
 | |
|       v2.a = b2n(v2.a);
 | |
|     }
 | |
|     return v2;
 | |
|   }
 | |
|   set rgb(obj) {
 | |
|     this._rgb = fromObject(obj);
 | |
|   }
 | |
|   rgbString() {
 | |
|     return this._valid ? rgbString(this._rgb) : void 0;
 | |
|   }
 | |
|   hexString() {
 | |
|     return this._valid ? hexString(this._rgb) : void 0;
 | |
|   }
 | |
|   hslString() {
 | |
|     return this._valid ? hslString(this._rgb) : void 0;
 | |
|   }
 | |
|   mix(color2, weight) {
 | |
|     if (color2) {
 | |
|       const c1 = this.rgb;
 | |
|       const c2 = color2.rgb;
 | |
|       let w2;
 | |
|       const p2 = weight === w2 ? 0.5 : weight;
 | |
|       const w3 = 2 * p2 - 1;
 | |
|       const a2 = c1.a - c2.a;
 | |
|       const w1 = ((w3 * a2 === -1 ? w3 : (w3 + a2) / (1 + w3 * a2)) + 1) / 2;
 | |
|       w2 = 1 - w1;
 | |
|       c1.r = 255 & w1 * c1.r + w2 * c2.r + 0.5;
 | |
|       c1.g = 255 & w1 * c1.g + w2 * c2.g + 0.5;
 | |
|       c1.b = 255 & w1 * c1.b + w2 * c2.b + 0.5;
 | |
|       c1.a = p2 * c1.a + (1 - p2) * c2.a;
 | |
|       this.rgb = c1;
 | |
|     }
 | |
|     return this;
 | |
|   }
 | |
|   interpolate(color2, t3) {
 | |
|     if (color2) {
 | |
|       this._rgb = interpolate2(this._rgb, color2._rgb, t3);
 | |
|     }
 | |
|     return this;
 | |
|   }
 | |
|   clone() {
 | |
|     return new _Color(this.rgb);
 | |
|   }
 | |
|   alpha(a2) {
 | |
|     this._rgb.a = n2b(a2);
 | |
|     return this;
 | |
|   }
 | |
|   clearer(ratio) {
 | |
|     const rgb = this._rgb;
 | |
|     rgb.a *= 1 - ratio;
 | |
|     return this;
 | |
|   }
 | |
|   greyscale() {
 | |
|     const rgb = this._rgb;
 | |
|     const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11);
 | |
|     rgb.r = rgb.g = rgb.b = val;
 | |
|     return this;
 | |
|   }
 | |
|   opaquer(ratio) {
 | |
|     const rgb = this._rgb;
 | |
|     rgb.a *= 1 + ratio;
 | |
|     return this;
 | |
|   }
 | |
|   negate() {
 | |
|     const v2 = this._rgb;
 | |
|     v2.r = 255 - v2.r;
 | |
|     v2.g = 255 - v2.g;
 | |
|     v2.b = 255 - v2.b;
 | |
|     return this;
 | |
|   }
 | |
|   lighten(ratio) {
 | |
|     modHSL(this._rgb, 2, ratio);
 | |
|     return this;
 | |
|   }
 | |
|   darken(ratio) {
 | |
|     modHSL(this._rgb, 2, -ratio);
 | |
|     return this;
 | |
|   }
 | |
|   saturate(ratio) {
 | |
|     modHSL(this._rgb, 1, ratio);
 | |
|     return this;
 | |
|   }
 | |
|   desaturate(ratio) {
 | |
|     modHSL(this._rgb, 1, -ratio);
 | |
|     return this;
 | |
|   }
 | |
|   rotate(deg) {
 | |
|     rotate(this._rgb, deg);
 | |
|     return this;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // node_modules/.pnpm/chart.js@4.4.8/node_modules/chart.js/dist/chunks/helpers.segment.js
 | |
| function noop() {
 | |
| }
 | |
| var uid = /* @__PURE__ */ (() => {
 | |
|   let id = 0;
 | |
|   return () => id++;
 | |
| })();
 | |
| function isNullOrUndef(value) {
 | |
|   return value === null || value === void 0;
 | |
| }
 | |
| function isArray(value) {
 | |
|   if (Array.isArray && Array.isArray(value)) {
 | |
|     return true;
 | |
|   }
 | |
|   const type = Object.prototype.toString.call(value);
 | |
|   if (type.slice(0, 7) === "[object" && type.slice(-6) === "Array]") {
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| function isObject(value) {
 | |
|   return value !== null && Object.prototype.toString.call(value) === "[object Object]";
 | |
| }
 | |
| function isNumberFinite(value) {
 | |
|   return (typeof value === "number" || value instanceof Number) && isFinite(+value);
 | |
| }
 | |
| function finiteOrDefault(value, defaultValue) {
 | |
|   return isNumberFinite(value) ? value : defaultValue;
 | |
| }
 | |
| function valueOrDefault(value, defaultValue) {
 | |
|   return typeof value === "undefined" ? defaultValue : value;
 | |
| }
 | |
| var toPercentage = (value, dimension) => typeof value === "string" && value.endsWith("%") ? parseFloat(value) / 100 : +value / dimension;
 | |
| var toDimension = (value, dimension) => typeof value === "string" && value.endsWith("%") ? parseFloat(value) / 100 * dimension : +value;
 | |
| function callback(fn2, args, thisArg) {
 | |
|   if (fn2 && typeof fn2.call === "function") {
 | |
|     return fn2.apply(thisArg, args);
 | |
|   }
 | |
| }
 | |
| function each(loopable, fn2, thisArg, reverse) {
 | |
|   let i2, len, keys;
 | |
|   if (isArray(loopable)) {
 | |
|     len = loopable.length;
 | |
|     if (reverse) {
 | |
|       for (i2 = len - 1; i2 >= 0; i2--) {
 | |
|         fn2.call(thisArg, loopable[i2], i2);
 | |
|       }
 | |
|     } else {
 | |
|       for (i2 = 0; i2 < len; i2++) {
 | |
|         fn2.call(thisArg, loopable[i2], i2);
 | |
|       }
 | |
|     }
 | |
|   } else if (isObject(loopable)) {
 | |
|     keys = Object.keys(loopable);
 | |
|     len = keys.length;
 | |
|     for (i2 = 0; i2 < len; i2++) {
 | |
|       fn2.call(thisArg, loopable[keys[i2]], keys[i2]);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function _elementsEqual(a0, a1) {
 | |
|   let i2, ilen, v0, v1;
 | |
|   if (!a0 || !a1 || a0.length !== a1.length) {
 | |
|     return false;
 | |
|   }
 | |
|   for (i2 = 0, ilen = a0.length; i2 < ilen; ++i2) {
 | |
|     v0 = a0[i2];
 | |
|     v1 = a1[i2];
 | |
|     if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function clone2(source) {
 | |
|   if (isArray(source)) {
 | |
|     return source.map(clone2);
 | |
|   }
 | |
|   if (isObject(source)) {
 | |
|     const target = /* @__PURE__ */ Object.create(null);
 | |
|     const keys = Object.keys(source);
 | |
|     const klen = keys.length;
 | |
|     let k = 0;
 | |
|     for (; k < klen; ++k) {
 | |
|       target[keys[k]] = clone2(source[keys[k]]);
 | |
|     }
 | |
|     return target;
 | |
|   }
 | |
|   return source;
 | |
| }
 | |
| function isValidKey(key) {
 | |
|   return [
 | |
|     "__proto__",
 | |
|     "prototype",
 | |
|     "constructor"
 | |
|   ].indexOf(key) === -1;
 | |
| }
 | |
| function _merger(key, target, source, options) {
 | |
|   if (!isValidKey(key)) {
 | |
|     return;
 | |
|   }
 | |
|   const tval = target[key];
 | |
|   const sval = source[key];
 | |
|   if (isObject(tval) && isObject(sval)) {
 | |
|     merge(tval, sval, options);
 | |
|   } else {
 | |
|     target[key] = clone2(sval);
 | |
|   }
 | |
| }
 | |
| function merge(target, source, options) {
 | |
|   const sources = isArray(source) ? source : [
 | |
|     source
 | |
|   ];
 | |
|   const ilen = sources.length;
 | |
|   if (!isObject(target)) {
 | |
|     return target;
 | |
|   }
 | |
|   options = options || {};
 | |
|   const merger = options.merger || _merger;
 | |
|   let current;
 | |
|   for (let i2 = 0; i2 < ilen; ++i2) {
 | |
|     current = sources[i2];
 | |
|     if (!isObject(current)) {
 | |
|       continue;
 | |
|     }
 | |
|     const keys = Object.keys(current);
 | |
|     for (let k = 0, klen = keys.length; k < klen; ++k) {
 | |
|       merger(keys[k], target, current, options);
 | |
|     }
 | |
|   }
 | |
|   return target;
 | |
| }
 | |
| function mergeIf(target, source) {
 | |
|   return merge(target, source, {
 | |
|     merger: _mergerIf
 | |
|   });
 | |
| }
 | |
| function _mergerIf(key, target, source) {
 | |
|   if (!isValidKey(key)) {
 | |
|     return;
 | |
|   }
 | |
|   const tval = target[key];
 | |
|   const sval = source[key];
 | |
|   if (isObject(tval) && isObject(sval)) {
 | |
|     mergeIf(tval, sval);
 | |
|   } else if (!Object.prototype.hasOwnProperty.call(target, key)) {
 | |
|     target[key] = clone2(sval);
 | |
|   }
 | |
| }
 | |
| var keyResolvers = {
 | |
|   // Chart.helpers.core resolveObjectKey should resolve empty key to root object
 | |
|   "": (v2) => v2,
 | |
|   // default resolvers
 | |
|   x: (o2) => o2.x,
 | |
|   y: (o2) => o2.y
 | |
| };
 | |
| function _splitKey(key) {
 | |
|   const parts = key.split(".");
 | |
|   const keys = [];
 | |
|   let tmp = "";
 | |
|   for (const part of parts) {
 | |
|     tmp += part;
 | |
|     if (tmp.endsWith("\\")) {
 | |
|       tmp = tmp.slice(0, -1) + ".";
 | |
|     } else {
 | |
|       keys.push(tmp);
 | |
|       tmp = "";
 | |
|     }
 | |
|   }
 | |
|   return keys;
 | |
| }
 | |
| function _getKeyResolver(key) {
 | |
|   const keys = _splitKey(key);
 | |
|   return (obj) => {
 | |
|     for (const k of keys) {
 | |
|       if (k === "") {
 | |
|         break;
 | |
|       }
 | |
|       obj = obj && obj[k];
 | |
|     }
 | |
|     return obj;
 | |
|   };
 | |
| }
 | |
| function resolveObjectKey(obj, key) {
 | |
|   const resolver = keyResolvers[key] || (keyResolvers[key] = _getKeyResolver(key));
 | |
|   return resolver(obj);
 | |
| }
 | |
| function _capitalize(str) {
 | |
|   return str.charAt(0).toUpperCase() + str.slice(1);
 | |
| }
 | |
| var defined = (value) => typeof value !== "undefined";
 | |
| var isFunction = (value) => typeof value === "function";
 | |
| var setsEqual = (a2, b2) => {
 | |
|   if (a2.size !== b2.size) {
 | |
|     return false;
 | |
|   }
 | |
|   for (const item of a2) {
 | |
|     if (!b2.has(item)) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| };
 | |
| function _isClickEvent(e2) {
 | |
|   return e2.type === "mouseup" || e2.type === "click" || e2.type === "contextmenu";
 | |
| }
 | |
| var PI = Math.PI;
 | |
| var TAU = 2 * PI;
 | |
| var PITAU = TAU + PI;
 | |
| var INFINITY = Number.POSITIVE_INFINITY;
 | |
| var RAD_PER_DEG = PI / 180;
 | |
| var HALF_PI = PI / 2;
 | |
| var QUARTER_PI = PI / 4;
 | |
| var TWO_THIRDS_PI = PI * 2 / 3;
 | |
| var log10 = Math.log10;
 | |
| var sign = Math.sign;
 | |
| function almostEquals(x2, y2, epsilon) {
 | |
|   return Math.abs(x2 - y2) < epsilon;
 | |
| }
 | |
| function niceNum(range) {
 | |
|   const roundedRange = Math.round(range);
 | |
|   range = almostEquals(range, roundedRange, range / 1e3) ? roundedRange : range;
 | |
|   const niceRange = Math.pow(10, Math.floor(log10(range)));
 | |
|   const fraction = range / niceRange;
 | |
|   const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;
 | |
|   return niceFraction * niceRange;
 | |
| }
 | |
| function _factorize(value) {
 | |
|   const result = [];
 | |
|   const sqrt = Math.sqrt(value);
 | |
|   let i2;
 | |
|   for (i2 = 1; i2 < sqrt; i2++) {
 | |
|     if (value % i2 === 0) {
 | |
|       result.push(i2);
 | |
|       result.push(value / i2);
 | |
|     }
 | |
|   }
 | |
|   if (sqrt === (sqrt | 0)) {
 | |
|     result.push(sqrt);
 | |
|   }
 | |
|   result.sort((a2, b2) => a2 - b2).pop();
 | |
|   return result;
 | |
| }
 | |
| function isNonPrimitive(n2) {
 | |
|   return typeof n2 === "symbol" || typeof n2 === "object" && n2 !== null && !(Symbol.toPrimitive in n2 || "toString" in n2 || "valueOf" in n2);
 | |
| }
 | |
| function isNumber(n2) {
 | |
|   return !isNonPrimitive(n2) && !isNaN(parseFloat(n2)) && isFinite(n2);
 | |
| }
 | |
| function almostWhole(x2, epsilon) {
 | |
|   const rounded = Math.round(x2);
 | |
|   return rounded - epsilon <= x2 && rounded + epsilon >= x2;
 | |
| }
 | |
| function _setMinAndMaxByKey(array, target, property) {
 | |
|   let i2, ilen, value;
 | |
|   for (i2 = 0, ilen = array.length; i2 < ilen; i2++) {
 | |
|     value = array[i2][property];
 | |
|     if (!isNaN(value)) {
 | |
|       target.min = Math.min(target.min, value);
 | |
|       target.max = Math.max(target.max, value);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function toRadians(degrees) {
 | |
|   return degrees * (PI / 180);
 | |
| }
 | |
| function toDegrees(radians) {
 | |
|   return radians * (180 / PI);
 | |
| }
 | |
| function _decimalPlaces(x2) {
 | |
|   if (!isNumberFinite(x2)) {
 | |
|     return;
 | |
|   }
 | |
|   let e2 = 1;
 | |
|   let p2 = 0;
 | |
|   while (Math.round(x2 * e2) / e2 !== x2) {
 | |
|     e2 *= 10;
 | |
|     p2++;
 | |
|   }
 | |
|   return p2;
 | |
| }
 | |
| function getAngleFromPoint(centrePoint, anglePoint) {
 | |
|   const distanceFromXCenter = anglePoint.x - centrePoint.x;
 | |
|   const distanceFromYCenter = anglePoint.y - centrePoint.y;
 | |
|   const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
 | |
|   let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
 | |
|   if (angle < -0.5 * PI) {
 | |
|     angle += TAU;
 | |
|   }
 | |
|   return {
 | |
|     angle,
 | |
|     distance: radialDistanceFromCenter
 | |
|   };
 | |
| }
 | |
| function distanceBetweenPoints(pt1, pt2) {
 | |
|   return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
 | |
| }
 | |
| function _normalizeAngle(a2) {
 | |
|   return (a2 % TAU + TAU) % TAU;
 | |
| }
 | |
| function _angleBetween(angle, start, end, sameAngleIsFullCircle) {
 | |
|   const a2 = _normalizeAngle(angle);
 | |
|   const s2 = _normalizeAngle(start);
 | |
|   const e2 = _normalizeAngle(end);
 | |
|   const angleToStart = _normalizeAngle(s2 - a2);
 | |
|   const angleToEnd = _normalizeAngle(e2 - a2);
 | |
|   const startToAngle = _normalizeAngle(a2 - s2);
 | |
|   const endToAngle = _normalizeAngle(a2 - e2);
 | |
|   return a2 === s2 || a2 === e2 || sameAngleIsFullCircle && s2 === e2 || angleToStart > angleToEnd && startToAngle < endToAngle;
 | |
| }
 | |
| function _limitValue(value, min, max) {
 | |
|   return Math.max(min, Math.min(max, value));
 | |
| }
 | |
| function _int16Range(value) {
 | |
|   return _limitValue(value, -32768, 32767);
 | |
| }
 | |
| function _isBetween(value, start, end, epsilon = 1e-6) {
 | |
|   return value >= Math.min(start, end) - epsilon && value <= Math.max(start, end) + epsilon;
 | |
| }
 | |
| function _lookup(table, value, cmp) {
 | |
|   cmp = cmp || ((index) => table[index] < value);
 | |
|   let hi = table.length - 1;
 | |
|   let lo = 0;
 | |
|   let mid;
 | |
|   while (hi - lo > 1) {
 | |
|     mid = lo + hi >> 1;
 | |
|     if (cmp(mid)) {
 | |
|       lo = mid;
 | |
|     } else {
 | |
|       hi = mid;
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     lo,
 | |
|     hi
 | |
|   };
 | |
| }
 | |
| var _lookupByKey = (table, key, value, last) => _lookup(table, value, last ? (index) => {
 | |
|   const ti = table[index][key];
 | |
|   return ti < value || ti === value && table[index + 1][key] === value;
 | |
| } : (index) => table[index][key] < value);
 | |
| var _rlookupByKey = (table, key, value) => _lookup(table, value, (index) => table[index][key] >= value);
 | |
| function _filterBetween(values, min, max) {
 | |
|   let start = 0;
 | |
|   let end = values.length;
 | |
|   while (start < end && values[start] < min) {
 | |
|     start++;
 | |
|   }
 | |
|   while (end > start && values[end - 1] > max) {
 | |
|     end--;
 | |
|   }
 | |
|   return start > 0 || end < values.length ? values.slice(start, end) : values;
 | |
| }
 | |
| var arrayEvents = [
 | |
|   "push",
 | |
|   "pop",
 | |
|   "shift",
 | |
|   "splice",
 | |
|   "unshift"
 | |
| ];
 | |
| function listenArrayEvents(array, listener) {
 | |
|   if (array._chartjs) {
 | |
|     array._chartjs.listeners.push(listener);
 | |
|     return;
 | |
|   }
 | |
|   Object.defineProperty(array, "_chartjs", {
 | |
|     configurable: true,
 | |
|     enumerable: false,
 | |
|     value: {
 | |
|       listeners: [
 | |
|         listener
 | |
|       ]
 | |
|     }
 | |
|   });
 | |
|   arrayEvents.forEach((key) => {
 | |
|     const method = "_onData" + _capitalize(key);
 | |
|     const base = array[key];
 | |
|     Object.defineProperty(array, key, {
 | |
|       configurable: true,
 | |
|       enumerable: false,
 | |
|       value(...args) {
 | |
|         const res = base.apply(this, args);
 | |
|         array._chartjs.listeners.forEach((object) => {
 | |
|           if (typeof object[method] === "function") {
 | |
|             object[method](...args);
 | |
|           }
 | |
|         });
 | |
|         return res;
 | |
|       }
 | |
|     });
 | |
|   });
 | |
| }
 | |
| function unlistenArrayEvents(array, listener) {
 | |
|   const stub = array._chartjs;
 | |
|   if (!stub) {
 | |
|     return;
 | |
|   }
 | |
|   const listeners = stub.listeners;
 | |
|   const index = listeners.indexOf(listener);
 | |
|   if (index !== -1) {
 | |
|     listeners.splice(index, 1);
 | |
|   }
 | |
|   if (listeners.length > 0) {
 | |
|     return;
 | |
|   }
 | |
|   arrayEvents.forEach((key) => {
 | |
|     delete array[key];
 | |
|   });
 | |
|   delete array._chartjs;
 | |
| }
 | |
| function _arrayUnique(items) {
 | |
|   const set2 = new Set(items);
 | |
|   if (set2.size === items.length) {
 | |
|     return items;
 | |
|   }
 | |
|   return Array.from(set2);
 | |
| }
 | |
| var requestAnimFrame = function() {
 | |
|   if (typeof window === "undefined") {
 | |
|     return function(callback2) {
 | |
|       return callback2();
 | |
|     };
 | |
|   }
 | |
|   return window.requestAnimationFrame;
 | |
| }();
 | |
| function throttled(fn2, thisArg) {
 | |
|   let argsToUse = [];
 | |
|   let ticking = false;
 | |
|   return function(...args) {
 | |
|     argsToUse = args;
 | |
|     if (!ticking) {
 | |
|       ticking = true;
 | |
|       requestAnimFrame.call(window, () => {
 | |
|         ticking = false;
 | |
|         fn2.apply(thisArg, argsToUse);
 | |
|       });
 | |
|     }
 | |
|   };
 | |
| }
 | |
| function debounce(fn2, delay) {
 | |
|   let timeout;
 | |
|   return function(...args) {
 | |
|     if (delay) {
 | |
|       clearTimeout(timeout);
 | |
|       timeout = setTimeout(fn2, delay, args);
 | |
|     } else {
 | |
|       fn2.apply(this, args);
 | |
|     }
 | |
|     return delay;
 | |
|   };
 | |
| }
 | |
| var _toLeftRightCenter = (align) => align === "start" ? "left" : align === "end" ? "right" : "center";
 | |
| var _alignStartEnd = (align, start, end) => align === "start" ? start : align === "end" ? end : (start + end) / 2;
 | |
| var _textX = (align, left, right, rtl) => {
 | |
|   const check = rtl ? "left" : "right";
 | |
|   return align === check ? right : align === "center" ? (left + right) / 2 : left;
 | |
| };
 | |
| var atEdge = (t3) => t3 === 0 || t3 === 1;
 | |
| var elasticIn = (t3, s2, p2) => -(Math.pow(2, 10 * (t3 -= 1)) * Math.sin((t3 - s2) * TAU / p2));
 | |
| var elasticOut = (t3, s2, p2) => Math.pow(2, -10 * t3) * Math.sin((t3 - s2) * TAU / p2) + 1;
 | |
| var effects = {
 | |
|   linear: (t3) => t3,
 | |
|   easeInQuad: (t3) => t3 * t3,
 | |
|   easeOutQuad: (t3) => -t3 * (t3 - 2),
 | |
|   easeInOutQuad: (t3) => (t3 /= 0.5) < 1 ? 0.5 * t3 * t3 : -0.5 * (--t3 * (t3 - 2) - 1),
 | |
|   easeInCubic: (t3) => t3 * t3 * t3,
 | |
|   easeOutCubic: (t3) => (t3 -= 1) * t3 * t3 + 1,
 | |
|   easeInOutCubic: (t3) => (t3 /= 0.5) < 1 ? 0.5 * t3 * t3 * t3 : 0.5 * ((t3 -= 2) * t3 * t3 + 2),
 | |
|   easeInQuart: (t3) => t3 * t3 * t3 * t3,
 | |
|   easeOutQuart: (t3) => -((t3 -= 1) * t3 * t3 * t3 - 1),
 | |
|   easeInOutQuart: (t3) => (t3 /= 0.5) < 1 ? 0.5 * t3 * t3 * t3 * t3 : -0.5 * ((t3 -= 2) * t3 * t3 * t3 - 2),
 | |
|   easeInQuint: (t3) => t3 * t3 * t3 * t3 * t3,
 | |
|   easeOutQuint: (t3) => (t3 -= 1) * t3 * t3 * t3 * t3 + 1,
 | |
|   easeInOutQuint: (t3) => (t3 /= 0.5) < 1 ? 0.5 * t3 * t3 * t3 * t3 * t3 : 0.5 * ((t3 -= 2) * t3 * t3 * t3 * t3 + 2),
 | |
|   easeInSine: (t3) => -Math.cos(t3 * HALF_PI) + 1,
 | |
|   easeOutSine: (t3) => Math.sin(t3 * HALF_PI),
 | |
|   easeInOutSine: (t3) => -0.5 * (Math.cos(PI * t3) - 1),
 | |
|   easeInExpo: (t3) => t3 === 0 ? 0 : Math.pow(2, 10 * (t3 - 1)),
 | |
|   easeOutExpo: (t3) => t3 === 1 ? 1 : -Math.pow(2, -10 * t3) + 1,
 | |
|   easeInOutExpo: (t3) => atEdge(t3) ? t3 : t3 < 0.5 ? 0.5 * Math.pow(2, 10 * (t3 * 2 - 1)) : 0.5 * (-Math.pow(2, -10 * (t3 * 2 - 1)) + 2),
 | |
|   easeInCirc: (t3) => t3 >= 1 ? t3 : -(Math.sqrt(1 - t3 * t3) - 1),
 | |
|   easeOutCirc: (t3) => Math.sqrt(1 - (t3 -= 1) * t3),
 | |
|   easeInOutCirc: (t3) => (t3 /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - t3 * t3) - 1) : 0.5 * (Math.sqrt(1 - (t3 -= 2) * t3) + 1),
 | |
|   easeInElastic: (t3) => atEdge(t3) ? t3 : elasticIn(t3, 0.075, 0.3),
 | |
|   easeOutElastic: (t3) => atEdge(t3) ? t3 : elasticOut(t3, 0.075, 0.3),
 | |
|   easeInOutElastic(t3) {
 | |
|     const s2 = 0.1125;
 | |
|     const p2 = 0.45;
 | |
|     return atEdge(t3) ? t3 : t3 < 0.5 ? 0.5 * elasticIn(t3 * 2, s2, p2) : 0.5 + 0.5 * elasticOut(t3 * 2 - 1, s2, p2);
 | |
|   },
 | |
|   easeInBack(t3) {
 | |
|     const s2 = 1.70158;
 | |
|     return t3 * t3 * ((s2 + 1) * t3 - s2);
 | |
|   },
 | |
|   easeOutBack(t3) {
 | |
|     const s2 = 1.70158;
 | |
|     return (t3 -= 1) * t3 * ((s2 + 1) * t3 + s2) + 1;
 | |
|   },
 | |
|   easeInOutBack(t3) {
 | |
|     let s2 = 1.70158;
 | |
|     if ((t3 /= 0.5) < 1) {
 | |
|       return 0.5 * (t3 * t3 * (((s2 *= 1.525) + 1) * t3 - s2));
 | |
|     }
 | |
|     return 0.5 * ((t3 -= 2) * t3 * (((s2 *= 1.525) + 1) * t3 + s2) + 2);
 | |
|   },
 | |
|   easeInBounce: (t3) => 1 - effects.easeOutBounce(1 - t3),
 | |
|   easeOutBounce(t3) {
 | |
|     const m2 = 7.5625;
 | |
|     const d2 = 2.75;
 | |
|     if (t3 < 1 / d2) {
 | |
|       return m2 * t3 * t3;
 | |
|     }
 | |
|     if (t3 < 2 / d2) {
 | |
|       return m2 * (t3 -= 1.5 / d2) * t3 + 0.75;
 | |
|     }
 | |
|     if (t3 < 2.5 / d2) {
 | |
|       return m2 * (t3 -= 2.25 / d2) * t3 + 0.9375;
 | |
|     }
 | |
|     return m2 * (t3 -= 2.625 / d2) * t3 + 0.984375;
 | |
|   },
 | |
|   easeInOutBounce: (t3) => t3 < 0.5 ? effects.easeInBounce(t3 * 2) * 0.5 : effects.easeOutBounce(t3 * 2 - 1) * 0.5 + 0.5
 | |
| };
 | |
| function isPatternOrGradient(value) {
 | |
|   if (value && typeof value === "object") {
 | |
|     const type = value.toString();
 | |
|     return type === "[object CanvasPattern]" || type === "[object CanvasGradient]";
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| function color(value) {
 | |
|   return isPatternOrGradient(value) ? value : new Color(value);
 | |
| }
 | |
| function getHoverColor(value) {
 | |
|   return isPatternOrGradient(value) ? value : new Color(value).saturate(0.5).darken(0.1).hexString();
 | |
| }
 | |
| var numbers = [
 | |
|   "x",
 | |
|   "y",
 | |
|   "borderWidth",
 | |
|   "radius",
 | |
|   "tension"
 | |
| ];
 | |
| var colors = [
 | |
|   "color",
 | |
|   "borderColor",
 | |
|   "backgroundColor"
 | |
| ];
 | |
| function applyAnimationsDefaults(defaults3) {
 | |
|   defaults3.set("animation", {
 | |
|     delay: void 0,
 | |
|     duration: 1e3,
 | |
|     easing: "easeOutQuart",
 | |
|     fn: void 0,
 | |
|     from: void 0,
 | |
|     loop: void 0,
 | |
|     to: void 0,
 | |
|     type: void 0
 | |
|   });
 | |
|   defaults3.describe("animation", {
 | |
|     _fallback: false,
 | |
|     _indexable: false,
 | |
|     _scriptable: (name) => name !== "onProgress" && name !== "onComplete" && name !== "fn"
 | |
|   });
 | |
|   defaults3.set("animations", {
 | |
|     colors: {
 | |
|       type: "color",
 | |
|       properties: colors
 | |
|     },
 | |
|     numbers: {
 | |
|       type: "number",
 | |
|       properties: numbers
 | |
|     }
 | |
|   });
 | |
|   defaults3.describe("animations", {
 | |
|     _fallback: "animation"
 | |
|   });
 | |
|   defaults3.set("transitions", {
 | |
|     active: {
 | |
|       animation: {
 | |
|         duration: 400
 | |
|       }
 | |
|     },
 | |
|     resize: {
 | |
|       animation: {
 | |
|         duration: 0
 | |
|       }
 | |
|     },
 | |
|     show: {
 | |
|       animations: {
 | |
|         colors: {
 | |
|           from: "transparent"
 | |
|         },
 | |
|         visible: {
 | |
|           type: "boolean",
 | |
|           duration: 0
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     hide: {
 | |
|       animations: {
 | |
|         colors: {
 | |
|           to: "transparent"
 | |
|         },
 | |
|         visible: {
 | |
|           type: "boolean",
 | |
|           easing: "linear",
 | |
|           fn: (v2) => v2 | 0
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   });
 | |
| }
 | |
| function applyLayoutsDefaults(defaults3) {
 | |
|   defaults3.set("layout", {
 | |
|     autoPadding: true,
 | |
|     padding: {
 | |
|       top: 0,
 | |
|       right: 0,
 | |
|       bottom: 0,
 | |
|       left: 0
 | |
|     }
 | |
|   });
 | |
| }
 | |
| var intlCache = /* @__PURE__ */ new Map();
 | |
| function getNumberFormat(locale2, options) {
 | |
|   options = options || {};
 | |
|   const cacheKey = locale2 + JSON.stringify(options);
 | |
|   let formatter = intlCache.get(cacheKey);
 | |
|   if (!formatter) {
 | |
|     formatter = new Intl.NumberFormat(locale2, options);
 | |
|     intlCache.set(cacheKey, formatter);
 | |
|   }
 | |
|   return formatter;
 | |
| }
 | |
| function formatNumber(num, locale2, options) {
 | |
|   return getNumberFormat(locale2, options).format(num);
 | |
| }
 | |
| var formatters = {
 | |
|   values(value) {
 | |
|     return isArray(value) ? value : "" + value;
 | |
|   },
 | |
|   numeric(tickValue, index, ticks) {
 | |
|     if (tickValue === 0) {
 | |
|       return "0";
 | |
|     }
 | |
|     const locale2 = this.chart.options.locale;
 | |
|     let notation;
 | |
|     let delta = tickValue;
 | |
|     if (ticks.length > 1) {
 | |
|       const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
 | |
|       if (maxTick < 1e-4 || maxTick > 1e15) {
 | |
|         notation = "scientific";
 | |
|       }
 | |
|       delta = calculateDelta(tickValue, ticks);
 | |
|     }
 | |
|     const logDelta = log10(Math.abs(delta));
 | |
|     const numDecimal = isNaN(logDelta) ? 1 : Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0);
 | |
|     const options = {
 | |
|       notation,
 | |
|       minimumFractionDigits: numDecimal,
 | |
|       maximumFractionDigits: numDecimal
 | |
|     };
 | |
|     Object.assign(options, this.options.ticks.format);
 | |
|     return formatNumber(tickValue, locale2, options);
 | |
|   },
 | |
|   logarithmic(tickValue, index, ticks) {
 | |
|     if (tickValue === 0) {
 | |
|       return "0";
 | |
|     }
 | |
|     const remain = ticks[index].significand || tickValue / Math.pow(10, Math.floor(log10(tickValue)));
 | |
|     if ([
 | |
|       1,
 | |
|       2,
 | |
|       3,
 | |
|       5,
 | |
|       10,
 | |
|       15
 | |
|     ].includes(remain) || index > 0.8 * ticks.length) {
 | |
|       return formatters.numeric.call(this, tickValue, index, ticks);
 | |
|     }
 | |
|     return "";
 | |
|   }
 | |
| };
 | |
| function calculateDelta(tickValue, ticks) {
 | |
|   let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
 | |
|   if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) {
 | |
|     delta = tickValue - Math.floor(tickValue);
 | |
|   }
 | |
|   return delta;
 | |
| }
 | |
| var Ticks = {
 | |
|   formatters
 | |
| };
 | |
| function applyScaleDefaults(defaults3) {
 | |
|   defaults3.set("scale", {
 | |
|     display: true,
 | |
|     offset: false,
 | |
|     reverse: false,
 | |
|     beginAtZero: false,
 | |
|     bounds: "ticks",
 | |
|     clip: true,
 | |
|     grace: 0,
 | |
|     grid: {
 | |
|       display: true,
 | |
|       lineWidth: 1,
 | |
|       drawOnChartArea: true,
 | |
|       drawTicks: true,
 | |
|       tickLength: 8,
 | |
|       tickWidth: (_ctx, options) => options.lineWidth,
 | |
|       tickColor: (_ctx, options) => options.color,
 | |
|       offset: false
 | |
|     },
 | |
|     border: {
 | |
|       display: true,
 | |
|       dash: [],
 | |
|       dashOffset: 0,
 | |
|       width: 1
 | |
|     },
 | |
|     title: {
 | |
|       display: false,
 | |
|       text: "",
 | |
|       padding: {
 | |
|         top: 4,
 | |
|         bottom: 4
 | |
|       }
 | |
|     },
 | |
|     ticks: {
 | |
|       minRotation: 0,
 | |
|       maxRotation: 50,
 | |
|       mirror: false,
 | |
|       textStrokeWidth: 0,
 | |
|       textStrokeColor: "",
 | |
|       padding: 3,
 | |
|       display: true,
 | |
|       autoSkip: true,
 | |
|       autoSkipPadding: 3,
 | |
|       labelOffset: 0,
 | |
|       callback: Ticks.formatters.values,
 | |
|       minor: {},
 | |
|       major: {},
 | |
|       align: "center",
 | |
|       crossAlign: "near",
 | |
|       showLabelBackdrop: false,
 | |
|       backdropColor: "rgba(255, 255, 255, 0.75)",
 | |
|       backdropPadding: 2
 | |
|     }
 | |
|   });
 | |
|   defaults3.route("scale.ticks", "color", "", "color");
 | |
|   defaults3.route("scale.grid", "color", "", "borderColor");
 | |
|   defaults3.route("scale.border", "color", "", "borderColor");
 | |
|   defaults3.route("scale.title", "color", "", "color");
 | |
|   defaults3.describe("scale", {
 | |
|     _fallback: false,
 | |
|     _scriptable: (name) => !name.startsWith("before") && !name.startsWith("after") && name !== "callback" && name !== "parser",
 | |
|     _indexable: (name) => name !== "borderDash" && name !== "tickBorderDash" && name !== "dash"
 | |
|   });
 | |
|   defaults3.describe("scales", {
 | |
|     _fallback: "scale"
 | |
|   });
 | |
|   defaults3.describe("scale.ticks", {
 | |
|     _scriptable: (name) => name !== "backdropPadding" && name !== "callback",
 | |
|     _indexable: (name) => name !== "backdropPadding"
 | |
|   });
 | |
| }
 | |
| var overrides = /* @__PURE__ */ Object.create(null);
 | |
| var descriptors = /* @__PURE__ */ Object.create(null);
 | |
| function getScope$1(node, key) {
 | |
|   if (!key) {
 | |
|     return node;
 | |
|   }
 | |
|   const keys = key.split(".");
 | |
|   for (let i2 = 0, n2 = keys.length; i2 < n2; ++i2) {
 | |
|     const k = keys[i2];
 | |
|     node = node[k] || (node[k] = /* @__PURE__ */ Object.create(null));
 | |
|   }
 | |
|   return node;
 | |
| }
 | |
| function set(root, scope, values) {
 | |
|   if (typeof scope === "string") {
 | |
|     return merge(getScope$1(root, scope), values);
 | |
|   }
 | |
|   return merge(getScope$1(root, ""), scope);
 | |
| }
 | |
| var Defaults = class {
 | |
|   constructor(_descriptors2, _appliers) {
 | |
|     this.animation = void 0;
 | |
|     this.backgroundColor = "rgba(0,0,0,0.1)";
 | |
|     this.borderColor = "rgba(0,0,0,0.1)";
 | |
|     this.color = "#666";
 | |
|     this.datasets = {};
 | |
|     this.devicePixelRatio = (context) => context.chart.platform.getDevicePixelRatio();
 | |
|     this.elements = {};
 | |
|     this.events = [
 | |
|       "mousemove",
 | |
|       "mouseout",
 | |
|       "click",
 | |
|       "touchstart",
 | |
|       "touchmove"
 | |
|     ];
 | |
|     this.font = {
 | |
|       family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
 | |
|       size: 12,
 | |
|       style: "normal",
 | |
|       lineHeight: 1.2,
 | |
|       weight: null
 | |
|     };
 | |
|     this.hover = {};
 | |
|     this.hoverBackgroundColor = (ctx, options) => getHoverColor(options.backgroundColor);
 | |
|     this.hoverBorderColor = (ctx, options) => getHoverColor(options.borderColor);
 | |
|     this.hoverColor = (ctx, options) => getHoverColor(options.color);
 | |
|     this.indexAxis = "x";
 | |
|     this.interaction = {
 | |
|       mode: "nearest",
 | |
|       intersect: true,
 | |
|       includeInvisible: false
 | |
|     };
 | |
|     this.maintainAspectRatio = true;
 | |
|     this.onHover = null;
 | |
|     this.onClick = null;
 | |
|     this.parsing = true;
 | |
|     this.plugins = {};
 | |
|     this.responsive = true;
 | |
|     this.scale = void 0;
 | |
|     this.scales = {};
 | |
|     this.showLine = true;
 | |
|     this.drawActiveElementsOnTop = true;
 | |
|     this.describe(_descriptors2);
 | |
|     this.apply(_appliers);
 | |
|   }
 | |
|   set(scope, values) {
 | |
|     return set(this, scope, values);
 | |
|   }
 | |
|   get(scope) {
 | |
|     return getScope$1(this, scope);
 | |
|   }
 | |
|   describe(scope, values) {
 | |
|     return set(descriptors, scope, values);
 | |
|   }
 | |
|   override(scope, values) {
 | |
|     return set(overrides, scope, values);
 | |
|   }
 | |
|   route(scope, name, targetScope, targetName) {
 | |
|     const scopeObject = getScope$1(this, scope);
 | |
|     const targetScopeObject = getScope$1(this, targetScope);
 | |
|     const privateName = "_" + name;
 | |
|     Object.defineProperties(scopeObject, {
 | |
|       [privateName]: {
 | |
|         value: scopeObject[name],
 | |
|         writable: true
 | |
|       },
 | |
|       [name]: {
 | |
|         enumerable: true,
 | |
|         get() {
 | |
|           const local = this[privateName];
 | |
|           const target = targetScopeObject[targetName];
 | |
|           if (isObject(local)) {
 | |
|             return Object.assign({}, target, local);
 | |
|           }
 | |
|           return valueOrDefault(local, target);
 | |
|         },
 | |
|         set(value) {
 | |
|           this[privateName] = value;
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   apply(appliers) {
 | |
|     appliers.forEach((apply) => apply(this));
 | |
|   }
 | |
| };
 | |
| var defaults2 = /* @__PURE__ */ new Defaults({
 | |
|   _scriptable: (name) => !name.startsWith("on"),
 | |
|   _indexable: (name) => name !== "events",
 | |
|   hover: {
 | |
|     _fallback: "interaction"
 | |
|   },
 | |
|   interaction: {
 | |
|     _scriptable: false,
 | |
|     _indexable: false
 | |
|   }
 | |
| }, [
 | |
|   applyAnimationsDefaults,
 | |
|   applyLayoutsDefaults,
 | |
|   applyScaleDefaults
 | |
| ]);
 | |
| function toFontString(font) {
 | |
|   if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) {
 | |
|     return null;
 | |
|   }
 | |
|   return (font.style ? font.style + " " : "") + (font.weight ? font.weight + " " : "") + font.size + "px " + font.family;
 | |
| }
 | |
| function _measureText(ctx, data, gc, longest, string) {
 | |
|   let textWidth = data[string];
 | |
|   if (!textWidth) {
 | |
|     textWidth = data[string] = ctx.measureText(string).width;
 | |
|     gc.push(string);
 | |
|   }
 | |
|   if (textWidth > longest) {
 | |
|     longest = textWidth;
 | |
|   }
 | |
|   return longest;
 | |
| }
 | |
| function _longestText(ctx, font, arrayOfThings, cache) {
 | |
|   cache = cache || {};
 | |
|   let data = cache.data = cache.data || {};
 | |
|   let gc = cache.garbageCollect = cache.garbageCollect || [];
 | |
|   if (cache.font !== font) {
 | |
|     data = cache.data = {};
 | |
|     gc = cache.garbageCollect = [];
 | |
|     cache.font = font;
 | |
|   }
 | |
|   ctx.save();
 | |
|   ctx.font = font;
 | |
|   let longest = 0;
 | |
|   const ilen = arrayOfThings.length;
 | |
|   let i2, j2, jlen, thing, nestedThing;
 | |
|   for (i2 = 0; i2 < ilen; i2++) {
 | |
|     thing = arrayOfThings[i2];
 | |
|     if (thing !== void 0 && thing !== null && !isArray(thing)) {
 | |
|       longest = _measureText(ctx, data, gc, longest, thing);
 | |
|     } else if (isArray(thing)) {
 | |
|       for (j2 = 0, jlen = thing.length; j2 < jlen; j2++) {
 | |
|         nestedThing = thing[j2];
 | |
|         if (nestedThing !== void 0 && nestedThing !== null && !isArray(nestedThing)) {
 | |
|           longest = _measureText(ctx, data, gc, longest, nestedThing);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   ctx.restore();
 | |
|   const gcLen = gc.length / 2;
 | |
|   if (gcLen > arrayOfThings.length) {
 | |
|     for (i2 = 0; i2 < gcLen; i2++) {
 | |
|       delete data[gc[i2]];
 | |
|     }
 | |
|     gc.splice(0, gcLen);
 | |
|   }
 | |
|   return longest;
 | |
| }
 | |
| function _alignPixel(chart, pixel, width) {
 | |
|   const devicePixelRatio = chart.currentDevicePixelRatio;
 | |
|   const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0;
 | |
|   return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;
 | |
| }
 | |
| function clearCanvas(canvas, ctx) {
 | |
|   if (!ctx && !canvas) {
 | |
|     return;
 | |
|   }
 | |
|   ctx = ctx || canvas.getContext("2d");
 | |
|   ctx.save();
 | |
|   ctx.resetTransform();
 | |
|   ctx.clearRect(0, 0, canvas.width, canvas.height);
 | |
|   ctx.restore();
 | |
| }
 | |
| function drawPoint(ctx, options, x2, y2) {
 | |
|   drawPointLegend(ctx, options, x2, y2, null);
 | |
| }
 | |
| function drawPointLegend(ctx, options, x2, y2, w2) {
 | |
|   let type, xOffset, yOffset, size, cornerRadius, width, xOffsetW, yOffsetW;
 | |
|   const style = options.pointStyle;
 | |
|   const rotation = options.rotation;
 | |
|   const radius = options.radius;
 | |
|   let rad = (rotation || 0) * RAD_PER_DEG;
 | |
|   if (style && typeof style === "object") {
 | |
|     type = style.toString();
 | |
|     if (type === "[object HTMLImageElement]" || type === "[object HTMLCanvasElement]") {
 | |
|       ctx.save();
 | |
|       ctx.translate(x2, y2);
 | |
|       ctx.rotate(rad);
 | |
|       ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);
 | |
|       ctx.restore();
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
|   if (isNaN(radius) || radius <= 0) {
 | |
|     return;
 | |
|   }
 | |
|   ctx.beginPath();
 | |
|   switch (style) {
 | |
|     // Default includes circle
 | |
|     default:
 | |
|       if (w2) {
 | |
|         ctx.ellipse(x2, y2, w2 / 2, radius, 0, 0, TAU);
 | |
|       } else {
 | |
|         ctx.arc(x2, y2, radius, 0, TAU);
 | |
|       }
 | |
|       ctx.closePath();
 | |
|       break;
 | |
|     case "triangle":
 | |
|       width = w2 ? w2 / 2 : radius;
 | |
|       ctx.moveTo(x2 + Math.sin(rad) * width, y2 - Math.cos(rad) * radius);
 | |
|       rad += TWO_THIRDS_PI;
 | |
|       ctx.lineTo(x2 + Math.sin(rad) * width, y2 - Math.cos(rad) * radius);
 | |
|       rad += TWO_THIRDS_PI;
 | |
|       ctx.lineTo(x2 + Math.sin(rad) * width, y2 - Math.cos(rad) * radius);
 | |
|       ctx.closePath();
 | |
|       break;
 | |
|     case "rectRounded":
 | |
|       cornerRadius = radius * 0.516;
 | |
|       size = radius - cornerRadius;
 | |
|       xOffset = Math.cos(rad + QUARTER_PI) * size;
 | |
|       xOffsetW = Math.cos(rad + QUARTER_PI) * (w2 ? w2 / 2 - cornerRadius : size);
 | |
|       yOffset = Math.sin(rad + QUARTER_PI) * size;
 | |
|       yOffsetW = Math.sin(rad + QUARTER_PI) * (w2 ? w2 / 2 - cornerRadius : size);
 | |
|       ctx.arc(x2 - xOffsetW, y2 - yOffset, cornerRadius, rad - PI, rad - HALF_PI);
 | |
|       ctx.arc(x2 + yOffsetW, y2 - xOffset, cornerRadius, rad - HALF_PI, rad);
 | |
|       ctx.arc(x2 + xOffsetW, y2 + yOffset, cornerRadius, rad, rad + HALF_PI);
 | |
|       ctx.arc(x2 - yOffsetW, y2 + xOffset, cornerRadius, rad + HALF_PI, rad + PI);
 | |
|       ctx.closePath();
 | |
|       break;
 | |
|     case "rect":
 | |
|       if (!rotation) {
 | |
|         size = Math.SQRT1_2 * radius;
 | |
|         width = w2 ? w2 / 2 : size;
 | |
|         ctx.rect(x2 - width, y2 - size, 2 * width, 2 * size);
 | |
|         break;
 | |
|       }
 | |
|       rad += QUARTER_PI;
 | |
|     /* falls through */
 | |
|     case "rectRot":
 | |
|       xOffsetW = Math.cos(rad) * (w2 ? w2 / 2 : radius);
 | |
|       xOffset = Math.cos(rad) * radius;
 | |
|       yOffset = Math.sin(rad) * radius;
 | |
|       yOffsetW = Math.sin(rad) * (w2 ? w2 / 2 : radius);
 | |
|       ctx.moveTo(x2 - xOffsetW, y2 - yOffset);
 | |
|       ctx.lineTo(x2 + yOffsetW, y2 - xOffset);
 | |
|       ctx.lineTo(x2 + xOffsetW, y2 + yOffset);
 | |
|       ctx.lineTo(x2 - yOffsetW, y2 + xOffset);
 | |
|       ctx.closePath();
 | |
|       break;
 | |
|     case "crossRot":
 | |
|       rad += QUARTER_PI;
 | |
|     /* falls through */
 | |
|     case "cross":
 | |
|       xOffsetW = Math.cos(rad) * (w2 ? w2 / 2 : radius);
 | |
|       xOffset = Math.cos(rad) * radius;
 | |
|       yOffset = Math.sin(rad) * radius;
 | |
|       yOffsetW = Math.sin(rad) * (w2 ? w2 / 2 : radius);
 | |
|       ctx.moveTo(x2 - xOffsetW, y2 - yOffset);
 | |
|       ctx.lineTo(x2 + xOffsetW, y2 + yOffset);
 | |
|       ctx.moveTo(x2 + yOffsetW, y2 - xOffset);
 | |
|       ctx.lineTo(x2 - yOffsetW, y2 + xOffset);
 | |
|       break;
 | |
|     case "star":
 | |
|       xOffsetW = Math.cos(rad) * (w2 ? w2 / 2 : radius);
 | |
|       xOffset = Math.cos(rad) * radius;
 | |
|       yOffset = Math.sin(rad) * radius;
 | |
|       yOffsetW = Math.sin(rad) * (w2 ? w2 / 2 : radius);
 | |
|       ctx.moveTo(x2 - xOffsetW, y2 - yOffset);
 | |
|       ctx.lineTo(x2 + xOffsetW, y2 + yOffset);
 | |
|       ctx.moveTo(x2 + yOffsetW, y2 - xOffset);
 | |
|       ctx.lineTo(x2 - yOffsetW, y2 + xOffset);
 | |
|       rad += QUARTER_PI;
 | |
|       xOffsetW = Math.cos(rad) * (w2 ? w2 / 2 : radius);
 | |
|       xOffset = Math.cos(rad) * radius;
 | |
|       yOffset = Math.sin(rad) * radius;
 | |
|       yOffsetW = Math.sin(rad) * (w2 ? w2 / 2 : radius);
 | |
|       ctx.moveTo(x2 - xOffsetW, y2 - yOffset);
 | |
|       ctx.lineTo(x2 + xOffsetW, y2 + yOffset);
 | |
|       ctx.moveTo(x2 + yOffsetW, y2 - xOffset);
 | |
|       ctx.lineTo(x2 - yOffsetW, y2 + xOffset);
 | |
|       break;
 | |
|     case "line":
 | |
|       xOffset = w2 ? w2 / 2 : Math.cos(rad) * radius;
 | |
|       yOffset = Math.sin(rad) * radius;
 | |
|       ctx.moveTo(x2 - xOffset, y2 - yOffset);
 | |
|       ctx.lineTo(x2 + xOffset, y2 + yOffset);
 | |
|       break;
 | |
|     case "dash":
 | |
|       ctx.moveTo(x2, y2);
 | |
|       ctx.lineTo(x2 + Math.cos(rad) * (w2 ? w2 / 2 : radius), y2 + Math.sin(rad) * radius);
 | |
|       break;
 | |
|     case false:
 | |
|       ctx.closePath();
 | |
|       break;
 | |
|   }
 | |
|   ctx.fill();
 | |
|   if (options.borderWidth > 0) {
 | |
|     ctx.stroke();
 | |
|   }
 | |
| }
 | |
| function _isPointInArea(point, area, margin) {
 | |
|   margin = margin || 0.5;
 | |
|   return !area || point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin;
 | |
| }
 | |
| function clipArea(ctx, area) {
 | |
|   ctx.save();
 | |
|   ctx.beginPath();
 | |
|   ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
 | |
|   ctx.clip();
 | |
| }
 | |
| function unclipArea(ctx) {
 | |
|   ctx.restore();
 | |
| }
 | |
| function setRenderOpts(ctx, opts) {
 | |
|   if (opts.translation) {
 | |
|     ctx.translate(opts.translation[0], opts.translation[1]);
 | |
|   }
 | |
|   if (!isNullOrUndef(opts.rotation)) {
 | |
|     ctx.rotate(opts.rotation);
 | |
|   }
 | |
|   if (opts.color) {
 | |
|     ctx.fillStyle = opts.color;
 | |
|   }
 | |
|   if (opts.textAlign) {
 | |
|     ctx.textAlign = opts.textAlign;
 | |
|   }
 | |
|   if (opts.textBaseline) {
 | |
|     ctx.textBaseline = opts.textBaseline;
 | |
|   }
 | |
| }
 | |
| function decorateText(ctx, x2, y2, line, opts) {
 | |
|   if (opts.strikethrough || opts.underline) {
 | |
|     const metrics = ctx.measureText(line);
 | |
|     const left = x2 - metrics.actualBoundingBoxLeft;
 | |
|     const right = x2 + metrics.actualBoundingBoxRight;
 | |
|     const top = y2 - metrics.actualBoundingBoxAscent;
 | |
|     const bottom = y2 + metrics.actualBoundingBoxDescent;
 | |
|     const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom;
 | |
|     ctx.strokeStyle = ctx.fillStyle;
 | |
|     ctx.beginPath();
 | |
|     ctx.lineWidth = opts.decorationWidth || 2;
 | |
|     ctx.moveTo(left, yDecoration);
 | |
|     ctx.lineTo(right, yDecoration);
 | |
|     ctx.stroke();
 | |
|   }
 | |
| }
 | |
| function drawBackdrop(ctx, opts) {
 | |
|   const oldColor = ctx.fillStyle;
 | |
|   ctx.fillStyle = opts.color;
 | |
|   ctx.fillRect(opts.left, opts.top, opts.width, opts.height);
 | |
|   ctx.fillStyle = oldColor;
 | |
| }
 | |
| function renderText(ctx, text, x2, y2, font, opts = {}) {
 | |
|   const lines = isArray(text) ? text : [
 | |
|     text
 | |
|   ];
 | |
|   const stroke = opts.strokeWidth > 0 && opts.strokeColor !== "";
 | |
|   let i2, line;
 | |
|   ctx.save();
 | |
|   ctx.font = font.string;
 | |
|   setRenderOpts(ctx, opts);
 | |
|   for (i2 = 0; i2 < lines.length; ++i2) {
 | |
|     line = lines[i2];
 | |
|     if (opts.backdrop) {
 | |
|       drawBackdrop(ctx, opts.backdrop);
 | |
|     }
 | |
|     if (stroke) {
 | |
|       if (opts.strokeColor) {
 | |
|         ctx.strokeStyle = opts.strokeColor;
 | |
|       }
 | |
|       if (!isNullOrUndef(opts.strokeWidth)) {
 | |
|         ctx.lineWidth = opts.strokeWidth;
 | |
|       }
 | |
|       ctx.strokeText(line, x2, y2, opts.maxWidth);
 | |
|     }
 | |
|     ctx.fillText(line, x2, y2, opts.maxWidth);
 | |
|     decorateText(ctx, x2, y2, line, opts);
 | |
|     y2 += Number(font.lineHeight);
 | |
|   }
 | |
|   ctx.restore();
 | |
| }
 | |
| function addRoundedRectPath(ctx, rect) {
 | |
|   const { x: x2, y: y2, w: w2, h: h6, radius } = rect;
 | |
|   ctx.arc(x2 + radius.topLeft, y2 + radius.topLeft, radius.topLeft, 1.5 * PI, PI, true);
 | |
|   ctx.lineTo(x2, y2 + h6 - radius.bottomLeft);
 | |
|   ctx.arc(x2 + radius.bottomLeft, y2 + h6 - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true);
 | |
|   ctx.lineTo(x2 + w2 - radius.bottomRight, y2 + h6);
 | |
|   ctx.arc(x2 + w2 - radius.bottomRight, y2 + h6 - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true);
 | |
|   ctx.lineTo(x2 + w2, y2 + radius.topRight);
 | |
|   ctx.arc(x2 + w2 - radius.topRight, y2 + radius.topRight, radius.topRight, 0, -HALF_PI, true);
 | |
|   ctx.lineTo(x2 + radius.topLeft, y2);
 | |
| }
 | |
| var LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/;
 | |
| var FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;
 | |
| function toLineHeight(value, size) {
 | |
|   const matches = ("" + value).match(LINE_HEIGHT);
 | |
|   if (!matches || matches[1] === "normal") {
 | |
|     return size * 1.2;
 | |
|   }
 | |
|   value = +matches[2];
 | |
|   switch (matches[3]) {
 | |
|     case "px":
 | |
|       return value;
 | |
|     case "%":
 | |
|       value /= 100;
 | |
|       break;
 | |
|   }
 | |
|   return size * value;
 | |
| }
 | |
| var numberOrZero = (v2) => +v2 || 0;
 | |
| function _readValueToProps(value, props) {
 | |
|   const ret = {};
 | |
|   const objProps = isObject(props);
 | |
|   const keys = objProps ? Object.keys(props) : props;
 | |
|   const read = isObject(value) ? objProps ? (prop) => valueOrDefault(value[prop], value[props[prop]]) : (prop) => value[prop] : () => value;
 | |
|   for (const prop of keys) {
 | |
|     ret[prop] = numberOrZero(read(prop));
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| function toTRBL(value) {
 | |
|   return _readValueToProps(value, {
 | |
|     top: "y",
 | |
|     right: "x",
 | |
|     bottom: "y",
 | |
|     left: "x"
 | |
|   });
 | |
| }
 | |
| function toTRBLCorners(value) {
 | |
|   return _readValueToProps(value, [
 | |
|     "topLeft",
 | |
|     "topRight",
 | |
|     "bottomLeft",
 | |
|     "bottomRight"
 | |
|   ]);
 | |
| }
 | |
| function toPadding(value) {
 | |
|   const obj = toTRBL(value);
 | |
|   obj.width = obj.left + obj.right;
 | |
|   obj.height = obj.top + obj.bottom;
 | |
|   return obj;
 | |
| }
 | |
| function toFont(options, fallback) {
 | |
|   options = options || {};
 | |
|   fallback = fallback || defaults2.font;
 | |
|   let size = valueOrDefault(options.size, fallback.size);
 | |
|   if (typeof size === "string") {
 | |
|     size = parseInt(size, 10);
 | |
|   }
 | |
|   let style = valueOrDefault(options.style, fallback.style);
 | |
|   if (style && !("" + style).match(FONT_STYLE)) {
 | |
|     console.warn('Invalid font style specified: "' + style + '"');
 | |
|     style = void 0;
 | |
|   }
 | |
|   const font = {
 | |
|     family: valueOrDefault(options.family, fallback.family),
 | |
|     lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size),
 | |
|     size,
 | |
|     style,
 | |
|     weight: valueOrDefault(options.weight, fallback.weight),
 | |
|     string: ""
 | |
|   };
 | |
|   font.string = toFontString(font);
 | |
|   return font;
 | |
| }
 | |
| function resolve(inputs, context, index, info) {
 | |
|   let cacheable = true;
 | |
|   let i2, ilen, value;
 | |
|   for (i2 = 0, ilen = inputs.length; i2 < ilen; ++i2) {
 | |
|     value = inputs[i2];
 | |
|     if (value === void 0) {
 | |
|       continue;
 | |
|     }
 | |
|     if (context !== void 0 && typeof value === "function") {
 | |
|       value = value(context);
 | |
|       cacheable = false;
 | |
|     }
 | |
|     if (index !== void 0 && isArray(value)) {
 | |
|       value = value[index % value.length];
 | |
|       cacheable = false;
 | |
|     }
 | |
|     if (value !== void 0) {
 | |
|       if (info && !cacheable) {
 | |
|         info.cacheable = false;
 | |
|       }
 | |
|       return value;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function _addGrace(minmax, grace, beginAtZero) {
 | |
|   const { min, max } = minmax;
 | |
|   const change = toDimension(grace, (max - min) / 2);
 | |
|   const keepZero = (value, add) => beginAtZero && value === 0 ? 0 : value + add;
 | |
|   return {
 | |
|     min: keepZero(min, -Math.abs(change)),
 | |
|     max: keepZero(max, change)
 | |
|   };
 | |
| }
 | |
| function createContext(parentContext, context) {
 | |
|   return Object.assign(Object.create(parentContext), context);
 | |
| }
 | |
| function _createResolver(scopes, prefixes = [
 | |
|   ""
 | |
| ], rootScopes, fallback, getTarget = () => scopes[0]) {
 | |
|   const finalRootScopes = rootScopes || scopes;
 | |
|   if (typeof fallback === "undefined") {
 | |
|     fallback = _resolve("_fallback", scopes);
 | |
|   }
 | |
|   const cache = {
 | |
|     [Symbol.toStringTag]: "Object",
 | |
|     _cacheable: true,
 | |
|     _scopes: scopes,
 | |
|     _rootScopes: finalRootScopes,
 | |
|     _fallback: fallback,
 | |
|     _getTarget: getTarget,
 | |
|     override: (scope) => _createResolver([
 | |
|       scope,
 | |
|       ...scopes
 | |
|     ], prefixes, finalRootScopes, fallback)
 | |
|   };
 | |
|   return new Proxy(cache, {
 | |
|     /**
 | |
|     * A trap for the delete operator.
 | |
|     */
 | |
|     deleteProperty(target, prop) {
 | |
|       delete target[prop];
 | |
|       delete target._keys;
 | |
|       delete scopes[0][prop];
 | |
|       return true;
 | |
|     },
 | |
|     /**
 | |
|     * A trap for getting property values.
 | |
|     */
 | |
|     get(target, prop) {
 | |
|       return _cached(target, prop, () => _resolveWithPrefixes(prop, prefixes, scopes, target));
 | |
|     },
 | |
|     /**
 | |
|     * A trap for Object.getOwnPropertyDescriptor.
 | |
|     * Also used by Object.hasOwnProperty.
 | |
|     */
 | |
|     getOwnPropertyDescriptor(target, prop) {
 | |
|       return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for Object.getPrototypeOf.
 | |
|     */
 | |
|     getPrototypeOf() {
 | |
|       return Reflect.getPrototypeOf(scopes[0]);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for the in operator.
 | |
|     */
 | |
|     has(target, prop) {
 | |
|       return getKeysFromAllScopes(target).includes(prop);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.
 | |
|     */
 | |
|     ownKeys(target) {
 | |
|       return getKeysFromAllScopes(target);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for setting property values.
 | |
|     */
 | |
|     set(target, prop, value) {
 | |
|       const storage = target._storage || (target._storage = getTarget());
 | |
|       target[prop] = storage[prop] = value;
 | |
|       delete target._keys;
 | |
|       return true;
 | |
|     }
 | |
|   });
 | |
| }
 | |
| function _attachContext(proxy, context, subProxy, descriptorDefaults) {
 | |
|   const cache = {
 | |
|     _cacheable: false,
 | |
|     _proxy: proxy,
 | |
|     _context: context,
 | |
|     _subProxy: subProxy,
 | |
|     _stack: /* @__PURE__ */ new Set(),
 | |
|     _descriptors: _descriptors(proxy, descriptorDefaults),
 | |
|     setContext: (ctx) => _attachContext(proxy, ctx, subProxy, descriptorDefaults),
 | |
|     override: (scope) => _attachContext(proxy.override(scope), context, subProxy, descriptorDefaults)
 | |
|   };
 | |
|   return new Proxy(cache, {
 | |
|     /**
 | |
|     * A trap for the delete operator.
 | |
|     */
 | |
|     deleteProperty(target, prop) {
 | |
|       delete target[prop];
 | |
|       delete proxy[prop];
 | |
|       return true;
 | |
|     },
 | |
|     /**
 | |
|     * A trap for getting property values.
 | |
|     */
 | |
|     get(target, prop, receiver) {
 | |
|       return _cached(target, prop, () => _resolveWithContext(target, prop, receiver));
 | |
|     },
 | |
|     /**
 | |
|     * A trap for Object.getOwnPropertyDescriptor.
 | |
|     * Also used by Object.hasOwnProperty.
 | |
|     */
 | |
|     getOwnPropertyDescriptor(target, prop) {
 | |
|       return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? {
 | |
|         enumerable: true,
 | |
|         configurable: true
 | |
|       } : void 0 : Reflect.getOwnPropertyDescriptor(proxy, prop);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for Object.getPrototypeOf.
 | |
|     */
 | |
|     getPrototypeOf() {
 | |
|       return Reflect.getPrototypeOf(proxy);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for the in operator.
 | |
|     */
 | |
|     has(target, prop) {
 | |
|       return Reflect.has(proxy, prop);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.
 | |
|     */
 | |
|     ownKeys() {
 | |
|       return Reflect.ownKeys(proxy);
 | |
|     },
 | |
|     /**
 | |
|     * A trap for setting property values.
 | |
|     */
 | |
|     set(target, prop, value) {
 | |
|       proxy[prop] = value;
 | |
|       delete target[prop];
 | |
|       return true;
 | |
|     }
 | |
|   });
 | |
| }
 | |
| function _descriptors(proxy, defaults3 = {
 | |
|   scriptable: true,
 | |
|   indexable: true
 | |
| }) {
 | |
|   const { _scriptable = defaults3.scriptable, _indexable = defaults3.indexable, _allKeys = defaults3.allKeys } = proxy;
 | |
|   return {
 | |
|     allKeys: _allKeys,
 | |
|     scriptable: _scriptable,
 | |
|     indexable: _indexable,
 | |
|     isScriptable: isFunction(_scriptable) ? _scriptable : () => _scriptable,
 | |
|     isIndexable: isFunction(_indexable) ? _indexable : () => _indexable
 | |
|   };
 | |
| }
 | |
| var readKey = (prefix, name) => prefix ? prefix + _capitalize(name) : name;
 | |
| var needsSubResolver = (prop, value) => isObject(value) && prop !== "adapters" && (Object.getPrototypeOf(value) === null || value.constructor === Object);
 | |
| function _cached(target, prop, resolve2) {
 | |
|   if (Object.prototype.hasOwnProperty.call(target, prop) || prop === "constructor") {
 | |
|     return target[prop];
 | |
|   }
 | |
|   const value = resolve2();
 | |
|   target[prop] = value;
 | |
|   return value;
 | |
| }
 | |
| function _resolveWithContext(target, prop, receiver) {
 | |
|   const { _proxy, _context, _subProxy, _descriptors: descriptors2 } = target;
 | |
|   let value = _proxy[prop];
 | |
|   if (isFunction(value) && descriptors2.isScriptable(prop)) {
 | |
|     value = _resolveScriptable(prop, value, target, receiver);
 | |
|   }
 | |
|   if (isArray(value) && value.length) {
 | |
|     value = _resolveArray(prop, value, target, descriptors2.isIndexable);
 | |
|   }
 | |
|   if (needsSubResolver(prop, value)) {
 | |
|     value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors2);
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| function _resolveScriptable(prop, getValue, target, receiver) {
 | |
|   const { _proxy, _context, _subProxy, _stack } = target;
 | |
|   if (_stack.has(prop)) {
 | |
|     throw new Error("Recursion detected: " + Array.from(_stack).join("->") + "->" + prop);
 | |
|   }
 | |
|   _stack.add(prop);
 | |
|   let value = getValue(_context, _subProxy || receiver);
 | |
|   _stack.delete(prop);
 | |
|   if (needsSubResolver(prop, value)) {
 | |
|     value = createSubResolver(_proxy._scopes, _proxy, prop, value);
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| function _resolveArray(prop, value, target, isIndexable) {
 | |
|   const { _proxy, _context, _subProxy, _descriptors: descriptors2 } = target;
 | |
|   if (typeof _context.index !== "undefined" && isIndexable(prop)) {
 | |
|     return value[_context.index % value.length];
 | |
|   } else if (isObject(value[0])) {
 | |
|     const arr = value;
 | |
|     const scopes = _proxy._scopes.filter((s2) => s2 !== arr);
 | |
|     value = [];
 | |
|     for (const item of arr) {
 | |
|       const resolver = createSubResolver(scopes, _proxy, prop, item);
 | |
|       value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors2));
 | |
|     }
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| function resolveFallback(fallback, prop, value) {
 | |
|   return isFunction(fallback) ? fallback(prop, value) : fallback;
 | |
| }
 | |
| var getScope = (key, parent) => key === true ? parent : typeof key === "string" ? resolveObjectKey(parent, key) : void 0;
 | |
| function addScopes(set2, parentScopes, key, parentFallback, value) {
 | |
|   for (const parent of parentScopes) {
 | |
|     const scope = getScope(key, parent);
 | |
|     if (scope) {
 | |
|       set2.add(scope);
 | |
|       const fallback = resolveFallback(scope._fallback, key, value);
 | |
|       if (typeof fallback !== "undefined" && fallback !== key && fallback !== parentFallback) {
 | |
|         return fallback;
 | |
|       }
 | |
|     } else if (scope === false && typeof parentFallback !== "undefined" && key !== parentFallback) {
 | |
|       return null;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| function createSubResolver(parentScopes, resolver, prop, value) {
 | |
|   const rootScopes = resolver._rootScopes;
 | |
|   const fallback = resolveFallback(resolver._fallback, prop, value);
 | |
|   const allScopes = [
 | |
|     ...parentScopes,
 | |
|     ...rootScopes
 | |
|   ];
 | |
|   const set2 = /* @__PURE__ */ new Set();
 | |
|   set2.add(value);
 | |
|   let key = addScopesFromKey(set2, allScopes, prop, fallback || prop, value);
 | |
|   if (key === null) {
 | |
|     return false;
 | |
|   }
 | |
|   if (typeof fallback !== "undefined" && fallback !== prop) {
 | |
|     key = addScopesFromKey(set2, allScopes, fallback, key, value);
 | |
|     if (key === null) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return _createResolver(Array.from(set2), [
 | |
|     ""
 | |
|   ], rootScopes, fallback, () => subGetTarget(resolver, prop, value));
 | |
| }
 | |
| function addScopesFromKey(set2, allScopes, key, fallback, item) {
 | |
|   while (key) {
 | |
|     key = addScopes(set2, allScopes, key, fallback, item);
 | |
|   }
 | |
|   return key;
 | |
| }
 | |
| function subGetTarget(resolver, prop, value) {
 | |
|   const parent = resolver._getTarget();
 | |
|   if (!(prop in parent)) {
 | |
|     parent[prop] = {};
 | |
|   }
 | |
|   const target = parent[prop];
 | |
|   if (isArray(target) && isObject(value)) {
 | |
|     return value;
 | |
|   }
 | |
|   return target || {};
 | |
| }
 | |
| function _resolveWithPrefixes(prop, prefixes, scopes, proxy) {
 | |
|   let value;
 | |
|   for (const prefix of prefixes) {
 | |
|     value = _resolve(readKey(prefix, prop), scopes);
 | |
|     if (typeof value !== "undefined") {
 | |
|       return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function _resolve(key, scopes) {
 | |
|   for (const scope of scopes) {
 | |
|     if (!scope) {
 | |
|       continue;
 | |
|     }
 | |
|     const value = scope[key];
 | |
|     if (typeof value !== "undefined") {
 | |
|       return value;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function getKeysFromAllScopes(target) {
 | |
|   let keys = target._keys;
 | |
|   if (!keys) {
 | |
|     keys = target._keys = resolveKeysFromAllScopes(target._scopes);
 | |
|   }
 | |
|   return keys;
 | |
| }
 | |
| function resolveKeysFromAllScopes(scopes) {
 | |
|   const set2 = /* @__PURE__ */ new Set();
 | |
|   for (const scope of scopes) {
 | |
|     for (const key of Object.keys(scope).filter((k) => !k.startsWith("_"))) {
 | |
|       set2.add(key);
 | |
|     }
 | |
|   }
 | |
|   return Array.from(set2);
 | |
| }
 | |
| var EPSILON = Number.EPSILON || 1e-14;
 | |
| function _isDomSupported() {
 | |
|   return typeof window !== "undefined" && typeof document !== "undefined";
 | |
| }
 | |
| function _getParentNode(domNode) {
 | |
|   let parent = domNode.parentNode;
 | |
|   if (parent && parent.toString() === "[object ShadowRoot]") {
 | |
|     parent = parent.host;
 | |
|   }
 | |
|   return parent;
 | |
| }
 | |
| function parseMaxStyle(styleValue, node, parentProperty) {
 | |
|   let valueInPixels;
 | |
|   if (typeof styleValue === "string") {
 | |
|     valueInPixels = parseInt(styleValue, 10);
 | |
|     if (styleValue.indexOf("%") !== -1) {
 | |
|       valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
 | |
|     }
 | |
|   } else {
 | |
|     valueInPixels = styleValue;
 | |
|   }
 | |
|   return valueInPixels;
 | |
| }
 | |
| var getComputedStyle2 = (element) => element.ownerDocument.defaultView.getComputedStyle(element, null);
 | |
| function getStyle(el, property) {
 | |
|   return getComputedStyle2(el).getPropertyValue(property);
 | |
| }
 | |
| var positions = [
 | |
|   "top",
 | |
|   "right",
 | |
|   "bottom",
 | |
|   "left"
 | |
| ];
 | |
| function getPositionedStyle(styles, style, suffix) {
 | |
|   const result = {};
 | |
|   suffix = suffix ? "-" + suffix : "";
 | |
|   for (let i2 = 0; i2 < 4; i2++) {
 | |
|     const pos = positions[i2];
 | |
|     result[pos] = parseFloat(styles[style + "-" + pos + suffix]) || 0;
 | |
|   }
 | |
|   result.width = result.left + result.right;
 | |
|   result.height = result.top + result.bottom;
 | |
|   return result;
 | |
| }
 | |
| var useOffsetPos = (x2, y2, target) => (x2 > 0 || y2 > 0) && (!target || !target.shadowRoot);
 | |
| function getCanvasPosition(e2, canvas) {
 | |
|   const touches = e2.touches;
 | |
|   const source = touches && touches.length ? touches[0] : e2;
 | |
|   const { offsetX, offsetY } = source;
 | |
|   let box = false;
 | |
|   let x2, y2;
 | |
|   if (useOffsetPos(offsetX, offsetY, e2.target)) {
 | |
|     x2 = offsetX;
 | |
|     y2 = offsetY;
 | |
|   } else {
 | |
|     const rect = canvas.getBoundingClientRect();
 | |
|     x2 = source.clientX - rect.left;
 | |
|     y2 = source.clientY - rect.top;
 | |
|     box = true;
 | |
|   }
 | |
|   return {
 | |
|     x: x2,
 | |
|     y: y2,
 | |
|     box
 | |
|   };
 | |
| }
 | |
| function getRelativePosition(event, chart) {
 | |
|   if ("native" in event) {
 | |
|     return event;
 | |
|   }
 | |
|   const { canvas, currentDevicePixelRatio } = chart;
 | |
|   const style = getComputedStyle2(canvas);
 | |
|   const borderBox = style.boxSizing === "border-box";
 | |
|   const paddings = getPositionedStyle(style, "padding");
 | |
|   const borders = getPositionedStyle(style, "border", "width");
 | |
|   const { x: x2, y: y2, box } = getCanvasPosition(event, canvas);
 | |
|   const xOffset = paddings.left + (box && borders.left);
 | |
|   const yOffset = paddings.top + (box && borders.top);
 | |
|   let { width, height } = chart;
 | |
|   if (borderBox) {
 | |
|     width -= paddings.width + borders.width;
 | |
|     height -= paddings.height + borders.height;
 | |
|   }
 | |
|   return {
 | |
|     x: Math.round((x2 - xOffset) / width * canvas.width / currentDevicePixelRatio),
 | |
|     y: Math.round((y2 - yOffset) / height * canvas.height / currentDevicePixelRatio)
 | |
|   };
 | |
| }
 | |
| function getContainerSize(canvas, width, height) {
 | |
|   let maxWidth, maxHeight;
 | |
|   if (width === void 0 || height === void 0) {
 | |
|     const container = canvas && _getParentNode(canvas);
 | |
|     if (!container) {
 | |
|       width = canvas.clientWidth;
 | |
|       height = canvas.clientHeight;
 | |
|     } else {
 | |
|       const rect = container.getBoundingClientRect();
 | |
|       const containerStyle = getComputedStyle2(container);
 | |
|       const containerBorder = getPositionedStyle(containerStyle, "border", "width");
 | |
|       const containerPadding = getPositionedStyle(containerStyle, "padding");
 | |
|       width = rect.width - containerPadding.width - containerBorder.width;
 | |
|       height = rect.height - containerPadding.height - containerBorder.height;
 | |
|       maxWidth = parseMaxStyle(containerStyle.maxWidth, container, "clientWidth");
 | |
|       maxHeight = parseMaxStyle(containerStyle.maxHeight, container, "clientHeight");
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     width,
 | |
|     height,
 | |
|     maxWidth: maxWidth || INFINITY,
 | |
|     maxHeight: maxHeight || INFINITY
 | |
|   };
 | |
| }
 | |
| var round1 = (v2) => Math.round(v2 * 10) / 10;
 | |
| function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) {
 | |
|   const style = getComputedStyle2(canvas);
 | |
|   const margins = getPositionedStyle(style, "margin");
 | |
|   const maxWidth = parseMaxStyle(style.maxWidth, canvas, "clientWidth") || INFINITY;
 | |
|   const maxHeight = parseMaxStyle(style.maxHeight, canvas, "clientHeight") || INFINITY;
 | |
|   const containerSize = getContainerSize(canvas, bbWidth, bbHeight);
 | |
|   let { width, height } = containerSize;
 | |
|   if (style.boxSizing === "content-box") {
 | |
|     const borders = getPositionedStyle(style, "border", "width");
 | |
|     const paddings = getPositionedStyle(style, "padding");
 | |
|     width -= paddings.width + borders.width;
 | |
|     height -= paddings.height + borders.height;
 | |
|   }
 | |
|   width = Math.max(0, width - margins.width);
 | |
|   height = Math.max(0, aspectRatio ? width / aspectRatio : height - margins.height);
 | |
|   width = round1(Math.min(width, maxWidth, containerSize.maxWidth));
 | |
|   height = round1(Math.min(height, maxHeight, containerSize.maxHeight));
 | |
|   if (width && !height) {
 | |
|     height = round1(width / 2);
 | |
|   }
 | |
|   const maintainHeight = bbWidth !== void 0 || bbHeight !== void 0;
 | |
|   if (maintainHeight && aspectRatio && containerSize.height && height > containerSize.height) {
 | |
|     height = containerSize.height;
 | |
|     width = round1(Math.floor(height * aspectRatio));
 | |
|   }
 | |
|   return {
 | |
|     width,
 | |
|     height
 | |
|   };
 | |
| }
 | |
| function retinaScale(chart, forceRatio, forceStyle) {
 | |
|   const pixelRatio = forceRatio || 1;
 | |
|   const deviceHeight = Math.floor(chart.height * pixelRatio);
 | |
|   const deviceWidth = Math.floor(chart.width * pixelRatio);
 | |
|   chart.height = Math.floor(chart.height);
 | |
|   chart.width = Math.floor(chart.width);
 | |
|   const canvas = chart.canvas;
 | |
|   if (canvas.style && (forceStyle || !canvas.style.height && !canvas.style.width)) {
 | |
|     canvas.style.height = `${chart.height}px`;
 | |
|     canvas.style.width = `${chart.width}px`;
 | |
|   }
 | |
|   if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) {
 | |
|     chart.currentDevicePixelRatio = pixelRatio;
 | |
|     canvas.height = deviceHeight;
 | |
|     canvas.width = deviceWidth;
 | |
|     chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| var supportsEventListenerOptions = function() {
 | |
|   let passiveSupported = false;
 | |
|   try {
 | |
|     const options = {
 | |
|       get passive() {
 | |
|         passiveSupported = true;
 | |
|         return false;
 | |
|       }
 | |
|     };
 | |
|     if (_isDomSupported()) {
 | |
|       window.addEventListener("test", null, options);
 | |
|       window.removeEventListener("test", null, options);
 | |
|     }
 | |
|   } catch (e2) {
 | |
|   }
 | |
|   return passiveSupported;
 | |
| }();
 | |
| function readUsedSize(element, property) {
 | |
|   const value = getStyle(element, property);
 | |
|   const matches = value && value.match(/^(\d+)(\.\d+)?px$/);
 | |
|   return matches ? +matches[1] : void 0;
 | |
| }
 | |
| var getRightToLeftAdapter = function(rectX, width) {
 | |
|   return {
 | |
|     x(x2) {
 | |
|       return rectX + rectX + width - x2;
 | |
|     },
 | |
|     setWidth(w2) {
 | |
|       width = w2;
 | |
|     },
 | |
|     textAlign(align) {
 | |
|       if (align === "center") {
 | |
|         return align;
 | |
|       }
 | |
|       return align === "right" ? "left" : "right";
 | |
|     },
 | |
|     xPlus(x2, value) {
 | |
|       return x2 - value;
 | |
|     },
 | |
|     leftForLtr(x2, itemWidth) {
 | |
|       return x2 - itemWidth;
 | |
|     }
 | |
|   };
 | |
| };
 | |
| var getLeftToRightAdapter = function() {
 | |
|   return {
 | |
|     x(x2) {
 | |
|       return x2;
 | |
|     },
 | |
|     setWidth(w2) {
 | |
|     },
 | |
|     textAlign(align) {
 | |
|       return align;
 | |
|     },
 | |
|     xPlus(x2, value) {
 | |
|       return x2 + value;
 | |
|     },
 | |
|     leftForLtr(x2, _itemWidth) {
 | |
|       return x2;
 | |
|     }
 | |
|   };
 | |
| };
 | |
| function getRtlAdapter(rtl, rectX, width) {
 | |
|   return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter();
 | |
| }
 | |
| function overrideTextDirection(ctx, direction) {
 | |
|   let style, original;
 | |
|   if (direction === "ltr" || direction === "rtl") {
 | |
|     style = ctx.canvas.style;
 | |
|     original = [
 | |
|       style.getPropertyValue("direction"),
 | |
|       style.getPropertyPriority("direction")
 | |
|     ];
 | |
|     style.setProperty("direction", direction, "important");
 | |
|     ctx.prevTextDirection = original;
 | |
|   }
 | |
| }
 | |
| function restoreTextDirection(ctx, original) {
 | |
|   if (original !== void 0) {
 | |
|     delete ctx.prevTextDirection;
 | |
|     ctx.canvas.style.setProperty("direction", original[0], original[1]);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // node_modules/.pnpm/chart.js@4.4.8/node_modules/chart.js/dist/chart.js
 | |
| var Animator = class {
 | |
|   constructor() {
 | |
|     this._request = null;
 | |
|     this._charts = /* @__PURE__ */ new Map();
 | |
|     this._running = false;
 | |
|     this._lastDate = void 0;
 | |
|   }
 | |
|   _notify(chart, anims, date, type) {
 | |
|     const callbacks = anims.listeners[type];
 | |
|     const numSteps = anims.duration;
 | |
|     callbacks.forEach((fn2) => fn2({
 | |
|       chart,
 | |
|       initial: anims.initial,
 | |
|       numSteps,
 | |
|       currentStep: Math.min(date - anims.start, numSteps)
 | |
|     }));
 | |
|   }
 | |
|   _refresh() {
 | |
|     if (this._request) {
 | |
|       return;
 | |
|     }
 | |
|     this._running = true;
 | |
|     this._request = requestAnimFrame.call(window, () => {
 | |
|       this._update();
 | |
|       this._request = null;
 | |
|       if (this._running) {
 | |
|         this._refresh();
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   _update(date = Date.now()) {
 | |
|     let remaining = 0;
 | |
|     this._charts.forEach((anims, chart) => {
 | |
|       if (!anims.running || !anims.items.length) {
 | |
|         return;
 | |
|       }
 | |
|       const items = anims.items;
 | |
|       let i2 = items.length - 1;
 | |
|       let draw = false;
 | |
|       let item;
 | |
|       for (; i2 >= 0; --i2) {
 | |
|         item = items[i2];
 | |
|         if (item._active) {
 | |
|           if (item._total > anims.duration) {
 | |
|             anims.duration = item._total;
 | |
|           }
 | |
|           item.tick(date);
 | |
|           draw = true;
 | |
|         } else {
 | |
|           items[i2] = items[items.length - 1];
 | |
|           items.pop();
 | |
|         }
 | |
|       }
 | |
|       if (draw) {
 | |
|         chart.draw();
 | |
|         this._notify(chart, anims, date, "progress");
 | |
|       }
 | |
|       if (!items.length) {
 | |
|         anims.running = false;
 | |
|         this._notify(chart, anims, date, "complete");
 | |
|         anims.initial = false;
 | |
|       }
 | |
|       remaining += items.length;
 | |
|     });
 | |
|     this._lastDate = date;
 | |
|     if (remaining === 0) {
 | |
|       this._running = false;
 | |
|     }
 | |
|   }
 | |
|   _getAnims(chart) {
 | |
|     const charts = this._charts;
 | |
|     let anims = charts.get(chart);
 | |
|     if (!anims) {
 | |
|       anims = {
 | |
|         running: false,
 | |
|         initial: true,
 | |
|         items: [],
 | |
|         listeners: {
 | |
|           complete: [],
 | |
|           progress: []
 | |
|         }
 | |
|       };
 | |
|       charts.set(chart, anims);
 | |
|     }
 | |
|     return anims;
 | |
|   }
 | |
|   listen(chart, event, cb) {
 | |
|     this._getAnims(chart).listeners[event].push(cb);
 | |
|   }
 | |
|   add(chart, items) {
 | |
|     if (!items || !items.length) {
 | |
|       return;
 | |
|     }
 | |
|     this._getAnims(chart).items.push(...items);
 | |
|   }
 | |
|   has(chart) {
 | |
|     return this._getAnims(chart).items.length > 0;
 | |
|   }
 | |
|   start(chart) {
 | |
|     const anims = this._charts.get(chart);
 | |
|     if (!anims) {
 | |
|       return;
 | |
|     }
 | |
|     anims.running = true;
 | |
|     anims.start = Date.now();
 | |
|     anims.duration = anims.items.reduce((acc, cur) => Math.max(acc, cur._duration), 0);
 | |
|     this._refresh();
 | |
|   }
 | |
|   running(chart) {
 | |
|     if (!this._running) {
 | |
|       return false;
 | |
|     }
 | |
|     const anims = this._charts.get(chart);
 | |
|     if (!anims || !anims.running || !anims.items.length) {
 | |
|       return false;
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
|   stop(chart) {
 | |
|     const anims = this._charts.get(chart);
 | |
|     if (!anims || !anims.items.length) {
 | |
|       return;
 | |
|     }
 | |
|     const items = anims.items;
 | |
|     let i2 = items.length - 1;
 | |
|     for (; i2 >= 0; --i2) {
 | |
|       items[i2].cancel();
 | |
|     }
 | |
|     anims.items = [];
 | |
|     this._notify(chart, anims, Date.now(), "complete");
 | |
|   }
 | |
|   remove(chart) {
 | |
|     return this._charts.delete(chart);
 | |
|   }
 | |
| };
 | |
| var animator = /* @__PURE__ */ new Animator();
 | |
| var transparent = "transparent";
 | |
| var interpolators = {
 | |
|   boolean(from2, to2, factor) {
 | |
|     return factor > 0.5 ? to2 : from2;
 | |
|   },
 | |
|   color(from2, to2, factor) {
 | |
|     const c0 = color(from2 || transparent);
 | |
|     const c1 = c0.valid && color(to2 || transparent);
 | |
|     return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to2;
 | |
|   },
 | |
|   number(from2, to2, factor) {
 | |
|     return from2 + (to2 - from2) * factor;
 | |
|   }
 | |
| };
 | |
| var Animation = class {
 | |
|   constructor(cfg, target, prop, to2) {
 | |
|     const currentValue = target[prop];
 | |
|     to2 = resolve([
 | |
|       cfg.to,
 | |
|       to2,
 | |
|       currentValue,
 | |
|       cfg.from
 | |
|     ]);
 | |
|     const from2 = resolve([
 | |
|       cfg.from,
 | |
|       currentValue,
 | |
|       to2
 | |
|     ]);
 | |
|     this._active = true;
 | |
|     this._fn = cfg.fn || interpolators[cfg.type || typeof from2];
 | |
|     this._easing = effects[cfg.easing] || effects.linear;
 | |
|     this._start = Math.floor(Date.now() + (cfg.delay || 0));
 | |
|     this._duration = this._total = Math.floor(cfg.duration);
 | |
|     this._loop = !!cfg.loop;
 | |
|     this._target = target;
 | |
|     this._prop = prop;
 | |
|     this._from = from2;
 | |
|     this._to = to2;
 | |
|     this._promises = void 0;
 | |
|   }
 | |
|   active() {
 | |
|     return this._active;
 | |
|   }
 | |
|   update(cfg, to2, date) {
 | |
|     if (this._active) {
 | |
|       this._notify(false);
 | |
|       const currentValue = this._target[this._prop];
 | |
|       const elapsed = date - this._start;
 | |
|       const remain = this._duration - elapsed;
 | |
|       this._start = date;
 | |
|       this._duration = Math.floor(Math.max(remain, cfg.duration));
 | |
|       this._total += elapsed;
 | |
|       this._loop = !!cfg.loop;
 | |
|       this._to = resolve([
 | |
|         cfg.to,
 | |
|         to2,
 | |
|         currentValue,
 | |
|         cfg.from
 | |
|       ]);
 | |
|       this._from = resolve([
 | |
|         cfg.from,
 | |
|         currentValue,
 | |
|         to2
 | |
|       ]);
 | |
|     }
 | |
|   }
 | |
|   cancel() {
 | |
|     if (this._active) {
 | |
|       this.tick(Date.now());
 | |
|       this._active = false;
 | |
|       this._notify(false);
 | |
|     }
 | |
|   }
 | |
|   tick(date) {
 | |
|     const elapsed = date - this._start;
 | |
|     const duration = this._duration;
 | |
|     const prop = this._prop;
 | |
|     const from2 = this._from;
 | |
|     const loop = this._loop;
 | |
|     const to2 = this._to;
 | |
|     let factor;
 | |
|     this._active = from2 !== to2 && (loop || elapsed < duration);
 | |
|     if (!this._active) {
 | |
|       this._target[prop] = to2;
 | |
|       this._notify(true);
 | |
|       return;
 | |
|     }
 | |
|     if (elapsed < 0) {
 | |
|       this._target[prop] = from2;
 | |
|       return;
 | |
|     }
 | |
|     factor = elapsed / duration % 2;
 | |
|     factor = loop && factor > 1 ? 2 - factor : factor;
 | |
|     factor = this._easing(Math.min(1, Math.max(0, factor)));
 | |
|     this._target[prop] = this._fn(from2, to2, factor);
 | |
|   }
 | |
|   wait() {
 | |
|     const promises = this._promises || (this._promises = []);
 | |
|     return new Promise((res, rej) => {
 | |
|       promises.push({
 | |
|         res,
 | |
|         rej
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   _notify(resolved) {
 | |
|     const method = resolved ? "res" : "rej";
 | |
|     const promises = this._promises || [];
 | |
|     for (let i2 = 0; i2 < promises.length; i2++) {
 | |
|       promises[i2][method]();
 | |
|     }
 | |
|   }
 | |
| };
 | |
| var Animations = class {
 | |
|   constructor(chart, config) {
 | |
|     this._chart = chart;
 | |
|     this._properties = /* @__PURE__ */ new Map();
 | |
|     this.configure(config);
 | |
|   }
 | |
|   configure(config) {
 | |
|     if (!isObject(config)) {
 | |
|       return;
 | |
|     }
 | |
|     const animationOptions = Object.keys(defaults2.animation);
 | |
|     const animatedProps = this._properties;
 | |
|     Object.getOwnPropertyNames(config).forEach((key) => {
 | |
|       const cfg = config[key];
 | |
|       if (!isObject(cfg)) {
 | |
|         return;
 | |
|       }
 | |
|       const resolved = {};
 | |
|       for (const option of animationOptions) {
 | |
|         resolved[option] = cfg[option];
 | |
|       }
 | |
|       (isArray(cfg.properties) && cfg.properties || [
 | |
|         key
 | |
|       ]).forEach((prop) => {
 | |
|         if (prop === key || !animatedProps.has(prop)) {
 | |
|           animatedProps.set(prop, resolved);
 | |
|         }
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   _animateOptions(target, values) {
 | |
|     const newOptions = values.options;
 | |
|     const options = resolveTargetOptions(target, newOptions);
 | |
|     if (!options) {
 | |
|       return [];
 | |
|     }
 | |
|     const animations = this._createAnimations(options, newOptions);
 | |
|     if (newOptions.$shared) {
 | |
|       awaitAll(target.options.$animations, newOptions).then(() => {
 | |
|         target.options = newOptions;
 | |
|       }, () => {
 | |
|       });
 | |
|     }
 | |
|     return animations;
 | |
|   }
 | |
|   _createAnimations(target, values) {
 | |
|     const animatedProps = this._properties;
 | |
|     const animations = [];
 | |
|     const running = target.$animations || (target.$animations = {});
 | |
|     const props = Object.keys(values);
 | |
|     const date = Date.now();
 | |
|     let i2;
 | |
|     for (i2 = props.length - 1; i2 >= 0; --i2) {
 | |
|       const prop = props[i2];
 | |
|       if (prop.charAt(0) === "$") {
 | |
|         continue;
 | |
|       }
 | |
|       if (prop === "options") {
 | |
|         animations.push(...this._animateOptions(target, values));
 | |
|         continue;
 | |
|       }
 | |
|       const value = values[prop];
 | |
|       let animation = running[prop];
 | |
|       const cfg = animatedProps.get(prop);
 | |
|       if (animation) {
 | |
|         if (cfg && animation.active()) {
 | |
|           animation.update(cfg, value, date);
 | |
|           continue;
 | |
|         } else {
 | |
|           animation.cancel();
 | |
|         }
 | |
|       }
 | |
|       if (!cfg || !cfg.duration) {
 | |
|         target[prop] = value;
 | |
|         continue;
 | |
|       }
 | |
|       running[prop] = animation = new Animation(cfg, target, prop, value);
 | |
|       animations.push(animation);
 | |
|     }
 | |
|     return animations;
 | |
|   }
 | |
|   update(target, values) {
 | |
|     if (this._properties.size === 0) {
 | |
|       Object.assign(target, values);
 | |
|       return;
 | |
|     }
 | |
|     const animations = this._createAnimations(target, values);
 | |
|     if (animations.length) {
 | |
|       animator.add(this._chart, animations);
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
| };
 | |
| function awaitAll(animations, properties) {
 | |
|   const running = [];
 | |
|   const keys = Object.keys(properties);
 | |
|   for (let i2 = 0; i2 < keys.length; i2++) {
 | |
|     const anim = animations[keys[i2]];
 | |
|     if (anim && anim.active()) {
 | |
|       running.push(anim.wait());
 | |
|     }
 | |
|   }
 | |
|   return Promise.all(running);
 | |
| }
 | |
| function resolveTargetOptions(target, newOptions) {
 | |
|   if (!newOptions) {
 | |
|     return;
 | |
|   }
 | |
|   let options = target.options;
 | |
|   if (!options) {
 | |
|     target.options = newOptions;
 | |
|     return;
 | |
|   }
 | |
|   if (options.$shared) {
 | |
|     target.options = options = Object.assign({}, options, {
 | |
|       $shared: false,
 | |
|       $animations: {}
 | |
|     });
 | |
|   }
 | |
|   return options;
 | |
| }
 | |
| function scaleClip(scale, allowedOverflow) {
 | |
|   const opts = scale && scale.options || {};
 | |
|   const reverse = opts.reverse;
 | |
|   const min = opts.min === void 0 ? allowedOverflow : 0;
 | |
|   const max = opts.max === void 0 ? allowedOverflow : 0;
 | |
|   return {
 | |
|     start: reverse ? max : min,
 | |
|     end: reverse ? min : max
 | |
|   };
 | |
| }
 | |
| function defaultClip(xScale, yScale, allowedOverflow) {
 | |
|   if (allowedOverflow === false) {
 | |
|     return false;
 | |
|   }
 | |
|   const x2 = scaleClip(xScale, allowedOverflow);
 | |
|   const y2 = scaleClip(yScale, allowedOverflow);
 | |
|   return {
 | |
|     top: y2.end,
 | |
|     right: x2.end,
 | |
|     bottom: y2.start,
 | |
|     left: x2.start
 | |
|   };
 | |
| }
 | |
| function toClip(value) {
 | |
|   let t3, r2, b2, l2;
 | |
|   if (isObject(value)) {
 | |
|     t3 = value.top;
 | |
|     r2 = value.right;
 | |
|     b2 = value.bottom;
 | |
|     l2 = value.left;
 | |
|   } else {
 | |
|     t3 = r2 = b2 = l2 = value;
 | |
|   }
 | |
|   return {
 | |
|     top: t3,
 | |
|     right: r2,
 | |
|     bottom: b2,
 | |
|     left: l2,
 | |
|     disabled: value === false
 | |
|   };
 | |
| }
 | |
| function getSortedDatasetIndices(chart, filterVisible) {
 | |
|   const keys = [];
 | |
|   const metasets = chart._getSortedDatasetMetas(filterVisible);
 | |
|   let i2, ilen;
 | |
|   for (i2 = 0, ilen = metasets.length; i2 < ilen; ++i2) {
 | |
|     keys.push(metasets[i2].index);
 | |
|   }
 | |
|   return keys;
 | |
| }
 | |
| function applyStack(stack, value, dsIndex, options = {}) {
 | |
|   const keys = stack.keys;
 | |
|   const singleMode = options.mode === "single";
 | |
|   let i2, ilen, datasetIndex, otherValue;
 | |
|   if (value === null) {
 | |
|     return;
 | |
|   }
 | |
|   let found = false;
 | |
|   for (i2 = 0, ilen = keys.length; i2 < ilen; ++i2) {
 | |
|     datasetIndex = +keys[i2];
 | |
|     if (datasetIndex === dsIndex) {
 | |
|       found = true;
 | |
|       if (options.all) {
 | |
|         continue;
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|     otherValue = stack.values[datasetIndex];
 | |
|     if (isNumberFinite(otherValue) && (singleMode || value === 0 || sign(value) === sign(otherValue))) {
 | |
|       value += otherValue;
 | |
|     }
 | |
|   }
 | |
|   if (!found && !options.all) {
 | |
|     return 0;
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| function convertObjectDataToArray(data, meta) {
 | |
|   const { iScale, vScale } = meta;
 | |
|   const iAxisKey = iScale.axis === "x" ? "x" : "y";
 | |
|   const vAxisKey = vScale.axis === "x" ? "x" : "y";
 | |
|   const keys = Object.keys(data);
 | |
|   const adata = new Array(keys.length);
 | |
|   let i2, ilen, key;
 | |
|   for (i2 = 0, ilen = keys.length; i2 < ilen; ++i2) {
 | |
|     key = keys[i2];
 | |
|     adata[i2] = {
 | |
|       [iAxisKey]: key,
 | |
|       [vAxisKey]: data[key]
 | |
|     };
 | |
|   }
 | |
|   return adata;
 | |
| }
 | |
| function isStacked(scale, meta) {
 | |
|   const stacked = scale && scale.options.stacked;
 | |
|   return stacked || stacked === void 0 && meta.stack !== void 0;
 | |
| }
 | |
| function getStackKey(indexScale, valueScale, meta) {
 | |
|   return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`;
 | |
| }
 | |
| function getUserBounds(scale) {
 | |
|   const { min, max, minDefined, maxDefined } = scale.getUserBounds();
 | |
|   return {
 | |
|     min: minDefined ? min : Number.NEGATIVE_INFINITY,
 | |
|     max: maxDefined ? max : Number.POSITIVE_INFINITY
 | |
|   };
 | |
| }
 | |
| function getOrCreateStack(stacks, stackKey, indexValue) {
 | |
|   const subStack = stacks[stackKey] || (stacks[stackKey] = {});
 | |
|   return subStack[indexValue] || (subStack[indexValue] = {});
 | |
| }
 | |
| function getLastIndexInStack(stack, vScale, positive, type) {
 | |
|   for (const meta of vScale.getMatchingVisibleMetas(type).reverse()) {
 | |
|     const value = stack[meta.index];
 | |
|     if (positive && value > 0 || !positive && value < 0) {
 | |
|       return meta.index;
 | |
|     }
 | |
|   }
 | |
|   return null;
 | |
| }
 | |
| function updateStacks(controller, parsed) {
 | |
|   const { chart, _cachedMeta: meta } = controller;
 | |
|   const stacks = chart._stacks || (chart._stacks = {});
 | |
|   const { iScale, vScale, index: datasetIndex } = meta;
 | |
|   const iAxis = iScale.axis;
 | |
|   const vAxis = vScale.axis;
 | |
|   const key = getStackKey(iScale, vScale, meta);
 | |
|   const ilen = parsed.length;
 | |
|   let stack;
 | |
|   for (let i2 = 0; i2 < ilen; ++i2) {
 | |
|     const item = parsed[i2];
 | |
|     const { [iAxis]: index, [vAxis]: value } = item;
 | |
|     const itemStacks = item._stacks || (item._stacks = {});
 | |
|     stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);
 | |
|     stack[datasetIndex] = value;
 | |
|     stack._top = getLastIndexInStack(stack, vScale, true, meta.type);
 | |
|     stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type);
 | |
|     const visualValues = stack._visualValues || (stack._visualValues = {});
 | |
|     visualValues[datasetIndex] = value;
 | |
|   }
 | |
| }
 | |
| function getFirstScaleId(chart, axis) {
 | |
|   const scales = chart.scales;
 | |
|   return Object.keys(scales).filter((key) => scales[key].axis === axis).shift();
 | |
| }
 | |
| function createDatasetContext(parent, index) {
 | |
|   return createContext(parent, {
 | |
|     active: false,
 | |
|     dataset: void 0,
 | |
|     datasetIndex: index,
 | |
|     index,
 | |
|     mode: "default",
 | |
|     type: "dataset"
 | |
|   });
 | |
| }
 | |
| function createDataContext(parent, index, element) {
 | |
|   return createContext(parent, {
 | |
|     active: false,
 | |
|     dataIndex: index,
 | |
|     parsed: void 0,
 | |
|     raw: void 0,
 | |
|     element,
 | |
|     index,
 | |
|     mode: "default",
 | |
|     type: "data"
 | |
|   });
 | |
| }
 | |
| function clearStacks(meta, items) {
 | |
|   const datasetIndex = meta.controller.index;
 | |
|   const axis = meta.vScale && meta.vScale.axis;
 | |
|   if (!axis) {
 | |
|     return;
 | |
|   }
 | |
|   items = items || meta._parsed;
 | |
|   for (const parsed of items) {
 | |
|     const stacks = parsed._stacks;
 | |
|     if (!stacks || stacks[axis] === void 0 || stacks[axis][datasetIndex] === void 0) {
 | |
|       return;
 | |
|     }
 | |
|     delete stacks[axis][datasetIndex];
 | |
|     if (stacks[axis]._visualValues !== void 0 && stacks[axis]._visualValues[datasetIndex] !== void 0) {
 | |
|       delete stacks[axis]._visualValues[datasetIndex];
 | |
|     }
 | |
|   }
 | |
| }
 | |
| var isDirectUpdateMode = (mode) => mode === "reset" || mode === "none";
 | |
| var cloneIfNotShared = (cached, shared) => shared ? cached : Object.assign({}, cached);
 | |
| var createStack = (canStack, meta, chart) => canStack && !meta.hidden && meta._stacked && {
 | |
|   keys: getSortedDatasetIndices(chart, true),
 | |
|   values: null
 | |
| };
 | |
| var DatasetController = class {
 | |
|   constructor(chart, datasetIndex) {
 | |
|     this.chart = chart;
 | |
|     this._ctx = chart.ctx;
 | |
|     this.index = datasetIndex;
 | |
|     this._cachedDataOpts = {};
 | |
|     this._cachedMeta = this.getMeta();
 | |
|     this._type = this._cachedMeta.type;
 | |
|     this.options = void 0;
 | |
|     this._parsing = false;
 | |
|     this._data = void 0;
 | |
|     this._objectData = void 0;
 | |
|     this._sharedOptions = void 0;
 | |
|     this._drawStart = void 0;
 | |
|     this._drawCount = void 0;
 | |
|     this.enableOptionSharing = false;
 | |
|     this.supportsDecimation = false;
 | |
|     this.$context = void 0;
 | |
|     this._syncList = [];
 | |
|     this.datasetElementType = new.target.datasetElementType;
 | |
|     this.dataElementType = new.target.dataElementType;
 | |
|     this.initialize();
 | |
|   }
 | |
|   initialize() {
 | |
|     const meta = this._cachedMeta;
 | |
|     this.configure();
 | |
|     this.linkScales();
 | |
|     meta._stacked = isStacked(meta.vScale, meta);
 | |
|     this.addElements();
 | |
|     if (this.options.fill && !this.chart.isPluginEnabled("filler")) {
 | |
|       console.warn("Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options");
 | |
|     }
 | |
|   }
 | |
|   updateIndex(datasetIndex) {
 | |
|     if (this.index !== datasetIndex) {
 | |
|       clearStacks(this._cachedMeta);
 | |
|     }
 | |
|     this.index = datasetIndex;
 | |
|   }
 | |
|   linkScales() {
 | |
|     const chart = this.chart;
 | |
|     const meta = this._cachedMeta;
 | |
|     const dataset = this.getDataset();
 | |
|     const chooseId = (axis, x2, y2, r2) => axis === "x" ? x2 : axis === "r" ? r2 : y2;
 | |
|     const xid = meta.xAxisID = valueOrDefault(dataset.xAxisID, getFirstScaleId(chart, "x"));
 | |
|     const yid = meta.yAxisID = valueOrDefault(dataset.yAxisID, getFirstScaleId(chart, "y"));
 | |
|     const rid = meta.rAxisID = valueOrDefault(dataset.rAxisID, getFirstScaleId(chart, "r"));
 | |
|     const indexAxis = meta.indexAxis;
 | |
|     const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);
 | |
|     const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);
 | |
|     meta.xScale = this.getScaleForId(xid);
 | |
|     meta.yScale = this.getScaleForId(yid);
 | |
|     meta.rScale = this.getScaleForId(rid);
 | |
|     meta.iScale = this.getScaleForId(iid);
 | |
|     meta.vScale = this.getScaleForId(vid);
 | |
|   }
 | |
|   getDataset() {
 | |
|     return this.chart.data.datasets[this.index];
 | |
|   }
 | |
|   getMeta() {
 | |
|     return this.chart.getDatasetMeta(this.index);
 | |
|   }
 | |
|   getScaleForId(scaleID) {
 | |
|     return this.chart.scales[scaleID];
 | |
|   }
 | |
|   _getOtherScale(scale) {
 | |
|     const meta = this._cachedMeta;
 | |
|     return scale === meta.iScale ? meta.vScale : meta.iScale;
 | |
|   }
 | |
|   reset() {
 | |
|     this._update("reset");
 | |
|   }
 | |
|   _destroy() {
 | |
|     const meta = this._cachedMeta;
 | |
|     if (this._data) {
 | |
|       unlistenArrayEvents(this._data, this);
 | |
|     }
 | |
|     if (meta._stacked) {
 | |
|       clearStacks(meta);
 | |
|     }
 | |
|   }
 | |
|   _dataCheck() {
 | |
|     const dataset = this.getDataset();
 | |
|     const data = dataset.data || (dataset.data = []);
 | |
|     const _data = this._data;
 | |
|     if (isObject(data)) {
 | |
|       const meta = this._cachedMeta;
 | |
|       this._data = convertObjectDataToArray(data, meta);
 | |
|     } else if (_data !== data) {
 | |
|       if (_data) {
 | |
|         unlistenArrayEvents(_data, this);
 | |
|         const meta = this._cachedMeta;
 | |
|         clearStacks(meta);
 | |
|         meta._parsed = [];
 | |
|       }
 | |
|       if (data && Object.isExtensible(data)) {
 | |
|         listenArrayEvents(data, this);
 | |
|       }
 | |
|       this._syncList = [];
 | |
|       this._data = data;
 | |
|     }
 | |
|   }
 | |
|   addElements() {
 | |
|     const meta = this._cachedMeta;
 | |
|     this._dataCheck();
 | |
|     if (this.datasetElementType) {
 | |
|       meta.dataset = new this.datasetElementType();
 | |
|     }
 | |
|   }
 | |
|   buildOrUpdateElements(resetNewElements) {
 | |
|     const meta = this._cachedMeta;
 | |
|     const dataset = this.getDataset();
 | |
|     let stackChanged = false;
 | |
|     this._dataCheck();
 | |
|     const oldStacked = meta._stacked;
 | |
|     meta._stacked = isStacked(meta.vScale, meta);
 | |
|     if (meta.stack !== dataset.stack) {
 | |
|       stackChanged = true;
 | |
|       clearStacks(meta);
 | |
|       meta.stack = dataset.stack;
 | |
|     }
 | |
|     this._resyncElements(resetNewElements);
 | |
|     if (stackChanged || oldStacked !== meta._stacked) {
 | |
|       updateStacks(this, meta._parsed);
 | |
|       meta._stacked = isStacked(meta.vScale, meta);
 | |
|     }
 | |
|   }
 | |
|   configure() {
 | |
|     const config = this.chart.config;
 | |
|     const scopeKeys = config.datasetScopeKeys(this._type);
 | |
|     const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);
 | |
|     this.options = config.createResolver(scopes, this.getContext());
 | |
|     this._parsing = this.options.parsing;
 | |
|     this._cachedDataOpts = {};
 | |
|   }
 | |
|   parse(start, count) {
 | |
|     const { _cachedMeta: meta, _data: data } = this;
 | |
|     const { iScale, _stacked } = meta;
 | |
|     const iAxis = iScale.axis;
 | |
|     let sorted = start === 0 && count === data.length ? true : meta._sorted;
 | |
|     let prev = start > 0 && meta._parsed[start - 1];
 | |
|     let i2, cur, parsed;
 | |
|     if (this._parsing === false) {
 | |
|       meta._parsed = data;
 | |
|       meta._sorted = true;
 | |
|       parsed = data;
 | |
|     } else {
 | |
|       if (isArray(data[start])) {
 | |
|         parsed = this.parseArrayData(meta, data, start, count);
 | |
|       } else if (isObject(data[start])) {
 | |
|         parsed = this.parseObjectData(meta, data, start, count);
 | |
|       } else {
 | |
|         parsed = this.parsePrimitiveData(meta, data, start, count);
 | |
|       }
 | |
|       const isNotInOrderComparedToPrev = () => cur[iAxis] === null || prev && cur[iAxis] < prev[iAxis];
 | |
|       for (i2 = 0; i2 < count; ++i2) {
 | |
|         meta._parsed[i2 + start] = cur = parsed[i2];
 | |
|         if (sorted) {
 | |
|           if (isNotInOrderComparedToPrev()) {
 | |
|             sorted = false;
 | |
|           }
 | |
|           prev = cur;
 | |
|         }
 | |
|       }
 | |
|       meta._sorted = sorted;
 | |
|     }
 | |
|     if (_stacked) {
 | |
|       updateStacks(this, parsed);
 | |
|     }
 | |
|   }
 | |
|   parsePrimitiveData(meta, data, start, count) {
 | |
|     const { iScale, vScale } = meta;
 | |
|     const iAxis = iScale.axis;
 | |
|     const vAxis = vScale.axis;
 | |
|     const labels = iScale.getLabels();
 | |
|     const singleScale = iScale === vScale;
 | |
|     const parsed = new Array(count);
 | |
|     let i2, ilen, index;
 | |
|     for (i2 = 0, ilen = count; i2 < ilen; ++i2) {
 | |
|       index = i2 + start;
 | |
|       parsed[i2] = {
 | |
|         [iAxis]: singleScale || iScale.parse(labels[index], index),
 | |
|         [vAxis]: vScale.parse(data[index], index)
 | |
|       };
 | |
|     }
 | |
|     return parsed;
 | |
|   }
 | |
|   parseArrayData(meta, data, start, count) {
 | |
|     const { xScale, yScale } = meta;
 | |
|     const parsed = new Array(count);
 | |
|     let i2, ilen, index, item;
 | |
|     for (i2 = 0, ilen = count; i2 < ilen; ++i2) {
 | |
|       index = i2 + start;
 | |
|       item = data[index];
 | |
|       parsed[i2] = {
 | |
|         x: xScale.parse(item[0], index),
 | |
|         y: yScale.parse(item[1], index)
 | |
|       };
 | |
|     }
 | |
|     return parsed;
 | |
|   }
 | |
|   parseObjectData(meta, data, start, count) {
 | |
|     const { xScale, yScale } = meta;
 | |
|     const { xAxisKey = "x", yAxisKey = "y" } = this._parsing;
 | |
|     const parsed = new Array(count);
 | |
|     let i2, ilen, index, item;
 | |
|     for (i2 = 0, ilen = count; i2 < ilen; ++i2) {
 | |
|       index = i2 + start;
 | |
|       item = data[index];
 | |
|       parsed[i2] = {
 | |
|         x: xScale.parse(resolveObjectKey(item, xAxisKey), index),
 | |
|         y: yScale.parse(resolveObjectKey(item, yAxisKey), index)
 | |
|       };
 | |
|     }
 | |
|     return parsed;
 | |
|   }
 | |
|   getParsed(index) {
 | |
|     return this._cachedMeta._parsed[index];
 | |
|   }
 | |
|   getDataElement(index) {
 | |
|     return this._cachedMeta.data[index];
 | |
|   }
 | |
|   applyStack(scale, parsed, mode) {
 | |
|     const chart = this.chart;
 | |
|     const meta = this._cachedMeta;
 | |
|     const value = parsed[scale.axis];
 | |
|     const stack = {
 | |
|       keys: getSortedDatasetIndices(chart, true),
 | |
|       values: parsed._stacks[scale.axis]._visualValues
 | |
|     };
 | |
|     return applyStack(stack, value, meta.index, {
 | |
|       mode
 | |
|     });
 | |
|   }
 | |
|   updateRangeFromParsed(range, scale, parsed, stack) {
 | |
|     const parsedValue = parsed[scale.axis];
 | |
|     let value = parsedValue === null ? NaN : parsedValue;
 | |
|     const values = stack && parsed._stacks[scale.axis];
 | |
|     if (stack && values) {
 | |
|       stack.values = values;
 | |
|       value = applyStack(stack, parsedValue, this._cachedMeta.index);
 | |
|     }
 | |
|     range.min = Math.min(range.min, value);
 | |
|     range.max = Math.max(range.max, value);
 | |
|   }
 | |
|   getMinMax(scale, canStack) {
 | |
|     const meta = this._cachedMeta;
 | |
|     const _parsed = meta._parsed;
 | |
|     const sorted = meta._sorted && scale === meta.iScale;
 | |
|     const ilen = _parsed.length;
 | |
|     const otherScale = this._getOtherScale(scale);
 | |
|     const stack = createStack(canStack, meta, this.chart);
 | |
|     const range = {
 | |
|       min: Number.POSITIVE_INFINITY,
 | |
|       max: Number.NEGATIVE_INFINITY
 | |
|     };
 | |
|     const { min: otherMin, max: otherMax } = getUserBounds(otherScale);
 | |
|     let i2, parsed;
 | |
|     function _skip() {
 | |
|       parsed = _parsed[i2];
 | |
|       const otherValue = parsed[otherScale.axis];
 | |
|       return !isNumberFinite(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;
 | |
|     }
 | |
|     for (i2 = 0; i2 < ilen; ++i2) {
 | |
|       if (_skip()) {
 | |
|         continue;
 | |
|       }
 | |
|       this.updateRangeFromParsed(range, scale, parsed, stack);
 | |
|       if (sorted) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (sorted) {
 | |
|       for (i2 = ilen - 1; i2 >= 0; --i2) {
 | |
|         if (_skip()) {
 | |
|           continue;
 | |
|         }
 | |
|         this.updateRangeFromParsed(range, scale, parsed, stack);
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     return range;
 | |
|   }
 | |
|   getAllParsedValues(scale) {
 | |
|     const parsed = this._cachedMeta._parsed;
 | |
|     const values = [];
 | |
|     let i2, ilen, value;
 | |
|     for (i2 = 0, ilen = parsed.length; i2 < ilen; ++i2) {
 | |
|       value = parsed[i2][scale.axis];
 | |
|       if (isNumberFinite(value)) {
 | |
|         values.push(value);
 | |
|       }
 | |
|     }
 | |
|     return values;
 | |
|   }
 | |
|   getMaxOverflow() {
 | |
|     return false;
 | |
|   }
 | |
|   getLabelAndValue(index) {
 | |
|     const meta = this._cachedMeta;
 | |
|     const iScale = meta.iScale;
 | |
|     const vScale = meta.vScale;
 | |
|     const parsed = this.getParsed(index);
 | |
|     return {
 | |
|       label: iScale ? "" + iScale.getLabelForValue(parsed[iScale.axis]) : "",
 | |
|       value: vScale ? "" + vScale.getLabelForValue(parsed[vScale.axis]) : ""
 | |
|     };
 | |
|   }
 | |
|   _update(mode) {
 | |
|     const meta = this._cachedMeta;
 | |
|     this.update(mode || "default");
 | |
|     meta._clip = toClip(valueOrDefault(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));
 | |
|   }
 | |
|   update(mode) {
 | |
|   }
 | |
|   draw() {
 | |
|     const ctx = this._ctx;
 | |
|     const chart = this.chart;
 | |
|     const meta = this._cachedMeta;
 | |
|     const elements = meta.data || [];
 | |
|     const area = chart.chartArea;
 | |
|     const active = [];
 | |
|     const start = this._drawStart || 0;
 | |
|     const count = this._drawCount || elements.length - start;
 | |
|     const drawActiveElementsOnTop = this.options.drawActiveElementsOnTop;
 | |
|     let i2;
 | |
|     if (meta.dataset) {
 | |
|       meta.dataset.draw(ctx, area, start, count);
 | |
|     }
 | |
|     for (i2 = start; i2 < start + count; ++i2) {
 | |
|       const element = elements[i2];
 | |
|       if (element.hidden) {
 | |
|         continue;
 | |
|       }
 | |
|       if (element.active && drawActiveElementsOnTop) {
 | |
|         active.push(element);
 | |
|       } else {
 | |
|         element.draw(ctx, area);
 | |
|       }
 | |
|     }
 | |
|     for (i2 = 0; i2 < active.length; ++i2) {
 | |
|       active[i2].draw(ctx, area);
 | |
|     }
 | |
|   }
 | |
|   getStyle(index, active) {
 | |
|     const mode = active ? "active" : "default";
 | |
|     return index === void 0 && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode);
 | |
|   }
 | |
|   getContext(index, active, mode) {
 | |
|     const dataset = this.getDataset();
 | |
|     let context;
 | |
|     if (index >= 0 && index < this._cachedMeta.data.length) {
 | |
|       const element = this._cachedMeta.data[index];
 | |
|       context = element.$context || (element.$context = createDataContext(this.getContext(), index, element));
 | |
|       context.parsed = this.getParsed(index);
 | |
|       context.raw = dataset.data[index];
 | |
|       context.index = context.dataIndex = index;
 | |
|     } else {
 | |
|       context = this.$context || (this.$context = createDatasetContext(this.chart.getContext(), this.index));
 | |
|       context.dataset = dataset;
 | |
|       context.index = context.datasetIndex = this.index;
 | |
|     }
 | |
|     context.active = !!active;
 | |
|     context.mode = mode;
 | |
|     return context;
 | |
|   }
 | |
|   resolveDatasetElementOptions(mode) {
 | |
|     return this._resolveElementOptions(this.datasetElementType.id, mode);
 | |
|   }
 | |
|   resolveDataElementOptions(index, mode) {
 | |
|     return this._resolveElementOptions(this.dataElementType.id, mode, index);
 | |
|   }
 | |
|   _resolveElementOptions(elementType, mode = "default", index) {
 | |
|     const active = mode === "active";
 | |
|     const cache = this._cachedDataOpts;
 | |
|     const cacheKey = elementType + "-" + mode;
 | |
|     const cached = cache[cacheKey];
 | |
|     const sharing = this.enableOptionSharing && defined(index);
 | |
|     if (cached) {
 | |
|       return cloneIfNotShared(cached, sharing);
 | |
|     }
 | |
|     const config = this.chart.config;
 | |
|     const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);
 | |
|     const prefixes = active ? [
 | |
|       `${elementType}Hover`,
 | |
|       "hover",
 | |
|       elementType,
 | |
|       ""
 | |
|     ] : [
 | |
|       elementType,
 | |
|       ""
 | |
|     ];
 | |
|     const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
 | |
|     const names2 = Object.keys(defaults2.elements[elementType]);
 | |
|     const context = () => this.getContext(index, active, mode);
 | |
|     const values = config.resolveNamedOptions(scopes, names2, context, prefixes);
 | |
|     if (values.$shared) {
 | |
|       values.$shared = sharing;
 | |
|       cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing));
 | |
|     }
 | |
|     return values;
 | |
|   }
 | |
|   _resolveAnimations(index, transition, active) {
 | |
|     const chart = this.chart;
 | |
|     const cache = this._cachedDataOpts;
 | |
|     const cacheKey = `animation-${transition}`;
 | |
|     const cached = cache[cacheKey];
 | |
|     if (cached) {
 | |
|       return cached;
 | |
|     }
 | |
|     let options;
 | |
|     if (chart.options.animation !== false) {
 | |
|       const config = this.chart.config;
 | |
|       const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);
 | |
|       const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
 | |
|       options = config.createResolver(scopes, this.getContext(index, active, transition));
 | |
|     }
 | |
|     const animations = new Animations(chart, options && options.animations);
 | |
|     if (options && options._cacheable) {
 | |
|       cache[cacheKey] = Object.freeze(animations);
 | |
|     }
 | |
|     return animations;
 | |
|   }
 | |
|   getSharedOptions(options) {
 | |
|     if (!options.$shared) {
 | |
|       return;
 | |
|     }
 | |
|     return this._sharedOptions || (this._sharedOptions = Object.assign({}, options));
 | |
|   }
 | |
|   includeOptions(mode, sharedOptions) {
 | |
|     return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled;
 | |
|   }
 | |
|   _getSharedOptions(start, mode) {
 | |
|     const firstOpts = this.resolveDataElementOptions(start, mode);
 | |
|     const previouslySharedOptions = this._sharedOptions;
 | |
|     const sharedOptions = this.getSharedOptions(firstOpts);
 | |
|     const includeOptions = this.includeOptions(mode, sharedOptions) || sharedOptions !== previouslySharedOptions;
 | |
|     this.updateSharedOptions(sharedOptions, mode, firstOpts);
 | |
|     return {
 | |
|       sharedOptions,
 | |
|       includeOptions
 | |
|     };
 | |
|   }
 | |
|   updateElement(element, index, properties, mode) {
 | |
|     if (isDirectUpdateMode(mode)) {
 | |
|       Object.assign(element, properties);
 | |
|     } else {
 | |
|       this._resolveAnimations(index, mode).update(element, properties);
 | |
|     }
 | |
|   }
 | |
|   updateSharedOptions(sharedOptions, mode, newOptions) {
 | |
|     if (sharedOptions && !isDirectUpdateMode(mode)) {
 | |
|       this._resolveAnimations(void 0, mode).update(sharedOptions, newOptions);
 | |
|     }
 | |
|   }
 | |
|   _setStyle(element, index, mode, active) {
 | |
|     element.active = active;
 | |
|     const options = this.getStyle(index, active);
 | |
|     this._resolveAnimations(index, mode, active).update(element, {
 | |
|       options: !active && this.getSharedOptions(options) || options
 | |
|     });
 | |
|   }
 | |
|   removeHoverStyle(element, datasetIndex, index) {
 | |
|     this._setStyle(element, index, "active", false);
 | |
|   }
 | |
|   setHoverStyle(element, datasetIndex, index) {
 | |
|     this._setStyle(element, index, "active", true);
 | |
|   }
 | |
|   _removeDatasetHoverStyle() {
 | |
|     const element = this._cachedMeta.dataset;
 | |
|     if (element) {
 | |
|       this._setStyle(element, void 0, "active", false);
 | |
|     }
 | |
|   }
 | |
|   _setDatasetHoverStyle() {
 | |
|     const element = this._cachedMeta.dataset;
 | |
|     if (element) {
 | |
|       this._setStyle(element, void 0, "active", true);
 | |
|     }
 | |
|   }
 | |
|   _resyncElements(resetNewElements) {
 | |
|     const data = this._data;
 | |
|     const elements = this._cachedMeta.data;
 | |
|     for (const [method, arg1, arg2] of this._syncList) {
 | |
|       this[method](arg1, arg2);
 | |
|     }
 | |
|     this._syncList = [];
 | |
|     const numMeta = elements.length;
 | |
|     const numData = data.length;
 | |
|     const count = Math.min(numData, numMeta);
 | |
|     if (count) {
 | |
|       this.parse(0, count);
 | |
|     }
 | |
|     if (numData > numMeta) {
 | |
|       this._insertElements(numMeta, numData - numMeta, resetNewElements);
 | |
|     } else if (numData < numMeta) {
 | |
|       this._removeElements(numData, numMeta - numData);
 | |
|     }
 | |
|   }
 | |
|   _insertElements(start, count, resetNewElements = true) {
 | |
|     const meta = this._cachedMeta;
 | |
|     const data = meta.data;
 | |
|     const end = start + count;
 | |
|     let i2;
 | |
|     const move = (arr) => {
 | |
|       arr.length += count;
 | |
|       for (i2 = arr.length - 1; i2 >= end; i2--) {
 | |
|         arr[i2] = arr[i2 - count];
 | |
|       }
 | |
|     };
 | |
|     move(data);
 | |
|     for (i2 = start; i2 < end; ++i2) {
 | |
|       data[i2] = new this.dataElementType();
 | |
|     }
 | |
|     if (this._parsing) {
 | |
|       move(meta._parsed);
 | |
|     }
 | |
|     this.parse(start, count);
 | |
|     if (resetNewElements) {
 | |
|       this.updateElements(data, start, count, "reset");
 | |
|     }
 | |
|   }
 | |
|   updateElements(element, start, count, mode) {
 | |
|   }
 | |
|   _removeElements(start, count) {
 | |
|     const meta = this._cachedMeta;
 | |
|     if (this._parsing) {
 | |
|       const removed = meta._parsed.splice(start, count);
 | |
|       if (meta._stacked) {
 | |
|         clearStacks(meta, removed);
 | |
|       }
 | |
|     }
 | |
|     meta.data.splice(start, count);
 | |
|   }
 | |
|   _sync(args) {
 | |
|     if (this._parsing) {
 | |
|       this._syncList.push(args);
 | |
|     } else {
 | |
|       const [method, arg1, arg2] = args;
 | |
|       this[method](arg1, arg2);
 | |
|     }
 | |
|     this.chart._dataChanges.push([
 | |
|       this.index,
 | |
|       ...args
 | |
|     ]);
 | |
|   }
 | |
|   _onDataPush() {
 | |
|     const count = arguments.length;
 | |
|     this._sync([
 | |
|       "_insertElements",
 | |
|       this.getDataset().data.length - count,
 | |
|       count
 | |
|     ]);
 | |
|   }
 | |
|   _onDataPop() {
 | |
|     this._sync([
 | |
|       "_removeElements",
 | |
|       this._cachedMeta.data.length - 1,
 | |
|       1
 | |
|     ]);
 | |
|   }
 | |
|   _onDataShift() {
 | |
|     this._sync([
 | |
|       "_removeElements",
 | |
|       0,
 | |
|       1
 | |
|     ]);
 | |
|   }
 | |
|   _onDataSplice(start, count) {
 | |
|     if (count) {
 | |
|       this._sync([
 | |
|         "_removeElements",
 | |
|         start,
 | |
|         count
 | |
|       ]);
 | |
|     }
 | |
|     const newCount = arguments.length - 2;
 | |
|     if (newCount) {
 | |
|       this._sync([
 | |
|         "_insertElements",
 | |
|         start,
 | |
|         newCount
 | |
|       ]);
 | |
|     }
 | |
|   }
 | |
|   _onDataUnshift() {
 | |
|     this._sync([
 | |
|       "_insertElements",
 | |
|       0,
 | |
|       arguments.length
 | |
|     ]);
 | |
|   }
 | |
| };
 | |
| __publicField(DatasetController, "defaults", {});
 | |
| __publicField(DatasetController, "datasetElementType", null);
 | |
| __publicField(DatasetController, "dataElementType", null);
 | |
| function getAllScaleValues(scale, type) {
 | |
|   if (!scale._cache.$bar) {
 | |
|     const visibleMetas = scale.getMatchingVisibleMetas(type);
 | |
|     let values = [];
 | |
|     for (let i2 = 0, ilen = visibleMetas.length; i2 < ilen; i2++) {
 | |
|       values = values.concat(visibleMetas[i2].controller.getAllParsedValues(scale));
 | |
|     }
 | |
|     scale._cache.$bar = _arrayUnique(values.sort((a2, b2) => a2 - b2));
 | |
|   }
 | |
|   return scale._cache.$bar;
 | |
| }
 | |
| function computeMinSampleSize(meta) {
 | |
|   const scale = meta.iScale;
 | |
|   const values = getAllScaleValues(scale, meta.type);
 | |
|   let min = scale._length;
 | |
|   let i2, ilen, curr, prev;
 | |
|   const updateMinAndPrev = () => {
 | |
|     if (curr === 32767 || curr === -32768) {
 | |
|       return;
 | |
|     }
 | |
|     if (defined(prev)) {
 | |
|       min = Math.min(min, Math.abs(curr - prev) || min);
 | |
|     }
 | |
|     prev = curr;
 | |
|   };
 | |
|   for (i2 = 0, ilen = values.length; i2 < ilen; ++i2) {
 | |
|     curr = scale.getPixelForValue(values[i2]);
 | |
|     updateMinAndPrev();
 | |
|   }
 | |
|   prev = void 0;
 | |
|   for (i2 = 0, ilen = scale.ticks.length; i2 < ilen; ++i2) {
 | |
|     curr = scale.getPixelForTick(i2);
 | |
|     updateMinAndPrev();
 | |
|   }
 | |
|   return min;
 | |
| }
 | |
| function computeFitCategoryTraits(index, ruler, options, stackCount) {
 | |
|   const thickness = options.barThickness;
 | |
|   let size, ratio;
 | |
|   if (isNullOrUndef(thickness)) {
 | |
|     size = ruler.min * options.categoryPercentage;
 | |
|     ratio = options.barPercentage;
 | |
|   } else {
 | |
|     size = thickness * stackCount;
 | |
|     ratio = 1;
 | |
|   }
 | |
|   return {
 | |
|     chunk: size / stackCount,
 | |
|     ratio,
 | |
|     start: ruler.pixels[index] - size / 2
 | |
|   };
 | |
| }
 | |
| function computeFlexCategoryTraits(index, ruler, options, stackCount) {
 | |
|   const pixels = ruler.pixels;
 | |
|   const curr = pixels[index];
 | |
|   let prev = index > 0 ? pixels[index - 1] : null;
 | |
|   let next = index < pixels.length - 1 ? pixels[index + 1] : null;
 | |
|   const percent = options.categoryPercentage;
 | |
|   if (prev === null) {
 | |
|     prev = curr - (next === null ? ruler.end - ruler.start : next - curr);
 | |
|   }
 | |
|   if (next === null) {
 | |
|     next = curr + curr - prev;
 | |
|   }
 | |
|   const start = curr - (curr - Math.min(prev, next)) / 2 * percent;
 | |
|   const size = Math.abs(next - prev) / 2 * percent;
 | |
|   return {
 | |
|     chunk: size / stackCount,
 | |
|     ratio: options.barPercentage,
 | |
|     start
 | |
|   };
 | |
| }
 | |
| function parseFloatBar(entry, item, vScale, i2) {
 | |
|   const startValue = vScale.parse(entry[0], i2);
 | |
|   const endValue = vScale.parse(entry[1], i2);
 | |
|   const min = Math.min(startValue, endValue);
 | |
|   const max = Math.max(startValue, endValue);
 | |
|   let barStart = min;
 | |
|   let barEnd = max;
 | |
|   if (Math.abs(min) > Math.abs(max)) {
 | |
|     barStart = max;
 | |
|     barEnd = min;
 | |
|   }
 | |
|   item[vScale.axis] = barEnd;
 | |
|   item._custom = {
 | |
|     barStart,
 | |
|     barEnd,
 | |
|     start: startValue,
 | |
|     end: endValue,
 | |
|     min,
 | |
|     max
 | |
|   };
 | |
| }
 | |
| function parseValue(entry, item, vScale, i2) {
 | |
|   if (isArray(entry)) {
 | |
|     parseFloatBar(entry, item, vScale, i2);
 | |
|   } else {
 | |
|     item[vScale.axis] = vScale.parse(entry, i2);
 | |
|   }
 | |
|   return item;
 | |
| }
 | |
| function parseArrayOrPrimitive(meta, data, start, count) {
 | |
|   const iScale = meta.iScale;
 | |
|   const vScale = meta.vScale;
 | |
|   const labels = iScale.getLabels();
 | |
|   const singleScale = iScale === vScale;
 | |
|   const parsed = [];
 | |
|   let i2, ilen, item, entry;
 | |
|   for (i2 = start, ilen = start + count; i2 < ilen; ++i2) {
 | |
|     entry = data[i2];
 | |
|     item = {};
 | |
|     item[iScale.axis] = singleScale || iScale.parse(labels[i2], i2);
 | |
|     parsed.push(parseValue(entry, item, vScale, i2));
 | |
|   }
 | |
|   return parsed;
 | |
| }
 | |
| function isFloatBar(custom) {
 | |
|   return custom && custom.barStart !== void 0 && custom.barEnd !== void 0;
 | |
| }
 | |
| function barSign(size, vScale, actualBase) {
 | |
|   if (size !== 0) {
 | |
|     return sign(size);
 | |
|   }
 | |
|   return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);
 | |
| }
 | |
| function borderProps(properties) {
 | |
|   let reverse, start, end, top, bottom;
 | |
|   if (properties.horizontal) {
 | |
|     reverse = properties.base > properties.x;
 | |
|     start = "left";
 | |
|     end = "right";
 | |
|   } else {
 | |
|     reverse = properties.base < properties.y;
 | |
|     start = "bottom";
 | |
|     end = "top";
 | |
|   }
 | |
|   if (reverse) {
 | |
|     top = "end";
 | |
|     bottom = "start";
 | |
|   } else {
 | |
|     top = "start";
 | |
|     bottom = "end";
 | |
|   }
 | |
|   return {
 | |
|     start,
 | |
|     end,
 | |
|     reverse,
 | |
|     top,
 | |
|     bottom
 | |
|   };
 | |
| }
 | |
| function setBorderSkipped(properties, options, stack, index) {
 | |
|   let edge = options.borderSkipped;
 | |
|   const res = {};
 | |
|   if (!edge) {
 | |
|     properties.borderSkipped = res;
 | |
|     return;
 | |
|   }
 | |
|   if (edge === true) {
 | |
|     properties.borderSkipped = {
 | |
|       top: true,
 | |
|       right: true,
 | |
|       bottom: true,
 | |
|       left: true
 | |
|     };
 | |
|     return;
 | |
|   }
 | |
|   const { start, end, reverse, top, bottom } = borderProps(properties);
 | |
|   if (edge === "middle" && stack) {
 | |
|     properties.enableBorderRadius = true;
 | |
|     if ((stack._top || 0) === index) {
 | |
|       edge = top;
 | |
|     } else if ((stack._bottom || 0) === index) {
 | |
|       edge = bottom;
 | |
|     } else {
 | |
|       res[parseEdge(bottom, start, end, reverse)] = true;
 | |
|       edge = top;
 | |
|     }
 | |
|   }
 | |
|   res[parseEdge(edge, start, end, reverse)] = true;
 | |
|   properties.borderSkipped = res;
 | |
| }
 | |
| function parseEdge(edge, a2, b2, reverse) {
 | |
|   if (reverse) {
 | |
|     edge = swap(edge, a2, b2);
 | |
|     edge = startEnd(edge, b2, a2);
 | |
|   } else {
 | |
|     edge = startEnd(edge, a2, b2);
 | |
|   }
 | |
|   return edge;
 | |
| }
 | |
| function swap(orig, v1, v2) {
 | |
|   return orig === v1 ? v2 : orig === v2 ? v1 : orig;
 | |
| }
 | |
| function startEnd(v2, start, end) {
 | |
|   return v2 === "start" ? start : v2 === "end" ? end : v2;
 | |
| }
 | |
| function setInflateAmount(properties, { inflateAmount }, ratio) {
 | |
|   properties.inflateAmount = inflateAmount === "auto" ? ratio === 1 ? 0.33 : 0 : inflateAmount;
 | |
| }
 | |
| var BarController = class extends DatasetController {
 | |
|   parsePrimitiveData(meta, data, start, count) {
 | |
|     return parseArrayOrPrimitive(meta, data, start, count);
 | |
|   }
 | |
|   parseArrayData(meta, data, start, count) {
 | |
|     return parseArrayOrPrimitive(meta, data, start, count);
 | |
|   }
 | |
|   parseObjectData(meta, data, start, count) {
 | |
|     const { iScale, vScale } = meta;
 | |
|     const { xAxisKey = "x", yAxisKey = "y" } = this._parsing;
 | |
|     const iAxisKey = iScale.axis === "x" ? xAxisKey : yAxisKey;
 | |
|     const vAxisKey = vScale.axis === "x" ? xAxisKey : yAxisKey;
 | |
|     const parsed = [];
 | |
|     let i2, ilen, item, obj;
 | |
|     for (i2 = start, ilen = start + count; i2 < ilen; ++i2) {
 | |
|       obj = data[i2];
 | |
|       item = {};
 | |
|       item[iScale.axis] = iScale.parse(resolveObjectKey(obj, iAxisKey), i2);
 | |
|       parsed.push(parseValue(resolveObjectKey(obj, vAxisKey), item, vScale, i2));
 | |
|     }
 | |
|     return parsed;
 | |
|   }
 | |
|   updateRangeFromParsed(range, scale, parsed, stack) {
 | |
|     super.updateRangeFromParsed(range, scale, parsed, stack);
 | |
|     const custom = parsed._custom;
 | |
|     if (custom && scale === this._cachedMeta.vScale) {
 | |
|       range.min = Math.min(range.min, custom.min);
 | |
|       range.max = Math.max(range.max, custom.max);
 | |
|     }
 | |
|   }
 | |
|   getMaxOverflow() {
 | |
|     return 0;
 | |
|   }
 | |
|   getLabelAndValue(index) {
 | |
|     const meta = this._cachedMeta;
 | |
|     const { iScale, vScale } = meta;
 | |
|     const parsed = this.getParsed(index);
 | |
|     const custom = parsed._custom;
 | |
|     const value = isFloatBar(custom) ? "[" + custom.start + ", " + custom.end + "]" : "" + vScale.getLabelForValue(parsed[vScale.axis]);
 | |
|     return {
 | |
|       label: "" + iScale.getLabelForValue(parsed[iScale.axis]),
 | |
|       value
 | |
|     };
 | |
|   }
 | |
|   initialize() {
 | |
|     this.enableOptionSharing = true;
 | |
|     super.initialize();
 | |
|     const meta = this._cachedMeta;
 | |
|     meta.stack = this.getDataset().stack;
 | |
|   }
 | |
|   update(mode) {
 | |
|     const meta = this._cachedMeta;
 | |
|     this.updateElements(meta.data, 0, meta.data.length, mode);
 | |
|   }
 | |
|   updateElements(bars, start, count, mode) {
 | |
|     const reset2 = mode === "reset";
 | |
|     const { index, _cachedMeta: { vScale } } = this;
 | |
|     const base = vScale.getBasePixel();
 | |
|     const horizontal = vScale.isHorizontal();
 | |
|     const ruler = this._getRuler();
 | |
|     const { sharedOptions, includeOptions } = this._getSharedOptions(start, mode);
 | |
|     for (let i2 = start; i2 < start + count; i2++) {
 | |
|       const parsed = this.getParsed(i2);
 | |
|       const vpixels = reset2 || isNullOrUndef(parsed[vScale.axis]) ? {
 | |
|         base,
 | |
|         head: base
 | |
|       } : this._calculateBarValuePixels(i2);
 | |
|       const ipixels = this._calculateBarIndexPixels(i2, ruler);
 | |
|       const stack = (parsed._stacks || {})[vScale.axis];
 | |
|       const properties = {
 | |
|         horizontal,
 | |
|         base: vpixels.base,
 | |
|         enableBorderRadius: !stack || isFloatBar(parsed._custom) || index === stack._top || index === stack._bottom,
 | |
|         x: horizontal ? vpixels.head : ipixels.center,
 | |
|         y: horizontal ? ipixels.center : vpixels.head,
 | |
|         height: horizontal ? ipixels.size : Math.abs(vpixels.size),
 | |
|         width: horizontal ? Math.abs(vpixels.size) : ipixels.size
 | |
|       };
 | |
|       if (includeOptions) {
 | |
|         properties.options = sharedOptions || this.resolveDataElementOptions(i2, bars[i2].active ? "active" : mode);
 | |
|       }
 | |
|       const options = properties.options || bars[i2].options;
 | |
|       setBorderSkipped(properties, options, stack, index);
 | |
|       setInflateAmount(properties, options, ruler.ratio);
 | |
|       this.updateElement(bars[i2], i2, properties, mode);
 | |
|     }
 | |
|   }
 | |
|   _getStacks(last, dataIndex) {
 | |
|     const { iScale } = this._cachedMeta;
 | |
|     const metasets = iScale.getMatchingVisibleMetas(this._type).filter((meta) => meta.controller.options.grouped);
 | |
|     const stacked = iScale.options.stacked;
 | |
|     const stacks = [];
 | |
|     const currentParsed = this._cachedMeta.controller.getParsed(dataIndex);
 | |
|     const iScaleValue = currentParsed && currentParsed[iScale.axis];
 | |
|     const skipNull = (meta) => {
 | |
|       const parsed = meta._parsed.find((item) => item[iScale.axis] === iScaleValue);
 | |
|       const val = parsed && parsed[meta.vScale.axis];
 | |
|       if (isNullOrUndef(val) || isNaN(val)) {
 | |
|         return true;
 | |
|       }
 | |
|     };
 | |
|     for (const meta of metasets) {
 | |
|       if (dataIndex !== void 0 && skipNull(meta)) {
 | |
|         continue;
 | |
|       }
 | |
|       if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === void 0 && meta.stack === void 0) {
 | |
|         stacks.push(meta.stack);
 | |
|       }
 | |
|       if (meta.index === last) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (!stacks.length) {
 | |
|       stacks.push(void 0);
 | |
|     }
 | |
|     return stacks;
 | |
|   }
 | |
|   _getStackCount(index) {
 | |
|     return this._getStacks(void 0, index).length;
 | |
|   }
 | |
|   _getStackIndex(datasetIndex, name, dataIndex) {
 | |
|     const stacks = this._getStacks(datasetIndex, dataIndex);
 | |
|     const index = name !== void 0 ? stacks.indexOf(name) : -1;
 | |
|     return index === -1 ? stacks.length - 1 : index;
 | |
|   }
 | |
|   _getRuler() {
 | |
|     const opts = this.options;
 | |
|     const meta = this._cachedMeta;
 | |
|     const iScale = meta.iScale;
 | |
|     const pixels = [];
 | |
|     let i2, ilen;
 | |
|     for (i2 = 0, ilen = meta.data.length; i2 < ilen; ++i2) {
 | |
|       pixels.push(iScale.getPixelForValue(this.getParsed(i2)[iScale.axis], i2));
 | |
|     }
 | |
|     const barThickness = opts.barThickness;
 | |
|     const min = barThickness || computeMinSampleSize(meta);
 | |
|     return {
 | |
|       min,
 | |
|       pixels,
 | |
|       start: iScale._startPixel,
 | |
|       end: iScale._endPixel,
 | |
|       stackCount: this._getStackCount(),
 | |
|       scale: iScale,
 | |
|       grouped: opts.grouped,
 | |
|       ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage
 | |
|     };
 | |
|   }
 | |
|   _calculateBarValuePixels(index) {
 | |
|     const { _cachedMeta: { vScale, _stacked, index: datasetIndex }, options: { base: baseValue, minBarLength } } = this;
 | |
|     const actualBase = baseValue || 0;
 | |
|     const parsed = this.getParsed(index);
 | |
|     const custom = parsed._custom;
 | |
|     const floating = isFloatBar(custom);
 | |
|     let value = parsed[vScale.axis];
 | |
|     let start = 0;
 | |
|     let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;
 | |
|     let head, size;
 | |
|     if (length !== value) {
 | |
|       start = length - value;
 | |
|       length = value;
 | |
|     }
 | |
|     if (floating) {
 | |
|       value = custom.barStart;
 | |
|       length = custom.barEnd - custom.barStart;
 | |
|       if (value !== 0 && sign(value) !== sign(custom.barEnd)) {
 | |
|         start = 0;
 | |
|       }
 | |
|       start += value;
 | |
|     }
 | |
|     const startValue = !isNullOrUndef(baseValue) && !floating ? baseValue : start;
 | |
|     let base = vScale.getPixelForValue(startValue);
 | |
|     if (this.chart.getDataVisibility(index)) {
 | |
|       head = vScale.getPixelForValue(start + length);
 | |
|     } else {
 | |
|       head = base;
 | |
|     }
 | |
|     size = head - base;
 | |
|     if (Math.abs(size) < minBarLength) {
 | |
|       size = barSign(size, vScale, actualBase) * minBarLength;
 | |
|       if (value === actualBase) {
 | |
|         base -= size / 2;
 | |
|       }
 | |
|       const startPixel = vScale.getPixelForDecimal(0);
 | |
|       const endPixel = vScale.getPixelForDecimal(1);
 | |
|       const min = Math.min(startPixel, endPixel);
 | |
|       const max = Math.max(startPixel, endPixel);
 | |
|       base = Math.max(Math.min(base, max), min);
 | |
|       head = base + size;
 | |
|       if (_stacked && !floating) {
 | |
|         parsed._stacks[vScale.axis]._visualValues[datasetIndex] = vScale.getValueForPixel(head) - vScale.getValueForPixel(base);
 | |
|       }
 | |
|     }
 | |
|     if (base === vScale.getPixelForValue(actualBase)) {
 | |
|       const halfGrid = sign(size) * vScale.getLineWidthForValue(actualBase) / 2;
 | |
|       base += halfGrid;
 | |
|       size -= halfGrid;
 | |
|     }
 | |
|     return {
 | |
|       size,
 | |
|       base,
 | |
|       head,
 | |
|       center: head + size / 2
 | |
|     };
 | |
|   }
 | |
|   _calculateBarIndexPixels(index, ruler) {
 | |
|     const scale = ruler.scale;
 | |
|     const options = this.options;
 | |
|     const skipNull = options.skipNull;
 | |
|     const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);
 | |
|     let center, size;
 | |
|     if (ruler.grouped) {
 | |
|       const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;
 | |
|       const range = options.barThickness === "flex" ? computeFlexCategoryTraits(index, ruler, options, stackCount) : computeFitCategoryTraits(index, ruler, options, stackCount);
 | |
|       const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : void 0);
 | |
|       center = range.start + range.chunk * stackIndex + range.chunk / 2;
 | |
|       size = Math.min(maxBarThickness, range.chunk * range.ratio);
 | |
|     } else {
 | |
|       center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);
 | |
|       size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
 | |
|     }
 | |
|     return {
 | |
|       base: center - size / 2,
 | |
|       head: center + size / 2,
 | |
|       center,
 | |
|       size
 | |
|     };
 | |
|   }
 | |
|   draw() {
 | |
|     const meta = this._cachedMeta;
 | |
|     const vScale = meta.vScale;
 | |
|     const rects = meta.data;
 | |
|     const ilen = rects.length;
 | |
|     let i2 = 0;
 | |
|     for (; i2 < ilen; ++i2) {
 | |
|       if (this.getParsed(i2)[vScale.axis] !== null && !rects[i2].hidden) {
 | |
|         rects[i2].draw(this._ctx);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| };
 | |
| __publicField(BarController, "id", "bar");
 | |
| __publicField(BarController, "defaults", {
 | |
|   datasetElementType: false,
 | |
|   dataElementType: "bar",
 | |
|   categoryPercentage: 0.8,
 | |
|   barPercentage: 0.9,
 | |
|   grouped: true,
 | |
|   animations: {
 | |
|     numbers: {
 | |
|       type: "number",
 | |
|       properties: [
 | |
|         "x",
 | |
|         "y",
 | |
|         "base",
 | |
|         "width",
 | |
|         "height"
 | |
|       ]
 | |
|     }
 | |
|   }
 | |
| });
 | |
| __publicField(BarController, "overrides", {
 | |
|   scales: {
 | |
|     _index_: {
 | |
|       type: "category",
 | |
|       offset: true,
 | |
|       grid: {
 | |
|         offset: true
 | |
|       }
 | |
|     },
 | |
|     _value_: {
 | |
|       type: "linear",
 | |
|       beginAtZero: true
 | |
|     }
 | |
|   }
 | |
| });
 | |
| function getRatioAndOffset(rotation, circumference, cutout) {
 | |
|   let ratioX = 1;
 | |
|   let ratioY = 1;
 | |
|   let offsetX = 0;
 | |
|   let offsetY = 0;
 | |
|   if (circumference < TAU) {
 | |
|     const startAngle = rotation;
 | |
|     const endAngle = startAngle + circumference;
 | |
|     const startX = Math.cos(startAngle);
 | |
|     const startY = Math.sin(startAngle);
 | |
|     const endX = Math.cos(endAngle);
 | |
|     const endY = Math.sin(endAngle);
 | |
|     const calcMax = (angle, a2, b2) => _angleBetween(angle, startAngle, endAngle, true) ? 1 : Math.max(a2, a2 * cutout, b2, b2 * cutout);
 | |
|     const calcMin = (angle, a2, b2) => _angleBetween(angle, startAngle, endAngle, true) ? -1 : Math.min(a2, a2 * cutout, b2, b2 * cutout);
 | |
|     const maxX = calcMax(0, startX, endX);
 | |
|     const maxY = calcMax(HALF_PI, startY, endY);
 | |
|     const minX = calcMin(PI, startX, endX);
 | |
|     const minY = calcMin(PI + HALF_PI, startY, endY);
 | |
|     ratioX = (maxX - minX) / 2;
 | |
|     ratioY = (maxY - minY) / 2;
 | |
|     offsetX = -(maxX + minX) / 2;
 | |
|     offsetY = -(maxY + minY) / 2;
 | |
|   }
 | |
|   return {
 | |
|     ratioX,
 | |
|     ratioY,
 | |
|     offsetX,
 | |
|     offsetY
 | |
|   };
 | |
| }
 | |
| var DoughnutController = class extends DatasetController {
 | |
|   constructor(chart, datasetIndex) {
 | |
|     super(chart, datasetIndex);
 | |
|     this.enableOptionSharing = true;
 | |
|     this.innerRadius = void 0;
 | |
|     this.outerRadius = void 0;
 | |
|     this.offsetX = void 0;
 | |
|     this.offsetY = void 0;
 | |
|   }
 | |
|   linkScales() {
 | |
|   }
 | |
|   parse(start, count) {
 | |
|     const data = this.getDataset().data;
 | |
|     const meta = this._cachedMeta;
 | |
|     if (this._parsing === false) {
 | |
|       meta._parsed = data;
 | |
|     } else {
 | |
|       let getter = (i3) => +data[i3];
 | |
|       if (isObject(data[start])) {
 | |
|         const { key = "value" } = this._parsing;
 | |
|         getter = (i3) => +resolveObjectKey(data[i3], key);
 | |
|       }
 | |
|       let i2, ilen;
 | |
|       for (i2 = start, ilen = start + count; i2 < ilen; ++i2) {
 | |
|         meta._parsed[i2] = getter(i2);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   _getRotation() {
 | |
|     return toRadians(this.options.rotation - 90);
 | |
|   }
 | |
|   _getCircumference() {
 | |
|     return toRadians(this.options.circumference);
 | |
|   }
 | |
|   _getRotationExtents() {
 | |
|     let min = TAU;
 | |
|     let max = -TAU;
 | |
|     for (let i2 = 0; i2 < this.chart.data.datasets.length; ++i2) {
 | |
|       if (this.chart.isDatasetVisible(i2) && this.chart.getDatasetMeta(i2).type === this._type) {
 | |
|         const controller = this.chart.getDatasetMeta(i2).controller;
 | |
|         const rotation = controller._getRotation();
 | |
|         const circumference = controller._getCircumference();
 | |
|         min = Math.min(min, rotation);
 | |
|         max = Math.max(max, rotation + circumference);
 | |
|       }
 | |
|     }
 | |
|     return {
 | |
|       rotation: min,
 | |
|       circumference: max - min
 | |
|     };
 | |
|   }
 | |
|   update(mode) {
 | |
|     const chart = this.chart;
 | |
|     const { chartArea } = chart;
 | |
|     const meta = this._cachedMeta;
 | |
|     const arcs = meta.data;
 | |
|     const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;
 | |
|     const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);
 | |
|     const cutout = Math.min(toPercentage(this.options.cutout, maxSize), 1);
 | |
|     const chartWeight = this._getRingWeight(this.index);
 | |
|     const { circumference, rotation } = this._getRotationExtents();
 | |
|     const { ratioX, ratioY, offsetX, offsetY } = getRatioAndOffset(rotation, circumference, cutout);
 | |
|     const maxWidth = (chartArea.width - spacing) / ratioX;
 | |
|     const maxHeight = (chartArea.height - spacing) / ratioY;
 | |
|     const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
 | |
|     const outerRadius = toDimension(this.options.radius, maxRadius);
 | |
|     const innerRadius = Math.max(outerRadius * cutout, 0);
 | |
|     const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();
 | |
|     this.offsetX = offsetX * outerRadius;
 | |
|     this.offsetY = offsetY * outerRadius;
 | |
|     meta.total = this.calculateTotal();
 | |
|     this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);
 | |
|     this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);
 | |
|     this.updateElements(arcs, 0, arcs.length, mode);
 | |
|   }
 | |
|   _circumference(i2, reset2) {
 | |
|     const opts = this.options;
 | |
|     const meta = this._cachedMeta;
 | |
|     const circumference = this._getCircumference();
 | |
|     if (reset2 && opts.animation.animateRotate || !this.chart.getDataVisibility(i2) || meta._parsed[i2] === null || meta.data[i2].hidden) {
 | |
|       return 0;
 | |
|     }
 | |
|     return this.calculateCircumference(meta._parsed[i2] * circumference / TAU);
 | |
|   }
 | |
|   updateElements(arcs, start, count, mode) {
 | |
|     const reset2 = mode === "reset";
 | |
|     const chart = this.chart;
 | |
|     const chartArea = chart.chartArea;
 | |
|     const opts = chart.options;
 | |
|     const animationOpts = opts.animation;
 | |
|     const centerX = (chartArea.left + chartArea.right) / 2;
 | |
|     const centerY = (chartArea.top + chartArea.bottom) / 2;
 | |
|     const animateScale = reset2 && animationOpts.animateScale;
 | |
|     const innerRadius = animateScale ? 0 : this.innerRadius;
 | |
|     const outerRadius = animateScale ? 0 : this.outerRadius;
 | |
|     const { sharedOptions, includeOptions } = this._getSharedOptions(start, mode);
 | |
|     let startAngle = this._getRotation();
 | |
|     let i2;
 | |
|     for (i2 = 0; i2 < start; ++i2) {
 | |
|       startAngle += this._circumference(i2, reset2);
 | |
|     }
 | |
|     for (i2 = start; i2 < start + count; ++i2) {
 | |
|       const circumference = this._circumference(i2, reset2);
 | |
|       const arc = arcs[i2];
 | |
|       const properties = {
 | |
|         x: centerX + this.offsetX,
 | |
|         y: centerY + this.offsetY,
 | |
|         startAngle,
 | |
|         endAngle: startAngle + circumference,
 | |
|         circumference,
 | |
|         outerRadius,
 | |
|         innerRadius
 | |
|       };
 | |
|       if (includeOptions) {
 | |
|         properties.options = sharedOptions || this.resolveDataElementOptions(i2, arc.active ? "active" : mode);
 | |
|       }
 | |
|       startAngle += circumference;
 | |
|       this.updateElement(arc, i2, properties, mode);
 | |
|     }
 | |
|   }
 | |
|   calculateTotal() {
 | |
|     const meta = this._cachedMeta;
 | |
|     const metaData = meta.data;
 | |
|     let total = 0;
 | |
|     let i2;
 | |
|     for (i2 = 0; i2 < metaData.length; i2++) {
 | |
|       const value = meta._parsed[i2];
 | |
|       if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i2) && !metaData[i2].hidden) {
 | |
|         total += Math.abs(value);
 | |
|       }
 | |
|     }
 | |
|     return total;
 | |
|   }
 | |
|   calculateCircumference(value) {
 | |
|     const total = this._cachedMeta.total;
 | |
|     if (total > 0 && !isNaN(value)) {
 | |
|       return TAU * (Math.abs(value) / total);
 | |
|     }
 | |
|     return 0;
 | |
|   }
 | |
|   getLabelAndValue(index) {
 | |
|     const meta = this._cachedMeta;
 | |
|     const chart = this.chart;
 | |
|     const labels = chart.data.labels || [];
 | |
|     const value = formatNumber(meta._parsed[index], chart.options.locale);
 | |
|     return {
 | |
|       label: labels[index] || "",
 | |
|       value
 | |
|     };
 | |
|   }
 | |
|   getMaxBorderWidth(arcs) {
 | |
|     let max = 0;
 | |
|     const chart = this.chart;
 | |
|     let i2, ilen, meta, controller, options;
 | |
|     if (!arcs) {
 | |
|       for (i2 = 0, ilen = chart.data.datasets.length; i2 < ilen; ++i2) {
 | |
|         if (chart.isDatasetVisible(i2)) {
 | |
|           meta = chart.getDatasetMeta(i2);
 | |
|           arcs = meta.data;
 | |
|           controller = meta.controller;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if (!arcs) {
 | |
|       return 0;
 | |
|     }
 | |
|     for (i2 = 0, ilen = arcs.length; i2 < ilen; ++i2) {
 | |
|       options = controller.resolveDataElementOptions(i2);
 | |
|       if (options.borderAlign !== "inner") {
 | |
|         max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0);
 | |
|       }
 | |
|     }
 | |
|     return max;
 | |
|   }
 | |
|   getMaxOffset(arcs) {
 | |
|     let max = 0;
 | |
|     for (let i2 = 0, ilen = arcs.length; i2 < ilen; ++i2) {
 | |
|       const options = this.resolveDataElementOptions(i2);
 | |
|       max = Math.max(max, options.offset || 0, options.hoverOffset || 0);
 | |
|     }
 | |
|     return max;
 | |
|   }
 | |
|   _getRingWeightOffset(datasetIndex) {
 | |
|     let ringWeightOffset = 0;
 | |
|     for (let i2 = 0; i2 < datasetIndex; ++i2) {
 | |
|       if (this.chart.isDatasetVisible(i2)) {
 | |
|         ringWeightOffset += this._getRingWeight(i2);
 | |
|       }
 | |
|     }
 | |
|     return ringWeightOffset;
 | |
|   }
 | |
|   _getRingWeight(datasetIndex) {
 | |
|     return Math.max(valueOrDefault(this.chart.data.datasets[datasetIndex].weight, 1), 0);
 | |
|   }
 | |
|   _getVisibleDatasetWeightTotal() {
 | |
|     return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;
 | |
|   }
 | |
| };
 | |
| __publicField(DoughnutController, "id", "doughnut");
 | |
| __publicField(DoughnutController, "defaults", {
 | |
|   datasetElementType: false,
 | |
|   dataElementType: "arc",
 | |
|   animation: {
 | |
|     animateRotate: true,
 | |
|     animateScale: false
 | |
|   },
 | |
|   animations: {
 | |
|     numbers: {
 | |
|       type: "number",
 | |
|       properties: [
 | |
|         "circumference",
 | |
|         "endAngle",
 | |
|         "innerRadius",
 | |
|         "outerRadius",
 | |
|         "startAngle",
 | |
|         "x",
 | |
|         "y",
 | |
|         "offset",
 | |
|         "borderWidth",
 | |
|         "spacing"
 | |
|       ]
 | |
|     }
 | |
|   },
 | |
|   cutout: "50%",
 | |
|   rotation: 0,
 | |
|   circumference: 360,
 | |
|   radius: "100%",
 | |
|   spacing: 0,
 | |
|   indexAxis: "r"
 | |
| });
 | |
| __publicField(DoughnutController, "descriptors", {
 | |
|   _scriptable: (name) => name !== "spacing",
 | |
|   _indexable: (name) => name !== "spacing" && !name.startsWith("borderDash") && !name.startsWith("hoverBorderDash")
 | |
| });
 | |
| __publicField(DoughnutController, "overrides", {
 | |
|   aspectRatio: 1,
 | |
|   plugins: {
 | |
|     legend: {
 | |
|       labels: {
 | |
|         generateLabels(chart) {
 | |
|           const data = chart.data;
 | |
|           if (data.labels.length && data.datasets.length) {
 | |
|             const { labels: { pointStyle, color: color2 } } = chart.legend.options;
 | |
|             return data.labels.map((label, i2) => {
 | |
|               const meta = chart.getDatasetMeta(0);
 | |
|               const style = meta.controller.getStyle(i2);
 | |
|               return {
 | |
|                 text: label,
 | |
|                 fillStyle: style.backgroundColor,
 | |
|                 strokeStyle: style.borderColor,
 | |
|                 fontColor: color2,
 | |
|                 lineWidth: style.borderWidth,
 | |
|                 pointStyle,
 | |
|                 hidden: !chart.getDataVisibility(i2),
 | |
|                 index: i2
 | |
|               };
 | |
|             });
 | |
|           }
 | |
|           return [];
 | |
|         }
 | |
|       },
 | |
|       onClick(e2, legendItem, legend) {
 | |
|         legend.chart.toggleDataVisibility(legendItem.index);
 | |
|         legend.chart.update();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| });
 | |
| var PieController = class extends DoughnutController {
 | |
| };
 | |
| __publicField(PieController, "id", "pie");
 | |
| __publicField(PieController, "defaults", {
 | |
|   cutout: 0,
 | |
|   rotation: 0,
 | |
|   circumference: 360,
 | |
|   radius: "100%"
 | |
| });
 | |
| function abstract() {
 | |
|   throw new Error("This method is not implemented: Check that a complete date adapter is provided.");
 | |
| }
 | |
| var DateAdapterBase = class _DateAdapterBase {
 | |
|   constructor(options) {
 | |
|     __publicField(this, "options");
 | |
|     this.options = options || {};
 | |
|   }
 | |
|   /**
 | |
|   * Override default date adapter methods.
 | |
|   * Accepts type parameter to define options type.
 | |
|   * @example
 | |
|   * Chart._adapters._date.override<{myAdapterOption: string}>({
 | |
|   *   init() {
 | |
|   *     console.log(this.options.myAdapterOption);
 | |
|   *   }
 | |
|   * })
 | |
|   */
 | |
|   static override(members) {
 | |
|     Object.assign(_DateAdapterBase.prototype, members);
 | |
|   }
 | |
|   // eslint-disable-next-line @typescript-eslint/no-empty-function
 | |
|   init() {
 | |
|   }
 | |
|   formats() {
 | |
|     return abstract();
 | |
|   }
 | |
|   parse() {
 | |
|     return abstract();
 | |
|   }
 | |
|   format() {
 | |
|     return abstract();
 | |
|   }
 | |
|   add() {
 | |
|     return abstract();
 | |
|   }
 | |
|   diff() {
 | |
|     return abstract();
 | |
|   }
 | |
|   startOf() {
 | |
|     return abstract();
 | |
|   }
 | |
|   endOf() {
 | |
|     return abstract();
 | |
|   }
 | |
| };
 | |
| var adapters = {
 | |
|   _date: DateAdapterBase
 | |
| };
 | |
| function binarySearch(metaset, axis, value, intersect) {
 | |
|   const { controller, data, _sorted } = metaset;
 | |
|   const iScale = controller._cachedMeta.iScale;
 | |
|   const spanGaps = metaset.dataset ? metaset.dataset.options ? metaset.dataset.options.spanGaps : null : null;
 | |
|   if (iScale && axis === iScale.axis && axis !== "r" && _sorted && data.length) {
 | |
|     const lookupMethod = iScale._reversePixels ? _rlookupByKey : _lookupByKey;
 | |
|     if (!intersect) {
 | |
|       const result = lookupMethod(data, axis, value);
 | |
|       if (spanGaps) {
 | |
|         const { vScale } = controller._cachedMeta;
 | |
|         const { _parsed } = metaset;
 | |
|         const distanceToDefinedLo = _parsed.slice(0, result.lo + 1).reverse().findIndex((point) => !isNullOrUndef(point[vScale.axis]));
 | |
|         result.lo -= Math.max(0, distanceToDefinedLo);
 | |
|         const distanceToDefinedHi = _parsed.slice(result.hi).findIndex((point) => !isNullOrUndef(point[vScale.axis]));
 | |
|         result.hi += Math.max(0, distanceToDefinedHi);
 | |
|       }
 | |
|       return result;
 | |
|     } else if (controller._sharedOptions) {
 | |
|       const el = data[0];
 | |
|       const range = typeof el.getRange === "function" && el.getRange(axis);
 | |
|       if (range) {
 | |
|         const start = lookupMethod(data, axis, value - range);
 | |
|         const end = lookupMethod(data, axis, value + range);
 | |
|         return {
 | |
|           lo: start.lo,
 | |
|           hi: end.hi
 | |
|         };
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     lo: 0,
 | |
|     hi: data.length - 1
 | |
|   };
 | |
| }
 | |
| function evaluateInteractionItems(chart, axis, position, handler, intersect) {
 | |
|   const metasets = chart.getSortedVisibleDatasetMetas();
 | |
|   const value = position[axis];
 | |
|   for (let i2 = 0, ilen = metasets.length; i2 < ilen; ++i2) {
 | |
|     const { index, data } = metasets[i2];
 | |
|     const { lo, hi } = binarySearch(metasets[i2], axis, value, intersect);
 | |
|     for (let j2 = lo; j2 <= hi; ++j2) {
 | |
|       const element = data[j2];
 | |
|       if (!element.skip) {
 | |
|         handler(element, index, j2);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function getDistanceMetricForAxis(axis) {
 | |
|   const useX = axis.indexOf("x") !== -1;
 | |
|   const useY = axis.indexOf("y") !== -1;
 | |
|   return function(pt1, pt2) {
 | |
|     const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
 | |
|     const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
 | |
|     return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
 | |
|   };
 | |
| }
 | |
| function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) {
 | |
|   const items = [];
 | |
|   if (!includeInvisible && !chart.isPointInArea(position)) {
 | |
|     return items;
 | |
|   }
 | |
|   const evaluationFunc = function(element, datasetIndex, index) {
 | |
|     if (!includeInvisible && !_isPointInArea(element, chart.chartArea, 0)) {
 | |
|       return;
 | |
|     }
 | |
|     if (element.inRange(position.x, position.y, useFinalPosition)) {
 | |
|       items.push({
 | |
|         element,
 | |
|         datasetIndex,
 | |
|         index
 | |
|       });
 | |
|     }
 | |
|   };
 | |
|   evaluateInteractionItems(chart, axis, position, evaluationFunc, true);
 | |
|   return items;
 | |
| }
 | |
| function getNearestRadialItems(chart, position, axis, useFinalPosition) {
 | |
|   let items = [];
 | |
|   function evaluationFunc(element, datasetIndex, index) {
 | |
|     const { startAngle, endAngle } = element.getProps([
 | |
|       "startAngle",
 | |
|       "endAngle"
 | |
|     ], useFinalPosition);
 | |
|     const { angle } = getAngleFromPoint(element, {
 | |
|       x: position.x,
 | |
|       y: position.y
 | |
|     });
 | |
|     if (_angleBetween(angle, startAngle, endAngle)) {
 | |
|       items.push({
 | |
|         element,
 | |
|         datasetIndex,
 | |
|         index
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   evaluateInteractionItems(chart, axis, position, evaluationFunc);
 | |
|   return items;
 | |
| }
 | |
| function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
 | |
|   let items = [];
 | |
|   const distanceMetric = getDistanceMetricForAxis(axis);
 | |
|   let minDistance = Number.POSITIVE_INFINITY;
 | |
|   function evaluationFunc(element, datasetIndex, index) {
 | |
|     const inRange2 = element.inRange(position.x, position.y, useFinalPosition);
 | |
|     if (intersect && !inRange2) {
 | |
|       return;
 | |
|     }
 | |
|     const center = element.getCenterPoint(useFinalPosition);
 | |
|     const pointInArea = !!includeInvisible || chart.isPointInArea(center);
 | |
|     if (!pointInArea && !inRange2) {
 | |
|       return;
 | |
|     }
 | |
|     const distance = distanceMetric(position, center);
 | |
|     if (distance < minDistance) {
 | |
|       items = [
 | |
|         {
 | |
|           element,
 | |
|           datasetIndex,
 | |
|           index
 | |
|         }
 | |
|       ];
 | |
|       minDistance = distance;
 | |
|     } else if (distance === minDistance) {
 | |
|       items.push({
 | |
|         element,
 | |
|         datasetIndex,
 | |
|         index
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   evaluateInteractionItems(chart, axis, position, evaluationFunc);
 | |
|   return items;
 | |
| }
 | |
| function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
 | |
|   if (!includeInvisible && !chart.isPointInArea(position)) {
 | |
|     return [];
 | |
|   }
 | |
|   return axis === "r" && !intersect ? getNearestRadialItems(chart, position, axis, useFinalPosition) : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible);
 | |
| }
 | |
| function getAxisItems(chart, position, axis, intersect, useFinalPosition) {
 | |
|   const items = [];
 | |
|   const rangeMethod = axis === "x" ? "inXRange" : "inYRange";
 | |
|   let intersectsItem = false;
 | |
|   evaluateInteractionItems(chart, axis, position, (element, datasetIndex, index) => {
 | |
|     if (element[rangeMethod] && element[rangeMethod](position[axis], useFinalPosition)) {
 | |
|       items.push({
 | |
|         element,
 | |
|         datasetIndex,
 | |
|         index
 | |
|       });
 | |
|       intersectsItem = intersectsItem || element.inRange(position.x, position.y, useFinalPosition);
 | |
|     }
 | |
|   });
 | |
|   if (intersect && !intersectsItem) {
 | |
|     return [];
 | |
|   }
 | |
|   return items;
 | |
| }
 | |
| var Interaction = {
 | |
|   evaluateInteractionItems,
 | |
|   modes: {
 | |
|     index(chart, e2, options, useFinalPosition) {
 | |
|       const position = getRelativePosition(e2, chart);
 | |
|       const axis = options.axis || "x";
 | |
|       const includeInvisible = options.includeInvisible || false;
 | |
|       const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
 | |
|       const elements = [];
 | |
|       if (!items.length) {
 | |
|         return [];
 | |
|       }
 | |
|       chart.getSortedVisibleDatasetMetas().forEach((meta) => {
 | |
|         const index = items[0].index;
 | |
|         const element = meta.data[index];
 | |
|         if (element && !element.skip) {
 | |
|           elements.push({
 | |
|             element,
 | |
|             datasetIndex: meta.index,
 | |
|             index
 | |
|           });
 | |
|         }
 | |
|       });
 | |
|       return elements;
 | |
|     },
 | |
|     dataset(chart, e2, options, useFinalPosition) {
 | |
|       const position = getRelativePosition(e2, chart);
 | |
|       const axis = options.axis || "xy";
 | |
|       const includeInvisible = options.includeInvisible || false;
 | |
|       let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
 | |
|       if (items.length > 0) {
 | |
|         const datasetIndex = items[0].datasetIndex;
 | |
|         const data = chart.getDatasetMeta(datasetIndex).data;
 | |
|         items = [];
 | |
|         for (let i2 = 0; i2 < data.length; ++i2) {
 | |
|           items.push({
 | |
|             element: data[i2],
 | |
|             datasetIndex,
 | |
|             index: i2
 | |
|           });
 | |
|         }
 | |
|       }
 | |
|       return items;
 | |
|     },
 | |
|     point(chart, e2, options, useFinalPosition) {
 | |
|       const position = getRelativePosition(e2, chart);
 | |
|       const axis = options.axis || "xy";
 | |
|       const includeInvisible = options.includeInvisible || false;
 | |
|       return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible);
 | |
|     },
 | |
|     nearest(chart, e2, options, useFinalPosition) {
 | |
|       const position = getRelativePosition(e2, chart);
 | |
|       const axis = options.axis || "xy";
 | |
|       const includeInvisible = options.includeInvisible || false;
 | |
|       return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible);
 | |
|     },
 | |
|     x(chart, e2, options, useFinalPosition) {
 | |
|       const position = getRelativePosition(e2, chart);
 | |
|       return getAxisItems(chart, position, "x", options.intersect, useFinalPosition);
 | |
|     },
 | |
|     y(chart, e2, options, useFinalPosition) {
 | |
|       const position = getRelativePosition(e2, chart);
 | |
|       return getAxisItems(chart, position, "y", options.intersect, useFinalPosition);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| var STATIC_POSITIONS = [
 | |
|   "left",
 | |
|   "top",
 | |
|   "right",
 | |
|   "bottom"
 | |
| ];
 | |
| function filterByPosition(array, position) {
 | |
|   return array.filter((v2) => v2.pos === position);
 | |
| }
 | |
| function filterDynamicPositionByAxis(array, axis) {
 | |
|   return array.filter((v2) => STATIC_POSITIONS.indexOf(v2.pos) === -1 && v2.box.axis === axis);
 | |
| }
 | |
| function sortByWeight(array, reverse) {
 | |
|   return array.sort((a2, b2) => {
 | |
|     const v0 = reverse ? b2 : a2;
 | |
|     const v1 = reverse ? a2 : b2;
 | |
|     return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight;
 | |
|   });
 | |
| }
 | |
| function wrapBoxes(boxes) {
 | |
|   const layoutBoxes = [];
 | |
|   let i2, ilen, box, pos, stack, stackWeight;
 | |
|   for (i2 = 0, ilen = (boxes || []).length; i2 < ilen; ++i2) {
 | |
|     box = boxes[i2];
 | |
|     ({ position: pos, options: { stack, stackWeight = 1 } } = box);
 | |
|     layoutBoxes.push({
 | |
|       index: i2,
 | |
|       box,
 | |
|       pos,
 | |
|       horizontal: box.isHorizontal(),
 | |
|       weight: box.weight,
 | |
|       stack: stack && pos + stack,
 | |
|       stackWeight
 | |
|     });
 | |
|   }
 | |
|   return layoutBoxes;
 | |
| }
 | |
| function buildStacks(layouts2) {
 | |
|   const stacks = {};
 | |
|   for (const wrap of layouts2) {
 | |
|     const { stack, pos, stackWeight } = wrap;
 | |
|     if (!stack || !STATIC_POSITIONS.includes(pos)) {
 | |
|       continue;
 | |
|     }
 | |
|     const _stack = stacks[stack] || (stacks[stack] = {
 | |
|       count: 0,
 | |
|       placed: 0,
 | |
|       weight: 0,
 | |
|       size: 0
 | |
|     });
 | |
|     _stack.count++;
 | |
|     _stack.weight += stackWeight;
 | |
|   }
 | |
|   return stacks;
 | |
| }
 | |
| function setLayoutDims(layouts2, params) {
 | |
|   const stacks = buildStacks(layouts2);
 | |
|   const { vBoxMaxWidth, hBoxMaxHeight } = params;
 | |
|   let i2, ilen, layout;
 | |
|   for (i2 = 0, ilen = layouts2.length; i2 < ilen; ++i2) {
 | |
|     layout = layouts2[i2];
 | |
|     const { fullSize } = layout.box;
 | |
|     const stack = stacks[layout.stack];
 | |
|     const factor = stack && layout.stackWeight / stack.weight;
 | |
|     if (layout.horizontal) {
 | |
|       layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth;
 | |
|       layout.height = hBoxMaxHeight;
 | |
|     } else {
 | |
|       layout.width = vBoxMaxWidth;
 | |
|       layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight;
 | |
|     }
 | |
|   }
 | |
|   return stacks;
 | |
| }
 | |
| function buildLayoutBoxes(boxes) {
 | |
|   const layoutBoxes = wrapBoxes(boxes);
 | |
|   const fullSize = sortByWeight(layoutBoxes.filter((wrap) => wrap.box.fullSize), true);
 | |
|   const left = sortByWeight(filterByPosition(layoutBoxes, "left"), true);
 | |
|   const right = sortByWeight(filterByPosition(layoutBoxes, "right"));
 | |
|   const top = sortByWeight(filterByPosition(layoutBoxes, "top"), true);
 | |
|   const bottom = sortByWeight(filterByPosition(layoutBoxes, "bottom"));
 | |
|   const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, "x");
 | |
|   const centerVertical = filterDynamicPositionByAxis(layoutBoxes, "y");
 | |
|   return {
 | |
|     fullSize,
 | |
|     leftAndTop: left.concat(top),
 | |
|     rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal),
 | |
|     chartArea: filterByPosition(layoutBoxes, "chartArea"),
 | |
|     vertical: left.concat(right).concat(centerVertical),
 | |
|     horizontal: top.concat(bottom).concat(centerHorizontal)
 | |
|   };
 | |
| }
 | |
| function getCombinedMax(maxPadding, chartArea, a2, b2) {
 | |
|   return Math.max(maxPadding[a2], chartArea[a2]) + Math.max(maxPadding[b2], chartArea[b2]);
 | |
| }
 | |
| function updateMaxPadding(maxPadding, boxPadding) {
 | |
|   maxPadding.top = Math.max(maxPadding.top, boxPadding.top);
 | |
|   maxPadding.left = Math.max(maxPadding.left, boxPadding.left);
 | |
|   maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);
 | |
|   maxPadding.right = Math.max(maxPadding.right, boxPadding.right);
 | |
| }
 | |
| function updateDims(chartArea, params, layout, stacks) {
 | |
|   const { pos, box } = layout;
 | |
|   const maxPadding = chartArea.maxPadding;
 | |
|   if (!isObject(pos)) {
 | |
|     if (layout.size) {
 | |
|       chartArea[pos] -= layout.size;
 | |
|     }
 | |
|     const stack = stacks[layout.stack] || {
 | |
|       size: 0,
 | |
|       count: 1
 | |
|     };
 | |
|     stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width);
 | |
|     layout.size = stack.size / stack.count;
 | |
|     chartArea[pos] += layout.size;
 | |
|   }
 | |
|   if (box.getPadding) {
 | |
|     updateMaxPadding(maxPadding, box.getPadding());
 | |
|   }
 | |
|   const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, "left", "right"));
 | |
|   const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, "top", "bottom"));
 | |
|   const widthChanged = newWidth !== chartArea.w;
 | |
|   const heightChanged = newHeight !== chartArea.h;
 | |
|   chartArea.w = newWidth;
 | |
|   chartArea.h = newHeight;
 | |
|   return layout.horizontal ? {
 | |
|     same: widthChanged,
 | |
|     other: heightChanged
 | |
|   } : {
 | |
|     same: heightChanged,
 | |
|     other: widthChanged
 | |
|   };
 | |
| }
 | |
| function handleMaxPadding(chartArea) {
 | |
|   const maxPadding = chartArea.maxPadding;
 | |
|   function updatePos(pos) {
 | |
|     const change = Math.max(maxPadding[pos] - chartArea[pos], 0);
 | |
|     chartArea[pos] += change;
 | |
|     return change;
 | |
|   }
 | |
|   chartArea.y += updatePos("top");
 | |
|   chartArea.x += updatePos("left");
 | |
|   updatePos("right");
 | |
|   updatePos("bottom");
 | |
| }
 | |
| function getMargins(horizontal, chartArea) {
 | |
|   const maxPadding = chartArea.maxPadding;
 | |
|   function marginForPositions(positions2) {
 | |
|     const margin = {
 | |
|       left: 0,
 | |
|       top: 0,
 | |
|       right: 0,
 | |
|       bottom: 0
 | |
|     };
 | |
|     positions2.forEach((pos) => {
 | |
|       margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);
 | |
|     });
 | |
|     return margin;
 | |
|   }
 | |
|   return horizontal ? marginForPositions([
 | |
|     "left",
 | |
|     "right"
 | |
|   ]) : marginForPositions([
 | |
|     "top",
 | |
|     "bottom"
 | |
|   ]);
 | |
| }
 | |
| function fitBoxes(boxes, chartArea, params, stacks) {
 | |
|   const refitBoxes = [];
 | |
|   let i2, ilen, layout, box, refit, changed;
 | |
|   for (i2 = 0, ilen = boxes.length, refit = 0; i2 < ilen; ++i2) {
 | |
|     layout = boxes[i2];
 | |
|     box = layout.box;
 | |
|     box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea));
 | |
|     const { same, other } = updateDims(chartArea, params, layout, stacks);
 | |
|     refit |= same && refitBoxes.length;
 | |
|     changed = changed || other;
 | |
|     if (!box.fullSize) {
 | |
|       refitBoxes.push(layout);
 | |
|     }
 | |
|   }
 | |
|   return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed;
 | |
| }
 | |
| function setBoxDims(box, left, top, width, height) {
 | |
|   box.top = top;
 | |
|   box.left = left;
 | |
|   box.right = left + width;
 | |
|   box.bottom = top + height;
 | |
|   box.width = width;
 | |
|   box.height = height;
 | |
| }
 | |
| function placeBoxes(boxes, chartArea, params, stacks) {
 | |
|   const userPadding = params.padding;
 | |
|   let { x: x2, y: y2 } = chartArea;
 | |
|   for (const layout of boxes) {
 | |
|     const box = layout.box;
 | |
|     const stack = stacks[layout.stack] || {
 | |
|       count: 1,
 | |
|       placed: 0,
 | |
|       weight: 1
 | |
|     };
 | |
|     const weight = layout.stackWeight / stack.weight || 1;
 | |
|     if (layout.horizontal) {
 | |
|       const width = chartArea.w * weight;
 | |
|       const height = stack.size || box.height;
 | |
|       if (defined(stack.start)) {
 | |
|         y2 = stack.start;
 | |
|       }
 | |
|       if (box.fullSize) {
 | |
|         setBoxDims(box, userPadding.left, y2, params.outerWidth - userPadding.right - userPadding.left, height);
 | |
|       } else {
 | |
|         setBoxDims(box, chartArea.left + stack.placed, y2, width, height);
 | |
|       }
 | |
|       stack.start = y2;
 | |
|       stack.placed += width;
 | |
|       y2 = box.bottom;
 | |
|     } else {
 | |
|       const height = chartArea.h * weight;
 | |
|       const width = stack.size || box.width;
 | |
|       if (defined(stack.start)) {
 | |
|         x2 = stack.start;
 | |
|       }
 | |
|       if (box.fullSize) {
 | |
|         setBoxDims(box, x2, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top);
 | |
|       } else {
 | |
|         setBoxDims(box, x2, chartArea.top + stack.placed, width, height);
 | |
|       }
 | |
|       stack.start = x2;
 | |
|       stack.placed += height;
 | |
|       x2 = box.right;
 | |
|     }
 | |
|   }
 | |
|   chartArea.x = x2;
 | |
|   chartArea.y = y2;
 | |
| }
 | |
| var layouts = {
 | |
|   addBox(chart, item) {
 | |
|     if (!chart.boxes) {
 | |
|       chart.boxes = [];
 | |
|     }
 | |
|     item.fullSize = item.fullSize || false;
 | |
|     item.position = item.position || "top";
 | |
|     item.weight = item.weight || 0;
 | |
|     item._layers = item._layers || function() {
 | |
|       return [
 | |
|         {
 | |
|           z: 0,
 | |
|           draw(chartArea) {
 | |
|             item.draw(chartArea);
 | |
|           }
 | |
|         }
 | |
|       ];
 | |
|     };
 | |
|     chart.boxes.push(item);
 | |
|   },
 | |
|   removeBox(chart, layoutItem) {
 | |
|     const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
 | |
|     if (index !== -1) {
 | |
|       chart.boxes.splice(index, 1);
 | |
|     }
 | |
|   },
 | |
|   configure(chart, item, options) {
 | |
|     item.fullSize = options.fullSize;
 | |
|     item.position = options.position;
 | |
|     item.weight = options.weight;
 | |
|   },
 | |
|   update(chart, width, height, minPadding) {
 | |
|     if (!chart) {
 | |
|       return;
 | |
|     }
 | |
|     const padding = toPadding(chart.options.layout.padding);
 | |
|     const availableWidth = Math.max(width - padding.width, 0);
 | |
|     const availableHeight = Math.max(height - padding.height, 0);
 | |
|     const boxes = buildLayoutBoxes(chart.boxes);
 | |
|     const verticalBoxes = boxes.vertical;
 | |
|     const horizontalBoxes = boxes.horizontal;
 | |
|     each(chart.boxes, (box) => {
 | |
|       if (typeof box.beforeLayout === "function") {
 | |
|         box.beforeLayout();
 | |
|       }
 | |
|     });
 | |
|     const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap) => wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1;
 | |
|     const params = Object.freeze({
 | |
|       outerWidth: width,
 | |
|       outerHeight: height,
 | |
|       padding,
 | |
|       availableWidth,
 | |
|       availableHeight,
 | |
|       vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount,
 | |
|       hBoxMaxHeight: availableHeight / 2
 | |
|     });
 | |
|     const maxPadding = Object.assign({}, padding);
 | |
|     updateMaxPadding(maxPadding, toPadding(minPadding));
 | |
|     const chartArea = Object.assign({
 | |
|       maxPadding,
 | |
|       w: availableWidth,
 | |
|       h: availableHeight,
 | |
|       x: padding.left,
 | |
|       y: padding.top
 | |
|     }, padding);
 | |
|     const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params);
 | |
|     fitBoxes(boxes.fullSize, chartArea, params, stacks);
 | |
|     fitBoxes(verticalBoxes, chartArea, params, stacks);
 | |
|     if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) {
 | |
|       fitBoxes(verticalBoxes, chartArea, params, stacks);
 | |
|     }
 | |
|     handleMaxPadding(chartArea);
 | |
|     placeBoxes(boxes.leftAndTop, chartArea, params, stacks);
 | |
|     chartArea.x += chartArea.w;
 | |
|     chartArea.y += chartArea.h;
 | |
|     placeBoxes(boxes.rightAndBottom, chartArea, params, stacks);
 | |
|     chart.chartArea = {
 | |
|       left: chartArea.left,
 | |
|       top: chartArea.top,
 | |
|       right: chartArea.left + chartArea.w,
 | |
|       bottom: chartArea.top + chartArea.h,
 | |
|       height: chartArea.h,
 | |
|       width: chartArea.w
 | |
|     };
 | |
|     each(boxes.chartArea, (layout) => {
 | |
|       const box = layout.box;
 | |
|       Object.assign(box, chart.chartArea);
 | |
|       box.update(chartArea.w, chartArea.h, {
 | |
|         left: 0,
 | |
|         top: 0,
 | |
|         right: 0,
 | |
|         bottom: 0
 | |
|       });
 | |
|     });
 | |
|   }
 | |
| };
 | |
| var BasePlatform = class {
 | |
|   acquireContext(canvas, aspectRatio) {
 | |
|   }
 | |
|   releaseContext(context) {
 | |
|     return false;
 | |
|   }
 | |
|   addEventListener(chart, type, listener) {
 | |
|   }
 | |
|   removeEventListener(chart, type, listener) {
 | |
|   }
 | |
|   getDevicePixelRatio() {
 | |
|     return 1;
 | |
|   }
 | |
|   getMaximumSize(element, width, height, aspectRatio) {
 | |
|     width = Math.max(0, width || element.width);
 | |
|     height = height || element.height;
 | |
|     return {
 | |
|       width,
 | |
|       height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height)
 | |
|     };
 | |
|   }
 | |
|   isAttached(canvas) {
 | |
|     return true;
 | |
|   }
 | |
|   updateConfig(config) {
 | |
|   }
 | |
| };
 | |
| var BasicPlatform = class extends BasePlatform {
 | |
|   acquireContext(item) {
 | |
|     return item && item.getContext && item.getContext("2d") || null;
 | |
|   }
 | |
|   updateConfig(config) {
 | |
|     config.options.animation = false;
 | |
|   }
 | |
| };
 | |
| var EXPANDO_KEY = "$chartjs";
 | |
| var EVENT_TYPES = {
 | |
|   touchstart: "mousedown",
 | |
|   touchmove: "mousemove",
 | |
|   touchend: "mouseup",
 | |
|   pointerenter: "mouseenter",
 | |
|   pointerdown: "mousedown",
 | |
|   pointermove: "mousemove",
 | |
|   pointerup: "mouseup",
 | |
|   pointerleave: "mouseout",
 | |
|   pointerout: "mouseout"
 | |
| };
 | |
| var isNullOrEmpty = (value) => value === null || value === "";
 | |
| function initCanvas(canvas, aspectRatio) {
 | |
|   const style = canvas.style;
 | |
|   const renderHeight = canvas.getAttribute("height");
 | |
|   const renderWidth = canvas.getAttribute("width");
 | |
|   canvas[EXPANDO_KEY] = {
 | |
|     initial: {
 | |
|       height: renderHeight,
 | |
|       width: renderWidth,
 | |
|       style: {
 | |
|         display: style.display,
 | |
|         height: style.height,
 | |
|         width: style.width
 | |
|       }
 | |
|     }
 | |
|   };
 | |
|   style.display = style.display || "block";
 | |
|   style.boxSizing = style.boxSizing || "border-box";
 | |
|   if (isNullOrEmpty(renderWidth)) {
 | |
|     const displayWidth = readUsedSize(canvas, "width");
 | |
|     if (displayWidth !== void 0) {
 | |
|       canvas.width = displayWidth;
 | |
|     }
 | |
|   }
 | |
|   if (isNullOrEmpty(renderHeight)) {
 | |
|     if (canvas.style.height === "") {
 | |
|       canvas.height = canvas.width / (aspectRatio || 2);
 | |
|     } else {
 | |
|       const displayHeight = readUsedSize(canvas, "height");
 | |
|       if (displayHeight !== void 0) {
 | |
|         canvas.height = displayHeight;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return canvas;
 | |
| }
 | |
| var eventListenerOptions = supportsEventListenerOptions ? {
 | |
|   passive: true
 | |
| } : false;
 | |
| function addListener(node, type, listener) {
 | |
|   if (node) {
 | |
|     node.addEventListener(type, listener, eventListenerOptions);
 | |
|   }
 | |
| }
 | |
| function removeListener(chart, type, listener) {
 | |
|   if (chart && chart.canvas) {
 | |
|     chart.canvas.removeEventListener(type, listener, eventListenerOptions);
 | |
|   }
 | |
| }
 | |
| function fromNativeEvent(event, chart) {
 | |
|   const type = EVENT_TYPES[event.type] || event.type;
 | |
|   const { x: x2, y: y2 } = getRelativePosition(event, chart);
 | |
|   return {
 | |
|     type,
 | |
|     chart,
 | |
|     native: event,
 | |
|     x: x2 !== void 0 ? x2 : null,
 | |
|     y: y2 !== void 0 ? y2 : null
 | |
|   };
 | |
| }
 | |
| function nodeListContains(nodeList, canvas) {
 | |
|   for (const node of nodeList) {
 | |
|     if (node === canvas || node.contains(canvas)) {
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function createAttachObserver(chart, type, listener) {
 | |
|   const canvas = chart.canvas;
 | |
|   const observer = new MutationObserver((entries) => {
 | |
|     let trigger = false;
 | |
|     for (const entry of entries) {
 | |
|       trigger = trigger || nodeListContains(entry.addedNodes, canvas);
 | |
|       trigger = trigger && !nodeListContains(entry.removedNodes, canvas);
 | |
|     }
 | |
|     if (trigger) {
 | |
|       listener();
 | |
|     }
 | |
|   });
 | |
|   observer.observe(document, {
 | |
|     childList: true,
 | |
|     subtree: true
 | |
|   });
 | |
|   return observer;
 | |
| }
 | |
| function createDetachObserver(chart, type, listener) {
 | |
|   const canvas = chart.canvas;
 | |
|   const observer = new MutationObserver((entries) => {
 | |
|     let trigger = false;
 | |
|     for (const entry of entries) {
 | |
|       trigger = trigger || nodeListContains(entry.removedNodes, canvas);
 | |
|       trigger = trigger && !nodeListContains(entry.addedNodes, canvas);
 | |
|     }
 | |
|     if (trigger) {
 | |
|       listener();
 | |
|     }
 | |
|   });
 | |
|   observer.observe(document, {
 | |
|     childList: true,
 | |
|     subtree: true
 | |
|   });
 | |
|   return observer;
 | |
| }
 | |
| var drpListeningCharts = /* @__PURE__ */ new Map();
 | |
| var oldDevicePixelRatio = 0;
 | |
| function onWindowResize() {
 | |
|   const dpr = window.devicePixelRatio;
 | |
|   if (dpr === oldDevicePixelRatio) {
 | |
|     return;
 | |
|   }
 | |
|   oldDevicePixelRatio = dpr;
 | |
|   drpListeningCharts.forEach((resize, chart) => {
 | |
|     if (chart.currentDevicePixelRatio !== dpr) {
 | |
|       resize();
 | |
|     }
 | |
|   });
 | |
| }
 | |
| function listenDevicePixelRatioChanges(chart, resize) {
 | |
|   if (!drpListeningCharts.size) {
 | |
|     window.addEventListener("resize", onWindowResize);
 | |
|   }
 | |
|   drpListeningCharts.set(chart, resize);
 | |
| }
 | |
| function unlistenDevicePixelRatioChanges(chart) {
 | |
|   drpListeningCharts.delete(chart);
 | |
|   if (!drpListeningCharts.size) {
 | |
|     window.removeEventListener("resize", onWindowResize);
 | |
|   }
 | |
| }
 | |
| function createResizeObserver(chart, type, listener) {
 | |
|   const canvas = chart.canvas;
 | |
|   const container = canvas && _getParentNode(canvas);
 | |
|   if (!container) {
 | |
|     return;
 | |
|   }
 | |
|   const resize = throttled((width, height) => {
 | |
|     const w2 = container.clientWidth;
 | |
|     listener(width, height);
 | |
|     if (w2 < container.clientWidth) {
 | |
|       listener();
 | |
|     }
 | |
|   }, window);
 | |
|   const observer = new ResizeObserver((entries) => {
 | |
|     const entry = entries[0];
 | |
|     const width = entry.contentRect.width;
 | |
|     const height = entry.contentRect.height;
 | |
|     if (width === 0 && height === 0) {
 | |
|       return;
 | |
|     }
 | |
|     resize(width, height);
 | |
|   });
 | |
|   observer.observe(container);
 | |
|   listenDevicePixelRatioChanges(chart, resize);
 | |
|   return observer;
 | |
| }
 | |
| function releaseObserver(chart, type, observer) {
 | |
|   if (observer) {
 | |
|     observer.disconnect();
 | |
|   }
 | |
|   if (type === "resize") {
 | |
|     unlistenDevicePixelRatioChanges(chart);
 | |
|   }
 | |
| }
 | |
| function createProxyAndListen(chart, type, listener) {
 | |
|   const canvas = chart.canvas;
 | |
|   const proxy = throttled((event) => {
 | |
|     if (chart.ctx !== null) {
 | |
|       listener(fromNativeEvent(event, chart));
 | |
|     }
 | |
|   }, chart);
 | |
|   addListener(canvas, type, proxy);
 | |
|   return proxy;
 | |
| }
 | |
| var DomPlatform = class extends BasePlatform {
 | |
|   acquireContext(canvas, aspectRatio) {
 | |
|     const context = canvas && canvas.getContext && canvas.getContext("2d");
 | |
|     if (context && context.canvas === canvas) {
 | |
|       initCanvas(canvas, aspectRatio);
 | |
|       return context;
 | |
|     }
 | |
|     return null;
 | |
|   }
 | |
|   releaseContext(context) {
 | |
|     const canvas = context.canvas;
 | |
|     if (!canvas[EXPANDO_KEY]) {
 | |
|       return false;
 | |
|     }
 | |
|     const initial = canvas[EXPANDO_KEY].initial;
 | |
|     [
 | |
|       "height",
 | |
|       "width"
 | |
|     ].forEach((prop) => {
 | |
|       const value = initial[prop];
 | |
|       if (isNullOrUndef(value)) {
 | |
|         canvas.removeAttribute(prop);
 | |
|       } else {
 | |
|         canvas.setAttribute(prop, value);
 | |
|       }
 | |
|     });
 | |
|     const style = initial.style || {};
 | |
|     Object.keys(style).forEach((key) => {
 | |
|       canvas.style[key] = style[key];
 | |
|     });
 | |
|     canvas.width = canvas.width;
 | |
|     delete canvas[EXPANDO_KEY];
 | |
|     return true;
 | |
|   }
 | |
|   addEventListener(chart, type, listener) {
 | |
|     this.removeEventListener(chart, type);
 | |
|     const proxies = chart.$proxies || (chart.$proxies = {});
 | |
|     const handlers = {
 | |
|       attach: createAttachObserver,
 | |
|       detach: createDetachObserver,
 | |
|       resize: createResizeObserver
 | |
|     };
 | |
|     const handler = handlers[type] || createProxyAndListen;
 | |
|     proxies[type] = handler(chart, type, listener);
 | |
|   }
 | |
|   removeEventListener(chart, type) {
 | |
|     const proxies = chart.$proxies || (chart.$proxies = {});
 | |
|     const proxy = proxies[type];
 | |
|     if (!proxy) {
 | |
|       return;
 | |
|     }
 | |
|     const handlers = {
 | |
|       attach: releaseObserver,
 | |
|       detach: releaseObserver,
 | |
|       resize: releaseObserver
 | |
|     };
 | |
|     const handler = handlers[type] || removeListener;
 | |
|     handler(chart, type, proxy);
 | |
|     proxies[type] = void 0;
 | |
|   }
 | |
|   getDevicePixelRatio() {
 | |
|     return window.devicePixelRatio;
 | |
|   }
 | |
|   getMaximumSize(canvas, width, height, aspectRatio) {
 | |
|     return getMaximumSize(canvas, width, height, aspectRatio);
 | |
|   }
 | |
|   isAttached(canvas) {
 | |
|     const container = canvas && _getParentNode(canvas);
 | |
|     return !!(container && container.isConnected);
 | |
|   }
 | |
| };
 | |
| function _detectPlatform(canvas) {
 | |
|   if (!_isDomSupported() || typeof OffscreenCanvas !== "undefined" && canvas instanceof OffscreenCanvas) {
 | |
|     return BasicPlatform;
 | |
|   }
 | |
|   return DomPlatform;
 | |
| }
 | |
| var Element = class {
 | |
|   constructor() {
 | |
|     __publicField(this, "x");
 | |
|     __publicField(this, "y");
 | |
|     __publicField(this, "active", false);
 | |
|     __publicField(this, "options");
 | |
|     __publicField(this, "$animations");
 | |
|   }
 | |
|   tooltipPosition(useFinalPosition) {
 | |
|     const { x: x2, y: y2 } = this.getProps([
 | |
|       "x",
 | |
|       "y"
 | |
|     ], useFinalPosition);
 | |
|     return {
 | |
|       x: x2,
 | |
|       y: y2
 | |
|     };
 | |
|   }
 | |
|   hasValue() {
 | |
|     return isNumber(this.x) && isNumber(this.y);
 | |
|   }
 | |
|   getProps(props, final) {
 | |
|     const anims = this.$animations;
 | |
|     if (!final || !anims) {
 | |
|       return this;
 | |
|     }
 | |
|     const ret = {};
 | |
|     props.forEach((prop) => {
 | |
|       ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];
 | |
|     });
 | |
|     return ret;
 | |
|   }
 | |
| };
 | |
| __publicField(Element, "defaults", {});
 | |
| __publicField(Element, "defaultRoutes");
 | |
| function autoSkip(scale, ticks) {
 | |
|   const tickOpts = scale.options.ticks;
 | |
|   const determinedMaxTicks = determineMaxTicks(scale);
 | |
|   const ticksLimit = Math.min(tickOpts.maxTicksLimit || determinedMaxTicks, determinedMaxTicks);
 | |
|   const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];
 | |
|   const numMajorIndices = majorIndices.length;
 | |
|   const first = majorIndices[0];
 | |
|   const last = majorIndices[numMajorIndices - 1];
 | |
|   const newTicks = [];
 | |
|   if (numMajorIndices > ticksLimit) {
 | |
|     skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);
 | |
|     return newTicks;
 | |
|   }
 | |
|   const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);
 | |
|   if (numMajorIndices > 0) {
 | |
|     let i2, ilen;
 | |
|     const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;
 | |
|     skip(ticks, newTicks, spacing, isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
 | |
|     for (i2 = 0, ilen = numMajorIndices - 1; i2 < ilen; i2++) {
 | |
|       skip(ticks, newTicks, spacing, majorIndices[i2], majorIndices[i2 + 1]);
 | |
|     }
 | |
|     skip(ticks, newTicks, spacing, last, isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
 | |
|     return newTicks;
 | |
|   }
 | |
|   skip(ticks, newTicks, spacing);
 | |
|   return newTicks;
 | |
| }
 | |
| function determineMaxTicks(scale) {
 | |
|   const offset = scale.options.offset;
 | |
|   const tickLength = scale._tickSize();
 | |
|   const maxScale = scale._length / tickLength + (offset ? 0 : 1);
 | |
|   const maxChart = scale._maxLength / tickLength;
 | |
|   return Math.floor(Math.min(maxScale, maxChart));
 | |
| }
 | |
| function calculateSpacing(majorIndices, ticks, ticksLimit) {
 | |
|   const evenMajorSpacing = getEvenSpacing(majorIndices);
 | |
|   const spacing = ticks.length / ticksLimit;
 | |
|   if (!evenMajorSpacing) {
 | |
|     return Math.max(spacing, 1);
 | |
|   }
 | |
|   const factors = _factorize(evenMajorSpacing);
 | |
|   for (let i2 = 0, ilen = factors.length - 1; i2 < ilen; i2++) {
 | |
|     const factor = factors[i2];
 | |
|     if (factor > spacing) {
 | |
|       return factor;
 | |
|     }
 | |
|   }
 | |
|   return Math.max(spacing, 1);
 | |
| }
 | |
| function getMajorIndices(ticks) {
 | |
|   const result = [];
 | |
|   let i2, ilen;
 | |
|   for (i2 = 0, ilen = ticks.length; i2 < ilen; i2++) {
 | |
|     if (ticks[i2].major) {
 | |
|       result.push(i2);
 | |
|     }
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function skipMajors(ticks, newTicks, majorIndices, spacing) {
 | |
|   let count = 0;
 | |
|   let next = majorIndices[0];
 | |
|   let i2;
 | |
|   spacing = Math.ceil(spacing);
 | |
|   for (i2 = 0; i2 < ticks.length; i2++) {
 | |
|     if (i2 === next) {
 | |
|       newTicks.push(ticks[i2]);
 | |
|       count++;
 | |
|       next = majorIndices[count * spacing];
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
 | |
|   const start = valueOrDefault(majorStart, 0);
 | |
|   const end = Math.min(valueOrDefault(majorEnd, ticks.length), ticks.length);
 | |
|   let count = 0;
 | |
|   let length, i2, next;
 | |
|   spacing = Math.ceil(spacing);
 | |
|   if (majorEnd) {
 | |
|     length = majorEnd - majorStart;
 | |
|     spacing = length / Math.floor(length / spacing);
 | |
|   }
 | |
|   next = start;
 | |
|   while (next < 0) {
 | |
|     count++;
 | |
|     next = Math.round(start + count * spacing);
 | |
|   }
 | |
|   for (i2 = Math.max(start, 0); i2 < end; i2++) {
 | |
|     if (i2 === next) {
 | |
|       newTicks.push(ticks[i2]);
 | |
|       count++;
 | |
|       next = Math.round(start + count * spacing);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function getEvenSpacing(arr) {
 | |
|   const len = arr.length;
 | |
|   let i2, diff;
 | |
|   if (len < 2) {
 | |
|     return false;
 | |
|   }
 | |
|   for (diff = arr[0], i2 = 1; i2 < len; ++i2) {
 | |
|     if (arr[i2] - arr[i2 - 1] !== diff) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return diff;
 | |
| }
 | |
| var reverseAlign = (align) => align === "left" ? "right" : align === "right" ? "left" : align;
 | |
| var offsetFromEdge = (scale, edge, offset) => edge === "top" || edge === "left" ? scale[edge] + offset : scale[edge] - offset;
 | |
| var getTicksLimit = (ticksLength, maxTicksLimit) => Math.min(maxTicksLimit || ticksLength, ticksLength);
 | |
| function sample(arr, numItems) {
 | |
|   const result = [];
 | |
|   const increment = arr.length / numItems;
 | |
|   const len = arr.length;
 | |
|   let i2 = 0;
 | |
|   for (; i2 < len; i2 += increment) {
 | |
|     result.push(arr[Math.floor(i2)]);
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function getPixelForGridLine(scale, index, offsetGridLines) {
 | |
|   const length = scale.ticks.length;
 | |
|   const validIndex2 = Math.min(index, length - 1);
 | |
|   const start = scale._startPixel;
 | |
|   const end = scale._endPixel;
 | |
|   const epsilon = 1e-6;
 | |
|   let lineValue = scale.getPixelForTick(validIndex2);
 | |
|   let offset;
 | |
|   if (offsetGridLines) {
 | |
|     if (length === 1) {
 | |
|       offset = Math.max(lineValue - start, end - lineValue);
 | |
|     } else if (index === 0) {
 | |
|       offset = (scale.getPixelForTick(1) - lineValue) / 2;
 | |
|     } else {
 | |
|       offset = (lineValue - scale.getPixelForTick(validIndex2 - 1)) / 2;
 | |
|     }
 | |
|     lineValue += validIndex2 < index ? offset : -offset;
 | |
|     if (lineValue < start - epsilon || lineValue > end + epsilon) {
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
|   return lineValue;
 | |
| }
 | |
| function garbageCollect(caches, length) {
 | |
|   each(caches, (cache) => {
 | |
|     const gc = cache.gc;
 | |
|     const gcLen = gc.length / 2;
 | |
|     let i2;
 | |
|     if (gcLen > length) {
 | |
|       for (i2 = 0; i2 < gcLen; ++i2) {
 | |
|         delete cache.data[gc[i2]];
 | |
|       }
 | |
|       gc.splice(0, gcLen);
 | |
|     }
 | |
|   });
 | |
| }
 | |
| function getTickMarkLength(options) {
 | |
|   return options.drawTicks ? options.tickLength : 0;
 | |
| }
 | |
| function getTitleHeight(options, fallback) {
 | |
|   if (!options.display) {
 | |
|     return 0;
 | |
|   }
 | |
|   const font = toFont(options.font, fallback);
 | |
|   const padding = toPadding(options.padding);
 | |
|   const lines = isArray(options.text) ? options.text.length : 1;
 | |
|   return lines * font.lineHeight + padding.height;
 | |
| }
 | |
| function createScaleContext(parent, scale) {
 | |
|   return createContext(parent, {
 | |
|     scale,
 | |
|     type: "scale"
 | |
|   });
 | |
| }
 | |
| function createTickContext(parent, index, tick) {
 | |
|   return createContext(parent, {
 | |
|     tick,
 | |
|     index,
 | |
|     type: "tick"
 | |
|   });
 | |
| }
 | |
| function titleAlign(align, position, reverse) {
 | |
|   let ret = _toLeftRightCenter(align);
 | |
|   if (reverse && position !== "right" || !reverse && position === "right") {
 | |
|     ret = reverseAlign(ret);
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| function titleArgs(scale, offset, position, align) {
 | |
|   const { top, left, bottom, right, chart } = scale;
 | |
|   const { chartArea, scales } = chart;
 | |
|   let rotation = 0;
 | |
|   let maxWidth, titleX, titleY;
 | |
|   const height = bottom - top;
 | |
|   const width = right - left;
 | |
|   if (scale.isHorizontal()) {
 | |
|     titleX = _alignStartEnd(align, left, right);
 | |
|     if (isObject(position)) {
 | |
|       const positionAxisID = Object.keys(position)[0];
 | |
|       const value = position[positionAxisID];
 | |
|       titleY = scales[positionAxisID].getPixelForValue(value) + height - offset;
 | |
|     } else if (position === "center") {
 | |
|       titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset;
 | |
|     } else {
 | |
|       titleY = offsetFromEdge(scale, position, offset);
 | |
|     }
 | |
|     maxWidth = right - left;
 | |
|   } else {
 | |
|     if (isObject(position)) {
 | |
|       const positionAxisID = Object.keys(position)[0];
 | |
|       const value = position[positionAxisID];
 | |
|       titleX = scales[positionAxisID].getPixelForValue(value) - width + offset;
 | |
|     } else if (position === "center") {
 | |
|       titleX = (chartArea.left + chartArea.right) / 2 - width + offset;
 | |
|     } else {
 | |
|       titleX = offsetFromEdge(scale, position, offset);
 | |
|     }
 | |
|     titleY = _alignStartEnd(align, bottom, top);
 | |
|     rotation = position === "left" ? -HALF_PI : HALF_PI;
 | |
|   }
 | |
|   return {
 | |
|     titleX,
 | |
|     titleY,
 | |
|     maxWidth,
 | |
|     rotation
 | |
|   };
 | |
| }
 | |
| var Scale = class _Scale extends Element {
 | |
|   constructor(cfg) {
 | |
|     super();
 | |
|     this.id = cfg.id;
 | |
|     this.type = cfg.type;
 | |
|     this.options = void 0;
 | |
|     this.ctx = cfg.ctx;
 | |
|     this.chart = cfg.chart;
 | |
|     this.top = void 0;
 | |
|     this.bottom = void 0;
 | |
|     this.left = void 0;
 | |
|     this.right = void 0;
 | |
|     this.width = void 0;
 | |
|     this.height = void 0;
 | |
|     this._margins = {
 | |
|       left: 0,
 | |
|       right: 0,
 | |
|       top: 0,
 | |
|       bottom: 0
 | |
|     };
 | |
|     this.maxWidth = void 0;
 | |
|     this.maxHeight = void 0;
 | |
|     this.paddingTop = void 0;
 | |
|     this.paddingBottom = void 0;
 | |
|     this.paddingLeft = void 0;
 | |
|     this.paddingRight = void 0;
 | |
|     this.axis = void 0;
 | |
|     this.labelRotation = void 0;
 | |
|     this.min = void 0;
 | |
|     this.max = void 0;
 | |
|     this._range = void 0;
 | |
|     this.ticks = [];
 | |
|     this._gridLineItems = null;
 | |
|     this._labelItems = null;
 | |
|     this._labelSizes = null;
 | |
|     this._length = 0;
 | |
|     this._maxLength = 0;
 | |
|     this._longestTextCache = {};
 | |
|     this._startPixel = void 0;
 | |
|     this._endPixel = void 0;
 | |
|     this._reversePixels = false;
 | |
|     this._userMax = void 0;
 | |
|     this._userMin = void 0;
 | |
|     this._suggestedMax = void 0;
 | |
|     this._suggestedMin = void 0;
 | |
|     this._ticksLength = 0;
 | |
|     this._borderValue = 0;
 | |
|     this._cache = {};
 | |
|     this._dataLimitsCached = false;
 | |
|     this.$context = void 0;
 | |
|   }
 | |
|   init(options) {
 | |
|     this.options = options.setContext(this.getContext());
 | |
|     this.axis = options.axis;
 | |
|     this._userMin = this.parse(options.min);
 | |
|     this._userMax = this.parse(options.max);
 | |
|     this._suggestedMin = this.parse(options.suggestedMin);
 | |
|     this._suggestedMax = this.parse(options.suggestedMax);
 | |
|   }
 | |
|   parse(raw, index) {
 | |
|     return raw;
 | |
|   }
 | |
|   getUserBounds() {
 | |
|     let { _userMin, _userMax, _suggestedMin, _suggestedMax } = this;
 | |
|     _userMin = finiteOrDefault(_userMin, Number.POSITIVE_INFINITY);
 | |
|     _userMax = finiteOrDefault(_userMax, Number.NEGATIVE_INFINITY);
 | |
|     _suggestedMin = finiteOrDefault(_suggestedMin, Number.POSITIVE_INFINITY);
 | |
|     _suggestedMax = finiteOrDefault(_suggestedMax, Number.NEGATIVE_INFINITY);
 | |
|     return {
 | |
|       min: finiteOrDefault(_userMin, _suggestedMin),
 | |
|       max: finiteOrDefault(_userMax, _suggestedMax),
 | |
|       minDefined: isNumberFinite(_userMin),
 | |
|       maxDefined: isNumberFinite(_userMax)
 | |
|     };
 | |
|   }
 | |
|   getMinMax(canStack) {
 | |
|     let { min, max, minDefined, maxDefined } = this.getUserBounds();
 | |
|     let range;
 | |
|     if (minDefined && maxDefined) {
 | |
|       return {
 | |
|         min,
 | |
|         max
 | |
|       };
 | |
|     }
 | |
|     const metas = this.getMatchingVisibleMetas();
 | |
|     for (let i2 = 0, ilen = metas.length; i2 < ilen; ++i2) {
 | |
|       range = metas[i2].controller.getMinMax(this, canStack);
 | |
|       if (!minDefined) {
 | |
|         min = Math.min(min, range.min);
 | |
|       }
 | |
|       if (!maxDefined) {
 | |
|         max = Math.max(max, range.max);
 | |
|       }
 | |
|     }
 | |
|     min = maxDefined && min > max ? max : min;
 | |
|     max = minDefined && min > max ? min : max;
 | |
|     return {
 | |
|       min: finiteOrDefault(min, finiteOrDefault(max, min)),
 | |
|       max: finiteOrDefault(max, finiteOrDefault(min, max))
 | |
|     };
 | |
|   }
 | |
|   getPadding() {
 | |
|     return {
 | |
|       left: this.paddingLeft || 0,
 | |
|       top: this.paddingTop || 0,
 | |
|       right: this.paddingRight || 0,
 | |
|       bottom: this.paddingBottom || 0
 | |
|     };
 | |
|   }
 | |
|   getTicks() {
 | |
|     return this.ticks;
 | |
|   }
 | |
|   getLabels() {
 | |
|     const data = this.chart.data;
 | |
|     return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];
 | |
|   }
 | |
|   getLabelItems(chartArea = this.chart.chartArea) {
 | |
|     const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
 | |
|     return items;
 | |
|   }
 | |
|   beforeLayout() {
 | |
|     this._cache = {};
 | |
|     this._dataLimitsCached = false;
 | |
|   }
 | |
|   beforeUpdate() {
 | |
|     callback(this.options.beforeUpdate, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   update(maxWidth, maxHeight, margins) {
 | |
|     const { beginAtZero, grace, ticks: tickOpts } = this.options;
 | |
|     const sampleSize = tickOpts.sampleSize;
 | |
|     this.beforeUpdate();
 | |
|     this.maxWidth = maxWidth;
 | |
|     this.maxHeight = maxHeight;
 | |
|     this._margins = margins = Object.assign({
 | |
|       left: 0,
 | |
|       right: 0,
 | |
|       top: 0,
 | |
|       bottom: 0
 | |
|     }, margins);
 | |
|     this.ticks = null;
 | |
|     this._labelSizes = null;
 | |
|     this._gridLineItems = null;
 | |
|     this._labelItems = null;
 | |
|     this.beforeSetDimensions();
 | |
|     this.setDimensions();
 | |
|     this.afterSetDimensions();
 | |
|     this._maxLength = this.isHorizontal() ? this.width + margins.left + margins.right : this.height + margins.top + margins.bottom;
 | |
|     if (!this._dataLimitsCached) {
 | |
|       this.beforeDataLimits();
 | |
|       this.determineDataLimits();
 | |
|       this.afterDataLimits();
 | |
|       this._range = _addGrace(this, grace, beginAtZero);
 | |
|       this._dataLimitsCached = true;
 | |
|     }
 | |
|     this.beforeBuildTicks();
 | |
|     this.ticks = this.buildTicks() || [];
 | |
|     this.afterBuildTicks();
 | |
|     const samplingEnabled = sampleSize < this.ticks.length;
 | |
|     this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);
 | |
|     this.configure();
 | |
|     this.beforeCalculateLabelRotation();
 | |
|     this.calculateLabelRotation();
 | |
|     this.afterCalculateLabelRotation();
 | |
|     if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === "auto")) {
 | |
|       this.ticks = autoSkip(this, this.ticks);
 | |
|       this._labelSizes = null;
 | |
|       this.afterAutoSkip();
 | |
|     }
 | |
|     if (samplingEnabled) {
 | |
|       this._convertTicksToLabels(this.ticks);
 | |
|     }
 | |
|     this.beforeFit();
 | |
|     this.fit();
 | |
|     this.afterFit();
 | |
|     this.afterUpdate();
 | |
|   }
 | |
|   configure() {
 | |
|     let reversePixels = this.options.reverse;
 | |
|     let startPixel, endPixel;
 | |
|     if (this.isHorizontal()) {
 | |
|       startPixel = this.left;
 | |
|       endPixel = this.right;
 | |
|     } else {
 | |
|       startPixel = this.top;
 | |
|       endPixel = this.bottom;
 | |
|       reversePixels = !reversePixels;
 | |
|     }
 | |
|     this._startPixel = startPixel;
 | |
|     this._endPixel = endPixel;
 | |
|     this._reversePixels = reversePixels;
 | |
|     this._length = endPixel - startPixel;
 | |
|     this._alignToPixels = this.options.alignToPixels;
 | |
|   }
 | |
|   afterUpdate() {
 | |
|     callback(this.options.afterUpdate, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   beforeSetDimensions() {
 | |
|     callback(this.options.beforeSetDimensions, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   setDimensions() {
 | |
|     if (this.isHorizontal()) {
 | |
|       this.width = this.maxWidth;
 | |
|       this.left = 0;
 | |
|       this.right = this.width;
 | |
|     } else {
 | |
|       this.height = this.maxHeight;
 | |
|       this.top = 0;
 | |
|       this.bottom = this.height;
 | |
|     }
 | |
|     this.paddingLeft = 0;
 | |
|     this.paddingTop = 0;
 | |
|     this.paddingRight = 0;
 | |
|     this.paddingBottom = 0;
 | |
|   }
 | |
|   afterSetDimensions() {
 | |
|     callback(this.options.afterSetDimensions, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   _callHooks(name) {
 | |
|     this.chart.notifyPlugins(name, this.getContext());
 | |
|     callback(this.options[name], [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   beforeDataLimits() {
 | |
|     this._callHooks("beforeDataLimits");
 | |
|   }
 | |
|   determineDataLimits() {
 | |
|   }
 | |
|   afterDataLimits() {
 | |
|     this._callHooks("afterDataLimits");
 | |
|   }
 | |
|   beforeBuildTicks() {
 | |
|     this._callHooks("beforeBuildTicks");
 | |
|   }
 | |
|   buildTicks() {
 | |
|     return [];
 | |
|   }
 | |
|   afterBuildTicks() {
 | |
|     this._callHooks("afterBuildTicks");
 | |
|   }
 | |
|   beforeTickToLabelConversion() {
 | |
|     callback(this.options.beforeTickToLabelConversion, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   generateTickLabels(ticks) {
 | |
|     const tickOpts = this.options.ticks;
 | |
|     let i2, ilen, tick;
 | |
|     for (i2 = 0, ilen = ticks.length; i2 < ilen; i2++) {
 | |
|       tick = ticks[i2];
 | |
|       tick.label = callback(tickOpts.callback, [
 | |
|         tick.value,
 | |
|         i2,
 | |
|         ticks
 | |
|       ], this);
 | |
|     }
 | |
|   }
 | |
|   afterTickToLabelConversion() {
 | |
|     callback(this.options.afterTickToLabelConversion, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   beforeCalculateLabelRotation() {
 | |
|     callback(this.options.beforeCalculateLabelRotation, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   calculateLabelRotation() {
 | |
|     const options = this.options;
 | |
|     const tickOpts = options.ticks;
 | |
|     const numTicks = getTicksLimit(this.ticks.length, options.ticks.maxTicksLimit);
 | |
|     const minRotation = tickOpts.minRotation || 0;
 | |
|     const maxRotation = tickOpts.maxRotation;
 | |
|     let labelRotation = minRotation;
 | |
|     let tickWidth, maxHeight, maxLabelDiagonal;
 | |
|     if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {
 | |
|       this.labelRotation = minRotation;
 | |
|       return;
 | |
|     }
 | |
|     const labelSizes = this._getLabelSizes();
 | |
|     const maxLabelWidth = labelSizes.widest.width;
 | |
|     const maxLabelHeight = labelSizes.highest.height;
 | |
|     const maxWidth = _limitValue(this.chart.width - maxLabelWidth, 0, this.maxWidth);
 | |
|     tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);
 | |
|     if (maxLabelWidth + 6 > tickWidth) {
 | |
|       tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));
 | |
|       maxHeight = this.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);
 | |
|       maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);
 | |
|       labelRotation = toDegrees(Math.min(Math.asin(_limitValue((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin(_limitValue(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin(_limitValue(maxLabelHeight / maxLabelDiagonal, -1, 1))));
 | |
|       labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));
 | |
|     }
 | |
|     this.labelRotation = labelRotation;
 | |
|   }
 | |
|   afterCalculateLabelRotation() {
 | |
|     callback(this.options.afterCalculateLabelRotation, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   afterAutoSkip() {
 | |
|   }
 | |
|   beforeFit() {
 | |
|     callback(this.options.beforeFit, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   fit() {
 | |
|     const minSize = {
 | |
|       width: 0,
 | |
|       height: 0
 | |
|     };
 | |
|     const { chart, options: { ticks: tickOpts, title: titleOpts, grid: gridOpts } } = this;
 | |
|     const display = this._isVisible();
 | |
|     const isHorizontal = this.isHorizontal();
 | |
|     if (display) {
 | |
|       const titleHeight = getTitleHeight(titleOpts, chart.options.font);
 | |
|       if (isHorizontal) {
 | |
|         minSize.width = this.maxWidth;
 | |
|         minSize.height = getTickMarkLength(gridOpts) + titleHeight;
 | |
|       } else {
 | |
|         minSize.height = this.maxHeight;
 | |
|         minSize.width = getTickMarkLength(gridOpts) + titleHeight;
 | |
|       }
 | |
|       if (tickOpts.display && this.ticks.length) {
 | |
|         const { first, last, widest, highest } = this._getLabelSizes();
 | |
|         const tickPadding = tickOpts.padding * 2;
 | |
|         const angleRadians = toRadians(this.labelRotation);
 | |
|         const cos = Math.cos(angleRadians);
 | |
|         const sin = Math.sin(angleRadians);
 | |
|         if (isHorizontal) {
 | |
|           const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;
 | |
|           minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);
 | |
|         } else {
 | |
|           const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;
 | |
|           minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);
 | |
|         }
 | |
|         this._calculatePadding(first, last, sin, cos);
 | |
|       }
 | |
|     }
 | |
|     this._handleMargins();
 | |
|     if (isHorizontal) {
 | |
|       this.width = this._length = chart.width - this._margins.left - this._margins.right;
 | |
|       this.height = minSize.height;
 | |
|     } else {
 | |
|       this.width = minSize.width;
 | |
|       this.height = this._length = chart.height - this._margins.top - this._margins.bottom;
 | |
|     }
 | |
|   }
 | |
|   _calculatePadding(first, last, sin, cos) {
 | |
|     const { ticks: { align, padding }, position } = this.options;
 | |
|     const isRotated = this.labelRotation !== 0;
 | |
|     const labelsBelowTicks = position !== "top" && this.axis === "x";
 | |
|     if (this.isHorizontal()) {
 | |
|       const offsetLeft = this.getPixelForTick(0) - this.left;
 | |
|       const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);
 | |
|       let paddingLeft = 0;
 | |
|       let paddingRight = 0;
 | |
|       if (isRotated) {
 | |
|         if (labelsBelowTicks) {
 | |
|           paddingLeft = cos * first.width;
 | |
|           paddingRight = sin * last.height;
 | |
|         } else {
 | |
|           paddingLeft = sin * first.height;
 | |
|           paddingRight = cos * last.width;
 | |
|         }
 | |
|       } else if (align === "start") {
 | |
|         paddingRight = last.width;
 | |
|       } else if (align === "end") {
 | |
|         paddingLeft = first.width;
 | |
|       } else if (align !== "inner") {
 | |
|         paddingLeft = first.width / 2;
 | |
|         paddingRight = last.width / 2;
 | |
|       }
 | |
|       this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);
 | |
|       this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);
 | |
|     } else {
 | |
|       let paddingTop = last.height / 2;
 | |
|       let paddingBottom = first.height / 2;
 | |
|       if (align === "start") {
 | |
|         paddingTop = 0;
 | |
|         paddingBottom = first.height;
 | |
|       } else if (align === "end") {
 | |
|         paddingTop = last.height;
 | |
|         paddingBottom = 0;
 | |
|       }
 | |
|       this.paddingTop = paddingTop + padding;
 | |
|       this.paddingBottom = paddingBottom + padding;
 | |
|     }
 | |
|   }
 | |
|   _handleMargins() {
 | |
|     if (this._margins) {
 | |
|       this._margins.left = Math.max(this.paddingLeft, this._margins.left);
 | |
|       this._margins.top = Math.max(this.paddingTop, this._margins.top);
 | |
|       this._margins.right = Math.max(this.paddingRight, this._margins.right);
 | |
|       this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);
 | |
|     }
 | |
|   }
 | |
|   afterFit() {
 | |
|     callback(this.options.afterFit, [
 | |
|       this
 | |
|     ]);
 | |
|   }
 | |
|   isHorizontal() {
 | |
|     const { axis, position } = this.options;
 | |
|     return position === "top" || position === "bottom" || axis === "x";
 | |
|   }
 | |
|   isFullSize() {
 | |
|     return this.options.fullSize;
 | |
|   }
 | |
|   _convertTicksToLabels(ticks) {
 | |
|     this.beforeTickToLabelConversion();
 | |
|     this.generateTickLabels(ticks);
 | |
|     let i2, ilen;
 | |
|     for (i2 = 0, ilen = ticks.length; i2 < ilen; i2++) {
 | |
|       if (isNullOrUndef(ticks[i2].label)) {
 | |
|         ticks.splice(i2, 1);
 | |
|         ilen--;
 | |
|         i2--;
 | |
|       }
 | |
|     }
 | |
|     this.afterTickToLabelConversion();
 | |
|   }
 | |
|   _getLabelSizes() {
 | |
|     let labelSizes = this._labelSizes;
 | |
|     if (!labelSizes) {
 | |
|       const sampleSize = this.options.ticks.sampleSize;
 | |
|       let ticks = this.ticks;
 | |
|       if (sampleSize < ticks.length) {
 | |
|         ticks = sample(ticks, sampleSize);
 | |
|       }
 | |
|       this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length, this.options.ticks.maxTicksLimit);
 | |
|     }
 | |
|     return labelSizes;
 | |
|   }
 | |
|   _computeLabelSizes(ticks, length, maxTicksLimit) {
 | |
|     const { ctx, _longestTextCache: caches } = this;
 | |
|     const widths = [];
 | |
|     const heights = [];
 | |
|     const increment = Math.floor(length / getTicksLimit(length, maxTicksLimit));
 | |
|     let widestLabelSize = 0;
 | |
|     let highestLabelSize = 0;
 | |
|     let i2, j2, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel;
 | |
|     for (i2 = 0; i2 < length; i2 += increment) {
 | |
|       label = ticks[i2].label;
 | |
|       tickFont = this._resolveTickFontOptions(i2);
 | |
|       ctx.font = fontString = tickFont.string;
 | |
|       cache = caches[fontString] = caches[fontString] || {
 | |
|         data: {},
 | |
|         gc: []
 | |
|       };
 | |
|       lineHeight = tickFont.lineHeight;
 | |
|       width = height = 0;
 | |
|       if (!isNullOrUndef(label) && !isArray(label)) {
 | |
|         width = _measureText(ctx, cache.data, cache.gc, width, label);
 | |
|         height = lineHeight;
 | |
|       } else if (isArray(label)) {
 | |
|         for (j2 = 0, jlen = label.length; j2 < jlen; ++j2) {
 | |
|           nestedLabel = label[j2];
 | |
|           if (!isNullOrUndef(nestedLabel) && !isArray(nestedLabel)) {
 | |
|             width = _measureText(ctx, cache.data, cache.gc, width, nestedLabel);
 | |
|             height += lineHeight;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       widths.push(width);
 | |
|       heights.push(height);
 | |
|       widestLabelSize = Math.max(width, widestLabelSize);
 | |
|       highestLabelSize = Math.max(height, highestLabelSize);
 | |
|     }
 | |
|     garbageCollect(caches, length);
 | |
|     const widest = widths.indexOf(widestLabelSize);
 | |
|     const highest = heights.indexOf(highestLabelSize);
 | |
|     const valueAt = (idx) => ({
 | |
|       width: widths[idx] || 0,
 | |
|       height: heights[idx] || 0
 | |
|     });
 | |
|     return {
 | |
|       first: valueAt(0),
 | |
|       last: valueAt(length - 1),
 | |
|       widest: valueAt(widest),
 | |
|       highest: valueAt(highest),
 | |
|       widths,
 | |
|       heights
 | |
|     };
 | |
|   }
 | |
|   getLabelForValue(value) {
 | |
|     return value;
 | |
|   }
 | |
|   getPixelForValue(value, index) {
 | |
|     return NaN;
 | |
|   }
 | |
|   getValueForPixel(pixel) {
 | |
|   }
 | |
|   getPixelForTick(index) {
 | |
|     const ticks = this.ticks;
 | |
|     if (index < 0 || index > ticks.length - 1) {
 | |
|       return null;
 | |
|     }
 | |
|     return this.getPixelForValue(ticks[index].value);
 | |
|   }
 | |
|   getPixelForDecimal(decimal) {
 | |
|     if (this._reversePixels) {
 | |
|       decimal = 1 - decimal;
 | |
|     }
 | |
|     const pixel = this._startPixel + decimal * this._length;
 | |
|     return _int16Range(this._alignToPixels ? _alignPixel(this.chart, pixel, 0) : pixel);
 | |
|   }
 | |
|   getDecimalForPixel(pixel) {
 | |
|     const decimal = (pixel - this._startPixel) / this._length;
 | |
|     return this._reversePixels ? 1 - decimal : decimal;
 | |
|   }
 | |
|   getBasePixel() {
 | |
|     return this.getPixelForValue(this.getBaseValue());
 | |
|   }
 | |
|   getBaseValue() {
 | |
|     const { min, max } = this;
 | |
|     return min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0;
 | |
|   }
 | |
|   getContext(index) {
 | |
|     const ticks = this.ticks || [];
 | |
|     if (index >= 0 && index < ticks.length) {
 | |
|       const tick = ticks[index];
 | |
|       return tick.$context || (tick.$context = createTickContext(this.getContext(), index, tick));
 | |
|     }
 | |
|     return this.$context || (this.$context = createScaleContext(this.chart.getContext(), this));
 | |
|   }
 | |
|   _tickSize() {
 | |
|     const optionTicks = this.options.ticks;
 | |
|     const rot = toRadians(this.labelRotation);
 | |
|     const cos = Math.abs(Math.cos(rot));
 | |
|     const sin = Math.abs(Math.sin(rot));
 | |
|     const labelSizes = this._getLabelSizes();
 | |
|     const padding = optionTicks.autoSkipPadding || 0;
 | |
|     const w2 = labelSizes ? labelSizes.widest.width + padding : 0;
 | |
|     const h6 = labelSizes ? labelSizes.highest.height + padding : 0;
 | |
|     return this.isHorizontal() ? h6 * cos > w2 * sin ? w2 / cos : h6 / sin : h6 * sin < w2 * cos ? h6 / cos : w2 / sin;
 | |
|   }
 | |
|   _isVisible() {
 | |
|     const display = this.options.display;
 | |
|     if (display !== "auto") {
 | |
|       return !!display;
 | |
|     }
 | |
|     return this.getMatchingVisibleMetas().length > 0;
 | |
|   }
 | |
|   _computeGridLineItems(chartArea) {
 | |
|     const axis = this.axis;
 | |
|     const chart = this.chart;
 | |
|     const options = this.options;
 | |
|     const { grid, position, border } = options;
 | |
|     const offset = grid.offset;
 | |
|     const isHorizontal = this.isHorizontal();
 | |
|     const ticks = this.ticks;
 | |
|     const ticksLength = ticks.length + (offset ? 1 : 0);
 | |
|     const tl = getTickMarkLength(grid);
 | |
|     const items = [];
 | |
|     const borderOpts = border.setContext(this.getContext());
 | |
|     const axisWidth = borderOpts.display ? borderOpts.width : 0;
 | |
|     const axisHalfWidth = axisWidth / 2;
 | |
|     const alignBorderValue = function(pixel) {
 | |
|       return _alignPixel(chart, pixel, axisWidth);
 | |
|     };
 | |
|     let borderValue, i2, lineValue, alignedLineValue;
 | |
|     let tx1, ty1, tx2, ty2, x1, y1, x2, y2;
 | |
|     if (position === "top") {
 | |
|       borderValue = alignBorderValue(this.bottom);
 | |
|       ty1 = this.bottom - tl;
 | |
|       ty2 = borderValue - axisHalfWidth;
 | |
|       y1 = alignBorderValue(chartArea.top) + axisHalfWidth;
 | |
|       y2 = chartArea.bottom;
 | |
|     } else if (position === "bottom") {
 | |
|       borderValue = alignBorderValue(this.top);
 | |
|       y1 = chartArea.top;
 | |
|       y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;
 | |
|       ty1 = borderValue + axisHalfWidth;
 | |
|       ty2 = this.top + tl;
 | |
|     } else if (position === "left") {
 | |
|       borderValue = alignBorderValue(this.right);
 | |
|       tx1 = this.right - tl;
 | |
|       tx2 = borderValue - axisHalfWidth;
 | |
|       x1 = alignBorderValue(chartArea.left) + axisHalfWidth;
 | |
|       x2 = chartArea.right;
 | |
|     } else if (position === "right") {
 | |
|       borderValue = alignBorderValue(this.left);
 | |
|       x1 = chartArea.left;
 | |
|       x2 = alignBorderValue(chartArea.right) - axisHalfWidth;
 | |
|       tx1 = borderValue + axisHalfWidth;
 | |
|       tx2 = this.left + tl;
 | |
|     } else if (axis === "x") {
 | |
|       if (position === "center") {
 | |
|         borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);
 | |
|       } else if (isObject(position)) {
 | |
|         const positionAxisID = Object.keys(position)[0];
 | |
|         const value = position[positionAxisID];
 | |
|         borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
 | |
|       }
 | |
|       y1 = chartArea.top;
 | |
|       y2 = chartArea.bottom;
 | |
|       ty1 = borderValue + axisHalfWidth;
 | |
|       ty2 = ty1 + tl;
 | |
|     } else if (axis === "y") {
 | |
|       if (position === "center") {
 | |
|         borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2);
 | |
|       } else if (isObject(position)) {
 | |
|         const positionAxisID = Object.keys(position)[0];
 | |
|         const value = position[positionAxisID];
 | |
|         borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
 | |
|       }
 | |
|       tx1 = borderValue - axisHalfWidth;
 | |
|       tx2 = tx1 - tl;
 | |
|       x1 = chartArea.left;
 | |
|       x2 = chartArea.right;
 | |
|     }
 | |
|     const limit = valueOrDefault(options.ticks.maxTicksLimit, ticksLength);
 | |
|     const step = Math.max(1, Math.ceil(ticksLength / limit));
 | |
|     for (i2 = 0; i2 < ticksLength; i2 += step) {
 | |
|       const context = this.getContext(i2);
 | |
|       const optsAtIndex = grid.setContext(context);
 | |
|       const optsAtIndexBorder = border.setContext(context);
 | |
|       const lineWidth = optsAtIndex.lineWidth;
 | |
|       const lineColor = optsAtIndex.color;
 | |
|       const borderDash = optsAtIndexBorder.dash || [];
 | |
|       const borderDashOffset = optsAtIndexBorder.dashOffset;
 | |
|       const tickWidth = optsAtIndex.tickWidth;
 | |
|       const tickColor = optsAtIndex.tickColor;
 | |
|       const tickBorderDash = optsAtIndex.tickBorderDash || [];
 | |
|       const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;
 | |
|       lineValue = getPixelForGridLine(this, i2, offset);
 | |
|       if (lineValue === void 0) {
 | |
|         continue;
 | |
|       }
 | |
|       alignedLineValue = _alignPixel(chart, lineValue, lineWidth);
 | |
|       if (isHorizontal) {
 | |
|         tx1 = tx2 = x1 = x2 = alignedLineValue;
 | |
|       } else {
 | |
|         ty1 = ty2 = y1 = y2 = alignedLineValue;
 | |
|       }
 | |
|       items.push({
 | |
|         tx1,
 | |
|         ty1,
 | |
|         tx2,
 | |
|         ty2,
 | |
|         x1,
 | |
|         y1,
 | |
|         x2,
 | |
|         y2,
 | |
|         width: lineWidth,
 | |
|         color: lineColor,
 | |
|         borderDash,
 | |
|         borderDashOffset,
 | |
|         tickWidth,
 | |
|         tickColor,
 | |
|         tickBorderDash,
 | |
|         tickBorderDashOffset
 | |
|       });
 | |
|     }
 | |
|     this._ticksLength = ticksLength;
 | |
|     this._borderValue = borderValue;
 | |
|     return items;
 | |
|   }
 | |
|   _computeLabelItems(chartArea) {
 | |
|     const axis = this.axis;
 | |
|     const options = this.options;
 | |
|     const { position, ticks: optionTicks } = options;
 | |
|     const isHorizontal = this.isHorizontal();
 | |
|     const ticks = this.ticks;
 | |
|     const { align, crossAlign, padding, mirror } = optionTicks;
 | |
|     const tl = getTickMarkLength(options.grid);
 | |
|     const tickAndPadding = tl + padding;
 | |
|     const hTickAndPadding = mirror ? -padding : tickAndPadding;
 | |
|     const rotation = -toRadians(this.labelRotation);
 | |
|     const items = [];
 | |
|     let i2, ilen, tick, label, x2, y2, textAlign, pixel, font, lineHeight, lineCount, textOffset;
 | |
|     let textBaseline = "middle";
 | |
|     if (position === "top") {
 | |
|       y2 = this.bottom - hTickAndPadding;
 | |
|       textAlign = this._getXAxisLabelAlignment();
 | |
|     } else if (position === "bottom") {
 | |
|       y2 = this.top + hTickAndPadding;
 | |
|       textAlign = this._getXAxisLabelAlignment();
 | |
|     } else if (position === "left") {
 | |
|       const ret = this._getYAxisLabelAlignment(tl);
 | |
|       textAlign = ret.textAlign;
 | |
|       x2 = ret.x;
 | |
|     } else if (position === "right") {
 | |
|       const ret = this._getYAxisLabelAlignment(tl);
 | |
|       textAlign = ret.textAlign;
 | |
|       x2 = ret.x;
 | |
|     } else if (axis === "x") {
 | |
|       if (position === "center") {
 | |
|         y2 = (chartArea.top + chartArea.bottom) / 2 + tickAndPadding;
 | |
|       } else if (isObject(position)) {
 | |
|         const positionAxisID = Object.keys(position)[0];
 | |
|         const value = position[positionAxisID];
 | |
|         y2 = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;
 | |
|       }
 | |
|       textAlign = this._getXAxisLabelAlignment();
 | |
|     } else if (axis === "y") {
 | |
|       if (position === "center") {
 | |
|         x2 = (chartArea.left + chartArea.right) / 2 - tickAndPadding;
 | |
|       } else if (isObject(position)) {
 | |
|         const positionAxisID = Object.keys(position)[0];
 | |
|         const value = position[positionAxisID];
 | |
|         x2 = this.chart.scales[positionAxisID].getPixelForValue(value);
 | |
|       }
 | |
|       textAlign = this._getYAxisLabelAlignment(tl).textAlign;
 | |
|     }
 | |
|     if (axis === "y") {
 | |
|       if (align === "start") {
 | |
|         textBaseline = "top";
 | |
|       } else if (align === "end") {
 | |
|         textBaseline = "bottom";
 | |
|       }
 | |
|     }
 | |
|     const labelSizes = this._getLabelSizes();
 | |
|     for (i2 = 0, ilen = ticks.length; i2 < ilen; ++i2) {
 | |
|       tick = ticks[i2];
 | |
|       label = tick.label;
 | |
|       const optsAtIndex = optionTicks.setContext(this.getContext(i2));
 | |
|       pixel = this.getPixelForTick(i2) + optionTicks.labelOffset;
 | |
|       font = this._resolveTickFontOptions(i2);
 | |
|       lineHeight = font.lineHeight;
 | |
|       lineCount = isArray(label) ? label.length : 1;
 | |
|       const halfCount = lineCount / 2;
 | |
|       const color2 = optsAtIndex.color;
 | |
|       const strokeColor = optsAtIndex.textStrokeColor;
 | |
|       const strokeWidth = optsAtIndex.textStrokeWidth;
 | |
|       let tickTextAlign = textAlign;
 | |
|       if (isHorizontal) {
 | |
|         x2 = pixel;
 | |
|         if (textAlign === "inner") {
 | |
|           if (i2 === ilen - 1) {
 | |
|             tickTextAlign = !this.options.reverse ? "right" : "left";
 | |
|           } else if (i2 === 0) {
 | |
|             tickTextAlign = !this.options.reverse ? "left" : "right";
 | |
|           } else {
 | |
|             tickTextAlign = "center";
 | |
|           }
 | |
|         }
 | |
|         if (position === "top") {
 | |
|           if (crossAlign === "near" || rotation !== 0) {
 | |
|             textOffset = -lineCount * lineHeight + lineHeight / 2;
 | |
|           } else if (crossAlign === "center") {
 | |
|             textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight;
 | |
|           } else {
 | |
|             textOffset = -labelSizes.highest.height + lineHeight / 2;
 | |
|           }
 | |
|         } else {
 | |
|           if (crossAlign === "near" || rotation !== 0) {
 | |
|             textOffset = lineHeight / 2;
 | |
|           } else if (crossAlign === "center") {
 | |
|             textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight;
 | |
|           } else {
 | |
|             textOffset = labelSizes.highest.height - lineCount * lineHeight;
 | |
|           }
 | |
|         }
 | |
|         if (mirror) {
 | |
|           textOffset *= -1;
 | |
|         }
 | |
|         if (rotation !== 0 && !optsAtIndex.showLabelBackdrop) {
 | |
|           x2 += lineHeight / 2 * Math.sin(rotation);
 | |
|         }
 | |
|       } else {
 | |
|         y2 = pixel;
 | |
|         textOffset = (1 - lineCount) * lineHeight / 2;
 | |
|       }
 | |
|       let backdrop;
 | |
|       if (optsAtIndex.showLabelBackdrop) {
 | |
|         const labelPadding = toPadding(optsAtIndex.backdropPadding);
 | |
|         const height = labelSizes.heights[i2];
 | |
|         const width = labelSizes.widths[i2];
 | |
|         let top = textOffset - labelPadding.top;
 | |
|         let left = 0 - labelPadding.left;
 | |
|         switch (textBaseline) {
 | |
|           case "middle":
 | |
|             top -= height / 2;
 | |
|             break;
 | |
|           case "bottom":
 | |
|             top -= height;
 | |
|             break;
 | |
|         }
 | |
|         switch (textAlign) {
 | |
|           case "center":
 | |
|             left -= width / 2;
 | |
|             break;
 | |
|           case "right":
 | |
|             left -= width;
 | |
|             break;
 | |
|           case "inner":
 | |
|             if (i2 === ilen - 1) {
 | |
|               left -= width;
 | |
|             } else if (i2 > 0) {
 | |
|               left -= width / 2;
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
|         backdrop = {
 | |
|           left,
 | |
|           top,
 | |
|           width: width + labelPadding.width,
 | |
|           height: height + labelPadding.height,
 | |
|           color: optsAtIndex.backdropColor
 | |
|         };
 | |
|       }
 | |
|       items.push({
 | |
|         label,
 | |
|         font,
 | |
|         textOffset,
 | |
|         options: {
 | |
|           rotation,
 | |
|           color: color2,
 | |
|           strokeColor,
 | |
|           strokeWidth,
 | |
|           textAlign: tickTextAlign,
 | |
|           textBaseline,
 | |
|           translation: [
 | |
|             x2,
 | |
|             y2
 | |
|           ],
 | |
|           backdrop
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|     return items;
 | |
|   }
 | |
|   _getXAxisLabelAlignment() {
 | |
|     const { position, ticks } = this.options;
 | |
|     const rotation = -toRadians(this.labelRotation);
 | |
|     if (rotation) {
 | |
|       return position === "top" ? "left" : "right";
 | |
|     }
 | |
|     let align = "center";
 | |
|     if (ticks.align === "start") {
 | |
|       align = "left";
 | |
|     } else if (ticks.align === "end") {
 | |
|       align = "right";
 | |
|     } else if (ticks.align === "inner") {
 | |
|       align = "inner";
 | |
|     }
 | |
|     return align;
 | |
|   }
 | |
|   _getYAxisLabelAlignment(tl) {
 | |
|     const { position, ticks: { crossAlign, mirror, padding } } = this.options;
 | |
|     const labelSizes = this._getLabelSizes();
 | |
|     const tickAndPadding = tl + padding;
 | |
|     const widest = labelSizes.widest.width;
 | |
|     let textAlign;
 | |
|     let x2;
 | |
|     if (position === "left") {
 | |
|       if (mirror) {
 | |
|         x2 = this.right + padding;
 | |
|         if (crossAlign === "near") {
 | |
|           textAlign = "left";
 | |
|         } else if (crossAlign === "center") {
 | |
|           textAlign = "center";
 | |
|           x2 += widest / 2;
 | |
|         } else {
 | |
|           textAlign = "right";
 | |
|           x2 += widest;
 | |
|         }
 | |
|       } else {
 | |
|         x2 = this.right - tickAndPadding;
 | |
|         if (crossAlign === "near") {
 | |
|           textAlign = "right";
 | |
|         } else if (crossAlign === "center") {
 | |
|           textAlign = "center";
 | |
|           x2 -= widest / 2;
 | |
|         } else {
 | |
|           textAlign = "left";
 | |
|           x2 = this.left;
 | |
|         }
 | |
|       }
 | |
|     } else if (position === "right") {
 | |
|       if (mirror) {
 | |
|         x2 = this.left + padding;
 | |
|         if (crossAlign === "near") {
 | |
|           textAlign = "right";
 | |
|         } else if (crossAlign === "center") {
 | |
|           textAlign = "center";
 | |
|           x2 -= widest / 2;
 | |
|         } else {
 | |
|           textAlign = "left";
 | |
|           x2 -= widest;
 | |
|         }
 | |
|       } else {
 | |
|         x2 = this.left + tickAndPadding;
 | |
|         if (crossAlign === "near") {
 | |
|           textAlign = "left";
 | |
|         } else if (crossAlign === "center") {
 | |
|           textAlign = "center";
 | |
|           x2 += widest / 2;
 | |
|         } else {
 | |
|           textAlign = "right";
 | |
|           x2 = this.right;
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       textAlign = "right";
 | |
|     }
 | |
|     return {
 | |
|       textAlign,
 | |
|       x: x2
 | |
|     };
 | |
|   }
 | |
|   _computeLabelArea() {
 | |
|     if (this.options.ticks.mirror) {
 | |
|       return;
 | |
|     }
 | |
|     const chart = this.chart;
 | |
|     const position = this.options.position;
 | |
|     if (position === "left" || position === "right") {
 | |
|       return {
 | |
|         top: 0,
 | |
|         left: this.left,
 | |
|         bottom: chart.height,
 | |
|         right: this.right
 | |
|       };
 | |
|     }
 | |
|     if (position === "top" || position === "bottom") {
 | |
|       return {
 | |
|         top: this.top,
 | |
|         left: 0,
 | |
|         bottom: this.bottom,
 | |
|         right: chart.width
 | |
|       };
 | |
|     }
 | |
|   }
 | |
|   drawBackground() {
 | |
|     const { ctx, options: { backgroundColor }, left, top, width, height } = this;
 | |
|     if (backgroundColor) {
 | |
|       ctx.save();
 | |
|       ctx.fillStyle = backgroundColor;
 | |
|       ctx.fillRect(left, top, width, height);
 | |
|       ctx.restore();
 | |
|     }
 | |
|   }
 | |
|   getLineWidthForValue(value) {
 | |
|     const grid = this.options.grid;
 | |
|     if (!this._isVisible() || !grid.display) {
 | |
|       return 0;
 | |
|     }
 | |
|     const ticks = this.ticks;
 | |
|     const index = ticks.findIndex((t3) => t3.value === value);
 | |
|     if (index >= 0) {
 | |
|       const opts = grid.setContext(this.getContext(index));
 | |
|       return opts.lineWidth;
 | |
|     }
 | |
|     return 0;
 | |
|   }
 | |
|   drawGrid(chartArea) {
 | |
|     const grid = this.options.grid;
 | |
|     const ctx = this.ctx;
 | |
|     const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));
 | |
|     let i2, ilen;
 | |
|     const drawLine = (p1, p2, style) => {
 | |
|       if (!style.width || !style.color) {
 | |
|         return;
 | |
|       }
 | |
|       ctx.save();
 | |
|       ctx.lineWidth = style.width;
 | |
|       ctx.strokeStyle = style.color;
 | |
|       ctx.setLineDash(style.borderDash || []);
 | |
|       ctx.lineDashOffset = style.borderDashOffset;
 | |
|       ctx.beginPath();
 | |
|       ctx.moveTo(p1.x, p1.y);
 | |
|       ctx.lineTo(p2.x, p2.y);
 | |
|       ctx.stroke();
 | |
|       ctx.restore();
 | |
|     };
 | |
|     if (grid.display) {
 | |
|       for (i2 = 0, ilen = items.length; i2 < ilen; ++i2) {
 | |
|         const item = items[i2];
 | |
|         if (grid.drawOnChartArea) {
 | |
|           drawLine({
 | |
|             x: item.x1,
 | |
|             y: item.y1
 | |
|           }, {
 | |
|             x: item.x2,
 | |
|             y: item.y2
 | |
|           }, item);
 | |
|         }
 | |
|         if (grid.drawTicks) {
 | |
|           drawLine({
 | |
|             x: item.tx1,
 | |
|             y: item.ty1
 | |
|           }, {
 | |
|             x: item.tx2,
 | |
|             y: item.ty2
 | |
|           }, {
 | |
|             color: item.tickColor,
 | |
|             width: item.tickWidth,
 | |
|             borderDash: item.tickBorderDash,
 | |
|             borderDashOffset: item.tickBorderDashOffset
 | |
|           });
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   drawBorder() {
 | |
|     const { chart, ctx, options: { border, grid } } = this;
 | |
|     const borderOpts = border.setContext(this.getContext());
 | |
|     const axisWidth = border.display ? borderOpts.width : 0;
 | |
|     if (!axisWidth) {
 | |
|       return;
 | |
|     }
 | |
|     const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;
 | |
|     const borderValue = this._borderValue;
 | |
|     let x1, x2, y1, y2;
 | |
|     if (this.isHorizontal()) {
 | |
|       x1 = _alignPixel(chart, this.left, axisWidth) - axisWidth / 2;
 | |
|       x2 = _alignPixel(chart, this.right, lastLineWidth) + lastLineWidth / 2;
 | |
|       y1 = y2 = borderValue;
 | |
|     } else {
 | |
|       y1 = _alignPixel(chart, this.top, axisWidth) - axisWidth / 2;
 | |
|       y2 = _alignPixel(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;
 | |
|       x1 = x2 = borderValue;
 | |
|     }
 | |
|     ctx.save();
 | |
|     ctx.lineWidth = borderOpts.width;
 | |
|     ctx.strokeStyle = borderOpts.color;
 | |
|     ctx.beginPath();
 | |
|     ctx.moveTo(x1, y1);
 | |
|     ctx.lineTo(x2, y2);
 | |
|     ctx.stroke();
 | |
|     ctx.restore();
 | |
|   }
 | |
|   drawLabels(chartArea) {
 | |
|     const optionTicks = this.options.ticks;
 | |
|     if (!optionTicks.display) {
 | |
|       return;
 | |
|     }
 | |
|     const ctx = this.ctx;
 | |
|     const area = this._computeLabelArea();
 | |
|     if (area) {
 | |
|       clipArea(ctx, area);
 | |
|     }
 | |
|     const items = this.getLabelItems(chartArea);
 | |
|     for (const item of items) {
 | |
|       const renderTextOptions = item.options;
 | |
|       const tickFont = item.font;
 | |
|       const label = item.label;
 | |
|       const y2 = item.textOffset;
 | |
|       renderText(ctx, label, 0, y2, tickFont, renderTextOptions);
 | |
|     }
 | |
|     if (area) {
 | |
|       unclipArea(ctx);
 | |
|     }
 | |
|   }
 | |
|   drawTitle() {
 | |
|     const { ctx, options: { position, title, reverse } } = this;
 | |
|     if (!title.display) {
 | |
|       return;
 | |
|     }
 | |
|     const font = toFont(title.font);
 | |
|     const padding = toPadding(title.padding);
 | |
|     const align = title.align;
 | |
|     let offset = font.lineHeight / 2;
 | |
|     if (position === "bottom" || position === "center" || isObject(position)) {
 | |
|       offset += padding.bottom;
 | |
|       if (isArray(title.text)) {
 | |
|         offset += font.lineHeight * (title.text.length - 1);
 | |
|       }
 | |
|     } else {
 | |
|       offset += padding.top;
 | |
|     }
 | |
|     const { titleX, titleY, maxWidth, rotation } = titleArgs(this, offset, position, align);
 | |
|     renderText(ctx, title.text, 0, 0, font, {
 | |
|       color: title.color,
 | |
|       maxWidth,
 | |
|       rotation,
 | |
|       textAlign: titleAlign(align, position, reverse),
 | |
|       textBaseline: "middle",
 | |
|       translation: [
 | |
|         titleX,
 | |
|         titleY
 | |
|       ]
 | |
|     });
 | |
|   }
 | |
|   draw(chartArea) {
 | |
|     if (!this._isVisible()) {
 | |
|       return;
 | |
|     }
 | |
|     this.drawBackground();
 | |
|     this.drawGrid(chartArea);
 | |
|     this.drawBorder();
 | |
|     this.drawTitle();
 | |
|     this.drawLabels(chartArea);
 | |
|   }
 | |
|   _layers() {
 | |
|     const opts = this.options;
 | |
|     const tz = opts.ticks && opts.ticks.z || 0;
 | |
|     const gz = valueOrDefault(opts.grid && opts.grid.z, -1);
 | |
|     const bz = valueOrDefault(opts.border && opts.border.z, 0);
 | |
|     if (!this._isVisible() || this.draw !== _Scale.prototype.draw) {
 | |
|       return [
 | |
|         {
 | |
|           z: tz,
 | |
|           draw: (chartArea) => {
 | |
|             this.draw(chartArea);
 | |
|           }
 | |
|         }
 | |
|       ];
 | |
|     }
 | |
|     return [
 | |
|       {
 | |
|         z: gz,
 | |
|         draw: (chartArea) => {
 | |
|           this.drawBackground();
 | |
|           this.drawGrid(chartArea);
 | |
|           this.drawTitle();
 | |
|         }
 | |
|       },
 | |
|       {
 | |
|         z: bz,
 | |
|         draw: () => {
 | |
|           this.drawBorder();
 | |
|         }
 | |
|       },
 | |
|       {
 | |
|         z: tz,
 | |
|         draw: (chartArea) => {
 | |
|           this.drawLabels(chartArea);
 | |
|         }
 | |
|       }
 | |
|     ];
 | |
|   }
 | |
|   getMatchingVisibleMetas(type) {
 | |
|     const metas = this.chart.getSortedVisibleDatasetMetas();
 | |
|     const axisID = this.axis + "AxisID";
 | |
|     const result = [];
 | |
|     let i2, ilen;
 | |
|     for (i2 = 0, ilen = metas.length; i2 < ilen; ++i2) {
 | |
|       const meta = metas[i2];
 | |
|       if (meta[axisID] === this.id && (!type || meta.type === type)) {
 | |
|         result.push(meta);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   _resolveTickFontOptions(index) {
 | |
|     const opts = this.options.ticks.setContext(this.getContext(index));
 | |
|     return toFont(opts.font);
 | |
|   }
 | |
|   _maxDigits() {
 | |
|     const fontSize = this._resolveTickFontOptions(0).lineHeight;
 | |
|     return (this.isHorizontal() ? this.width : this.height) / fontSize;
 | |
|   }
 | |
| };
 | |
| var TypedRegistry = class {
 | |
|   constructor(type, scope, override) {
 | |
|     this.type = type;
 | |
|     this.scope = scope;
 | |
|     this.override = override;
 | |
|     this.items = /* @__PURE__ */ Object.create(null);
 | |
|   }
 | |
|   isForType(type) {
 | |
|     return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);
 | |
|   }
 | |
|   register(item) {
 | |
|     const proto = Object.getPrototypeOf(item);
 | |
|     let parentScope;
 | |
|     if (isIChartComponent(proto)) {
 | |
|       parentScope = this.register(proto);
 | |
|     }
 | |
|     const items = this.items;
 | |
|     const id = item.id;
 | |
|     const scope = this.scope + "." + id;
 | |
|     if (!id) {
 | |
|       throw new Error("class does not have id: " + item);
 | |
|     }
 | |
|     if (id in items) {
 | |
|       return scope;
 | |
|     }
 | |
|     items[id] = item;
 | |
|     registerDefaults(item, scope, parentScope);
 | |
|     if (this.override) {
 | |
|       defaults2.override(item.id, item.overrides);
 | |
|     }
 | |
|     return scope;
 | |
|   }
 | |
|   get(id) {
 | |
|     return this.items[id];
 | |
|   }
 | |
|   unregister(item) {
 | |
|     const items = this.items;
 | |
|     const id = item.id;
 | |
|     const scope = this.scope;
 | |
|     if (id in items) {
 | |
|       delete items[id];
 | |
|     }
 | |
|     if (scope && id in defaults2[scope]) {
 | |
|       delete defaults2[scope][id];
 | |
|       if (this.override) {
 | |
|         delete overrides[id];
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| };
 | |
| function registerDefaults(item, scope, parentScope) {
 | |
|   const itemDefaults = merge(/* @__PURE__ */ Object.create(null), [
 | |
|     parentScope ? defaults2.get(parentScope) : {},
 | |
|     defaults2.get(scope),
 | |
|     item.defaults
 | |
|   ]);
 | |
|   defaults2.set(scope, itemDefaults);
 | |
|   if (item.defaultRoutes) {
 | |
|     routeDefaults(scope, item.defaultRoutes);
 | |
|   }
 | |
|   if (item.descriptors) {
 | |
|     defaults2.describe(scope, item.descriptors);
 | |
|   }
 | |
| }
 | |
| function routeDefaults(scope, routes) {
 | |
|   Object.keys(routes).forEach((property) => {
 | |
|     const propertyParts = property.split(".");
 | |
|     const sourceName = propertyParts.pop();
 | |
|     const sourceScope = [
 | |
|       scope
 | |
|     ].concat(propertyParts).join(".");
 | |
|     const parts = routes[property].split(".");
 | |
|     const targetName = parts.pop();
 | |
|     const targetScope = parts.join(".");
 | |
|     defaults2.route(sourceScope, sourceName, targetScope, targetName);
 | |
|   });
 | |
| }
 | |
| function isIChartComponent(proto) {
 | |
|   return "id" in proto && "defaults" in proto;
 | |
| }
 | |
| var Registry = class {
 | |
|   constructor() {
 | |
|     this.controllers = new TypedRegistry(DatasetController, "datasets", true);
 | |
|     this.elements = new TypedRegistry(Element, "elements");
 | |
|     this.plugins = new TypedRegistry(Object, "plugins");
 | |
|     this.scales = new TypedRegistry(Scale, "scales");
 | |
|     this._typedRegistries = [
 | |
|       this.controllers,
 | |
|       this.scales,
 | |
|       this.elements
 | |
|     ];
 | |
|   }
 | |
|   add(...args) {
 | |
|     this._each("register", args);
 | |
|   }
 | |
|   remove(...args) {
 | |
|     this._each("unregister", args);
 | |
|   }
 | |
|   addControllers(...args) {
 | |
|     this._each("register", args, this.controllers);
 | |
|   }
 | |
|   addElements(...args) {
 | |
|     this._each("register", args, this.elements);
 | |
|   }
 | |
|   addPlugins(...args) {
 | |
|     this._each("register", args, this.plugins);
 | |
|   }
 | |
|   addScales(...args) {
 | |
|     this._each("register", args, this.scales);
 | |
|   }
 | |
|   getController(id) {
 | |
|     return this._get(id, this.controllers, "controller");
 | |
|   }
 | |
|   getElement(id) {
 | |
|     return this._get(id, this.elements, "element");
 | |
|   }
 | |
|   getPlugin(id) {
 | |
|     return this._get(id, this.plugins, "plugin");
 | |
|   }
 | |
|   getScale(id) {
 | |
|     return this._get(id, this.scales, "scale");
 | |
|   }
 | |
|   removeControllers(...args) {
 | |
|     this._each("unregister", args, this.controllers);
 | |
|   }
 | |
|   removeElements(...args) {
 | |
|     this._each("unregister", args, this.elements);
 | |
|   }
 | |
|   removePlugins(...args) {
 | |
|     this._each("unregister", args, this.plugins);
 | |
|   }
 | |
|   removeScales(...args) {
 | |
|     this._each("unregister", args, this.scales);
 | |
|   }
 | |
|   _each(method, args, typedRegistry) {
 | |
|     [
 | |
|       ...args
 | |
|     ].forEach((arg) => {
 | |
|       const reg = typedRegistry || this._getRegistryForType(arg);
 | |
|       if (typedRegistry || reg.isForType(arg) || reg === this.plugins && arg.id) {
 | |
|         this._exec(method, reg, arg);
 | |
|       } else {
 | |
|         each(arg, (item) => {
 | |
|           const itemReg = typedRegistry || this._getRegistryForType(item);
 | |
|           this._exec(method, itemReg, item);
 | |
|         });
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   _exec(method, registry2, component) {
 | |
|     const camelMethod = _capitalize(method);
 | |
|     callback(component["before" + camelMethod], [], component);
 | |
|     registry2[method](component);
 | |
|     callback(component["after" + camelMethod], [], component);
 | |
|   }
 | |
|   _getRegistryForType(type) {
 | |
|     for (let i2 = 0; i2 < this._typedRegistries.length; i2++) {
 | |
|       const reg = this._typedRegistries[i2];
 | |
|       if (reg.isForType(type)) {
 | |
|         return reg;
 | |
|       }
 | |
|     }
 | |
|     return this.plugins;
 | |
|   }
 | |
|   _get(id, typedRegistry, type) {
 | |
|     const item = typedRegistry.get(id);
 | |
|     if (item === void 0) {
 | |
|       throw new Error('"' + id + '" is not a registered ' + type + ".");
 | |
|     }
 | |
|     return item;
 | |
|   }
 | |
| };
 | |
| var registry = /* @__PURE__ */ new Registry();
 | |
| var PluginService = class {
 | |
|   constructor() {
 | |
|     this._init = [];
 | |
|   }
 | |
|   notify(chart, hook, args, filter2) {
 | |
|     if (hook === "beforeInit") {
 | |
|       this._init = this._createDescriptors(chart, true);
 | |
|       this._notify(this._init, chart, "install");
 | |
|     }
 | |
|     const descriptors2 = filter2 ? this._descriptors(chart).filter(filter2) : this._descriptors(chart);
 | |
|     const result = this._notify(descriptors2, chart, hook, args);
 | |
|     if (hook === "afterDestroy") {
 | |
|       this._notify(descriptors2, chart, "stop");
 | |
|       this._notify(this._init, chart, "uninstall");
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   _notify(descriptors2, chart, hook, args) {
 | |
|     args = args || {};
 | |
|     for (const descriptor of descriptors2) {
 | |
|       const plugin = descriptor.plugin;
 | |
|       const method = plugin[hook];
 | |
|       const params = [
 | |
|         chart,
 | |
|         args,
 | |
|         descriptor.options
 | |
|       ];
 | |
|       if (callback(method, params, plugin) === false && args.cancelable) {
 | |
|         return false;
 | |
|       }
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
|   invalidate() {
 | |
|     if (!isNullOrUndef(this._cache)) {
 | |
|       this._oldCache = this._cache;
 | |
|       this._cache = void 0;
 | |
|     }
 | |
|   }
 | |
|   _descriptors(chart) {
 | |
|     if (this._cache) {
 | |
|       return this._cache;
 | |
|     }
 | |
|     const descriptors2 = this._cache = this._createDescriptors(chart);
 | |
|     this._notifyStateChanges(chart);
 | |
|     return descriptors2;
 | |
|   }
 | |
|   _createDescriptors(chart, all) {
 | |
|     const config = chart && chart.config;
 | |
|     const options = valueOrDefault(config.options && config.options.plugins, {});
 | |
|     const plugins = allPlugins(config);
 | |
|     return options === false && !all ? [] : createDescriptors(chart, plugins, options, all);
 | |
|   }
 | |
|   _notifyStateChanges(chart) {
 | |
|     const previousDescriptors = this._oldCache || [];
 | |
|     const descriptors2 = this._cache;
 | |
|     const diff = (a2, b2) => a2.filter((x2) => !b2.some((y2) => x2.plugin.id === y2.plugin.id));
 | |
|     this._notify(diff(previousDescriptors, descriptors2), chart, "stop");
 | |
|     this._notify(diff(descriptors2, previousDescriptors), chart, "start");
 | |
|   }
 | |
| };
 | |
| function allPlugins(config) {
 | |
|   const localIds = {};
 | |
|   const plugins = [];
 | |
|   const keys = Object.keys(registry.plugins.items);
 | |
|   for (let i2 = 0; i2 < keys.length; i2++) {
 | |
|     plugins.push(registry.getPlugin(keys[i2]));
 | |
|   }
 | |
|   const local = config.plugins || [];
 | |
|   for (let i2 = 0; i2 < local.length; i2++) {
 | |
|     const plugin = local[i2];
 | |
|     if (plugins.indexOf(plugin) === -1) {
 | |
|       plugins.push(plugin);
 | |
|       localIds[plugin.id] = true;
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     plugins,
 | |
|     localIds
 | |
|   };
 | |
| }
 | |
| function getOpts(options, all) {
 | |
|   if (!all && options === false) {
 | |
|     return null;
 | |
|   }
 | |
|   if (options === true) {
 | |
|     return {};
 | |
|   }
 | |
|   return options;
 | |
| }
 | |
| function createDescriptors(chart, { plugins, localIds }, options, all) {
 | |
|   const result = [];
 | |
|   const context = chart.getContext();
 | |
|   for (const plugin of plugins) {
 | |
|     const id = plugin.id;
 | |
|     const opts = getOpts(options[id], all);
 | |
|     if (opts === null) {
 | |
|       continue;
 | |
|     }
 | |
|     result.push({
 | |
|       plugin,
 | |
|       options: pluginOpts(chart.config, {
 | |
|         plugin,
 | |
|         local: localIds[id]
 | |
|       }, opts, context)
 | |
|     });
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function pluginOpts(config, { plugin, local }, opts, context) {
 | |
|   const keys = config.pluginScopeKeys(plugin);
 | |
|   const scopes = config.getOptionScopes(opts, keys);
 | |
|   if (local && plugin.defaults) {
 | |
|     scopes.push(plugin.defaults);
 | |
|   }
 | |
|   return config.createResolver(scopes, context, [
 | |
|     ""
 | |
|   ], {
 | |
|     scriptable: false,
 | |
|     indexable: false,
 | |
|     allKeys: true
 | |
|   });
 | |
| }
 | |
| function getIndexAxis(type, options) {
 | |
|   const datasetDefaults = defaults2.datasets[type] || {};
 | |
|   const datasetOptions = (options.datasets || {})[type] || {};
 | |
|   return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || "x";
 | |
| }
 | |
| function getAxisFromDefaultScaleID(id, indexAxis) {
 | |
|   let axis = id;
 | |
|   if (id === "_index_") {
 | |
|     axis = indexAxis;
 | |
|   } else if (id === "_value_") {
 | |
|     axis = indexAxis === "x" ? "y" : "x";
 | |
|   }
 | |
|   return axis;
 | |
| }
 | |
| function getDefaultScaleIDFromAxis(axis, indexAxis) {
 | |
|   return axis === indexAxis ? "_index_" : "_value_";
 | |
| }
 | |
| function idMatchesAxis(id) {
 | |
|   if (id === "x" || id === "y" || id === "r") {
 | |
|     return id;
 | |
|   }
 | |
| }
 | |
| function axisFromPosition(position) {
 | |
|   if (position === "top" || position === "bottom") {
 | |
|     return "x";
 | |
|   }
 | |
|   if (position === "left" || position === "right") {
 | |
|     return "y";
 | |
|   }
 | |
| }
 | |
| function determineAxis(id, ...scaleOptions) {
 | |
|   if (idMatchesAxis(id)) {
 | |
|     return id;
 | |
|   }
 | |
|   for (const opts of scaleOptions) {
 | |
|     const axis = opts.axis || axisFromPosition(opts.position) || id.length > 1 && idMatchesAxis(id[0].toLowerCase());
 | |
|     if (axis) {
 | |
|       return axis;
 | |
|     }
 | |
|   }
 | |
|   throw new Error(`Cannot determine type of '${id}' axis. Please provide 'axis' or 'position' option.`);
 | |
| }
 | |
| function getAxisFromDataset(id, axis, dataset) {
 | |
|   if (dataset[axis + "AxisID"] === id) {
 | |
|     return {
 | |
|       axis
 | |
|     };
 | |
|   }
 | |
| }
 | |
| function retrieveAxisFromDatasets(id, config) {
 | |
|   if (config.data && config.data.datasets) {
 | |
|     const boundDs = config.data.datasets.filter((d2) => d2.xAxisID === id || d2.yAxisID === id);
 | |
|     if (boundDs.length) {
 | |
|       return getAxisFromDataset(id, "x", boundDs[0]) || getAxisFromDataset(id, "y", boundDs[0]);
 | |
|     }
 | |
|   }
 | |
|   return {};
 | |
| }
 | |
| function mergeScaleConfig(config, options) {
 | |
|   const chartDefaults = overrides[config.type] || {
 | |
|     scales: {}
 | |
|   };
 | |
|   const configScales = options.scales || {};
 | |
|   const chartIndexAxis = getIndexAxis(config.type, options);
 | |
|   const scales = /* @__PURE__ */ Object.create(null);
 | |
|   Object.keys(configScales).forEach((id) => {
 | |
|     const scaleConf = configScales[id];
 | |
|     if (!isObject(scaleConf)) {
 | |
|       return console.error(`Invalid scale configuration for scale: ${id}`);
 | |
|     }
 | |
|     if (scaleConf._proxy) {
 | |
|       return console.warn(`Ignoring resolver passed as options for scale: ${id}`);
 | |
|     }
 | |
|     const axis = determineAxis(id, scaleConf, retrieveAxisFromDatasets(id, config), defaults2.scales[scaleConf.type]);
 | |
|     const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis);
 | |
|     const defaultScaleOptions = chartDefaults.scales || {};
 | |
|     scales[id] = mergeIf(/* @__PURE__ */ Object.create(null), [
 | |
|       {
 | |
|         axis
 | |
|       },
 | |
|       scaleConf,
 | |
|       defaultScaleOptions[axis],
 | |
|       defaultScaleOptions[defaultId]
 | |
|     ]);
 | |
|   });
 | |
|   config.data.datasets.forEach((dataset) => {
 | |
|     const type = dataset.type || config.type;
 | |
|     const indexAxis = dataset.indexAxis || getIndexAxis(type, options);
 | |
|     const datasetDefaults = overrides[type] || {};
 | |
|     const defaultScaleOptions = datasetDefaults.scales || {};
 | |
|     Object.keys(defaultScaleOptions).forEach((defaultID) => {
 | |
|       const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);
 | |
|       const id = dataset[axis + "AxisID"] || axis;
 | |
|       scales[id] = scales[id] || /* @__PURE__ */ Object.create(null);
 | |
|       mergeIf(scales[id], [
 | |
|         {
 | |
|           axis
 | |
|         },
 | |
|         configScales[id],
 | |
|         defaultScaleOptions[defaultID]
 | |
|       ]);
 | |
|     });
 | |
|   });
 | |
|   Object.keys(scales).forEach((key) => {
 | |
|     const scale = scales[key];
 | |
|     mergeIf(scale, [
 | |
|       defaults2.scales[scale.type],
 | |
|       defaults2.scale
 | |
|     ]);
 | |
|   });
 | |
|   return scales;
 | |
| }
 | |
| function initOptions(config) {
 | |
|   const options = config.options || (config.options = {});
 | |
|   options.plugins = valueOrDefault(options.plugins, {});
 | |
|   options.scales = mergeScaleConfig(config, options);
 | |
| }
 | |
| function initData(data) {
 | |
|   data = data || {};
 | |
|   data.datasets = data.datasets || [];
 | |
|   data.labels = data.labels || [];
 | |
|   return data;
 | |
| }
 | |
| function initConfig(config) {
 | |
|   config = config || {};
 | |
|   config.data = initData(config.data);
 | |
|   initOptions(config);
 | |
|   return config;
 | |
| }
 | |
| var keyCache = /* @__PURE__ */ new Map();
 | |
| var keysCached = /* @__PURE__ */ new Set();
 | |
| function cachedKeys(cacheKey, generate) {
 | |
|   let keys = keyCache.get(cacheKey);
 | |
|   if (!keys) {
 | |
|     keys = generate();
 | |
|     keyCache.set(cacheKey, keys);
 | |
|     keysCached.add(keys);
 | |
|   }
 | |
|   return keys;
 | |
| }
 | |
| var addIfFound = (set2, obj, key) => {
 | |
|   const opts = resolveObjectKey(obj, key);
 | |
|   if (opts !== void 0) {
 | |
|     set2.add(opts);
 | |
|   }
 | |
| };
 | |
| var Config = class {
 | |
|   constructor(config) {
 | |
|     this._config = initConfig(config);
 | |
|     this._scopeCache = /* @__PURE__ */ new Map();
 | |
|     this._resolverCache = /* @__PURE__ */ new Map();
 | |
|   }
 | |
|   get platform() {
 | |
|     return this._config.platform;
 | |
|   }
 | |
|   get type() {
 | |
|     return this._config.type;
 | |
|   }
 | |
|   set type(type) {
 | |
|     this._config.type = type;
 | |
|   }
 | |
|   get data() {
 | |
|     return this._config.data;
 | |
|   }
 | |
|   set data(data) {
 | |
|     this._config.data = initData(data);
 | |
|   }
 | |
|   get options() {
 | |
|     return this._config.options;
 | |
|   }
 | |
|   set options(options) {
 | |
|     this._config.options = options;
 | |
|   }
 | |
|   get plugins() {
 | |
|     return this._config.plugins;
 | |
|   }
 | |
|   update() {
 | |
|     const config = this._config;
 | |
|     this.clearCache();
 | |
|     initOptions(config);
 | |
|   }
 | |
|   clearCache() {
 | |
|     this._scopeCache.clear();
 | |
|     this._resolverCache.clear();
 | |
|   }
 | |
|   datasetScopeKeys(datasetType) {
 | |
|     return cachedKeys(datasetType, () => [
 | |
|       [
 | |
|         `datasets.${datasetType}`,
 | |
|         ""
 | |
|       ]
 | |
|     ]);
 | |
|   }
 | |
|   datasetAnimationScopeKeys(datasetType, transition) {
 | |
|     return cachedKeys(`${datasetType}.transition.${transition}`, () => [
 | |
|       [
 | |
|         `datasets.${datasetType}.transitions.${transition}`,
 | |
|         `transitions.${transition}`
 | |
|       ],
 | |
|       [
 | |
|         `datasets.${datasetType}`,
 | |
|         ""
 | |
|       ]
 | |
|     ]);
 | |
|   }
 | |
|   datasetElementScopeKeys(datasetType, elementType) {
 | |
|     return cachedKeys(`${datasetType}-${elementType}`, () => [
 | |
|       [
 | |
|         `datasets.${datasetType}.elements.${elementType}`,
 | |
|         `datasets.${datasetType}`,
 | |
|         `elements.${elementType}`,
 | |
|         ""
 | |
|       ]
 | |
|     ]);
 | |
|   }
 | |
|   pluginScopeKeys(plugin) {
 | |
|     const id = plugin.id;
 | |
|     const type = this.type;
 | |
|     return cachedKeys(`${type}-plugin-${id}`, () => [
 | |
|       [
 | |
|         `plugins.${id}`,
 | |
|         ...plugin.additionalOptionScopes || []
 | |
|       ]
 | |
|     ]);
 | |
|   }
 | |
|   _cachedScopes(mainScope, resetCache) {
 | |
|     const _scopeCache = this._scopeCache;
 | |
|     let cache = _scopeCache.get(mainScope);
 | |
|     if (!cache || resetCache) {
 | |
|       cache = /* @__PURE__ */ new Map();
 | |
|       _scopeCache.set(mainScope, cache);
 | |
|     }
 | |
|     return cache;
 | |
|   }
 | |
|   getOptionScopes(mainScope, keyLists, resetCache) {
 | |
|     const { options, type } = this;
 | |
|     const cache = this._cachedScopes(mainScope, resetCache);
 | |
|     const cached = cache.get(keyLists);
 | |
|     if (cached) {
 | |
|       return cached;
 | |
|     }
 | |
|     const scopes = /* @__PURE__ */ new Set();
 | |
|     keyLists.forEach((keys) => {
 | |
|       if (mainScope) {
 | |
|         scopes.add(mainScope);
 | |
|         keys.forEach((key) => addIfFound(scopes, mainScope, key));
 | |
|       }
 | |
|       keys.forEach((key) => addIfFound(scopes, options, key));
 | |
|       keys.forEach((key) => addIfFound(scopes, overrides[type] || {}, key));
 | |
|       keys.forEach((key) => addIfFound(scopes, defaults2, key));
 | |
|       keys.forEach((key) => addIfFound(scopes, descriptors, key));
 | |
|     });
 | |
|     const array = Array.from(scopes);
 | |
|     if (array.length === 0) {
 | |
|       array.push(/* @__PURE__ */ Object.create(null));
 | |
|     }
 | |
|     if (keysCached.has(keyLists)) {
 | |
|       cache.set(keyLists, array);
 | |
|     }
 | |
|     return array;
 | |
|   }
 | |
|   chartOptionScopes() {
 | |
|     const { options, type } = this;
 | |
|     return [
 | |
|       options,
 | |
|       overrides[type] || {},
 | |
|       defaults2.datasets[type] || {},
 | |
|       {
 | |
|         type
 | |
|       },
 | |
|       defaults2,
 | |
|       descriptors
 | |
|     ];
 | |
|   }
 | |
|   resolveNamedOptions(scopes, names2, context, prefixes = [
 | |
|     ""
 | |
|   ]) {
 | |
|     const result = {
 | |
|       $shared: true
 | |
|     };
 | |
|     const { resolver, subPrefixes } = getResolver(this._resolverCache, scopes, prefixes);
 | |
|     let options = resolver;
 | |
|     if (needContext(resolver, names2)) {
 | |
|       result.$shared = false;
 | |
|       context = isFunction(context) ? context() : context;
 | |
|       const subResolver = this.createResolver(scopes, context, subPrefixes);
 | |
|       options = _attachContext(resolver, context, subResolver);
 | |
|     }
 | |
|     for (const prop of names2) {
 | |
|       result[prop] = options[prop];
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   createResolver(scopes, context, prefixes = [
 | |
|     ""
 | |
|   ], descriptorDefaults) {
 | |
|     const { resolver } = getResolver(this._resolverCache, scopes, prefixes);
 | |
|     return isObject(context) ? _attachContext(resolver, context, void 0, descriptorDefaults) : resolver;
 | |
|   }
 | |
| };
 | |
| function getResolver(resolverCache, scopes, prefixes) {
 | |
|   let cache = resolverCache.get(scopes);
 | |
|   if (!cache) {
 | |
|     cache = /* @__PURE__ */ new Map();
 | |
|     resolverCache.set(scopes, cache);
 | |
|   }
 | |
|   const cacheKey = prefixes.join();
 | |
|   let cached = cache.get(cacheKey);
 | |
|   if (!cached) {
 | |
|     const resolver = _createResolver(scopes, prefixes);
 | |
|     cached = {
 | |
|       resolver,
 | |
|       subPrefixes: prefixes.filter((p2) => !p2.toLowerCase().includes("hover"))
 | |
|     };
 | |
|     cache.set(cacheKey, cached);
 | |
|   }
 | |
|   return cached;
 | |
| }
 | |
| var hasFunction = (value) => isObject(value) && Object.getOwnPropertyNames(value).some((key) => isFunction(value[key]));
 | |
| function needContext(proxy, names2) {
 | |
|   const { isScriptable, isIndexable } = _descriptors(proxy);
 | |
|   for (const prop of names2) {
 | |
|     const scriptable = isScriptable(prop);
 | |
|     const indexable = isIndexable(prop);
 | |
|     const value = (indexable || scriptable) && proxy[prop];
 | |
|     if (scriptable && (isFunction(value) || hasFunction(value)) || indexable && isArray(value)) {
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| var version = "4.4.8";
 | |
| var KNOWN_POSITIONS = [
 | |
|   "top",
 | |
|   "bottom",
 | |
|   "left",
 | |
|   "right",
 | |
|   "chartArea"
 | |
| ];
 | |
| function positionIsHorizontal(position, axis) {
 | |
|   return position === "top" || position === "bottom" || KNOWN_POSITIONS.indexOf(position) === -1 && axis === "x";
 | |
| }
 | |
| function compare2Level(l1, l2) {
 | |
|   return function(a2, b2) {
 | |
|     return a2[l1] === b2[l1] ? a2[l2] - b2[l2] : a2[l1] - b2[l1];
 | |
|   };
 | |
| }
 | |
| function onAnimationsComplete(context) {
 | |
|   const chart = context.chart;
 | |
|   const animationOptions = chart.options.animation;
 | |
|   chart.notifyPlugins("afterRender");
 | |
|   callback(animationOptions && animationOptions.onComplete, [
 | |
|     context
 | |
|   ], chart);
 | |
| }
 | |
| function onAnimationProgress(context) {
 | |
|   const chart = context.chart;
 | |
|   const animationOptions = chart.options.animation;
 | |
|   callback(animationOptions && animationOptions.onProgress, [
 | |
|     context
 | |
|   ], chart);
 | |
| }
 | |
| function getCanvas(item) {
 | |
|   if (_isDomSupported() && typeof item === "string") {
 | |
|     item = document.getElementById(item);
 | |
|   } else if (item && item.length) {
 | |
|     item = item[0];
 | |
|   }
 | |
|   if (item && item.canvas) {
 | |
|     item = item.canvas;
 | |
|   }
 | |
|   return item;
 | |
| }
 | |
| var instances = {};
 | |
| var getChart = (key) => {
 | |
|   const canvas = getCanvas(key);
 | |
|   return Object.values(instances).filter((c2) => c2.canvas === canvas).pop();
 | |
| };
 | |
| function moveNumericKeys(obj, start, move) {
 | |
|   const keys = Object.keys(obj);
 | |
|   for (const key of keys) {
 | |
|     const intKey = +key;
 | |
|     if (intKey >= start) {
 | |
|       const value = obj[key];
 | |
|       delete obj[key];
 | |
|       if (move > 0 || intKey > start) {
 | |
|         obj[intKey + move] = value;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function determineLastEvent(e2, lastEvent, inChartArea, isClick) {
 | |
|   if (!inChartArea || e2.type === "mouseout") {
 | |
|     return null;
 | |
|   }
 | |
|   if (isClick) {
 | |
|     return lastEvent;
 | |
|   }
 | |
|   return e2;
 | |
| }
 | |
| function getSizeForArea(scale, chartArea, field) {
 | |
|   return scale.options.clip ? scale[field] : chartArea[field];
 | |
| }
 | |
| function getDatasetArea(meta, chartArea) {
 | |
|   const { xScale, yScale } = meta;
 | |
|   if (xScale && yScale) {
 | |
|     return {
 | |
|       left: getSizeForArea(xScale, chartArea, "left"),
 | |
|       right: getSizeForArea(xScale, chartArea, "right"),
 | |
|       top: getSizeForArea(yScale, chartArea, "top"),
 | |
|       bottom: getSizeForArea(yScale, chartArea, "bottom")
 | |
|     };
 | |
|   }
 | |
|   return chartArea;
 | |
| }
 | |
| var Chart = class {
 | |
|   static register(...items) {
 | |
|     registry.add(...items);
 | |
|     invalidatePlugins();
 | |
|   }
 | |
|   static unregister(...items) {
 | |
|     registry.remove(...items);
 | |
|     invalidatePlugins();
 | |
|   }
 | |
|   constructor(item, userConfig) {
 | |
|     const config = this.config = new Config(userConfig);
 | |
|     const initialCanvas = getCanvas(item);
 | |
|     const existingChart = getChart(initialCanvas);
 | |
|     if (existingChart) {
 | |
|       throw new Error("Canvas is already in use. Chart with ID '" + existingChart.id + "' must be destroyed before the canvas with ID '" + existingChart.canvas.id + "' can be reused.");
 | |
|     }
 | |
|     const options = config.createResolver(config.chartOptionScopes(), this.getContext());
 | |
|     this.platform = new (config.platform || _detectPlatform(initialCanvas))();
 | |
|     this.platform.updateConfig(config);
 | |
|     const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);
 | |
|     const canvas = context && context.canvas;
 | |
|     const height = canvas && canvas.height;
 | |
|     const width = canvas && canvas.width;
 | |
|     this.id = uid();
 | |
|     this.ctx = context;
 | |
|     this.canvas = canvas;
 | |
|     this.width = width;
 | |
|     this.height = height;
 | |
|     this._options = options;
 | |
|     this._aspectRatio = this.aspectRatio;
 | |
|     this._layers = [];
 | |
|     this._metasets = [];
 | |
|     this._stacks = void 0;
 | |
|     this.boxes = [];
 | |
|     this.currentDevicePixelRatio = void 0;
 | |
|     this.chartArea = void 0;
 | |
|     this._active = [];
 | |
|     this._lastEvent = void 0;
 | |
|     this._listeners = {};
 | |
|     this._responsiveListeners = void 0;
 | |
|     this._sortedMetasets = [];
 | |
|     this.scales = {};
 | |
|     this._plugins = new PluginService();
 | |
|     this.$proxies = {};
 | |
|     this._hiddenIndices = {};
 | |
|     this.attached = false;
 | |
|     this._animationsDisabled = void 0;
 | |
|     this.$context = void 0;
 | |
|     this._doResize = debounce((mode) => this.update(mode), options.resizeDelay || 0);
 | |
|     this._dataChanges = [];
 | |
|     instances[this.id] = this;
 | |
|     if (!context || !canvas) {
 | |
|       console.error("Failed to create chart: can't acquire context from the given item");
 | |
|       return;
 | |
|     }
 | |
|     animator.listen(this, "complete", onAnimationsComplete);
 | |
|     animator.listen(this, "progress", onAnimationProgress);
 | |
|     this._initialize();
 | |
|     if (this.attached) {
 | |
|       this.update();
 | |
|     }
 | |
|   }
 | |
|   get aspectRatio() {
 | |
|     const { options: { aspectRatio, maintainAspectRatio }, width, height, _aspectRatio } = this;
 | |
|     if (!isNullOrUndef(aspectRatio)) {
 | |
|       return aspectRatio;
 | |
|     }
 | |
|     if (maintainAspectRatio && _aspectRatio) {
 | |
|       return _aspectRatio;
 | |
|     }
 | |
|     return height ? width / height : null;
 | |
|   }
 | |
|   get data() {
 | |
|     return this.config.data;
 | |
|   }
 | |
|   set data(data) {
 | |
|     this.config.data = data;
 | |
|   }
 | |
|   get options() {
 | |
|     return this._options;
 | |
|   }
 | |
|   set options(options) {
 | |
|     this.config.options = options;
 | |
|   }
 | |
|   get registry() {
 | |
|     return registry;
 | |
|   }
 | |
|   _initialize() {
 | |
|     this.notifyPlugins("beforeInit");
 | |
|     if (this.options.responsive) {
 | |
|       this.resize();
 | |
|     } else {
 | |
|       retinaScale(this, this.options.devicePixelRatio);
 | |
|     }
 | |
|     this.bindEvents();
 | |
|     this.notifyPlugins("afterInit");
 | |
|     return this;
 | |
|   }
 | |
|   clear() {
 | |
|     clearCanvas(this.canvas, this.ctx);
 | |
|     return this;
 | |
|   }
 | |
|   stop() {
 | |
|     animator.stop(this);
 | |
|     return this;
 | |
|   }
 | |
|   resize(width, height) {
 | |
|     if (!animator.running(this)) {
 | |
|       this._resize(width, height);
 | |
|     } else {
 | |
|       this._resizeBeforeDraw = {
 | |
|         width,
 | |
|         height
 | |
|       };
 | |
|     }
 | |
|   }
 | |
|   _resize(width, height) {
 | |
|     const options = this.options;
 | |
|     const canvas = this.canvas;
 | |
|     const aspectRatio = options.maintainAspectRatio && this.aspectRatio;
 | |
|     const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);
 | |
|     const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();
 | |
|     const mode = this.width ? "resize" : "attach";
 | |
|     this.width = newSize.width;
 | |
|     this.height = newSize.height;
 | |
|     this._aspectRatio = this.aspectRatio;
 | |
|     if (!retinaScale(this, newRatio, true)) {
 | |
|       return;
 | |
|     }
 | |
|     this.notifyPlugins("resize", {
 | |
|       size: newSize
 | |
|     });
 | |
|     callback(options.onResize, [
 | |
|       this,
 | |
|       newSize
 | |
|     ], this);
 | |
|     if (this.attached) {
 | |
|       if (this._doResize(mode)) {
 | |
|         this.render();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   ensureScalesHaveIDs() {
 | |
|     const options = this.options;
 | |
|     const scalesOptions = options.scales || {};
 | |
|     each(scalesOptions, (axisOptions, axisID) => {
 | |
|       axisOptions.id = axisID;
 | |
|     });
 | |
|   }
 | |
|   buildOrUpdateScales() {
 | |
|     const options = this.options;
 | |
|     const scaleOpts = options.scales;
 | |
|     const scales = this.scales;
 | |
|     const updated = Object.keys(scales).reduce((obj, id) => {
 | |
|       obj[id] = false;
 | |
|       return obj;
 | |
|     }, {});
 | |
|     let items = [];
 | |
|     if (scaleOpts) {
 | |
|       items = items.concat(Object.keys(scaleOpts).map((id) => {
 | |
|         const scaleOptions = scaleOpts[id];
 | |
|         const axis = determineAxis(id, scaleOptions);
 | |
|         const isRadial = axis === "r";
 | |
|         const isHorizontal = axis === "x";
 | |
|         return {
 | |
|           options: scaleOptions,
 | |
|           dposition: isRadial ? "chartArea" : isHorizontal ? "bottom" : "left",
 | |
|           dtype: isRadial ? "radialLinear" : isHorizontal ? "category" : "linear"
 | |
|         };
 | |
|       }));
 | |
|     }
 | |
|     each(items, (item) => {
 | |
|       const scaleOptions = item.options;
 | |
|       const id = scaleOptions.id;
 | |
|       const axis = determineAxis(id, scaleOptions);
 | |
|       const scaleType = valueOrDefault(scaleOptions.type, item.dtype);
 | |
|       if (scaleOptions.position === void 0 || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) {
 | |
|         scaleOptions.position = item.dposition;
 | |
|       }
 | |
|       updated[id] = true;
 | |
|       let scale = null;
 | |
|       if (id in scales && scales[id].type === scaleType) {
 | |
|         scale = scales[id];
 | |
|       } else {
 | |
|         const scaleClass = registry.getScale(scaleType);
 | |
|         scale = new scaleClass({
 | |
|           id,
 | |
|           type: scaleType,
 | |
|           ctx: this.ctx,
 | |
|           chart: this
 | |
|         });
 | |
|         scales[scale.id] = scale;
 | |
|       }
 | |
|       scale.init(scaleOptions, options);
 | |
|     });
 | |
|     each(updated, (hasUpdated, id) => {
 | |
|       if (!hasUpdated) {
 | |
|         delete scales[id];
 | |
|       }
 | |
|     });
 | |
|     each(scales, (scale) => {
 | |
|       layouts.configure(this, scale, scale.options);
 | |
|       layouts.addBox(this, scale);
 | |
|     });
 | |
|   }
 | |
|   _updateMetasets() {
 | |
|     const metasets = this._metasets;
 | |
|     const numData = this.data.datasets.length;
 | |
|     const numMeta = metasets.length;
 | |
|     metasets.sort((a2, b2) => a2.index - b2.index);
 | |
|     if (numMeta > numData) {
 | |
|       for (let i2 = numData; i2 < numMeta; ++i2) {
 | |
|         this._destroyDatasetMeta(i2);
 | |
|       }
 | |
|       metasets.splice(numData, numMeta - numData);
 | |
|     }
 | |
|     this._sortedMetasets = metasets.slice(0).sort(compare2Level("order", "index"));
 | |
|   }
 | |
|   _removeUnreferencedMetasets() {
 | |
|     const { _metasets: metasets, data: { datasets } } = this;
 | |
|     if (metasets.length > datasets.length) {
 | |
|       delete this._stacks;
 | |
|     }
 | |
|     metasets.forEach((meta, index) => {
 | |
|       if (datasets.filter((x2) => x2 === meta._dataset).length === 0) {
 | |
|         this._destroyDatasetMeta(index);
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   buildOrUpdateControllers() {
 | |
|     const newControllers = [];
 | |
|     const datasets = this.data.datasets;
 | |
|     let i2, ilen;
 | |
|     this._removeUnreferencedMetasets();
 | |
|     for (i2 = 0, ilen = datasets.length; i2 < ilen; i2++) {
 | |
|       const dataset = datasets[i2];
 | |
|       let meta = this.getDatasetMeta(i2);
 | |
|       const type = dataset.type || this.config.type;
 | |
|       if (meta.type && meta.type !== type) {
 | |
|         this._destroyDatasetMeta(i2);
 | |
|         meta = this.getDatasetMeta(i2);
 | |
|       }
 | |
|       meta.type = type;
 | |
|       meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);
 | |
|       meta.order = dataset.order || 0;
 | |
|       meta.index = i2;
 | |
|       meta.label = "" + dataset.label;
 | |
|       meta.visible = this.isDatasetVisible(i2);
 | |
|       if (meta.controller) {
 | |
|         meta.controller.updateIndex(i2);
 | |
|         meta.controller.linkScales();
 | |
|       } else {
 | |
|         const ControllerClass = registry.getController(type);
 | |
|         const { datasetElementType, dataElementType } = defaults2.datasets[type];
 | |
|         Object.assign(ControllerClass, {
 | |
|           dataElementType: registry.getElement(dataElementType),
 | |
|           datasetElementType: datasetElementType && registry.getElement(datasetElementType)
 | |
|         });
 | |
|         meta.controller = new ControllerClass(this, i2);
 | |
|         newControllers.push(meta.controller);
 | |
|       }
 | |
|     }
 | |
|     this._updateMetasets();
 | |
|     return newControllers;
 | |
|   }
 | |
|   _resetElements() {
 | |
|     each(this.data.datasets, (dataset, datasetIndex) => {
 | |
|       this.getDatasetMeta(datasetIndex).controller.reset();
 | |
|     }, this);
 | |
|   }
 | |
|   reset() {
 | |
|     this._resetElements();
 | |
|     this.notifyPlugins("reset");
 | |
|   }
 | |
|   update(mode) {
 | |
|     const config = this.config;
 | |
|     config.update();
 | |
|     const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext());
 | |
|     const animsDisabled = this._animationsDisabled = !options.animation;
 | |
|     this._updateScales();
 | |
|     this._checkEventBindings();
 | |
|     this._updateHiddenIndices();
 | |
|     this._plugins.invalidate();
 | |
|     if (this.notifyPlugins("beforeUpdate", {
 | |
|       mode,
 | |
|       cancelable: true
 | |
|     }) === false) {
 | |
|       return;
 | |
|     }
 | |
|     const newControllers = this.buildOrUpdateControllers();
 | |
|     this.notifyPlugins("beforeElementsUpdate");
 | |
|     let minPadding = 0;
 | |
|     for (let i2 = 0, ilen = this.data.datasets.length; i2 < ilen; i2++) {
 | |
|       const { controller } = this.getDatasetMeta(i2);
 | |
|       const reset2 = !animsDisabled && newControllers.indexOf(controller) === -1;
 | |
|       controller.buildOrUpdateElements(reset2);
 | |
|       minPadding = Math.max(+controller.getMaxOverflow(), minPadding);
 | |
|     }
 | |
|     minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0;
 | |
|     this._updateLayout(minPadding);
 | |
|     if (!animsDisabled) {
 | |
|       each(newControllers, (controller) => {
 | |
|         controller.reset();
 | |
|       });
 | |
|     }
 | |
|     this._updateDatasets(mode);
 | |
|     this.notifyPlugins("afterUpdate", {
 | |
|       mode
 | |
|     });
 | |
|     this._layers.sort(compare2Level("z", "_idx"));
 | |
|     const { _active, _lastEvent } = this;
 | |
|     if (_lastEvent) {
 | |
|       this._eventHandler(_lastEvent, true);
 | |
|     } else if (_active.length) {
 | |
|       this._updateHoverStyles(_active, _active, true);
 | |
|     }
 | |
|     this.render();
 | |
|   }
 | |
|   _updateScales() {
 | |
|     each(this.scales, (scale) => {
 | |
|       layouts.removeBox(this, scale);
 | |
|     });
 | |
|     this.ensureScalesHaveIDs();
 | |
|     this.buildOrUpdateScales();
 | |
|   }
 | |
|   _checkEventBindings() {
 | |
|     const options = this.options;
 | |
|     const existingEvents = new Set(Object.keys(this._listeners));
 | |
|     const newEvents = new Set(options.events);
 | |
|     if (!setsEqual(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) {
 | |
|       this.unbindEvents();
 | |
|       this.bindEvents();
 | |
|     }
 | |
|   }
 | |
|   _updateHiddenIndices() {
 | |
|     const { _hiddenIndices } = this;
 | |
|     const changes = this._getUniformDataChanges() || [];
 | |
|     for (const { method, start, count } of changes) {
 | |
|       const move = method === "_removeElements" ? -count : count;
 | |
|       moveNumericKeys(_hiddenIndices, start, move);
 | |
|     }
 | |
|   }
 | |
|   _getUniformDataChanges() {
 | |
|     const _dataChanges = this._dataChanges;
 | |
|     if (!_dataChanges || !_dataChanges.length) {
 | |
|       return;
 | |
|     }
 | |
|     this._dataChanges = [];
 | |
|     const datasetCount = this.data.datasets.length;
 | |
|     const makeSet = (idx) => new Set(_dataChanges.filter((c2) => c2[0] === idx).map((c2, i2) => i2 + "," + c2.splice(1).join(",")));
 | |
|     const changeSet = makeSet(0);
 | |
|     for (let i2 = 1; i2 < datasetCount; i2++) {
 | |
|       if (!setsEqual(changeSet, makeSet(i2))) {
 | |
|         return;
 | |
|       }
 | |
|     }
 | |
|     return Array.from(changeSet).map((c2) => c2.split(",")).map((a2) => ({
 | |
|       method: a2[1],
 | |
|       start: +a2[2],
 | |
|       count: +a2[3]
 | |
|     }));
 | |
|   }
 | |
|   _updateLayout(minPadding) {
 | |
|     if (this.notifyPlugins("beforeLayout", {
 | |
|       cancelable: true
 | |
|     }) === false) {
 | |
|       return;
 | |
|     }
 | |
|     layouts.update(this, this.width, this.height, minPadding);
 | |
|     const area = this.chartArea;
 | |
|     const noArea = area.width <= 0 || area.height <= 0;
 | |
|     this._layers = [];
 | |
|     each(this.boxes, (box) => {
 | |
|       if (noArea && box.position === "chartArea") {
 | |
|         return;
 | |
|       }
 | |
|       if (box.configure) {
 | |
|         box.configure();
 | |
|       }
 | |
|       this._layers.push(...box._layers());
 | |
|     }, this);
 | |
|     this._layers.forEach((item, index) => {
 | |
|       item._idx = index;
 | |
|     });
 | |
|     this.notifyPlugins("afterLayout");
 | |
|   }
 | |
|   _updateDatasets(mode) {
 | |
|     if (this.notifyPlugins("beforeDatasetsUpdate", {
 | |
|       mode,
 | |
|       cancelable: true
 | |
|     }) === false) {
 | |
|       return;
 | |
|     }
 | |
|     for (let i2 = 0, ilen = this.data.datasets.length; i2 < ilen; ++i2) {
 | |
|       this.getDatasetMeta(i2).controller.configure();
 | |
|     }
 | |
|     for (let i2 = 0, ilen = this.data.datasets.length; i2 < ilen; ++i2) {
 | |
|       this._updateDataset(i2, isFunction(mode) ? mode({
 | |
|         datasetIndex: i2
 | |
|       }) : mode);
 | |
|     }
 | |
|     this.notifyPlugins("afterDatasetsUpdate", {
 | |
|       mode
 | |
|     });
 | |
|   }
 | |
|   _updateDataset(index, mode) {
 | |
|     const meta = this.getDatasetMeta(index);
 | |
|     const args = {
 | |
|       meta,
 | |
|       index,
 | |
|       mode,
 | |
|       cancelable: true
 | |
|     };
 | |
|     if (this.notifyPlugins("beforeDatasetUpdate", args) === false) {
 | |
|       return;
 | |
|     }
 | |
|     meta.controller._update(mode);
 | |
|     args.cancelable = false;
 | |
|     this.notifyPlugins("afterDatasetUpdate", args);
 | |
|   }
 | |
|   render() {
 | |
|     if (this.notifyPlugins("beforeRender", {
 | |
|       cancelable: true
 | |
|     }) === false) {
 | |
|       return;
 | |
|     }
 | |
|     if (animator.has(this)) {
 | |
|       if (this.attached && !animator.running(this)) {
 | |
|         animator.start(this);
 | |
|       }
 | |
|     } else {
 | |
|       this.draw();
 | |
|       onAnimationsComplete({
 | |
|         chart: this
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   draw() {
 | |
|     let i2;
 | |
|     if (this._resizeBeforeDraw) {
 | |
|       const { width, height } = this._resizeBeforeDraw;
 | |
|       this._resizeBeforeDraw = null;
 | |
|       this._resize(width, height);
 | |
|     }
 | |
|     this.clear();
 | |
|     if (this.width <= 0 || this.height <= 0) {
 | |
|       return;
 | |
|     }
 | |
|     if (this.notifyPlugins("beforeDraw", {
 | |
|       cancelable: true
 | |
|     }) === false) {
 | |
|       return;
 | |
|     }
 | |
|     const layers = this._layers;
 | |
|     for (i2 = 0; i2 < layers.length && layers[i2].z <= 0; ++i2) {
 | |
|       layers[i2].draw(this.chartArea);
 | |
|     }
 | |
|     this._drawDatasets();
 | |
|     for (; i2 < layers.length; ++i2) {
 | |
|       layers[i2].draw(this.chartArea);
 | |
|     }
 | |
|     this.notifyPlugins("afterDraw");
 | |
|   }
 | |
|   _getSortedDatasetMetas(filterVisible) {
 | |
|     const metasets = this._sortedMetasets;
 | |
|     const result = [];
 | |
|     let i2, ilen;
 | |
|     for (i2 = 0, ilen = metasets.length; i2 < ilen; ++i2) {
 | |
|       const meta = metasets[i2];
 | |
|       if (!filterVisible || meta.visible) {
 | |
|         result.push(meta);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   getSortedVisibleDatasetMetas() {
 | |
|     return this._getSortedDatasetMetas(true);
 | |
|   }
 | |
|   _drawDatasets() {
 | |
|     if (this.notifyPlugins("beforeDatasetsDraw", {
 | |
|       cancelable: true
 | |
|     }) === false) {
 | |
|       return;
 | |
|     }
 | |
|     const metasets = this.getSortedVisibleDatasetMetas();
 | |
|     for (let i2 = metasets.length - 1; i2 >= 0; --i2) {
 | |
|       this._drawDataset(metasets[i2]);
 | |
|     }
 | |
|     this.notifyPlugins("afterDatasetsDraw");
 | |
|   }
 | |
|   _drawDataset(meta) {
 | |
|     const ctx = this.ctx;
 | |
|     const clip = meta._clip;
 | |
|     const useClip = !clip.disabled;
 | |
|     const area = getDatasetArea(meta, this.chartArea);
 | |
|     const args = {
 | |
|       meta,
 | |
|       index: meta.index,
 | |
|       cancelable: true
 | |
|     };
 | |
|     if (this.notifyPlugins("beforeDatasetDraw", args) === false) {
 | |
|       return;
 | |
|     }
 | |
|     if (useClip) {
 | |
|       clipArea(ctx, {
 | |
|         left: clip.left === false ? 0 : area.left - clip.left,
 | |
|         right: clip.right === false ? this.width : area.right + clip.right,
 | |
|         top: clip.top === false ? 0 : area.top - clip.top,
 | |
|         bottom: clip.bottom === false ? this.height : area.bottom + clip.bottom
 | |
|       });
 | |
|     }
 | |
|     meta.controller.draw();
 | |
|     if (useClip) {
 | |
|       unclipArea(ctx);
 | |
|     }
 | |
|     args.cancelable = false;
 | |
|     this.notifyPlugins("afterDatasetDraw", args);
 | |
|   }
 | |
|   isPointInArea(point) {
 | |
|     return _isPointInArea(point, this.chartArea, this._minPadding);
 | |
|   }
 | |
|   getElementsAtEventForMode(e2, mode, options, useFinalPosition) {
 | |
|     const method = Interaction.modes[mode];
 | |
|     if (typeof method === "function") {
 | |
|       return method(this, e2, options, useFinalPosition);
 | |
|     }
 | |
|     return [];
 | |
|   }
 | |
|   getDatasetMeta(datasetIndex) {
 | |
|     const dataset = this.data.datasets[datasetIndex];
 | |
|     const metasets = this._metasets;
 | |
|     let meta = metasets.filter((x2) => x2 && x2._dataset === dataset).pop();
 | |
|     if (!meta) {
 | |
|       meta = {
 | |
|         type: null,
 | |
|         data: [],
 | |
|         dataset: null,
 | |
|         controller: null,
 | |
|         hidden: null,
 | |
|         xAxisID: null,
 | |
|         yAxisID: null,
 | |
|         order: dataset && dataset.order || 0,
 | |
|         index: datasetIndex,
 | |
|         _dataset: dataset,
 | |
|         _parsed: [],
 | |
|         _sorted: false
 | |
|       };
 | |
|       metasets.push(meta);
 | |
|     }
 | |
|     return meta;
 | |
|   }
 | |
|   getContext() {
 | |
|     return this.$context || (this.$context = createContext(null, {
 | |
|       chart: this,
 | |
|       type: "chart"
 | |
|     }));
 | |
|   }
 | |
|   getVisibleDatasetCount() {
 | |
|     return this.getSortedVisibleDatasetMetas().length;
 | |
|   }
 | |
|   isDatasetVisible(datasetIndex) {
 | |
|     const dataset = this.data.datasets[datasetIndex];
 | |
|     if (!dataset) {
 | |
|       return false;
 | |
|     }
 | |
|     const meta = this.getDatasetMeta(datasetIndex);
 | |
|     return typeof meta.hidden === "boolean" ? !meta.hidden : !dataset.hidden;
 | |
|   }
 | |
|   setDatasetVisibility(datasetIndex, visible) {
 | |
|     const meta = this.getDatasetMeta(datasetIndex);
 | |
|     meta.hidden = !visible;
 | |
|   }
 | |
|   toggleDataVisibility(index) {
 | |
|     this._hiddenIndices[index] = !this._hiddenIndices[index];
 | |
|   }
 | |
|   getDataVisibility(index) {
 | |
|     return !this._hiddenIndices[index];
 | |
|   }
 | |
|   _updateVisibility(datasetIndex, dataIndex, visible) {
 | |
|     const mode = visible ? "show" : "hide";
 | |
|     const meta = this.getDatasetMeta(datasetIndex);
 | |
|     const anims = meta.controller._resolveAnimations(void 0, mode);
 | |
|     if (defined(dataIndex)) {
 | |
|       meta.data[dataIndex].hidden = !visible;
 | |
|       this.update();
 | |
|     } else {
 | |
|       this.setDatasetVisibility(datasetIndex, visible);
 | |
|       anims.update(meta, {
 | |
|         visible
 | |
|       });
 | |
|       this.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : void 0);
 | |
|     }
 | |
|   }
 | |
|   hide(datasetIndex, dataIndex) {
 | |
|     this._updateVisibility(datasetIndex, dataIndex, false);
 | |
|   }
 | |
|   show(datasetIndex, dataIndex) {
 | |
|     this._updateVisibility(datasetIndex, dataIndex, true);
 | |
|   }
 | |
|   _destroyDatasetMeta(datasetIndex) {
 | |
|     const meta = this._metasets[datasetIndex];
 | |
|     if (meta && meta.controller) {
 | |
|       meta.controller._destroy();
 | |
|     }
 | |
|     delete this._metasets[datasetIndex];
 | |
|   }
 | |
|   _stop() {
 | |
|     let i2, ilen;
 | |
|     this.stop();
 | |
|     animator.remove(this);
 | |
|     for (i2 = 0, ilen = this.data.datasets.length; i2 < ilen; ++i2) {
 | |
|       this._destroyDatasetMeta(i2);
 | |
|     }
 | |
|   }
 | |
|   destroy() {
 | |
|     this.notifyPlugins("beforeDestroy");
 | |
|     const { canvas, ctx } = this;
 | |
|     this._stop();
 | |
|     this.config.clearCache();
 | |
|     if (canvas) {
 | |
|       this.unbindEvents();
 | |
|       clearCanvas(canvas, ctx);
 | |
|       this.platform.releaseContext(ctx);
 | |
|       this.canvas = null;
 | |
|       this.ctx = null;
 | |
|     }
 | |
|     delete instances[this.id];
 | |
|     this.notifyPlugins("afterDestroy");
 | |
|   }
 | |
|   toBase64Image(...args) {
 | |
|     return this.canvas.toDataURL(...args);
 | |
|   }
 | |
|   bindEvents() {
 | |
|     this.bindUserEvents();
 | |
|     if (this.options.responsive) {
 | |
|       this.bindResponsiveEvents();
 | |
|     } else {
 | |
|       this.attached = true;
 | |
|     }
 | |
|   }
 | |
|   bindUserEvents() {
 | |
|     const listeners = this._listeners;
 | |
|     const platform = this.platform;
 | |
|     const _add = (type, listener2) => {
 | |
|       platform.addEventListener(this, type, listener2);
 | |
|       listeners[type] = listener2;
 | |
|     };
 | |
|     const listener = (e2, x2, y2) => {
 | |
|       e2.offsetX = x2;
 | |
|       e2.offsetY = y2;
 | |
|       this._eventHandler(e2);
 | |
|     };
 | |
|     each(this.options.events, (type) => _add(type, listener));
 | |
|   }
 | |
|   bindResponsiveEvents() {
 | |
|     if (!this._responsiveListeners) {
 | |
|       this._responsiveListeners = {};
 | |
|     }
 | |
|     const listeners = this._responsiveListeners;
 | |
|     const platform = this.platform;
 | |
|     const _add = (type, listener2) => {
 | |
|       platform.addEventListener(this, type, listener2);
 | |
|       listeners[type] = listener2;
 | |
|     };
 | |
|     const _remove = (type, listener2) => {
 | |
|       if (listeners[type]) {
 | |
|         platform.removeEventListener(this, type, listener2);
 | |
|         delete listeners[type];
 | |
|       }
 | |
|     };
 | |
|     const listener = (width, height) => {
 | |
|       if (this.canvas) {
 | |
|         this.resize(width, height);
 | |
|       }
 | |
|     };
 | |
|     let detached;
 | |
|     const attached = () => {
 | |
|       _remove("attach", attached);
 | |
|       this.attached = true;
 | |
|       this.resize();
 | |
|       _add("resize", listener);
 | |
|       _add("detach", detached);
 | |
|     };
 | |
|     detached = () => {
 | |
|       this.attached = false;
 | |
|       _remove("resize", listener);
 | |
|       this._stop();
 | |
|       this._resize(0, 0);
 | |
|       _add("attach", attached);
 | |
|     };
 | |
|     if (platform.isAttached(this.canvas)) {
 | |
|       attached();
 | |
|     } else {
 | |
|       detached();
 | |
|     }
 | |
|   }
 | |
|   unbindEvents() {
 | |
|     each(this._listeners, (listener, type) => {
 | |
|       this.platform.removeEventListener(this, type, listener);
 | |
|     });
 | |
|     this._listeners = {};
 | |
|     each(this._responsiveListeners, (listener, type) => {
 | |
|       this.platform.removeEventListener(this, type, listener);
 | |
|     });
 | |
|     this._responsiveListeners = void 0;
 | |
|   }
 | |
|   updateHoverStyle(items, mode, enabled) {
 | |
|     const prefix = enabled ? "set" : "remove";
 | |
|     let meta, item, i2, ilen;
 | |
|     if (mode === "dataset") {
 | |
|       meta = this.getDatasetMeta(items[0].datasetIndex);
 | |
|       meta.controller["_" + prefix + "DatasetHoverStyle"]();
 | |
|     }
 | |
|     for (i2 = 0, ilen = items.length; i2 < ilen; ++i2) {
 | |
|       item = items[i2];
 | |
|       const controller = item && this.getDatasetMeta(item.datasetIndex).controller;
 | |
|       if (controller) {
 | |
|         controller[prefix + "HoverStyle"](item.element, item.datasetIndex, item.index);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   getActiveElements() {
 | |
|     return this._active || [];
 | |
|   }
 | |
|   setActiveElements(activeElements) {
 | |
|     const lastActive = this._active || [];
 | |
|     const active = activeElements.map(({ datasetIndex, index }) => {
 | |
|       const meta = this.getDatasetMeta(datasetIndex);
 | |
|       if (!meta) {
 | |
|         throw new Error("No dataset found at index " + datasetIndex);
 | |
|       }
 | |
|       return {
 | |
|         datasetIndex,
 | |
|         element: meta.data[index],
 | |
|         index
 | |
|       };
 | |
|     });
 | |
|     const changed = !_elementsEqual(active, lastActive);
 | |
|     if (changed) {
 | |
|       this._active = active;
 | |
|       this._lastEvent = null;
 | |
|       this._updateHoverStyles(active, lastActive);
 | |
|     }
 | |
|   }
 | |
|   notifyPlugins(hook, args, filter2) {
 | |
|     return this._plugins.notify(this, hook, args, filter2);
 | |
|   }
 | |
|   isPluginEnabled(pluginId) {
 | |
|     return this._plugins._cache.filter((p2) => p2.plugin.id === pluginId).length === 1;
 | |
|   }
 | |
|   _updateHoverStyles(active, lastActive, replay) {
 | |
|     const hoverOptions = this.options.hover;
 | |
|     const diff = (a2, b2) => a2.filter((x2) => !b2.some((y2) => x2.datasetIndex === y2.datasetIndex && x2.index === y2.index));
 | |
|     const deactivated = diff(lastActive, active);
 | |
|     const activated = replay ? active : diff(active, lastActive);
 | |
|     if (deactivated.length) {
 | |
|       this.updateHoverStyle(deactivated, hoverOptions.mode, false);
 | |
|     }
 | |
|     if (activated.length && hoverOptions.mode) {
 | |
|       this.updateHoverStyle(activated, hoverOptions.mode, true);
 | |
|     }
 | |
|   }
 | |
|   _eventHandler(e2, replay) {
 | |
|     const args = {
 | |
|       event: e2,
 | |
|       replay,
 | |
|       cancelable: true,
 | |
|       inChartArea: this.isPointInArea(e2)
 | |
|     };
 | |
|     const eventFilter = (plugin) => (plugin.options.events || this.options.events).includes(e2.native.type);
 | |
|     if (this.notifyPlugins("beforeEvent", args, eventFilter) === false) {
 | |
|       return;
 | |
|     }
 | |
|     const changed = this._handleEvent(e2, replay, args.inChartArea);
 | |
|     args.cancelable = false;
 | |
|     this.notifyPlugins("afterEvent", args, eventFilter);
 | |
|     if (changed || args.changed) {
 | |
|       this.render();
 | |
|     }
 | |
|     return this;
 | |
|   }
 | |
|   _handleEvent(e2, replay, inChartArea) {
 | |
|     const { _active: lastActive = [], options } = this;
 | |
|     const useFinalPosition = replay;
 | |
|     const active = this._getActiveElements(e2, lastActive, inChartArea, useFinalPosition);
 | |
|     const isClick = _isClickEvent(e2);
 | |
|     const lastEvent = determineLastEvent(e2, this._lastEvent, inChartArea, isClick);
 | |
|     if (inChartArea) {
 | |
|       this._lastEvent = null;
 | |
|       callback(options.onHover, [
 | |
|         e2,
 | |
|         active,
 | |
|         this
 | |
|       ], this);
 | |
|       if (isClick) {
 | |
|         callback(options.onClick, [
 | |
|           e2,
 | |
|           active,
 | |
|           this
 | |
|         ], this);
 | |
|       }
 | |
|     }
 | |
|     const changed = !_elementsEqual(active, lastActive);
 | |
|     if (changed || replay) {
 | |
|       this._active = active;
 | |
|       this._updateHoverStyles(active, lastActive, replay);
 | |
|     }
 | |
|     this._lastEvent = lastEvent;
 | |
|     return changed;
 | |
|   }
 | |
|   _getActiveElements(e2, lastActive, inChartArea, useFinalPosition) {
 | |
|     if (e2.type === "mouseout") {
 | |
|       return [];
 | |
|     }
 | |
|     if (!inChartArea) {
 | |
|       return lastActive;
 | |
|     }
 | |
|     const hoverOptions = this.options.hover;
 | |
|     return this.getElementsAtEventForMode(e2, hoverOptions.mode, hoverOptions, useFinalPosition);
 | |
|   }
 | |
| };
 | |
| __publicField(Chart, "defaults", defaults2);
 | |
| __publicField(Chart, "instances", instances);
 | |
| __publicField(Chart, "overrides", overrides);
 | |
| __publicField(Chart, "registry", registry);
 | |
| __publicField(Chart, "version", version);
 | |
| __publicField(Chart, "getChart", getChart);
 | |
| function invalidatePlugins() {
 | |
|   return each(Chart.instances, (chart) => chart._plugins.invalidate());
 | |
| }
 | |
| function clipArc(ctx, element, endAngle) {
 | |
|   const { startAngle, pixelMargin, x: x2, y: y2, outerRadius, innerRadius } = element;
 | |
|   let angleMargin = pixelMargin / outerRadius;
 | |
|   ctx.beginPath();
 | |
|   ctx.arc(x2, y2, outerRadius, startAngle - angleMargin, endAngle + angleMargin);
 | |
|   if (innerRadius > pixelMargin) {
 | |
|     angleMargin = pixelMargin / innerRadius;
 | |
|     ctx.arc(x2, y2, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);
 | |
|   } else {
 | |
|     ctx.arc(x2, y2, pixelMargin, endAngle + HALF_PI, startAngle - HALF_PI);
 | |
|   }
 | |
|   ctx.closePath();
 | |
|   ctx.clip();
 | |
| }
 | |
| function toRadiusCorners(value) {
 | |
|   return _readValueToProps(value, [
 | |
|     "outerStart",
 | |
|     "outerEnd",
 | |
|     "innerStart",
 | |
|     "innerEnd"
 | |
|   ]);
 | |
| }
 | |
| function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) {
 | |
|   const o2 = toRadiusCorners(arc.options.borderRadius);
 | |
|   const halfThickness = (outerRadius - innerRadius) / 2;
 | |
|   const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2);
 | |
|   const computeOuterLimit = (val) => {
 | |
|     const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2;
 | |
|     return _limitValue(val, 0, Math.min(halfThickness, outerArcLimit));
 | |
|   };
 | |
|   return {
 | |
|     outerStart: computeOuterLimit(o2.outerStart),
 | |
|     outerEnd: computeOuterLimit(o2.outerEnd),
 | |
|     innerStart: _limitValue(o2.innerStart, 0, innerLimit),
 | |
|     innerEnd: _limitValue(o2.innerEnd, 0, innerLimit)
 | |
|   };
 | |
| }
 | |
| function rThetaToXY(r2, theta, x2, y2) {
 | |
|   return {
 | |
|     x: x2 + r2 * Math.cos(theta),
 | |
|     y: y2 + r2 * Math.sin(theta)
 | |
|   };
 | |
| }
 | |
| function pathArc(ctx, element, offset, spacing, end, circular) {
 | |
|   const { x: x2, y: y2, startAngle: start, pixelMargin, innerRadius: innerR } = element;
 | |
|   const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0);
 | |
|   const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0;
 | |
|   let spacingOffset = 0;
 | |
|   const alpha2 = end - start;
 | |
|   if (spacing) {
 | |
|     const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0;
 | |
|     const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0;
 | |
|     const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;
 | |
|     const adjustedAngle = avNogSpacingRadius !== 0 ? alpha2 * avNogSpacingRadius / (avNogSpacingRadius + spacing) : alpha2;
 | |
|     spacingOffset = (alpha2 - adjustedAngle) / 2;
 | |
|   }
 | |
|   const beta = Math.max(1e-3, alpha2 * outerRadius - offset / PI) / outerRadius;
 | |
|   const angleOffset = (alpha2 - beta) / 2;
 | |
|   const startAngle = start + angleOffset + spacingOffset;
 | |
|   const endAngle = end - angleOffset - spacingOffset;
 | |
|   const { outerStart, outerEnd, innerStart, innerEnd } = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle);
 | |
|   const outerStartAdjustedRadius = outerRadius - outerStart;
 | |
|   const outerEndAdjustedRadius = outerRadius - outerEnd;
 | |
|   const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius;
 | |
|   const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius;
 | |
|   const innerStartAdjustedRadius = innerRadius + innerStart;
 | |
|   const innerEndAdjustedRadius = innerRadius + innerEnd;
 | |
|   const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius;
 | |
|   const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius;
 | |
|   ctx.beginPath();
 | |
|   if (circular) {
 | |
|     const outerMidAdjustedAngle = (outerStartAdjustedAngle + outerEndAdjustedAngle) / 2;
 | |
|     ctx.arc(x2, y2, outerRadius, outerStartAdjustedAngle, outerMidAdjustedAngle);
 | |
|     ctx.arc(x2, y2, outerRadius, outerMidAdjustedAngle, outerEndAdjustedAngle);
 | |
|     if (outerEnd > 0) {
 | |
|       const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x2, y2);
 | |
|       ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + HALF_PI);
 | |
|     }
 | |
|     const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x2, y2);
 | |
|     ctx.lineTo(p4.x, p4.y);
 | |
|     if (innerEnd > 0) {
 | |
|       const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x2, y2);
 | |
|       ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + HALF_PI, innerEndAdjustedAngle + Math.PI);
 | |
|     }
 | |
|     const innerMidAdjustedAngle = (endAngle - innerEnd / innerRadius + (startAngle + innerStart / innerRadius)) / 2;
 | |
|     ctx.arc(x2, y2, innerRadius, endAngle - innerEnd / innerRadius, innerMidAdjustedAngle, true);
 | |
|     ctx.arc(x2, y2, innerRadius, innerMidAdjustedAngle, startAngle + innerStart / innerRadius, true);
 | |
|     if (innerStart > 0) {
 | |
|       const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x2, y2);
 | |
|       ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - HALF_PI);
 | |
|     }
 | |
|     const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x2, y2);
 | |
|     ctx.lineTo(p8.x, p8.y);
 | |
|     if (outerStart > 0) {
 | |
|       const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x2, y2);
 | |
|       ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - HALF_PI, outerStartAdjustedAngle);
 | |
|     }
 | |
|   } else {
 | |
|     ctx.moveTo(x2, y2);
 | |
|     const outerStartX = Math.cos(outerStartAdjustedAngle) * outerRadius + x2;
 | |
|     const outerStartY = Math.sin(outerStartAdjustedAngle) * outerRadius + y2;
 | |
|     ctx.lineTo(outerStartX, outerStartY);
 | |
|     const outerEndX = Math.cos(outerEndAdjustedAngle) * outerRadius + x2;
 | |
|     const outerEndY = Math.sin(outerEndAdjustedAngle) * outerRadius + y2;
 | |
|     ctx.lineTo(outerEndX, outerEndY);
 | |
|   }
 | |
|   ctx.closePath();
 | |
| }
 | |
| function drawArc(ctx, element, offset, spacing, circular) {
 | |
|   const { fullCircles, startAngle, circumference } = element;
 | |
|   let endAngle = element.endAngle;
 | |
|   if (fullCircles) {
 | |
|     pathArc(ctx, element, offset, spacing, endAngle, circular);
 | |
|     for (let i2 = 0; i2 < fullCircles; ++i2) {
 | |
|       ctx.fill();
 | |
|     }
 | |
|     if (!isNaN(circumference)) {
 | |
|       endAngle = startAngle + (circumference % TAU || TAU);
 | |
|     }
 | |
|   }
 | |
|   pathArc(ctx, element, offset, spacing, endAngle, circular);
 | |
|   ctx.fill();
 | |
|   return endAngle;
 | |
| }
 | |
| function drawBorder(ctx, element, offset, spacing, circular) {
 | |
|   const { fullCircles, startAngle, circumference, options } = element;
 | |
|   const { borderWidth, borderJoinStyle, borderDash, borderDashOffset } = options;
 | |
|   const inner = options.borderAlign === "inner";
 | |
|   if (!borderWidth) {
 | |
|     return;
 | |
|   }
 | |
|   ctx.setLineDash(borderDash || []);
 | |
|   ctx.lineDashOffset = borderDashOffset;
 | |
|   if (inner) {
 | |
|     ctx.lineWidth = borderWidth * 2;
 | |
|     ctx.lineJoin = borderJoinStyle || "round";
 | |
|   } else {
 | |
|     ctx.lineWidth = borderWidth;
 | |
|     ctx.lineJoin = borderJoinStyle || "bevel";
 | |
|   }
 | |
|   let endAngle = element.endAngle;
 | |
|   if (fullCircles) {
 | |
|     pathArc(ctx, element, offset, spacing, endAngle, circular);
 | |
|     for (let i2 = 0; i2 < fullCircles; ++i2) {
 | |
|       ctx.stroke();
 | |
|     }
 | |
|     if (!isNaN(circumference)) {
 | |
|       endAngle = startAngle + (circumference % TAU || TAU);
 | |
|     }
 | |
|   }
 | |
|   if (inner) {
 | |
|     clipArc(ctx, element, endAngle);
 | |
|   }
 | |
|   if (!fullCircles) {
 | |
|     pathArc(ctx, element, offset, spacing, endAngle, circular);
 | |
|     ctx.stroke();
 | |
|   }
 | |
| }
 | |
| var ArcElement = class extends Element {
 | |
|   constructor(cfg) {
 | |
|     super();
 | |
|     __publicField(this, "circumference");
 | |
|     __publicField(this, "endAngle");
 | |
|     __publicField(this, "fullCircles");
 | |
|     __publicField(this, "innerRadius");
 | |
|     __publicField(this, "outerRadius");
 | |
|     __publicField(this, "pixelMargin");
 | |
|     __publicField(this, "startAngle");
 | |
|     this.options = void 0;
 | |
|     this.circumference = void 0;
 | |
|     this.startAngle = void 0;
 | |
|     this.endAngle = void 0;
 | |
|     this.innerRadius = void 0;
 | |
|     this.outerRadius = void 0;
 | |
|     this.pixelMargin = 0;
 | |
|     this.fullCircles = 0;
 | |
|     if (cfg) {
 | |
|       Object.assign(this, cfg);
 | |
|     }
 | |
|   }
 | |
|   inRange(chartX, chartY, useFinalPosition) {
 | |
|     const point = this.getProps([
 | |
|       "x",
 | |
|       "y"
 | |
|     ], useFinalPosition);
 | |
|     const { angle, distance } = getAngleFromPoint(point, {
 | |
|       x: chartX,
 | |
|       y: chartY
 | |
|     });
 | |
|     const { startAngle, endAngle, innerRadius, outerRadius, circumference } = this.getProps([
 | |
|       "startAngle",
 | |
|       "endAngle",
 | |
|       "innerRadius",
 | |
|       "outerRadius",
 | |
|       "circumference"
 | |
|     ], useFinalPosition);
 | |
|     const rAdjust = (this.options.spacing + this.options.borderWidth) / 2;
 | |
|     const _circumference = valueOrDefault(circumference, endAngle - startAngle);
 | |
|     const nonZeroBetween = _angleBetween(angle, startAngle, endAngle) && startAngle !== endAngle;
 | |
|     const betweenAngles = _circumference >= TAU || nonZeroBetween;
 | |
|     const withinRadius = _isBetween(distance, innerRadius + rAdjust, outerRadius + rAdjust);
 | |
|     return betweenAngles && withinRadius;
 | |
|   }
 | |
|   getCenterPoint(useFinalPosition) {
 | |
|     const { x: x2, y: y2, startAngle, endAngle, innerRadius, outerRadius } = this.getProps([
 | |
|       "x",
 | |
|       "y",
 | |
|       "startAngle",
 | |
|       "endAngle",
 | |
|       "innerRadius",
 | |
|       "outerRadius"
 | |
|     ], useFinalPosition);
 | |
|     const { offset, spacing } = this.options;
 | |
|     const halfAngle = (startAngle + endAngle) / 2;
 | |
|     const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2;
 | |
|     return {
 | |
|       x: x2 + Math.cos(halfAngle) * halfRadius,
 | |
|       y: y2 + Math.sin(halfAngle) * halfRadius
 | |
|     };
 | |
|   }
 | |
|   tooltipPosition(useFinalPosition) {
 | |
|     return this.getCenterPoint(useFinalPosition);
 | |
|   }
 | |
|   draw(ctx) {
 | |
|     const { options, circumference } = this;
 | |
|     const offset = (options.offset || 0) / 4;
 | |
|     const spacing = (options.spacing || 0) / 2;
 | |
|     const circular = options.circular;
 | |
|     this.pixelMargin = options.borderAlign === "inner" ? 0.33 : 0;
 | |
|     this.fullCircles = circumference > TAU ? Math.floor(circumference / TAU) : 0;
 | |
|     if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) {
 | |
|       return;
 | |
|     }
 | |
|     ctx.save();
 | |
|     const halfAngle = (this.startAngle + this.endAngle) / 2;
 | |
|     ctx.translate(Math.cos(halfAngle) * offset, Math.sin(halfAngle) * offset);
 | |
|     const fix = 1 - Math.sin(Math.min(PI, circumference || 0));
 | |
|     const radiusOffset = offset * fix;
 | |
|     ctx.fillStyle = options.backgroundColor;
 | |
|     ctx.strokeStyle = options.borderColor;
 | |
|     drawArc(ctx, this, radiusOffset, spacing, circular);
 | |
|     drawBorder(ctx, this, radiusOffset, spacing, circular);
 | |
|     ctx.restore();
 | |
|   }
 | |
| };
 | |
| __publicField(ArcElement, "id", "arc");
 | |
| __publicField(ArcElement, "defaults", {
 | |
|   borderAlign: "center",
 | |
|   borderColor: "#fff",
 | |
|   borderDash: [],
 | |
|   borderDashOffset: 0,
 | |
|   borderJoinStyle: void 0,
 | |
|   borderRadius: 0,
 | |
|   borderWidth: 2,
 | |
|   offset: 0,
 | |
|   spacing: 0,
 | |
|   angle: void 0,
 | |
|   circular: true
 | |
| });
 | |
| __publicField(ArcElement, "defaultRoutes", {
 | |
|   backgroundColor: "backgroundColor"
 | |
| });
 | |
| __publicField(ArcElement, "descriptors", {
 | |
|   _scriptable: true,
 | |
|   _indexable: (name) => name !== "borderDash"
 | |
| });
 | |
| function getBarBounds(bar, useFinalPosition) {
 | |
|   const { x: x2, y: y2, base, width, height } = bar.getProps([
 | |
|     "x",
 | |
|     "y",
 | |
|     "base",
 | |
|     "width",
 | |
|     "height"
 | |
|   ], useFinalPosition);
 | |
|   let left, right, top, bottom, half;
 | |
|   if (bar.horizontal) {
 | |
|     half = height / 2;
 | |
|     left = Math.min(x2, base);
 | |
|     right = Math.max(x2, base);
 | |
|     top = y2 - half;
 | |
|     bottom = y2 + half;
 | |
|   } else {
 | |
|     half = width / 2;
 | |
|     left = x2 - half;
 | |
|     right = x2 + half;
 | |
|     top = Math.min(y2, base);
 | |
|     bottom = Math.max(y2, base);
 | |
|   }
 | |
|   return {
 | |
|     left,
 | |
|     top,
 | |
|     right,
 | |
|     bottom
 | |
|   };
 | |
| }
 | |
| function skipOrLimit(skip2, value, min, max) {
 | |
|   return skip2 ? 0 : _limitValue(value, min, max);
 | |
| }
 | |
| function parseBorderWidth(bar, maxW, maxH) {
 | |
|   const value = bar.options.borderWidth;
 | |
|   const skip2 = bar.borderSkipped;
 | |
|   const o2 = toTRBL(value);
 | |
|   return {
 | |
|     t: skipOrLimit(skip2.top, o2.top, 0, maxH),
 | |
|     r: skipOrLimit(skip2.right, o2.right, 0, maxW),
 | |
|     b: skipOrLimit(skip2.bottom, o2.bottom, 0, maxH),
 | |
|     l: skipOrLimit(skip2.left, o2.left, 0, maxW)
 | |
|   };
 | |
| }
 | |
| function parseBorderRadius(bar, maxW, maxH) {
 | |
|   const { enableBorderRadius } = bar.getProps([
 | |
|     "enableBorderRadius"
 | |
|   ]);
 | |
|   const value = bar.options.borderRadius;
 | |
|   const o2 = toTRBLCorners(value);
 | |
|   const maxR = Math.min(maxW, maxH);
 | |
|   const skip2 = bar.borderSkipped;
 | |
|   const enableBorder = enableBorderRadius || isObject(value);
 | |
|   return {
 | |
|     topLeft: skipOrLimit(!enableBorder || skip2.top || skip2.left, o2.topLeft, 0, maxR),
 | |
|     topRight: skipOrLimit(!enableBorder || skip2.top || skip2.right, o2.topRight, 0, maxR),
 | |
|     bottomLeft: skipOrLimit(!enableBorder || skip2.bottom || skip2.left, o2.bottomLeft, 0, maxR),
 | |
|     bottomRight: skipOrLimit(!enableBorder || skip2.bottom || skip2.right, o2.bottomRight, 0, maxR)
 | |
|   };
 | |
| }
 | |
| function boundingRects(bar) {
 | |
|   const bounds = getBarBounds(bar);
 | |
|   const width = bounds.right - bounds.left;
 | |
|   const height = bounds.bottom - bounds.top;
 | |
|   const border = parseBorderWidth(bar, width / 2, height / 2);
 | |
|   const radius = parseBorderRadius(bar, width / 2, height / 2);
 | |
|   return {
 | |
|     outer: {
 | |
|       x: bounds.left,
 | |
|       y: bounds.top,
 | |
|       w: width,
 | |
|       h: height,
 | |
|       radius
 | |
|     },
 | |
|     inner: {
 | |
|       x: bounds.left + border.l,
 | |
|       y: bounds.top + border.t,
 | |
|       w: width - border.l - border.r,
 | |
|       h: height - border.t - border.b,
 | |
|       radius: {
 | |
|         topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
 | |
|         topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
 | |
|         bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),
 | |
|         bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r))
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| }
 | |
| function inRange(bar, x2, y2, useFinalPosition) {
 | |
|   const skipX = x2 === null;
 | |
|   const skipY = y2 === null;
 | |
|   const skipBoth = skipX && skipY;
 | |
|   const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);
 | |
|   return bounds && (skipX || _isBetween(x2, bounds.left, bounds.right)) && (skipY || _isBetween(y2, bounds.top, bounds.bottom));
 | |
| }
 | |
| function hasRadius(radius) {
 | |
|   return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;
 | |
| }
 | |
| function addNormalRectPath(ctx, rect) {
 | |
|   ctx.rect(rect.x, rect.y, rect.w, rect.h);
 | |
| }
 | |
| function inflateRect(rect, amount, refRect = {}) {
 | |
|   const x2 = rect.x !== refRect.x ? -amount : 0;
 | |
|   const y2 = rect.y !== refRect.y ? -amount : 0;
 | |
|   const w2 = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x2;
 | |
|   const h6 = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y2;
 | |
|   return {
 | |
|     x: rect.x + x2,
 | |
|     y: rect.y + y2,
 | |
|     w: rect.w + w2,
 | |
|     h: rect.h + h6,
 | |
|     radius: rect.radius
 | |
|   };
 | |
| }
 | |
| var BarElement = class extends Element {
 | |
|   constructor(cfg) {
 | |
|     super();
 | |
|     this.options = void 0;
 | |
|     this.horizontal = void 0;
 | |
|     this.base = void 0;
 | |
|     this.width = void 0;
 | |
|     this.height = void 0;
 | |
|     this.inflateAmount = void 0;
 | |
|     if (cfg) {
 | |
|       Object.assign(this, cfg);
 | |
|     }
 | |
|   }
 | |
|   draw(ctx) {
 | |
|     const { inflateAmount, options: { borderColor, backgroundColor } } = this;
 | |
|     const { inner, outer } = boundingRects(this);
 | |
|     const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
 | |
|     ctx.save();
 | |
|     if (outer.w !== inner.w || outer.h !== inner.h) {
 | |
|       ctx.beginPath();
 | |
|       addRectPath(ctx, inflateRect(outer, inflateAmount, inner));
 | |
|       ctx.clip();
 | |
|       addRectPath(ctx, inflateRect(inner, -inflateAmount, outer));
 | |
|       ctx.fillStyle = borderColor;
 | |
|       ctx.fill("evenodd");
 | |
|     }
 | |
|     ctx.beginPath();
 | |
|     addRectPath(ctx, inflateRect(inner, inflateAmount));
 | |
|     ctx.fillStyle = backgroundColor;
 | |
|     ctx.fill();
 | |
|     ctx.restore();
 | |
|   }
 | |
|   inRange(mouseX, mouseY, useFinalPosition) {
 | |
|     return inRange(this, mouseX, mouseY, useFinalPosition);
 | |
|   }
 | |
|   inXRange(mouseX, useFinalPosition) {
 | |
|     return inRange(this, mouseX, null, useFinalPosition);
 | |
|   }
 | |
|   inYRange(mouseY, useFinalPosition) {
 | |
|     return inRange(this, null, mouseY, useFinalPosition);
 | |
|   }
 | |
|   getCenterPoint(useFinalPosition) {
 | |
|     const { x: x2, y: y2, base, horizontal } = this.getProps([
 | |
|       "x",
 | |
|       "y",
 | |
|       "base",
 | |
|       "horizontal"
 | |
|     ], useFinalPosition);
 | |
|     return {
 | |
|       x: horizontal ? (x2 + base) / 2 : x2,
 | |
|       y: horizontal ? y2 : (y2 + base) / 2
 | |
|     };
 | |
|   }
 | |
|   getRange(axis) {
 | |
|     return axis === "x" ? this.width / 2 : this.height / 2;
 | |
|   }
 | |
| };
 | |
| __publicField(BarElement, "id", "bar");
 | |
| __publicField(BarElement, "defaults", {
 | |
|   borderSkipped: "start",
 | |
|   borderWidth: 0,
 | |
|   borderRadius: 0,
 | |
|   inflateAmount: "auto",
 | |
|   pointStyle: void 0
 | |
| });
 | |
| __publicField(BarElement, "defaultRoutes", {
 | |
|   backgroundColor: "backgroundColor",
 | |
|   borderColor: "borderColor"
 | |
| });
 | |
| var getBoxSize = (labelOpts, fontSize) => {
 | |
|   let { boxHeight = fontSize, boxWidth = fontSize } = labelOpts;
 | |
|   if (labelOpts.usePointStyle) {
 | |
|     boxHeight = Math.min(boxHeight, fontSize);
 | |
|     boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize);
 | |
|   }
 | |
|   return {
 | |
|     boxWidth,
 | |
|     boxHeight,
 | |
|     itemHeight: Math.max(fontSize, boxHeight)
 | |
|   };
 | |
| };
 | |
| var itemsEqual = (a2, b2) => a2 !== null && b2 !== null && a2.datasetIndex === b2.datasetIndex && a2.index === b2.index;
 | |
| var Legend = class extends Element {
 | |
|   constructor(config) {
 | |
|     super();
 | |
|     this._added = false;
 | |
|     this.legendHitBoxes = [];
 | |
|     this._hoveredItem = null;
 | |
|     this.doughnutMode = false;
 | |
|     this.chart = config.chart;
 | |
|     this.options = config.options;
 | |
|     this.ctx = config.ctx;
 | |
|     this.legendItems = void 0;
 | |
|     this.columnSizes = void 0;
 | |
|     this.lineWidths = void 0;
 | |
|     this.maxHeight = void 0;
 | |
|     this.maxWidth = void 0;
 | |
|     this.top = void 0;
 | |
|     this.bottom = void 0;
 | |
|     this.left = void 0;
 | |
|     this.right = void 0;
 | |
|     this.height = void 0;
 | |
|     this.width = void 0;
 | |
|     this._margins = void 0;
 | |
|     this.position = void 0;
 | |
|     this.weight = void 0;
 | |
|     this.fullSize = void 0;
 | |
|   }
 | |
|   update(maxWidth, maxHeight, margins) {
 | |
|     this.maxWidth = maxWidth;
 | |
|     this.maxHeight = maxHeight;
 | |
|     this._margins = margins;
 | |
|     this.setDimensions();
 | |
|     this.buildLabels();
 | |
|     this.fit();
 | |
|   }
 | |
|   setDimensions() {
 | |
|     if (this.isHorizontal()) {
 | |
|       this.width = this.maxWidth;
 | |
|       this.left = this._margins.left;
 | |
|       this.right = this.width;
 | |
|     } else {
 | |
|       this.height = this.maxHeight;
 | |
|       this.top = this._margins.top;
 | |
|       this.bottom = this.height;
 | |
|     }
 | |
|   }
 | |
|   buildLabels() {
 | |
|     const labelOpts = this.options.labels || {};
 | |
|     let legendItems = callback(labelOpts.generateLabels, [
 | |
|       this.chart
 | |
|     ], this) || [];
 | |
|     if (labelOpts.filter) {
 | |
|       legendItems = legendItems.filter((item) => labelOpts.filter(item, this.chart.data));
 | |
|     }
 | |
|     if (labelOpts.sort) {
 | |
|       legendItems = legendItems.sort((a2, b2) => labelOpts.sort(a2, b2, this.chart.data));
 | |
|     }
 | |
|     if (this.options.reverse) {
 | |
|       legendItems.reverse();
 | |
|     }
 | |
|     this.legendItems = legendItems;
 | |
|   }
 | |
|   fit() {
 | |
|     const { options, ctx } = this;
 | |
|     if (!options.display) {
 | |
|       this.width = this.height = 0;
 | |
|       return;
 | |
|     }
 | |
|     const labelOpts = options.labels;
 | |
|     const labelFont = toFont(labelOpts.font);
 | |
|     const fontSize = labelFont.size;
 | |
|     const titleHeight = this._computeTitleHeight();
 | |
|     const { boxWidth, itemHeight } = getBoxSize(labelOpts, fontSize);
 | |
|     let width, height;
 | |
|     ctx.font = labelFont.string;
 | |
|     if (this.isHorizontal()) {
 | |
|       width = this.maxWidth;
 | |
|       height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;
 | |
|     } else {
 | |
|       height = this.maxHeight;
 | |
|       width = this._fitCols(titleHeight, labelFont, boxWidth, itemHeight) + 10;
 | |
|     }
 | |
|     this.width = Math.min(width, options.maxWidth || this.maxWidth);
 | |
|     this.height = Math.min(height, options.maxHeight || this.maxHeight);
 | |
|   }
 | |
|   _fitRows(titleHeight, fontSize, boxWidth, itemHeight) {
 | |
|     const { ctx, maxWidth, options: { labels: { padding } } } = this;
 | |
|     const hitboxes = this.legendHitBoxes = [];
 | |
|     const lineWidths = this.lineWidths = [
 | |
|       0
 | |
|     ];
 | |
|     const lineHeight = itemHeight + padding;
 | |
|     let totalHeight = titleHeight;
 | |
|     ctx.textAlign = "left";
 | |
|     ctx.textBaseline = "middle";
 | |
|     let row = -1;
 | |
|     let top = -lineHeight;
 | |
|     this.legendItems.forEach((legendItem, i2) => {
 | |
|       const itemWidth = boxWidth + fontSize / 2 + ctx.measureText(legendItem.text).width;
 | |
|       if (i2 === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {
 | |
|         totalHeight += lineHeight;
 | |
|         lineWidths[lineWidths.length - (i2 > 0 ? 0 : 1)] = 0;
 | |
|         top += lineHeight;
 | |
|         row++;
 | |
|       }
 | |
|       hitboxes[i2] = {
 | |
|         left: 0,
 | |
|         top,
 | |
|         row,
 | |
|         width: itemWidth,
 | |
|         height: itemHeight
 | |
|       };
 | |
|       lineWidths[lineWidths.length - 1] += itemWidth + padding;
 | |
|     });
 | |
|     return totalHeight;
 | |
|   }
 | |
|   _fitCols(titleHeight, labelFont, boxWidth, _itemHeight) {
 | |
|     const { ctx, maxHeight, options: { labels: { padding } } } = this;
 | |
|     const hitboxes = this.legendHitBoxes = [];
 | |
|     const columnSizes = this.columnSizes = [];
 | |
|     const heightLimit = maxHeight - titleHeight;
 | |
|     let totalWidth = padding;
 | |
|     let currentColWidth = 0;
 | |
|     let currentColHeight = 0;
 | |
|     let left = 0;
 | |
|     let col = 0;
 | |
|     this.legendItems.forEach((legendItem, i2) => {
 | |
|       const { itemWidth, itemHeight } = calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight);
 | |
|       if (i2 > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) {
 | |
|         totalWidth += currentColWidth + padding;
 | |
|         columnSizes.push({
 | |
|           width: currentColWidth,
 | |
|           height: currentColHeight
 | |
|         });
 | |
|         left += currentColWidth + padding;
 | |
|         col++;
 | |
|         currentColWidth = currentColHeight = 0;
 | |
|       }
 | |
|       hitboxes[i2] = {
 | |
|         left,
 | |
|         top: currentColHeight,
 | |
|         col,
 | |
|         width: itemWidth,
 | |
|         height: itemHeight
 | |
|       };
 | |
|       currentColWidth = Math.max(currentColWidth, itemWidth);
 | |
|       currentColHeight += itemHeight + padding;
 | |
|     });
 | |
|     totalWidth += currentColWidth;
 | |
|     columnSizes.push({
 | |
|       width: currentColWidth,
 | |
|       height: currentColHeight
 | |
|     });
 | |
|     return totalWidth;
 | |
|   }
 | |
|   adjustHitBoxes() {
 | |
|     if (!this.options.display) {
 | |
|       return;
 | |
|     }
 | |
|     const titleHeight = this._computeTitleHeight();
 | |
|     const { legendHitBoxes: hitboxes, options: { align, labels: { padding }, rtl } } = this;
 | |
|     const rtlHelper = getRtlAdapter(rtl, this.left, this.width);
 | |
|     if (this.isHorizontal()) {
 | |
|       let row = 0;
 | |
|       let left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
 | |
|       for (const hitbox of hitboxes) {
 | |
|         if (row !== hitbox.row) {
 | |
|           row = hitbox.row;
 | |
|           left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
 | |
|         }
 | |
|         hitbox.top += this.top + titleHeight + padding;
 | |
|         hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);
 | |
|         left += hitbox.width + padding;
 | |
|       }
 | |
|     } else {
 | |
|       let col = 0;
 | |
|       let top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
 | |
|       for (const hitbox of hitboxes) {
 | |
|         if (hitbox.col !== col) {
 | |
|           col = hitbox.col;
 | |
|           top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
 | |
|         }
 | |
|         hitbox.top = top;
 | |
|         hitbox.left += this.left + padding;
 | |
|         hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);
 | |
|         top += hitbox.height + padding;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   isHorizontal() {
 | |
|     return this.options.position === "top" || this.options.position === "bottom";
 | |
|   }
 | |
|   draw() {
 | |
|     if (this.options.display) {
 | |
|       const ctx = this.ctx;
 | |
|       clipArea(ctx, this);
 | |
|       this._draw();
 | |
|       unclipArea(ctx);
 | |
|     }
 | |
|   }
 | |
|   _draw() {
 | |
|     const { options: opts, columnSizes, lineWidths, ctx } = this;
 | |
|     const { align, labels: labelOpts } = opts;
 | |
|     const defaultColor = defaults2.color;
 | |
|     const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
 | |
|     const labelFont = toFont(labelOpts.font);
 | |
|     const { padding } = labelOpts;
 | |
|     const fontSize = labelFont.size;
 | |
|     const halfFontSize = fontSize / 2;
 | |
|     let cursor;
 | |
|     this.drawTitle();
 | |
|     ctx.textAlign = rtlHelper.textAlign("left");
 | |
|     ctx.textBaseline = "middle";
 | |
|     ctx.lineWidth = 0.5;
 | |
|     ctx.font = labelFont.string;
 | |
|     const { boxWidth, boxHeight, itemHeight } = getBoxSize(labelOpts, fontSize);
 | |
|     const drawLegendBox = function(x2, y2, legendItem) {
 | |
|       if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {
 | |
|         return;
 | |
|       }
 | |
|       ctx.save();
 | |
|       const lineWidth = valueOrDefault(legendItem.lineWidth, 1);
 | |
|       ctx.fillStyle = valueOrDefault(legendItem.fillStyle, defaultColor);
 | |
|       ctx.lineCap = valueOrDefault(legendItem.lineCap, "butt");
 | |
|       ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, 0);
 | |
|       ctx.lineJoin = valueOrDefault(legendItem.lineJoin, "miter");
 | |
|       ctx.lineWidth = lineWidth;
 | |
|       ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, defaultColor);
 | |
|       ctx.setLineDash(valueOrDefault(legendItem.lineDash, []));
 | |
|       if (labelOpts.usePointStyle) {
 | |
|         const drawOptions = {
 | |
|           radius: boxHeight * Math.SQRT2 / 2,
 | |
|           pointStyle: legendItem.pointStyle,
 | |
|           rotation: legendItem.rotation,
 | |
|           borderWidth: lineWidth
 | |
|         };
 | |
|         const centerX = rtlHelper.xPlus(x2, boxWidth / 2);
 | |
|         const centerY = y2 + halfFontSize;
 | |
|         drawPointLegend(ctx, drawOptions, centerX, centerY, labelOpts.pointStyleWidth && boxWidth);
 | |
|       } else {
 | |
|         const yBoxTop = y2 + Math.max((fontSize - boxHeight) / 2, 0);
 | |
|         const xBoxLeft = rtlHelper.leftForLtr(x2, boxWidth);
 | |
|         const borderRadius = toTRBLCorners(legendItem.borderRadius);
 | |
|         ctx.beginPath();
 | |
|         if (Object.values(borderRadius).some((v2) => v2 !== 0)) {
 | |
|           addRoundedRectPath(ctx, {
 | |
|             x: xBoxLeft,
 | |
|             y: yBoxTop,
 | |
|             w: boxWidth,
 | |
|             h: boxHeight,
 | |
|             radius: borderRadius
 | |
|           });
 | |
|         } else {
 | |
|           ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);
 | |
|         }
 | |
|         ctx.fill();
 | |
|         if (lineWidth !== 0) {
 | |
|           ctx.stroke();
 | |
|         }
 | |
|       }
 | |
|       ctx.restore();
 | |
|     };
 | |
|     const fillText = function(x2, y2, legendItem) {
 | |
|       renderText(ctx, legendItem.text, x2, y2 + itemHeight / 2, labelFont, {
 | |
|         strikethrough: legendItem.hidden,
 | |
|         textAlign: rtlHelper.textAlign(legendItem.textAlign)
 | |
|       });
 | |
|     };
 | |
|     const isHorizontal = this.isHorizontal();
 | |
|     const titleHeight = this._computeTitleHeight();
 | |
|     if (isHorizontal) {
 | |
|       cursor = {
 | |
|         x: _alignStartEnd(align, this.left + padding, this.right - lineWidths[0]),
 | |
|         y: this.top + padding + titleHeight,
 | |
|         line: 0
 | |
|       };
 | |
|     } else {
 | |
|       cursor = {
 | |
|         x: this.left + padding,
 | |
|         y: _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),
 | |
|         line: 0
 | |
|       };
 | |
|     }
 | |
|     overrideTextDirection(this.ctx, opts.textDirection);
 | |
|     const lineHeight = itemHeight + padding;
 | |
|     this.legendItems.forEach((legendItem, i2) => {
 | |
|       ctx.strokeStyle = legendItem.fontColor;
 | |
|       ctx.fillStyle = legendItem.fontColor;
 | |
|       const textWidth = ctx.measureText(legendItem.text).width;
 | |
|       const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));
 | |
|       const width = boxWidth + halfFontSize + textWidth;
 | |
|       let x2 = cursor.x;
 | |
|       let y2 = cursor.y;
 | |
|       rtlHelper.setWidth(this.width);
 | |
|       if (isHorizontal) {
 | |
|         if (i2 > 0 && x2 + width + padding > this.right) {
 | |
|           y2 = cursor.y += lineHeight;
 | |
|           cursor.line++;
 | |
|           x2 = cursor.x = _alignStartEnd(align, this.left + padding, this.right - lineWidths[cursor.line]);
 | |
|         }
 | |
|       } else if (i2 > 0 && y2 + lineHeight > this.bottom) {
 | |
|         x2 = cursor.x = x2 + columnSizes[cursor.line].width + padding;
 | |
|         cursor.line++;
 | |
|         y2 = cursor.y = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);
 | |
|       }
 | |
|       const realX = rtlHelper.x(x2);
 | |
|       drawLegendBox(realX, y2, legendItem);
 | |
|       x2 = _textX(textAlign, x2 + boxWidth + halfFontSize, isHorizontal ? x2 + width : this.right, opts.rtl);
 | |
|       fillText(rtlHelper.x(x2), y2, legendItem);
 | |
|       if (isHorizontal) {
 | |
|         cursor.x += width + padding;
 | |
|       } else if (typeof legendItem.text !== "string") {
 | |
|         const fontLineHeight = labelFont.lineHeight;
 | |
|         cursor.y += calculateLegendItemHeight(legendItem, fontLineHeight) + padding;
 | |
|       } else {
 | |
|         cursor.y += lineHeight;
 | |
|       }
 | |
|     });
 | |
|     restoreTextDirection(this.ctx, opts.textDirection);
 | |
|   }
 | |
|   drawTitle() {
 | |
|     const opts = this.options;
 | |
|     const titleOpts = opts.title;
 | |
|     const titleFont = toFont(titleOpts.font);
 | |
|     const titlePadding = toPadding(titleOpts.padding);
 | |
|     if (!titleOpts.display) {
 | |
|       return;
 | |
|     }
 | |
|     const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
 | |
|     const ctx = this.ctx;
 | |
|     const position = titleOpts.position;
 | |
|     const halfFontSize = titleFont.size / 2;
 | |
|     const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;
 | |
|     let y2;
 | |
|     let left = this.left;
 | |
|     let maxWidth = this.width;
 | |
|     if (this.isHorizontal()) {
 | |
|       maxWidth = Math.max(...this.lineWidths);
 | |
|       y2 = this.top + topPaddingPlusHalfFontSize;
 | |
|       left = _alignStartEnd(opts.align, left, this.right - maxWidth);
 | |
|     } else {
 | |
|       const maxHeight = this.columnSizes.reduce((acc, size) => Math.max(acc, size.height), 0);
 | |
|       y2 = topPaddingPlusHalfFontSize + _alignStartEnd(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());
 | |
|     }
 | |
|     const x2 = _alignStartEnd(position, left, left + maxWidth);
 | |
|     ctx.textAlign = rtlHelper.textAlign(_toLeftRightCenter(position));
 | |
|     ctx.textBaseline = "middle";
 | |
|     ctx.strokeStyle = titleOpts.color;
 | |
|     ctx.fillStyle = titleOpts.color;
 | |
|     ctx.font = titleFont.string;
 | |
|     renderText(ctx, titleOpts.text, x2, y2, titleFont);
 | |
|   }
 | |
|   _computeTitleHeight() {
 | |
|     const titleOpts = this.options.title;
 | |
|     const titleFont = toFont(titleOpts.font);
 | |
|     const titlePadding = toPadding(titleOpts.padding);
 | |
|     return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0;
 | |
|   }
 | |
|   _getLegendItemAt(x2, y2) {
 | |
|     let i2, hitBox, lh;
 | |
|     if (_isBetween(x2, this.left, this.right) && _isBetween(y2, this.top, this.bottom)) {
 | |
|       lh = this.legendHitBoxes;
 | |
|       for (i2 = 0; i2 < lh.length; ++i2) {
 | |
|         hitBox = lh[i2];
 | |
|         if (_isBetween(x2, hitBox.left, hitBox.left + hitBox.width) && _isBetween(y2, hitBox.top, hitBox.top + hitBox.height)) {
 | |
|           return this.legendItems[i2];
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return null;
 | |
|   }
 | |
|   handleEvent(e2) {
 | |
|     const opts = this.options;
 | |
|     if (!isListened(e2.type, opts)) {
 | |
|       return;
 | |
|     }
 | |
|     const hoveredItem = this._getLegendItemAt(e2.x, e2.y);
 | |
|     if (e2.type === "mousemove" || e2.type === "mouseout") {
 | |
|       const previous = this._hoveredItem;
 | |
|       const sameItem = itemsEqual(previous, hoveredItem);
 | |
|       if (previous && !sameItem) {
 | |
|         callback(opts.onLeave, [
 | |
|           e2,
 | |
|           previous,
 | |
|           this
 | |
|         ], this);
 | |
|       }
 | |
|       this._hoveredItem = hoveredItem;
 | |
|       if (hoveredItem && !sameItem) {
 | |
|         callback(opts.onHover, [
 | |
|           e2,
 | |
|           hoveredItem,
 | |
|           this
 | |
|         ], this);
 | |
|       }
 | |
|     } else if (hoveredItem) {
 | |
|       callback(opts.onClick, [
 | |
|         e2,
 | |
|         hoveredItem,
 | |
|         this
 | |
|       ], this);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| function calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight) {
 | |
|   const itemWidth = calculateItemWidth(legendItem, boxWidth, labelFont, ctx);
 | |
|   const itemHeight = calculateItemHeight(_itemHeight, legendItem, labelFont.lineHeight);
 | |
|   return {
 | |
|     itemWidth,
 | |
|     itemHeight
 | |
|   };
 | |
| }
 | |
| function calculateItemWidth(legendItem, boxWidth, labelFont, ctx) {
 | |
|   let legendItemText = legendItem.text;
 | |
|   if (legendItemText && typeof legendItemText !== "string") {
 | |
|     legendItemText = legendItemText.reduce((a2, b2) => a2.length > b2.length ? a2 : b2);
 | |
|   }
 | |
|   return boxWidth + labelFont.size / 2 + ctx.measureText(legendItemText).width;
 | |
| }
 | |
| function calculateItemHeight(_itemHeight, legendItem, fontLineHeight) {
 | |
|   let itemHeight = _itemHeight;
 | |
|   if (typeof legendItem.text !== "string") {
 | |
|     itemHeight = calculateLegendItemHeight(legendItem, fontLineHeight);
 | |
|   }
 | |
|   return itemHeight;
 | |
| }
 | |
| function calculateLegendItemHeight(legendItem, fontLineHeight) {
 | |
|   const labelHeight = legendItem.text ? legendItem.text.length : 0;
 | |
|   return fontLineHeight * labelHeight;
 | |
| }
 | |
| function isListened(type, opts) {
 | |
|   if ((type === "mousemove" || type === "mouseout") && (opts.onHover || opts.onLeave)) {
 | |
|     return true;
 | |
|   }
 | |
|   if (opts.onClick && (type === "click" || type === "mouseup")) {
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| var plugin_legend = {
 | |
|   id: "legend",
 | |
|   _element: Legend,
 | |
|   start(chart, _args, options) {
 | |
|     const legend = chart.legend = new Legend({
 | |
|       ctx: chart.ctx,
 | |
|       options,
 | |
|       chart
 | |
|     });
 | |
|     layouts.configure(chart, legend, options);
 | |
|     layouts.addBox(chart, legend);
 | |
|   },
 | |
|   stop(chart) {
 | |
|     layouts.removeBox(chart, chart.legend);
 | |
|     delete chart.legend;
 | |
|   },
 | |
|   beforeUpdate(chart, _args, options) {
 | |
|     const legend = chart.legend;
 | |
|     layouts.configure(chart, legend, options);
 | |
|     legend.options = options;
 | |
|   },
 | |
|   afterUpdate(chart) {
 | |
|     const legend = chart.legend;
 | |
|     legend.buildLabels();
 | |
|     legend.adjustHitBoxes();
 | |
|   },
 | |
|   afterEvent(chart, args) {
 | |
|     if (!args.replay) {
 | |
|       chart.legend.handleEvent(args.event);
 | |
|     }
 | |
|   },
 | |
|   defaults: {
 | |
|     display: true,
 | |
|     position: "top",
 | |
|     align: "center",
 | |
|     fullSize: true,
 | |
|     reverse: false,
 | |
|     weight: 1e3,
 | |
|     onClick(e2, legendItem, legend) {
 | |
|       const index = legendItem.datasetIndex;
 | |
|       const ci = legend.chart;
 | |
|       if (ci.isDatasetVisible(index)) {
 | |
|         ci.hide(index);
 | |
|         legendItem.hidden = true;
 | |
|       } else {
 | |
|         ci.show(index);
 | |
|         legendItem.hidden = false;
 | |
|       }
 | |
|     },
 | |
|     onHover: null,
 | |
|     onLeave: null,
 | |
|     labels: {
 | |
|       color: (ctx) => ctx.chart.options.color,
 | |
|       boxWidth: 40,
 | |
|       padding: 10,
 | |
|       generateLabels(chart) {
 | |
|         const datasets = chart.data.datasets;
 | |
|         const { labels: { usePointStyle, pointStyle, textAlign, color: color2, useBorderRadius, borderRadius } } = chart.legend.options;
 | |
|         return chart._getSortedDatasetMetas().map((meta) => {
 | |
|           const style = meta.controller.getStyle(usePointStyle ? 0 : void 0);
 | |
|           const borderWidth = toPadding(style.borderWidth);
 | |
|           return {
 | |
|             text: datasets[meta.index].label,
 | |
|             fillStyle: style.backgroundColor,
 | |
|             fontColor: color2,
 | |
|             hidden: !meta.visible,
 | |
|             lineCap: style.borderCapStyle,
 | |
|             lineDash: style.borderDash,
 | |
|             lineDashOffset: style.borderDashOffset,
 | |
|             lineJoin: style.borderJoinStyle,
 | |
|             lineWidth: (borderWidth.width + borderWidth.height) / 4,
 | |
|             strokeStyle: style.borderColor,
 | |
|             pointStyle: pointStyle || style.pointStyle,
 | |
|             rotation: style.rotation,
 | |
|             textAlign: textAlign || style.textAlign,
 | |
|             borderRadius: useBorderRadius && (borderRadius || style.borderRadius),
 | |
|             datasetIndex: meta.index
 | |
|           };
 | |
|         }, this);
 | |
|       }
 | |
|     },
 | |
|     title: {
 | |
|       color: (ctx) => ctx.chart.options.color,
 | |
|       display: false,
 | |
|       position: "center",
 | |
|       text: ""
 | |
|     }
 | |
|   },
 | |
|   descriptors: {
 | |
|     _scriptable: (name) => !name.startsWith("on"),
 | |
|     labels: {
 | |
|       _scriptable: (name) => ![
 | |
|         "generateLabels",
 | |
|         "filter",
 | |
|         "sort"
 | |
|       ].includes(name)
 | |
|     }
 | |
|   }
 | |
| };
 | |
| var Title = class extends Element {
 | |
|   constructor(config) {
 | |
|     super();
 | |
|     this.chart = config.chart;
 | |
|     this.options = config.options;
 | |
|     this.ctx = config.ctx;
 | |
|     this._padding = void 0;
 | |
|     this.top = void 0;
 | |
|     this.bottom = void 0;
 | |
|     this.left = void 0;
 | |
|     this.right = void 0;
 | |
|     this.width = void 0;
 | |
|     this.height = void 0;
 | |
|     this.position = void 0;
 | |
|     this.weight = void 0;
 | |
|     this.fullSize = void 0;
 | |
|   }
 | |
|   update(maxWidth, maxHeight) {
 | |
|     const opts = this.options;
 | |
|     this.left = 0;
 | |
|     this.top = 0;
 | |
|     if (!opts.display) {
 | |
|       this.width = this.height = this.right = this.bottom = 0;
 | |
|       return;
 | |
|     }
 | |
|     this.width = this.right = maxWidth;
 | |
|     this.height = this.bottom = maxHeight;
 | |
|     const lineCount = isArray(opts.text) ? opts.text.length : 1;
 | |
|     this._padding = toPadding(opts.padding);
 | |
|     const textSize = lineCount * toFont(opts.font).lineHeight + this._padding.height;
 | |
|     if (this.isHorizontal()) {
 | |
|       this.height = textSize;
 | |
|     } else {
 | |
|       this.width = textSize;
 | |
|     }
 | |
|   }
 | |
|   isHorizontal() {
 | |
|     const pos = this.options.position;
 | |
|     return pos === "top" || pos === "bottom";
 | |
|   }
 | |
|   _drawArgs(offset) {
 | |
|     const { top, left, bottom, right, options } = this;
 | |
|     const align = options.align;
 | |
|     let rotation = 0;
 | |
|     let maxWidth, titleX, titleY;
 | |
|     if (this.isHorizontal()) {
 | |
|       titleX = _alignStartEnd(align, left, right);
 | |
|       titleY = top + offset;
 | |
|       maxWidth = right - left;
 | |
|     } else {
 | |
|       if (options.position === "left") {
 | |
|         titleX = left + offset;
 | |
|         titleY = _alignStartEnd(align, bottom, top);
 | |
|         rotation = PI * -0.5;
 | |
|       } else {
 | |
|         titleX = right - offset;
 | |
|         titleY = _alignStartEnd(align, top, bottom);
 | |
|         rotation = PI * 0.5;
 | |
|       }
 | |
|       maxWidth = bottom - top;
 | |
|     }
 | |
|     return {
 | |
|       titleX,
 | |
|       titleY,
 | |
|       maxWidth,
 | |
|       rotation
 | |
|     };
 | |
|   }
 | |
|   draw() {
 | |
|     const ctx = this.ctx;
 | |
|     const opts = this.options;
 | |
|     if (!opts.display) {
 | |
|       return;
 | |
|     }
 | |
|     const fontOpts = toFont(opts.font);
 | |
|     const lineHeight = fontOpts.lineHeight;
 | |
|     const offset = lineHeight / 2 + this._padding.top;
 | |
|     const { titleX, titleY, maxWidth, rotation } = this._drawArgs(offset);
 | |
|     renderText(ctx, opts.text, 0, 0, fontOpts, {
 | |
|       color: opts.color,
 | |
|       maxWidth,
 | |
|       rotation,
 | |
|       textAlign: _toLeftRightCenter(opts.align),
 | |
|       textBaseline: "middle",
 | |
|       translation: [
 | |
|         titleX,
 | |
|         titleY
 | |
|       ]
 | |
|     });
 | |
|   }
 | |
| };
 | |
| function createTitle(chart, titleOpts) {
 | |
|   const title = new Title({
 | |
|     ctx: chart.ctx,
 | |
|     options: titleOpts,
 | |
|     chart
 | |
|   });
 | |
|   layouts.configure(chart, title, titleOpts);
 | |
|   layouts.addBox(chart, title);
 | |
|   chart.titleBlock = title;
 | |
| }
 | |
| var plugin_title = {
 | |
|   id: "title",
 | |
|   _element: Title,
 | |
|   start(chart, _args, options) {
 | |
|     createTitle(chart, options);
 | |
|   },
 | |
|   stop(chart) {
 | |
|     const titleBlock = chart.titleBlock;
 | |
|     layouts.removeBox(chart, titleBlock);
 | |
|     delete chart.titleBlock;
 | |
|   },
 | |
|   beforeUpdate(chart, _args, options) {
 | |
|     const title = chart.titleBlock;
 | |
|     layouts.configure(chart, title, options);
 | |
|     title.options = options;
 | |
|   },
 | |
|   defaults: {
 | |
|     align: "center",
 | |
|     display: false,
 | |
|     font: {
 | |
|       weight: "bold"
 | |
|     },
 | |
|     fullSize: true,
 | |
|     padding: 10,
 | |
|     position: "top",
 | |
|     text: "",
 | |
|     weight: 2e3
 | |
|   },
 | |
|   defaultRoutes: {
 | |
|     color: "color"
 | |
|   },
 | |
|   descriptors: {
 | |
|     _scriptable: true,
 | |
|     _indexable: false
 | |
|   }
 | |
| };
 | |
| var map2 = /* @__PURE__ */ new WeakMap();
 | |
| var plugin_subtitle = {
 | |
|   id: "subtitle",
 | |
|   start(chart, _args, options) {
 | |
|     const title = new Title({
 | |
|       ctx: chart.ctx,
 | |
|       options,
 | |
|       chart
 | |
|     });
 | |
|     layouts.configure(chart, title, options);
 | |
|     layouts.addBox(chart, title);
 | |
|     map2.set(chart, title);
 | |
|   },
 | |
|   stop(chart) {
 | |
|     layouts.removeBox(chart, map2.get(chart));
 | |
|     map2.delete(chart);
 | |
|   },
 | |
|   beforeUpdate(chart, _args, options) {
 | |
|     const title = map2.get(chart);
 | |
|     layouts.configure(chart, title, options);
 | |
|     title.options = options;
 | |
|   },
 | |
|   defaults: {
 | |
|     align: "center",
 | |
|     display: false,
 | |
|     font: {
 | |
|       weight: "normal"
 | |
|     },
 | |
|     fullSize: true,
 | |
|     padding: 0,
 | |
|     position: "top",
 | |
|     text: "",
 | |
|     weight: 1500
 | |
|   },
 | |
|   defaultRoutes: {
 | |
|     color: "color"
 | |
|   },
 | |
|   descriptors: {
 | |
|     _scriptable: true,
 | |
|     _indexable: false
 | |
|   }
 | |
| };
 | |
| var positioners = {
 | |
|   average(items) {
 | |
|     if (!items.length) {
 | |
|       return false;
 | |
|     }
 | |
|     let i2, len;
 | |
|     let xSet = /* @__PURE__ */ new Set();
 | |
|     let y2 = 0;
 | |
|     let count = 0;
 | |
|     for (i2 = 0, len = items.length; i2 < len; ++i2) {
 | |
|       const el = items[i2].element;
 | |
|       if (el && el.hasValue()) {
 | |
|         const pos = el.tooltipPosition();
 | |
|         xSet.add(pos.x);
 | |
|         y2 += pos.y;
 | |
|         ++count;
 | |
|       }
 | |
|     }
 | |
|     if (count === 0 || xSet.size === 0) {
 | |
|       return false;
 | |
|     }
 | |
|     const xAverage = [
 | |
|       ...xSet
 | |
|     ].reduce((a2, b2) => a2 + b2) / xSet.size;
 | |
|     return {
 | |
|       x: xAverage,
 | |
|       y: y2 / count
 | |
|     };
 | |
|   },
 | |
|   nearest(items, eventPosition) {
 | |
|     if (!items.length) {
 | |
|       return false;
 | |
|     }
 | |
|     let x2 = eventPosition.x;
 | |
|     let y2 = eventPosition.y;
 | |
|     let minDistance = Number.POSITIVE_INFINITY;
 | |
|     let i2, len, nearestElement;
 | |
|     for (i2 = 0, len = items.length; i2 < len; ++i2) {
 | |
|       const el = items[i2].element;
 | |
|       if (el && el.hasValue()) {
 | |
|         const center = el.getCenterPoint();
 | |
|         const d2 = distanceBetweenPoints(eventPosition, center);
 | |
|         if (d2 < minDistance) {
 | |
|           minDistance = d2;
 | |
|           nearestElement = el;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if (nearestElement) {
 | |
|       const tp = nearestElement.tooltipPosition();
 | |
|       x2 = tp.x;
 | |
|       y2 = tp.y;
 | |
|     }
 | |
|     return {
 | |
|       x: x2,
 | |
|       y: y2
 | |
|     };
 | |
|   }
 | |
| };
 | |
| function pushOrConcat(base, toPush) {
 | |
|   if (toPush) {
 | |
|     if (isArray(toPush)) {
 | |
|       Array.prototype.push.apply(base, toPush);
 | |
|     } else {
 | |
|       base.push(toPush);
 | |
|     }
 | |
|   }
 | |
|   return base;
 | |
| }
 | |
| function splitNewlines(str) {
 | |
|   if ((typeof str === "string" || str instanceof String) && str.indexOf("\n") > -1) {
 | |
|     return str.split("\n");
 | |
|   }
 | |
|   return str;
 | |
| }
 | |
| function createTooltipItem(chart, item) {
 | |
|   const { element, datasetIndex, index } = item;
 | |
|   const controller = chart.getDatasetMeta(datasetIndex).controller;
 | |
|   const { label, value } = controller.getLabelAndValue(index);
 | |
|   return {
 | |
|     chart,
 | |
|     label,
 | |
|     parsed: controller.getParsed(index),
 | |
|     raw: chart.data.datasets[datasetIndex].data[index],
 | |
|     formattedValue: value,
 | |
|     dataset: controller.getDataset(),
 | |
|     dataIndex: index,
 | |
|     datasetIndex,
 | |
|     element
 | |
|   };
 | |
| }
 | |
| function getTooltipSize(tooltip, options) {
 | |
|   const ctx = tooltip.chart.ctx;
 | |
|   const { body, footer, title } = tooltip;
 | |
|   const { boxWidth, boxHeight } = options;
 | |
|   const bodyFont = toFont(options.bodyFont);
 | |
|   const titleFont = toFont(options.titleFont);
 | |
|   const footerFont = toFont(options.footerFont);
 | |
|   const titleLineCount = title.length;
 | |
|   const footerLineCount = footer.length;
 | |
|   const bodyLineItemCount = body.length;
 | |
|   const padding = toPadding(options.padding);
 | |
|   let height = padding.height;
 | |
|   let width = 0;
 | |
|   let combinedBodyLength = body.reduce((count, bodyItem) => count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0);
 | |
|   combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;
 | |
|   if (titleLineCount) {
 | |
|     height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom;
 | |
|   }
 | |
|   if (combinedBodyLength) {
 | |
|     const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;
 | |
|     height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing;
 | |
|   }
 | |
|   if (footerLineCount) {
 | |
|     height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing;
 | |
|   }
 | |
|   let widthPadding = 0;
 | |
|   const maxLineWidth = function(line) {
 | |
|     width = Math.max(width, ctx.measureText(line).width + widthPadding);
 | |
|   };
 | |
|   ctx.save();
 | |
|   ctx.font = titleFont.string;
 | |
|   each(tooltip.title, maxLineWidth);
 | |
|   ctx.font = bodyFont.string;
 | |
|   each(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);
 | |
|   widthPadding = options.displayColors ? boxWidth + 2 + options.boxPadding : 0;
 | |
|   each(body, (bodyItem) => {
 | |
|     each(bodyItem.before, maxLineWidth);
 | |
|     each(bodyItem.lines, maxLineWidth);
 | |
|     each(bodyItem.after, maxLineWidth);
 | |
|   });
 | |
|   widthPadding = 0;
 | |
|   ctx.font = footerFont.string;
 | |
|   each(tooltip.footer, maxLineWidth);
 | |
|   ctx.restore();
 | |
|   width += padding.width;
 | |
|   return {
 | |
|     width,
 | |
|     height
 | |
|   };
 | |
| }
 | |
| function determineYAlign(chart, size) {
 | |
|   const { y: y2, height } = size;
 | |
|   if (y2 < height / 2) {
 | |
|     return "top";
 | |
|   } else if (y2 > chart.height - height / 2) {
 | |
|     return "bottom";
 | |
|   }
 | |
|   return "center";
 | |
| }
 | |
| function doesNotFitWithAlign(xAlign, chart, options, size) {
 | |
|   const { x: x2, width } = size;
 | |
|   const caret = options.caretSize + options.caretPadding;
 | |
|   if (xAlign === "left" && x2 + width + caret > chart.width) {
 | |
|     return true;
 | |
|   }
 | |
|   if (xAlign === "right" && x2 - width - caret < 0) {
 | |
|     return true;
 | |
|   }
 | |
| }
 | |
| function determineXAlign(chart, options, size, yAlign) {
 | |
|   const { x: x2, width } = size;
 | |
|   const { width: chartWidth, chartArea: { left, right } } = chart;
 | |
|   let xAlign = "center";
 | |
|   if (yAlign === "center") {
 | |
|     xAlign = x2 <= (left + right) / 2 ? "left" : "right";
 | |
|   } else if (x2 <= width / 2) {
 | |
|     xAlign = "left";
 | |
|   } else if (x2 >= chartWidth - width / 2) {
 | |
|     xAlign = "right";
 | |
|   }
 | |
|   if (doesNotFitWithAlign(xAlign, chart, options, size)) {
 | |
|     xAlign = "center";
 | |
|   }
 | |
|   return xAlign;
 | |
| }
 | |
| function determineAlignment(chart, options, size) {
 | |
|   const yAlign = size.yAlign || options.yAlign || determineYAlign(chart, size);
 | |
|   return {
 | |
|     xAlign: size.xAlign || options.xAlign || determineXAlign(chart, options, size, yAlign),
 | |
|     yAlign
 | |
|   };
 | |
| }
 | |
| function alignX(size, xAlign) {
 | |
|   let { x: x2, width } = size;
 | |
|   if (xAlign === "right") {
 | |
|     x2 -= width;
 | |
|   } else if (xAlign === "center") {
 | |
|     x2 -= width / 2;
 | |
|   }
 | |
|   return x2;
 | |
| }
 | |
| function alignY(size, yAlign, paddingAndSize) {
 | |
|   let { y: y2, height } = size;
 | |
|   if (yAlign === "top") {
 | |
|     y2 += paddingAndSize;
 | |
|   } else if (yAlign === "bottom") {
 | |
|     y2 -= height + paddingAndSize;
 | |
|   } else {
 | |
|     y2 -= height / 2;
 | |
|   }
 | |
|   return y2;
 | |
| }
 | |
| function getBackgroundPoint(options, size, alignment, chart) {
 | |
|   const { caretSize, caretPadding, cornerRadius } = options;
 | |
|   const { xAlign, yAlign } = alignment;
 | |
|   const paddingAndSize = caretSize + caretPadding;
 | |
|   const { topLeft, topRight, bottomLeft, bottomRight } = toTRBLCorners(cornerRadius);
 | |
|   let x2 = alignX(size, xAlign);
 | |
|   const y2 = alignY(size, yAlign, paddingAndSize);
 | |
|   if (yAlign === "center") {
 | |
|     if (xAlign === "left") {
 | |
|       x2 += paddingAndSize;
 | |
|     } else if (xAlign === "right") {
 | |
|       x2 -= paddingAndSize;
 | |
|     }
 | |
|   } else if (xAlign === "left") {
 | |
|     x2 -= Math.max(topLeft, bottomLeft) + caretSize;
 | |
|   } else if (xAlign === "right") {
 | |
|     x2 += Math.max(topRight, bottomRight) + caretSize;
 | |
|   }
 | |
|   return {
 | |
|     x: _limitValue(x2, 0, chart.width - size.width),
 | |
|     y: _limitValue(y2, 0, chart.height - size.height)
 | |
|   };
 | |
| }
 | |
| function getAlignedX(tooltip, align, options) {
 | |
|   const padding = toPadding(options.padding);
 | |
|   return align === "center" ? tooltip.x + tooltip.width / 2 : align === "right" ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left;
 | |
| }
 | |
| function getBeforeAfterBodyLines(callback2) {
 | |
|   return pushOrConcat([], splitNewlines(callback2));
 | |
| }
 | |
| function createTooltipContext(parent, tooltip, tooltipItems) {
 | |
|   return createContext(parent, {
 | |
|     tooltip,
 | |
|     tooltipItems,
 | |
|     type: "tooltip"
 | |
|   });
 | |
| }
 | |
| function overrideCallbacks(callbacks, context) {
 | |
|   const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks;
 | |
|   return override ? callbacks.override(override) : callbacks;
 | |
| }
 | |
| var defaultCallbacks = {
 | |
|   beforeTitle: noop,
 | |
|   title(tooltipItems) {
 | |
|     if (tooltipItems.length > 0) {
 | |
|       const item = tooltipItems[0];
 | |
|       const labels = item.chart.data.labels;
 | |
|       const labelCount = labels ? labels.length : 0;
 | |
|       if (this && this.options && this.options.mode === "dataset") {
 | |
|         return item.dataset.label || "";
 | |
|       } else if (item.label) {
 | |
|         return item.label;
 | |
|       } else if (labelCount > 0 && item.dataIndex < labelCount) {
 | |
|         return labels[item.dataIndex];
 | |
|       }
 | |
|     }
 | |
|     return "";
 | |
|   },
 | |
|   afterTitle: noop,
 | |
|   beforeBody: noop,
 | |
|   beforeLabel: noop,
 | |
|   label(tooltipItem) {
 | |
|     if (this && this.options && this.options.mode === "dataset") {
 | |
|       return tooltipItem.label + ": " + tooltipItem.formattedValue || tooltipItem.formattedValue;
 | |
|     }
 | |
|     let label = tooltipItem.dataset.label || "";
 | |
|     if (label) {
 | |
|       label += ": ";
 | |
|     }
 | |
|     const value = tooltipItem.formattedValue;
 | |
|     if (!isNullOrUndef(value)) {
 | |
|       label += value;
 | |
|     }
 | |
|     return label;
 | |
|   },
 | |
|   labelColor(tooltipItem) {
 | |
|     const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
 | |
|     const options = meta.controller.getStyle(tooltipItem.dataIndex);
 | |
|     return {
 | |
|       borderColor: options.borderColor,
 | |
|       backgroundColor: options.backgroundColor,
 | |
|       borderWidth: options.borderWidth,
 | |
|       borderDash: options.borderDash,
 | |
|       borderDashOffset: options.borderDashOffset,
 | |
|       borderRadius: 0
 | |
|     };
 | |
|   },
 | |
|   labelTextColor() {
 | |
|     return this.options.bodyColor;
 | |
|   },
 | |
|   labelPointStyle(tooltipItem) {
 | |
|     const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
 | |
|     const options = meta.controller.getStyle(tooltipItem.dataIndex);
 | |
|     return {
 | |
|       pointStyle: options.pointStyle,
 | |
|       rotation: options.rotation
 | |
|     };
 | |
|   },
 | |
|   afterLabel: noop,
 | |
|   afterBody: noop,
 | |
|   beforeFooter: noop,
 | |
|   footer: noop,
 | |
|   afterFooter: noop
 | |
| };
 | |
| function invokeCallbackWithFallback(callbacks, name, ctx, arg) {
 | |
|   const result = callbacks[name].call(ctx, arg);
 | |
|   if (typeof result === "undefined") {
 | |
|     return defaultCallbacks[name].call(ctx, arg);
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| var Tooltip = class extends Element {
 | |
|   constructor(config) {
 | |
|     super();
 | |
|     this.opacity = 0;
 | |
|     this._active = [];
 | |
|     this._eventPosition = void 0;
 | |
|     this._size = void 0;
 | |
|     this._cachedAnimations = void 0;
 | |
|     this._tooltipItems = [];
 | |
|     this.$animations = void 0;
 | |
|     this.$context = void 0;
 | |
|     this.chart = config.chart;
 | |
|     this.options = config.options;
 | |
|     this.dataPoints = void 0;
 | |
|     this.title = void 0;
 | |
|     this.beforeBody = void 0;
 | |
|     this.body = void 0;
 | |
|     this.afterBody = void 0;
 | |
|     this.footer = void 0;
 | |
|     this.xAlign = void 0;
 | |
|     this.yAlign = void 0;
 | |
|     this.x = void 0;
 | |
|     this.y = void 0;
 | |
|     this.height = void 0;
 | |
|     this.width = void 0;
 | |
|     this.caretX = void 0;
 | |
|     this.caretY = void 0;
 | |
|     this.labelColors = void 0;
 | |
|     this.labelPointStyles = void 0;
 | |
|     this.labelTextColors = void 0;
 | |
|   }
 | |
|   initialize(options) {
 | |
|     this.options = options;
 | |
|     this._cachedAnimations = void 0;
 | |
|     this.$context = void 0;
 | |
|   }
 | |
|   _resolveAnimations() {
 | |
|     const cached = this._cachedAnimations;
 | |
|     if (cached) {
 | |
|       return cached;
 | |
|     }
 | |
|     const chart = this.chart;
 | |
|     const options = this.options.setContext(this.getContext());
 | |
|     const opts = options.enabled && chart.options.animation && options.animations;
 | |
|     const animations = new Animations(this.chart, opts);
 | |
|     if (opts._cacheable) {
 | |
|       this._cachedAnimations = Object.freeze(animations);
 | |
|     }
 | |
|     return animations;
 | |
|   }
 | |
|   getContext() {
 | |
|     return this.$context || (this.$context = createTooltipContext(this.chart.getContext(), this, this._tooltipItems));
 | |
|   }
 | |
|   getTitle(context, options) {
 | |
|     const { callbacks } = options;
 | |
|     const beforeTitle = invokeCallbackWithFallback(callbacks, "beforeTitle", this, context);
 | |
|     const title = invokeCallbackWithFallback(callbacks, "title", this, context);
 | |
|     const afterTitle = invokeCallbackWithFallback(callbacks, "afterTitle", this, context);
 | |
|     let lines = [];
 | |
|     lines = pushOrConcat(lines, splitNewlines(beforeTitle));
 | |
|     lines = pushOrConcat(lines, splitNewlines(title));
 | |
|     lines = pushOrConcat(lines, splitNewlines(afterTitle));
 | |
|     return lines;
 | |
|   }
 | |
|   getBeforeBody(tooltipItems, options) {
 | |
|     return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, "beforeBody", this, tooltipItems));
 | |
|   }
 | |
|   getBody(tooltipItems, options) {
 | |
|     const { callbacks } = options;
 | |
|     const bodyItems = [];
 | |
|     each(tooltipItems, (context) => {
 | |
|       const bodyItem = {
 | |
|         before: [],
 | |
|         lines: [],
 | |
|         after: []
 | |
|       };
 | |
|       const scoped = overrideCallbacks(callbacks, context);
 | |
|       pushOrConcat(bodyItem.before, splitNewlines(invokeCallbackWithFallback(scoped, "beforeLabel", this, context)));
 | |
|       pushOrConcat(bodyItem.lines, invokeCallbackWithFallback(scoped, "label", this, context));
 | |
|       pushOrConcat(bodyItem.after, splitNewlines(invokeCallbackWithFallback(scoped, "afterLabel", this, context)));
 | |
|       bodyItems.push(bodyItem);
 | |
|     });
 | |
|     return bodyItems;
 | |
|   }
 | |
|   getAfterBody(tooltipItems, options) {
 | |
|     return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, "afterBody", this, tooltipItems));
 | |
|   }
 | |
|   getFooter(tooltipItems, options) {
 | |
|     const { callbacks } = options;
 | |
|     const beforeFooter = invokeCallbackWithFallback(callbacks, "beforeFooter", this, tooltipItems);
 | |
|     const footer = invokeCallbackWithFallback(callbacks, "footer", this, tooltipItems);
 | |
|     const afterFooter = invokeCallbackWithFallback(callbacks, "afterFooter", this, tooltipItems);
 | |
|     let lines = [];
 | |
|     lines = pushOrConcat(lines, splitNewlines(beforeFooter));
 | |
|     lines = pushOrConcat(lines, splitNewlines(footer));
 | |
|     lines = pushOrConcat(lines, splitNewlines(afterFooter));
 | |
|     return lines;
 | |
|   }
 | |
|   _createItems(options) {
 | |
|     const active = this._active;
 | |
|     const data = this.chart.data;
 | |
|     const labelColors = [];
 | |
|     const labelPointStyles = [];
 | |
|     const labelTextColors = [];
 | |
|     let tooltipItems = [];
 | |
|     let i2, len;
 | |
|     for (i2 = 0, len = active.length; i2 < len; ++i2) {
 | |
|       tooltipItems.push(createTooltipItem(this.chart, active[i2]));
 | |
|     }
 | |
|     if (options.filter) {
 | |
|       tooltipItems = tooltipItems.filter((element, index, array) => options.filter(element, index, array, data));
 | |
|     }
 | |
|     if (options.itemSort) {
 | |
|       tooltipItems = tooltipItems.sort((a2, b2) => options.itemSort(a2, b2, data));
 | |
|     }
 | |
|     each(tooltipItems, (context) => {
 | |
|       const scoped = overrideCallbacks(options.callbacks, context);
 | |
|       labelColors.push(invokeCallbackWithFallback(scoped, "labelColor", this, context));
 | |
|       labelPointStyles.push(invokeCallbackWithFallback(scoped, "labelPointStyle", this, context));
 | |
|       labelTextColors.push(invokeCallbackWithFallback(scoped, "labelTextColor", this, context));
 | |
|     });
 | |
|     this.labelColors = labelColors;
 | |
|     this.labelPointStyles = labelPointStyles;
 | |
|     this.labelTextColors = labelTextColors;
 | |
|     this.dataPoints = tooltipItems;
 | |
|     return tooltipItems;
 | |
|   }
 | |
|   update(changed, replay) {
 | |
|     const options = this.options.setContext(this.getContext());
 | |
|     const active = this._active;
 | |
|     let properties;
 | |
|     let tooltipItems = [];
 | |
|     if (!active.length) {
 | |
|       if (this.opacity !== 0) {
 | |
|         properties = {
 | |
|           opacity: 0
 | |
|         };
 | |
|       }
 | |
|     } else {
 | |
|       const position = positioners[options.position].call(this, active, this._eventPosition);
 | |
|       tooltipItems = this._createItems(options);
 | |
|       this.title = this.getTitle(tooltipItems, options);
 | |
|       this.beforeBody = this.getBeforeBody(tooltipItems, options);
 | |
|       this.body = this.getBody(tooltipItems, options);
 | |
|       this.afterBody = this.getAfterBody(tooltipItems, options);
 | |
|       this.footer = this.getFooter(tooltipItems, options);
 | |
|       const size = this._size = getTooltipSize(this, options);
 | |
|       const positionAndSize = Object.assign({}, position, size);
 | |
|       const alignment = determineAlignment(this.chart, options, positionAndSize);
 | |
|       const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this.chart);
 | |
|       this.xAlign = alignment.xAlign;
 | |
|       this.yAlign = alignment.yAlign;
 | |
|       properties = {
 | |
|         opacity: 1,
 | |
|         x: backgroundPoint.x,
 | |
|         y: backgroundPoint.y,
 | |
|         width: size.width,
 | |
|         height: size.height,
 | |
|         caretX: position.x,
 | |
|         caretY: position.y
 | |
|       };
 | |
|     }
 | |
|     this._tooltipItems = tooltipItems;
 | |
|     this.$context = void 0;
 | |
|     if (properties) {
 | |
|       this._resolveAnimations().update(this, properties);
 | |
|     }
 | |
|     if (changed && options.external) {
 | |
|       options.external.call(this, {
 | |
|         chart: this.chart,
 | |
|         tooltip: this,
 | |
|         replay
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   drawCaret(tooltipPoint, ctx, size, options) {
 | |
|     const caretPosition = this.getCaretPosition(tooltipPoint, size, options);
 | |
|     ctx.lineTo(caretPosition.x1, caretPosition.y1);
 | |
|     ctx.lineTo(caretPosition.x2, caretPosition.y2);
 | |
|     ctx.lineTo(caretPosition.x3, caretPosition.y3);
 | |
|   }
 | |
|   getCaretPosition(tooltipPoint, size, options) {
 | |
|     const { xAlign, yAlign } = this;
 | |
|     const { caretSize, cornerRadius } = options;
 | |
|     const { topLeft, topRight, bottomLeft, bottomRight } = toTRBLCorners(cornerRadius);
 | |
|     const { x: ptX, y: ptY } = tooltipPoint;
 | |
|     const { width, height } = size;
 | |
|     let x1, x2, x3, y1, y2, y3;
 | |
|     if (yAlign === "center") {
 | |
|       y2 = ptY + height / 2;
 | |
|       if (xAlign === "left") {
 | |
|         x1 = ptX;
 | |
|         x2 = x1 - caretSize;
 | |
|         y1 = y2 + caretSize;
 | |
|         y3 = y2 - caretSize;
 | |
|       } else {
 | |
|         x1 = ptX + width;
 | |
|         x2 = x1 + caretSize;
 | |
|         y1 = y2 - caretSize;
 | |
|         y3 = y2 + caretSize;
 | |
|       }
 | |
|       x3 = x1;
 | |
|     } else {
 | |
|       if (xAlign === "left") {
 | |
|         x2 = ptX + Math.max(topLeft, bottomLeft) + caretSize;
 | |
|       } else if (xAlign === "right") {
 | |
|         x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;
 | |
|       } else {
 | |
|         x2 = this.caretX;
 | |
|       }
 | |
|       if (yAlign === "top") {
 | |
|         y1 = ptY;
 | |
|         y2 = y1 - caretSize;
 | |
|         x1 = x2 - caretSize;
 | |
|         x3 = x2 + caretSize;
 | |
|       } else {
 | |
|         y1 = ptY + height;
 | |
|         y2 = y1 + caretSize;
 | |
|         x1 = x2 + caretSize;
 | |
|         x3 = x2 - caretSize;
 | |
|       }
 | |
|       y3 = y1;
 | |
|     }
 | |
|     return {
 | |
|       x1,
 | |
|       x2,
 | |
|       x3,
 | |
|       y1,
 | |
|       y2,
 | |
|       y3
 | |
|     };
 | |
|   }
 | |
|   drawTitle(pt2, ctx, options) {
 | |
|     const title = this.title;
 | |
|     const length = title.length;
 | |
|     let titleFont, titleSpacing, i2;
 | |
|     if (length) {
 | |
|       const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
 | |
|       pt2.x = getAlignedX(this, options.titleAlign, options);
 | |
|       ctx.textAlign = rtlHelper.textAlign(options.titleAlign);
 | |
|       ctx.textBaseline = "middle";
 | |
|       titleFont = toFont(options.titleFont);
 | |
|       titleSpacing = options.titleSpacing;
 | |
|       ctx.fillStyle = options.titleColor;
 | |
|       ctx.font = titleFont.string;
 | |
|       for (i2 = 0; i2 < length; ++i2) {
 | |
|         ctx.fillText(title[i2], rtlHelper.x(pt2.x), pt2.y + titleFont.lineHeight / 2);
 | |
|         pt2.y += titleFont.lineHeight + titleSpacing;
 | |
|         if (i2 + 1 === length) {
 | |
|           pt2.y += options.titleMarginBottom - titleSpacing;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   _drawColorBox(ctx, pt2, i2, rtlHelper, options) {
 | |
|     const labelColor = this.labelColors[i2];
 | |
|     const labelPointStyle = this.labelPointStyles[i2];
 | |
|     const { boxHeight, boxWidth } = options;
 | |
|     const bodyFont = toFont(options.bodyFont);
 | |
|     const colorX = getAlignedX(this, "left", options);
 | |
|     const rtlColorX = rtlHelper.x(colorX);
 | |
|     const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;
 | |
|     const colorY = pt2.y + yOffSet;
 | |
|     if (options.usePointStyle) {
 | |
|       const drawOptions = {
 | |
|         radius: Math.min(boxWidth, boxHeight) / 2,
 | |
|         pointStyle: labelPointStyle.pointStyle,
 | |
|         rotation: labelPointStyle.rotation,
 | |
|         borderWidth: 1
 | |
|       };
 | |
|       const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2;
 | |
|       const centerY = colorY + boxHeight / 2;
 | |
|       ctx.strokeStyle = options.multiKeyBackground;
 | |
|       ctx.fillStyle = options.multiKeyBackground;
 | |
|       drawPoint(ctx, drawOptions, centerX, centerY);
 | |
|       ctx.strokeStyle = labelColor.borderColor;
 | |
|       ctx.fillStyle = labelColor.backgroundColor;
 | |
|       drawPoint(ctx, drawOptions, centerX, centerY);
 | |
|     } else {
 | |
|       ctx.lineWidth = isObject(labelColor.borderWidth) ? Math.max(...Object.values(labelColor.borderWidth)) : labelColor.borderWidth || 1;
 | |
|       ctx.strokeStyle = labelColor.borderColor;
 | |
|       ctx.setLineDash(labelColor.borderDash || []);
 | |
|       ctx.lineDashOffset = labelColor.borderDashOffset || 0;
 | |
|       const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth);
 | |
|       const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2);
 | |
|       const borderRadius = toTRBLCorners(labelColor.borderRadius);
 | |
|       if (Object.values(borderRadius).some((v2) => v2 !== 0)) {
 | |
|         ctx.beginPath();
 | |
|         ctx.fillStyle = options.multiKeyBackground;
 | |
|         addRoundedRectPath(ctx, {
 | |
|           x: outerX,
 | |
|           y: colorY,
 | |
|           w: boxWidth,
 | |
|           h: boxHeight,
 | |
|           radius: borderRadius
 | |
|         });
 | |
|         ctx.fill();
 | |
|         ctx.stroke();
 | |
|         ctx.fillStyle = labelColor.backgroundColor;
 | |
|         ctx.beginPath();
 | |
|         addRoundedRectPath(ctx, {
 | |
|           x: innerX,
 | |
|           y: colorY + 1,
 | |
|           w: boxWidth - 2,
 | |
|           h: boxHeight - 2,
 | |
|           radius: borderRadius
 | |
|         });
 | |
|         ctx.fill();
 | |
|       } else {
 | |
|         ctx.fillStyle = options.multiKeyBackground;
 | |
|         ctx.fillRect(outerX, colorY, boxWidth, boxHeight);
 | |
|         ctx.strokeRect(outerX, colorY, boxWidth, boxHeight);
 | |
|         ctx.fillStyle = labelColor.backgroundColor;
 | |
|         ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2);
 | |
|       }
 | |
|     }
 | |
|     ctx.fillStyle = this.labelTextColors[i2];
 | |
|   }
 | |
|   drawBody(pt2, ctx, options) {
 | |
|     const { body } = this;
 | |
|     const { bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth, boxPadding } = options;
 | |
|     const bodyFont = toFont(options.bodyFont);
 | |
|     let bodyLineHeight = bodyFont.lineHeight;
 | |
|     let xLinePadding = 0;
 | |
|     const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
 | |
|     const fillLineOfText = function(line) {
 | |
|       ctx.fillText(line, rtlHelper.x(pt2.x + xLinePadding), pt2.y + bodyLineHeight / 2);
 | |
|       pt2.y += bodyLineHeight + bodySpacing;
 | |
|     };
 | |
|     const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign);
 | |
|     let bodyItem, textColor, lines, i2, j2, ilen, jlen;
 | |
|     ctx.textAlign = bodyAlign;
 | |
|     ctx.textBaseline = "middle";
 | |
|     ctx.font = bodyFont.string;
 | |
|     pt2.x = getAlignedX(this, bodyAlignForCalculation, options);
 | |
|     ctx.fillStyle = options.bodyColor;
 | |
|     each(this.beforeBody, fillLineOfText);
 | |
|     xLinePadding = displayColors && bodyAlignForCalculation !== "right" ? bodyAlign === "center" ? boxWidth / 2 + boxPadding : boxWidth + 2 + boxPadding : 0;
 | |
|     for (i2 = 0, ilen = body.length; i2 < ilen; ++i2) {
 | |
|       bodyItem = body[i2];
 | |
|       textColor = this.labelTextColors[i2];
 | |
|       ctx.fillStyle = textColor;
 | |
|       each(bodyItem.before, fillLineOfText);
 | |
|       lines = bodyItem.lines;
 | |
|       if (displayColors && lines.length) {
 | |
|         this._drawColorBox(ctx, pt2, i2, rtlHelper, options);
 | |
|         bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);
 | |
|       }
 | |
|       for (j2 = 0, jlen = lines.length; j2 < jlen; ++j2) {
 | |
|         fillLineOfText(lines[j2]);
 | |
|         bodyLineHeight = bodyFont.lineHeight;
 | |
|       }
 | |
|       each(bodyItem.after, fillLineOfText);
 | |
|     }
 | |
|     xLinePadding = 0;
 | |
|     bodyLineHeight = bodyFont.lineHeight;
 | |
|     each(this.afterBody, fillLineOfText);
 | |
|     pt2.y -= bodySpacing;
 | |
|   }
 | |
|   drawFooter(pt2, ctx, options) {
 | |
|     const footer = this.footer;
 | |
|     const length = footer.length;
 | |
|     let footerFont, i2;
 | |
|     if (length) {
 | |
|       const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
 | |
|       pt2.x = getAlignedX(this, options.footerAlign, options);
 | |
|       pt2.y += options.footerMarginTop;
 | |
|       ctx.textAlign = rtlHelper.textAlign(options.footerAlign);
 | |
|       ctx.textBaseline = "middle";
 | |
|       footerFont = toFont(options.footerFont);
 | |
|       ctx.fillStyle = options.footerColor;
 | |
|       ctx.font = footerFont.string;
 | |
|       for (i2 = 0; i2 < length; ++i2) {
 | |
|         ctx.fillText(footer[i2], rtlHelper.x(pt2.x), pt2.y + footerFont.lineHeight / 2);
 | |
|         pt2.y += footerFont.lineHeight + options.footerSpacing;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   drawBackground(pt2, ctx, tooltipSize, options) {
 | |
|     const { xAlign, yAlign } = this;
 | |
|     const { x: x2, y: y2 } = pt2;
 | |
|     const { width, height } = tooltipSize;
 | |
|     const { topLeft, topRight, bottomLeft, bottomRight } = toTRBLCorners(options.cornerRadius);
 | |
|     ctx.fillStyle = options.backgroundColor;
 | |
|     ctx.strokeStyle = options.borderColor;
 | |
|     ctx.lineWidth = options.borderWidth;
 | |
|     ctx.beginPath();
 | |
|     ctx.moveTo(x2 + topLeft, y2);
 | |
|     if (yAlign === "top") {
 | |
|       this.drawCaret(pt2, ctx, tooltipSize, options);
 | |
|     }
 | |
|     ctx.lineTo(x2 + width - topRight, y2);
 | |
|     ctx.quadraticCurveTo(x2 + width, y2, x2 + width, y2 + topRight);
 | |
|     if (yAlign === "center" && xAlign === "right") {
 | |
|       this.drawCaret(pt2, ctx, tooltipSize, options);
 | |
|     }
 | |
|     ctx.lineTo(x2 + width, y2 + height - bottomRight);
 | |
|     ctx.quadraticCurveTo(x2 + width, y2 + height, x2 + width - bottomRight, y2 + height);
 | |
|     if (yAlign === "bottom") {
 | |
|       this.drawCaret(pt2, ctx, tooltipSize, options);
 | |
|     }
 | |
|     ctx.lineTo(x2 + bottomLeft, y2 + height);
 | |
|     ctx.quadraticCurveTo(x2, y2 + height, x2, y2 + height - bottomLeft);
 | |
|     if (yAlign === "center" && xAlign === "left") {
 | |
|       this.drawCaret(pt2, ctx, tooltipSize, options);
 | |
|     }
 | |
|     ctx.lineTo(x2, y2 + topLeft);
 | |
|     ctx.quadraticCurveTo(x2, y2, x2 + topLeft, y2);
 | |
|     ctx.closePath();
 | |
|     ctx.fill();
 | |
|     if (options.borderWidth > 0) {
 | |
|       ctx.stroke();
 | |
|     }
 | |
|   }
 | |
|   _updateAnimationTarget(options) {
 | |
|     const chart = this.chart;
 | |
|     const anims = this.$animations;
 | |
|     const animX = anims && anims.x;
 | |
|     const animY = anims && anims.y;
 | |
|     if (animX || animY) {
 | |
|       const position = positioners[options.position].call(this, this._active, this._eventPosition);
 | |
|       if (!position) {
 | |
|         return;
 | |
|       }
 | |
|       const size = this._size = getTooltipSize(this, options);
 | |
|       const positionAndSize = Object.assign({}, position, this._size);
 | |
|       const alignment = determineAlignment(chart, options, positionAndSize);
 | |
|       const point = getBackgroundPoint(options, positionAndSize, alignment, chart);
 | |
|       if (animX._to !== point.x || animY._to !== point.y) {
 | |
|         this.xAlign = alignment.xAlign;
 | |
|         this.yAlign = alignment.yAlign;
 | |
|         this.width = size.width;
 | |
|         this.height = size.height;
 | |
|         this.caretX = position.x;
 | |
|         this.caretY = position.y;
 | |
|         this._resolveAnimations().update(this, point);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   _willRender() {
 | |
|     return !!this.opacity;
 | |
|   }
 | |
|   draw(ctx) {
 | |
|     const options = this.options.setContext(this.getContext());
 | |
|     let opacity = this.opacity;
 | |
|     if (!opacity) {
 | |
|       return;
 | |
|     }
 | |
|     this._updateAnimationTarget(options);
 | |
|     const tooltipSize = {
 | |
|       width: this.width,
 | |
|       height: this.height
 | |
|     };
 | |
|     const pt2 = {
 | |
|       x: this.x,
 | |
|       y: this.y
 | |
|     };
 | |
|     opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity;
 | |
|     const padding = toPadding(options.padding);
 | |
|     const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;
 | |
|     if (options.enabled && hasTooltipContent) {
 | |
|       ctx.save();
 | |
|       ctx.globalAlpha = opacity;
 | |
|       this.drawBackground(pt2, ctx, tooltipSize, options);
 | |
|       overrideTextDirection(ctx, options.textDirection);
 | |
|       pt2.y += padding.top;
 | |
|       this.drawTitle(pt2, ctx, options);
 | |
|       this.drawBody(pt2, ctx, options);
 | |
|       this.drawFooter(pt2, ctx, options);
 | |
|       restoreTextDirection(ctx, options.textDirection);
 | |
|       ctx.restore();
 | |
|     }
 | |
|   }
 | |
|   getActiveElements() {
 | |
|     return this._active || [];
 | |
|   }
 | |
|   setActiveElements(activeElements, eventPosition) {
 | |
|     const lastActive = this._active;
 | |
|     const active = activeElements.map(({ datasetIndex, index }) => {
 | |
|       const meta = this.chart.getDatasetMeta(datasetIndex);
 | |
|       if (!meta) {
 | |
|         throw new Error("Cannot find a dataset at index " + datasetIndex);
 | |
|       }
 | |
|       return {
 | |
|         datasetIndex,
 | |
|         element: meta.data[index],
 | |
|         index
 | |
|       };
 | |
|     });
 | |
|     const changed = !_elementsEqual(lastActive, active);
 | |
|     const positionChanged = this._positionChanged(active, eventPosition);
 | |
|     if (changed || positionChanged) {
 | |
|       this._active = active;
 | |
|       this._eventPosition = eventPosition;
 | |
|       this._ignoreReplayEvents = true;
 | |
|       this.update(true);
 | |
|     }
 | |
|   }
 | |
|   handleEvent(e2, replay, inChartArea = true) {
 | |
|     if (replay && this._ignoreReplayEvents) {
 | |
|       return false;
 | |
|     }
 | |
|     this._ignoreReplayEvents = false;
 | |
|     const options = this.options;
 | |
|     const lastActive = this._active || [];
 | |
|     const active = this._getActiveElements(e2, lastActive, replay, inChartArea);
 | |
|     const positionChanged = this._positionChanged(active, e2);
 | |
|     const changed = replay || !_elementsEqual(active, lastActive) || positionChanged;
 | |
|     if (changed) {
 | |
|       this._active = active;
 | |
|       if (options.enabled || options.external) {
 | |
|         this._eventPosition = {
 | |
|           x: e2.x,
 | |
|           y: e2.y
 | |
|         };
 | |
|         this.update(true, replay);
 | |
|       }
 | |
|     }
 | |
|     return changed;
 | |
|   }
 | |
|   _getActiveElements(e2, lastActive, replay, inChartArea) {
 | |
|     const options = this.options;
 | |
|     if (e2.type === "mouseout") {
 | |
|       return [];
 | |
|     }
 | |
|     if (!inChartArea) {
 | |
|       return lastActive.filter((i2) => this.chart.data.datasets[i2.datasetIndex] && this.chart.getDatasetMeta(i2.datasetIndex).controller.getParsed(i2.index) !== void 0);
 | |
|     }
 | |
|     const active = this.chart.getElementsAtEventForMode(e2, options.mode, options, replay);
 | |
|     if (options.reverse) {
 | |
|       active.reverse();
 | |
|     }
 | |
|     return active;
 | |
|   }
 | |
|   _positionChanged(active, e2) {
 | |
|     const { caretX, caretY, options } = this;
 | |
|     const position = positioners[options.position].call(this, active, e2);
 | |
|     return position !== false && (caretX !== position.x || caretY !== position.y);
 | |
|   }
 | |
| };
 | |
| __publicField(Tooltip, "positioners", positioners);
 | |
| var plugin_tooltip = {
 | |
|   id: "tooltip",
 | |
|   _element: Tooltip,
 | |
|   positioners,
 | |
|   afterInit(chart, _args, options) {
 | |
|     if (options) {
 | |
|       chart.tooltip = new Tooltip({
 | |
|         chart,
 | |
|         options
 | |
|       });
 | |
|     }
 | |
|   },
 | |
|   beforeUpdate(chart, _args, options) {
 | |
|     if (chart.tooltip) {
 | |
|       chart.tooltip.initialize(options);
 | |
|     }
 | |
|   },
 | |
|   reset(chart, _args, options) {
 | |
|     if (chart.tooltip) {
 | |
|       chart.tooltip.initialize(options);
 | |
|     }
 | |
|   },
 | |
|   afterDraw(chart) {
 | |
|     const tooltip = chart.tooltip;
 | |
|     if (tooltip && tooltip._willRender()) {
 | |
|       const args = {
 | |
|         tooltip
 | |
|       };
 | |
|       if (chart.notifyPlugins("beforeTooltipDraw", {
 | |
|         ...args,
 | |
|         cancelable: true
 | |
|       }) === false) {
 | |
|         return;
 | |
|       }
 | |
|       tooltip.draw(chart.ctx);
 | |
|       chart.notifyPlugins("afterTooltipDraw", args);
 | |
|     }
 | |
|   },
 | |
|   afterEvent(chart, args) {
 | |
|     if (chart.tooltip) {
 | |
|       const useFinalPosition = args.replay;
 | |
|       if (chart.tooltip.handleEvent(args.event, useFinalPosition, args.inChartArea)) {
 | |
|         args.changed = true;
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   defaults: {
 | |
|     enabled: true,
 | |
|     external: null,
 | |
|     position: "average",
 | |
|     backgroundColor: "rgba(0,0,0,0.8)",
 | |
|     titleColor: "#fff",
 | |
|     titleFont: {
 | |
|       weight: "bold"
 | |
|     },
 | |
|     titleSpacing: 2,
 | |
|     titleMarginBottom: 6,
 | |
|     titleAlign: "left",
 | |
|     bodyColor: "#fff",
 | |
|     bodySpacing: 2,
 | |
|     bodyFont: {},
 | |
|     bodyAlign: "left",
 | |
|     footerColor: "#fff",
 | |
|     footerSpacing: 2,
 | |
|     footerMarginTop: 6,
 | |
|     footerFont: {
 | |
|       weight: "bold"
 | |
|     },
 | |
|     footerAlign: "left",
 | |
|     padding: 6,
 | |
|     caretPadding: 2,
 | |
|     caretSize: 5,
 | |
|     cornerRadius: 6,
 | |
|     boxHeight: (ctx, opts) => opts.bodyFont.size,
 | |
|     boxWidth: (ctx, opts) => opts.bodyFont.size,
 | |
|     multiKeyBackground: "#fff",
 | |
|     displayColors: true,
 | |
|     boxPadding: 0,
 | |
|     borderColor: "rgba(0,0,0,0)",
 | |
|     borderWidth: 0,
 | |
|     animation: {
 | |
|       duration: 400,
 | |
|       easing: "easeOutQuart"
 | |
|     },
 | |
|     animations: {
 | |
|       numbers: {
 | |
|         type: "number",
 | |
|         properties: [
 | |
|           "x",
 | |
|           "y",
 | |
|           "width",
 | |
|           "height",
 | |
|           "caretX",
 | |
|           "caretY"
 | |
|         ]
 | |
|       },
 | |
|       opacity: {
 | |
|         easing: "linear",
 | |
|         duration: 200
 | |
|       }
 | |
|     },
 | |
|     callbacks: defaultCallbacks
 | |
|   },
 | |
|   defaultRoutes: {
 | |
|     bodyFont: "font",
 | |
|     footerFont: "font",
 | |
|     titleFont: "font"
 | |
|   },
 | |
|   descriptors: {
 | |
|     _scriptable: (name) => name !== "filter" && name !== "itemSort" && name !== "external",
 | |
|     _indexable: false,
 | |
|     callbacks: {
 | |
|       _scriptable: false,
 | |
|       _indexable: false
 | |
|     },
 | |
|     animation: {
 | |
|       _fallback: false
 | |
|     },
 | |
|     animations: {
 | |
|       _fallback: "animation"
 | |
|     }
 | |
|   },
 | |
|   additionalOptionScopes: [
 | |
|     "interaction"
 | |
|   ]
 | |
| };
 | |
| var addIfString = (labels, raw, index, addedLabels) => {
 | |
|   if (typeof raw === "string") {
 | |
|     index = labels.push(raw) - 1;
 | |
|     addedLabels.unshift({
 | |
|       index,
 | |
|       label: raw
 | |
|     });
 | |
|   } else if (isNaN(raw)) {
 | |
|     index = null;
 | |
|   }
 | |
|   return index;
 | |
| };
 | |
| function findOrAddLabel(labels, raw, index, addedLabels) {
 | |
|   const first = labels.indexOf(raw);
 | |
|   if (first === -1) {
 | |
|     return addIfString(labels, raw, index, addedLabels);
 | |
|   }
 | |
|   const last = labels.lastIndexOf(raw);
 | |
|   return first !== last ? index : first;
 | |
| }
 | |
| var validIndex = (index, max) => index === null ? null : _limitValue(Math.round(index), 0, max);
 | |
| function _getLabelForValue(value) {
 | |
|   const labels = this.getLabels();
 | |
|   if (value >= 0 && value < labels.length) {
 | |
|     return labels[value];
 | |
|   }
 | |
|   return value;
 | |
| }
 | |
| var CategoryScale = class extends Scale {
 | |
|   constructor(cfg) {
 | |
|     super(cfg);
 | |
|     this._startValue = void 0;
 | |
|     this._valueRange = 0;
 | |
|     this._addedLabels = [];
 | |
|   }
 | |
|   init(scaleOptions) {
 | |
|     const added = this._addedLabels;
 | |
|     if (added.length) {
 | |
|       const labels = this.getLabels();
 | |
|       for (const { index, label } of added) {
 | |
|         if (labels[index] === label) {
 | |
|           labels.splice(index, 1);
 | |
|         }
 | |
|       }
 | |
|       this._addedLabels = [];
 | |
|     }
 | |
|     super.init(scaleOptions);
 | |
|   }
 | |
|   parse(raw, index) {
 | |
|     if (isNullOrUndef(raw)) {
 | |
|       return null;
 | |
|     }
 | |
|     const labels = this.getLabels();
 | |
|     index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, valueOrDefault(index, raw), this._addedLabels);
 | |
|     return validIndex(index, labels.length - 1);
 | |
|   }
 | |
|   determineDataLimits() {
 | |
|     const { minDefined, maxDefined } = this.getUserBounds();
 | |
|     let { min, max } = this.getMinMax(true);
 | |
|     if (this.options.bounds === "ticks") {
 | |
|       if (!minDefined) {
 | |
|         min = 0;
 | |
|       }
 | |
|       if (!maxDefined) {
 | |
|         max = this.getLabels().length - 1;
 | |
|       }
 | |
|     }
 | |
|     this.min = min;
 | |
|     this.max = max;
 | |
|   }
 | |
|   buildTicks() {
 | |
|     const min = this.min;
 | |
|     const max = this.max;
 | |
|     const offset = this.options.offset;
 | |
|     const ticks = [];
 | |
|     let labels = this.getLabels();
 | |
|     labels = min === 0 && max === labels.length - 1 ? labels : labels.slice(min, max + 1);
 | |
|     this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);
 | |
|     this._startValue = this.min - (offset ? 0.5 : 0);
 | |
|     for (let value = min; value <= max; value++) {
 | |
|       ticks.push({
 | |
|         value
 | |
|       });
 | |
|     }
 | |
|     return ticks;
 | |
|   }
 | |
|   getLabelForValue(value) {
 | |
|     return _getLabelForValue.call(this, value);
 | |
|   }
 | |
|   configure() {
 | |
|     super.configure();
 | |
|     if (!this.isHorizontal()) {
 | |
|       this._reversePixels = !this._reversePixels;
 | |
|     }
 | |
|   }
 | |
|   getPixelForValue(value) {
 | |
|     if (typeof value !== "number") {
 | |
|       value = this.parse(value);
 | |
|     }
 | |
|     return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
 | |
|   }
 | |
|   getPixelForTick(index) {
 | |
|     const ticks = this.ticks;
 | |
|     if (index < 0 || index > ticks.length - 1) {
 | |
|       return null;
 | |
|     }
 | |
|     return this.getPixelForValue(ticks[index].value);
 | |
|   }
 | |
|   getValueForPixel(pixel) {
 | |
|     return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);
 | |
|   }
 | |
|   getBasePixel() {
 | |
|     return this.bottom;
 | |
|   }
 | |
| };
 | |
| __publicField(CategoryScale, "id", "category");
 | |
| __publicField(CategoryScale, "defaults", {
 | |
|   ticks: {
 | |
|     callback: _getLabelForValue
 | |
|   }
 | |
| });
 | |
| function generateTicks$1(generationOptions, dataRange) {
 | |
|   const ticks = [];
 | |
|   const MIN_SPACING = 1e-14;
 | |
|   const { bounds, step, min, max, precision, count, maxTicks, maxDigits, includeBounds } = generationOptions;
 | |
|   const unit = step || 1;
 | |
|   const maxSpaces = maxTicks - 1;
 | |
|   const { min: rmin, max: rmax } = dataRange;
 | |
|   const minDefined = !isNullOrUndef(min);
 | |
|   const maxDefined = !isNullOrUndef(max);
 | |
|   const countDefined = !isNullOrUndef(count);
 | |
|   const minSpacing = (rmax - rmin) / (maxDigits + 1);
 | |
|   let spacing = niceNum((rmax - rmin) / maxSpaces / unit) * unit;
 | |
|   let factor, niceMin, niceMax, numSpaces;
 | |
|   if (spacing < MIN_SPACING && !minDefined && !maxDefined) {
 | |
|     return [
 | |
|       {
 | |
|         value: rmin
 | |
|       },
 | |
|       {
 | |
|         value: rmax
 | |
|       }
 | |
|     ];
 | |
|   }
 | |
|   numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
 | |
|   if (numSpaces > maxSpaces) {
 | |
|     spacing = niceNum(numSpaces * spacing / maxSpaces / unit) * unit;
 | |
|   }
 | |
|   if (!isNullOrUndef(precision)) {
 | |
|     factor = Math.pow(10, precision);
 | |
|     spacing = Math.ceil(spacing * factor) / factor;
 | |
|   }
 | |
|   if (bounds === "ticks") {
 | |
|     niceMin = Math.floor(rmin / spacing) * spacing;
 | |
|     niceMax = Math.ceil(rmax / spacing) * spacing;
 | |
|   } else {
 | |
|     niceMin = rmin;
 | |
|     niceMax = rmax;
 | |
|   }
 | |
|   if (minDefined && maxDefined && step && almostWhole((max - min) / step, spacing / 1e3)) {
 | |
|     numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks));
 | |
|     spacing = (max - min) / numSpaces;
 | |
|     niceMin = min;
 | |
|     niceMax = max;
 | |
|   } else if (countDefined) {
 | |
|     niceMin = minDefined ? min : niceMin;
 | |
|     niceMax = maxDefined ? max : niceMax;
 | |
|     numSpaces = count - 1;
 | |
|     spacing = (niceMax - niceMin) / numSpaces;
 | |
|   } else {
 | |
|     numSpaces = (niceMax - niceMin) / spacing;
 | |
|     if (almostEquals(numSpaces, Math.round(numSpaces), spacing / 1e3)) {
 | |
|       numSpaces = Math.round(numSpaces);
 | |
|     } else {
 | |
|       numSpaces = Math.ceil(numSpaces);
 | |
|     }
 | |
|   }
 | |
|   const decimalPlaces = Math.max(_decimalPlaces(spacing), _decimalPlaces(niceMin));
 | |
|   factor = Math.pow(10, isNullOrUndef(precision) ? decimalPlaces : precision);
 | |
|   niceMin = Math.round(niceMin * factor) / factor;
 | |
|   niceMax = Math.round(niceMax * factor) / factor;
 | |
|   let j2 = 0;
 | |
|   if (minDefined) {
 | |
|     if (includeBounds && niceMin !== min) {
 | |
|       ticks.push({
 | |
|         value: min
 | |
|       });
 | |
|       if (niceMin < min) {
 | |
|         j2++;
 | |
|       }
 | |
|       if (almostEquals(Math.round((niceMin + j2 * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) {
 | |
|         j2++;
 | |
|       }
 | |
|     } else if (niceMin < min) {
 | |
|       j2++;
 | |
|     }
 | |
|   }
 | |
|   for (; j2 < numSpaces; ++j2) {
 | |
|     const tickValue = Math.round((niceMin + j2 * spacing) * factor) / factor;
 | |
|     if (maxDefined && tickValue > max) {
 | |
|       break;
 | |
|     }
 | |
|     ticks.push({
 | |
|       value: tickValue
 | |
|     });
 | |
|   }
 | |
|   if (maxDefined && includeBounds && niceMax !== max) {
 | |
|     if (ticks.length && almostEquals(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) {
 | |
|       ticks[ticks.length - 1].value = max;
 | |
|     } else {
 | |
|       ticks.push({
 | |
|         value: max
 | |
|       });
 | |
|     }
 | |
|   } else if (!maxDefined || niceMax === max) {
 | |
|     ticks.push({
 | |
|       value: niceMax
 | |
|     });
 | |
|   }
 | |
|   return ticks;
 | |
| }
 | |
| function relativeLabelSize(value, minSpacing, { horizontal, minRotation }) {
 | |
|   const rad = toRadians(minRotation);
 | |
|   const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 1e-3;
 | |
|   const length = 0.75 * minSpacing * ("" + value).length;
 | |
|   return Math.min(minSpacing / ratio, length);
 | |
| }
 | |
| var LinearScaleBase = class extends Scale {
 | |
|   constructor(cfg) {
 | |
|     super(cfg);
 | |
|     this.start = void 0;
 | |
|     this.end = void 0;
 | |
|     this._startValue = void 0;
 | |
|     this._endValue = void 0;
 | |
|     this._valueRange = 0;
 | |
|   }
 | |
|   parse(raw, index) {
 | |
|     if (isNullOrUndef(raw)) {
 | |
|       return null;
 | |
|     }
 | |
|     if ((typeof raw === "number" || raw instanceof Number) && !isFinite(+raw)) {
 | |
|       return null;
 | |
|     }
 | |
|     return +raw;
 | |
|   }
 | |
|   handleTickRangeOptions() {
 | |
|     const { beginAtZero } = this.options;
 | |
|     const { minDefined, maxDefined } = this.getUserBounds();
 | |
|     let { min, max } = this;
 | |
|     const setMin = (v2) => min = minDefined ? min : v2;
 | |
|     const setMax = (v2) => max = maxDefined ? max : v2;
 | |
|     if (beginAtZero) {
 | |
|       const minSign = sign(min);
 | |
|       const maxSign = sign(max);
 | |
|       if (minSign < 0 && maxSign < 0) {
 | |
|         setMax(0);
 | |
|       } else if (minSign > 0 && maxSign > 0) {
 | |
|         setMin(0);
 | |
|       }
 | |
|     }
 | |
|     if (min === max) {
 | |
|       let offset = max === 0 ? 1 : Math.abs(max * 0.05);
 | |
|       setMax(max + offset);
 | |
|       if (!beginAtZero) {
 | |
|         setMin(min - offset);
 | |
|       }
 | |
|     }
 | |
|     this.min = min;
 | |
|     this.max = max;
 | |
|   }
 | |
|   getTickLimit() {
 | |
|     const tickOpts = this.options.ticks;
 | |
|     let { maxTicksLimit, stepSize } = tickOpts;
 | |
|     let maxTicks;
 | |
|     if (stepSize) {
 | |
|       maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;
 | |
|       if (maxTicks > 1e3) {
 | |
|         console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`);
 | |
|         maxTicks = 1e3;
 | |
|       }
 | |
|     } else {
 | |
|       maxTicks = this.computeTickLimit();
 | |
|       maxTicksLimit = maxTicksLimit || 11;
 | |
|     }
 | |
|     if (maxTicksLimit) {
 | |
|       maxTicks = Math.min(maxTicksLimit, maxTicks);
 | |
|     }
 | |
|     return maxTicks;
 | |
|   }
 | |
|   computeTickLimit() {
 | |
|     return Number.POSITIVE_INFINITY;
 | |
|   }
 | |
|   buildTicks() {
 | |
|     const opts = this.options;
 | |
|     const tickOpts = opts.ticks;
 | |
|     let maxTicks = this.getTickLimit();
 | |
|     maxTicks = Math.max(2, maxTicks);
 | |
|     const numericGeneratorOptions = {
 | |
|       maxTicks,
 | |
|       bounds: opts.bounds,
 | |
|       min: opts.min,
 | |
|       max: opts.max,
 | |
|       precision: tickOpts.precision,
 | |
|       step: tickOpts.stepSize,
 | |
|       count: tickOpts.count,
 | |
|       maxDigits: this._maxDigits(),
 | |
|       horizontal: this.isHorizontal(),
 | |
|       minRotation: tickOpts.minRotation || 0,
 | |
|       includeBounds: tickOpts.includeBounds !== false
 | |
|     };
 | |
|     const dataRange = this._range || this;
 | |
|     const ticks = generateTicks$1(numericGeneratorOptions, dataRange);
 | |
|     if (opts.bounds === "ticks") {
 | |
|       _setMinAndMaxByKey(ticks, this, "value");
 | |
|     }
 | |
|     if (opts.reverse) {
 | |
|       ticks.reverse();
 | |
|       this.start = this.max;
 | |
|       this.end = this.min;
 | |
|     } else {
 | |
|       this.start = this.min;
 | |
|       this.end = this.max;
 | |
|     }
 | |
|     return ticks;
 | |
|   }
 | |
|   configure() {
 | |
|     const ticks = this.ticks;
 | |
|     let start = this.min;
 | |
|     let end = this.max;
 | |
|     super.configure();
 | |
|     if (this.options.offset && ticks.length) {
 | |
|       const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2;
 | |
|       start -= offset;
 | |
|       end += offset;
 | |
|     }
 | |
|     this._startValue = start;
 | |
|     this._endValue = end;
 | |
|     this._valueRange = end - start;
 | |
|   }
 | |
|   getLabelForValue(value) {
 | |
|     return formatNumber(value, this.chart.options.locale, this.options.ticks.format);
 | |
|   }
 | |
| };
 | |
| var LinearScale = class extends LinearScaleBase {
 | |
|   determineDataLimits() {
 | |
|     const { min, max } = this.getMinMax(true);
 | |
|     this.min = isNumberFinite(min) ? min : 0;
 | |
|     this.max = isNumberFinite(max) ? max : 1;
 | |
|     this.handleTickRangeOptions();
 | |
|   }
 | |
|   computeTickLimit() {
 | |
|     const horizontal = this.isHorizontal();
 | |
|     const length = horizontal ? this.width : this.height;
 | |
|     const minRotation = toRadians(this.options.ticks.minRotation);
 | |
|     const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 1e-3;
 | |
|     const tickFont = this._resolveTickFontOptions(0);
 | |
|     return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));
 | |
|   }
 | |
|   getPixelForValue(value) {
 | |
|     return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
 | |
|   }
 | |
|   getValueForPixel(pixel) {
 | |
|     return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange;
 | |
|   }
 | |
| };
 | |
| __publicField(LinearScale, "id", "linear");
 | |
| __publicField(LinearScale, "defaults", {
 | |
|   ticks: {
 | |
|     callback: Ticks.formatters.numeric
 | |
|   }
 | |
| });
 | |
| var log10Floor = (v2) => Math.floor(log10(v2));
 | |
| var changeExponent = (v2, m2) => Math.pow(10, log10Floor(v2) + m2);
 | |
| function isMajor(tickVal) {
 | |
|   const remain = tickVal / Math.pow(10, log10Floor(tickVal));
 | |
|   return remain === 1;
 | |
| }
 | |
| function steps(min, max, rangeExp) {
 | |
|   const rangeStep = Math.pow(10, rangeExp);
 | |
|   const start = Math.floor(min / rangeStep);
 | |
|   const end = Math.ceil(max / rangeStep);
 | |
|   return end - start;
 | |
| }
 | |
| function startExp(min, max) {
 | |
|   const range = max - min;
 | |
|   let rangeExp = log10Floor(range);
 | |
|   while (steps(min, max, rangeExp) > 10) {
 | |
|     rangeExp++;
 | |
|   }
 | |
|   while (steps(min, max, rangeExp) < 10) {
 | |
|     rangeExp--;
 | |
|   }
 | |
|   return Math.min(rangeExp, log10Floor(min));
 | |
| }
 | |
| function generateTicks(generationOptions, { min, max }) {
 | |
|   min = finiteOrDefault(generationOptions.min, min);
 | |
|   const ticks = [];
 | |
|   const minExp = log10Floor(min);
 | |
|   let exp = startExp(min, max);
 | |
|   let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;
 | |
|   const stepSize = Math.pow(10, exp);
 | |
|   const base = minExp > exp ? Math.pow(10, minExp) : 0;
 | |
|   const start = Math.round((min - base) * precision) / precision;
 | |
|   const offset = Math.floor((min - base) / stepSize / 10) * stepSize * 10;
 | |
|   let significand = Math.floor((start - offset) / Math.pow(10, exp));
 | |
|   let value = finiteOrDefault(generationOptions.min, Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision);
 | |
|   while (value < max) {
 | |
|     ticks.push({
 | |
|       value,
 | |
|       major: isMajor(value),
 | |
|       significand
 | |
|     });
 | |
|     if (significand >= 10) {
 | |
|       significand = significand < 15 ? 15 : 20;
 | |
|     } else {
 | |
|       significand++;
 | |
|     }
 | |
|     if (significand >= 20) {
 | |
|       exp++;
 | |
|       significand = 2;
 | |
|       precision = exp >= 0 ? 1 : precision;
 | |
|     }
 | |
|     value = Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision;
 | |
|   }
 | |
|   const lastTick = finiteOrDefault(generationOptions.max, value);
 | |
|   ticks.push({
 | |
|     value: lastTick,
 | |
|     major: isMajor(lastTick),
 | |
|     significand
 | |
|   });
 | |
|   return ticks;
 | |
| }
 | |
| var LogarithmicScale = class extends Scale {
 | |
|   constructor(cfg) {
 | |
|     super(cfg);
 | |
|     this.start = void 0;
 | |
|     this.end = void 0;
 | |
|     this._startValue = void 0;
 | |
|     this._valueRange = 0;
 | |
|   }
 | |
|   parse(raw, index) {
 | |
|     const value = LinearScaleBase.prototype.parse.apply(this, [
 | |
|       raw,
 | |
|       index
 | |
|     ]);
 | |
|     if (value === 0) {
 | |
|       this._zero = true;
 | |
|       return void 0;
 | |
|     }
 | |
|     return isNumberFinite(value) && value > 0 ? value : null;
 | |
|   }
 | |
|   determineDataLimits() {
 | |
|     const { min, max } = this.getMinMax(true);
 | |
|     this.min = isNumberFinite(min) ? Math.max(0, min) : null;
 | |
|     this.max = isNumberFinite(max) ? Math.max(0, max) : null;
 | |
|     if (this.options.beginAtZero) {
 | |
|       this._zero = true;
 | |
|     }
 | |
|     if (this._zero && this.min !== this._suggestedMin && !isNumberFinite(this._userMin)) {
 | |
|       this.min = min === changeExponent(this.min, 0) ? changeExponent(this.min, -1) : changeExponent(this.min, 0);
 | |
|     }
 | |
|     this.handleTickRangeOptions();
 | |
|   }
 | |
|   handleTickRangeOptions() {
 | |
|     const { minDefined, maxDefined } = this.getUserBounds();
 | |
|     let min = this.min;
 | |
|     let max = this.max;
 | |
|     const setMin = (v2) => min = minDefined ? min : v2;
 | |
|     const setMax = (v2) => max = maxDefined ? max : v2;
 | |
|     if (min === max) {
 | |
|       if (min <= 0) {
 | |
|         setMin(1);
 | |
|         setMax(10);
 | |
|       } else {
 | |
|         setMin(changeExponent(min, -1));
 | |
|         setMax(changeExponent(max, 1));
 | |
|       }
 | |
|     }
 | |
|     if (min <= 0) {
 | |
|       setMin(changeExponent(max, -1));
 | |
|     }
 | |
|     if (max <= 0) {
 | |
|       setMax(changeExponent(min, 1));
 | |
|     }
 | |
|     this.min = min;
 | |
|     this.max = max;
 | |
|   }
 | |
|   buildTicks() {
 | |
|     const opts = this.options;
 | |
|     const generationOptions = {
 | |
|       min: this._userMin,
 | |
|       max: this._userMax
 | |
|     };
 | |
|     const ticks = generateTicks(generationOptions, this);
 | |
|     if (opts.bounds === "ticks") {
 | |
|       _setMinAndMaxByKey(ticks, this, "value");
 | |
|     }
 | |
|     if (opts.reverse) {
 | |
|       ticks.reverse();
 | |
|       this.start = this.max;
 | |
|       this.end = this.min;
 | |
|     } else {
 | |
|       this.start = this.min;
 | |
|       this.end = this.max;
 | |
|     }
 | |
|     return ticks;
 | |
|   }
 | |
|   getLabelForValue(value) {
 | |
|     return value === void 0 ? "0" : formatNumber(value, this.chart.options.locale, this.options.ticks.format);
 | |
|   }
 | |
|   configure() {
 | |
|     const start = this.min;
 | |
|     super.configure();
 | |
|     this._startValue = log10(start);
 | |
|     this._valueRange = log10(this.max) - log10(start);
 | |
|   }
 | |
|   getPixelForValue(value) {
 | |
|     if (value === void 0 || value === 0) {
 | |
|       value = this.min;
 | |
|     }
 | |
|     if (value === null || isNaN(value)) {
 | |
|       return NaN;
 | |
|     }
 | |
|     return this.getPixelForDecimal(value === this.min ? 0 : (log10(value) - this._startValue) / this._valueRange);
 | |
|   }
 | |
|   getValueForPixel(pixel) {
 | |
|     const decimal = this.getDecimalForPixel(pixel);
 | |
|     return Math.pow(10, this._startValue + decimal * this._valueRange);
 | |
|   }
 | |
| };
 | |
| __publicField(LogarithmicScale, "id", "logarithmic");
 | |
| __publicField(LogarithmicScale, "defaults", {
 | |
|   ticks: {
 | |
|     callback: Ticks.formatters.logarithmic,
 | |
|     major: {
 | |
|       enabled: true
 | |
|     }
 | |
|   }
 | |
| });
 | |
| function getTickBackdropHeight(opts) {
 | |
|   const tickOpts = opts.ticks;
 | |
|   if (tickOpts.display && opts.display) {
 | |
|     const padding = toPadding(tickOpts.backdropPadding);
 | |
|     return valueOrDefault(tickOpts.font && tickOpts.font.size, defaults2.font.size) + padding.height;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| function measureLabelSize(ctx, font, label) {
 | |
|   label = isArray(label) ? label : [
 | |
|     label
 | |
|   ];
 | |
|   return {
 | |
|     w: _longestText(ctx, font.string, label),
 | |
|     h: label.length * font.lineHeight
 | |
|   };
 | |
| }
 | |
| function determineLimits(angle, pos, size, min, max) {
 | |
|   if (angle === min || angle === max) {
 | |
|     return {
 | |
|       start: pos - size / 2,
 | |
|       end: pos + size / 2
 | |
|     };
 | |
|   } else if (angle < min || angle > max) {
 | |
|     return {
 | |
|       start: pos - size,
 | |
|       end: pos
 | |
|     };
 | |
|   }
 | |
|   return {
 | |
|     start: pos,
 | |
|     end: pos + size
 | |
|   };
 | |
| }
 | |
| function fitWithPointLabels(scale) {
 | |
|   const orig = {
 | |
|     l: scale.left + scale._padding.left,
 | |
|     r: scale.right - scale._padding.right,
 | |
|     t: scale.top + scale._padding.top,
 | |
|     b: scale.bottom - scale._padding.bottom
 | |
|   };
 | |
|   const limits = Object.assign({}, orig);
 | |
|   const labelSizes = [];
 | |
|   const padding = [];
 | |
|   const valueCount = scale._pointLabels.length;
 | |
|   const pointLabelOpts = scale.options.pointLabels;
 | |
|   const additionalAngle = pointLabelOpts.centerPointLabels ? PI / valueCount : 0;
 | |
|   for (let i2 = 0; i2 < valueCount; i2++) {
 | |
|     const opts = pointLabelOpts.setContext(scale.getPointLabelContext(i2));
 | |
|     padding[i2] = opts.padding;
 | |
|     const pointPosition = scale.getPointPosition(i2, scale.drawingArea + padding[i2], additionalAngle);
 | |
|     const plFont = toFont(opts.font);
 | |
|     const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i2]);
 | |
|     labelSizes[i2] = textSize;
 | |
|     const angleRadians = _normalizeAngle(scale.getIndexAngle(i2) + additionalAngle);
 | |
|     const angle = Math.round(toDegrees(angleRadians));
 | |
|     const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
 | |
|     const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
 | |
|     updateLimits(limits, orig, angleRadians, hLimits, vLimits);
 | |
|   }
 | |
|   scale.setCenterPoint(orig.l - limits.l, limits.r - orig.r, orig.t - limits.t, limits.b - orig.b);
 | |
|   scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding);
 | |
| }
 | |
| function updateLimits(limits, orig, angle, hLimits, vLimits) {
 | |
|   const sin = Math.abs(Math.sin(angle));
 | |
|   const cos = Math.abs(Math.cos(angle));
 | |
|   let x2 = 0;
 | |
|   let y2 = 0;
 | |
|   if (hLimits.start < orig.l) {
 | |
|     x2 = (orig.l - hLimits.start) / sin;
 | |
|     limits.l = Math.min(limits.l, orig.l - x2);
 | |
|   } else if (hLimits.end > orig.r) {
 | |
|     x2 = (hLimits.end - orig.r) / sin;
 | |
|     limits.r = Math.max(limits.r, orig.r + x2);
 | |
|   }
 | |
|   if (vLimits.start < orig.t) {
 | |
|     y2 = (orig.t - vLimits.start) / cos;
 | |
|     limits.t = Math.min(limits.t, orig.t - y2);
 | |
|   } else if (vLimits.end > orig.b) {
 | |
|     y2 = (vLimits.end - orig.b) / cos;
 | |
|     limits.b = Math.max(limits.b, orig.b + y2);
 | |
|   }
 | |
| }
 | |
| function createPointLabelItem(scale, index, itemOpts) {
 | |
|   const outerDistance = scale.drawingArea;
 | |
|   const { extra, additionalAngle, padding, size } = itemOpts;
 | |
|   const pointLabelPosition = scale.getPointPosition(index, outerDistance + extra + padding, additionalAngle);
 | |
|   const angle = Math.round(toDegrees(_normalizeAngle(pointLabelPosition.angle + HALF_PI)));
 | |
|   const y2 = yForAngle(pointLabelPosition.y, size.h, angle);
 | |
|   const textAlign = getTextAlignForAngle(angle);
 | |
|   const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign);
 | |
|   return {
 | |
|     visible: true,
 | |
|     x: pointLabelPosition.x,
 | |
|     y: y2,
 | |
|     textAlign,
 | |
|     left,
 | |
|     top: y2,
 | |
|     right: left + size.w,
 | |
|     bottom: y2 + size.h
 | |
|   };
 | |
| }
 | |
| function isNotOverlapped(item, area) {
 | |
|   if (!area) {
 | |
|     return true;
 | |
|   }
 | |
|   const { left, top, right, bottom } = item;
 | |
|   const apexesInArea = _isPointInArea({
 | |
|     x: left,
 | |
|     y: top
 | |
|   }, area) || _isPointInArea({
 | |
|     x: left,
 | |
|     y: bottom
 | |
|   }, area) || _isPointInArea({
 | |
|     x: right,
 | |
|     y: top
 | |
|   }, area) || _isPointInArea({
 | |
|     x: right,
 | |
|     y: bottom
 | |
|   }, area);
 | |
|   return !apexesInArea;
 | |
| }
 | |
| function buildPointLabelItems(scale, labelSizes, padding) {
 | |
|   const items = [];
 | |
|   const valueCount = scale._pointLabels.length;
 | |
|   const opts = scale.options;
 | |
|   const { centerPointLabels, display } = opts.pointLabels;
 | |
|   const itemOpts = {
 | |
|     extra: getTickBackdropHeight(opts) / 2,
 | |
|     additionalAngle: centerPointLabels ? PI / valueCount : 0
 | |
|   };
 | |
|   let area;
 | |
|   for (let i2 = 0; i2 < valueCount; i2++) {
 | |
|     itemOpts.padding = padding[i2];
 | |
|     itemOpts.size = labelSizes[i2];
 | |
|     const item = createPointLabelItem(scale, i2, itemOpts);
 | |
|     items.push(item);
 | |
|     if (display === "auto") {
 | |
|       item.visible = isNotOverlapped(item, area);
 | |
|       if (item.visible) {
 | |
|         area = item;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return items;
 | |
| }
 | |
| function getTextAlignForAngle(angle) {
 | |
|   if (angle === 0 || angle === 180) {
 | |
|     return "center";
 | |
|   } else if (angle < 180) {
 | |
|     return "left";
 | |
|   }
 | |
|   return "right";
 | |
| }
 | |
| function leftForTextAlign(x2, w2, align) {
 | |
|   if (align === "right") {
 | |
|     x2 -= w2;
 | |
|   } else if (align === "center") {
 | |
|     x2 -= w2 / 2;
 | |
|   }
 | |
|   return x2;
 | |
| }
 | |
| function yForAngle(y2, h6, angle) {
 | |
|   if (angle === 90 || angle === 270) {
 | |
|     y2 -= h6 / 2;
 | |
|   } else if (angle > 270 || angle < 90) {
 | |
|     y2 -= h6;
 | |
|   }
 | |
|   return y2;
 | |
| }
 | |
| function drawPointLabelBox(ctx, opts, item) {
 | |
|   const { left, top, right, bottom } = item;
 | |
|   const { backdropColor } = opts;
 | |
|   if (!isNullOrUndef(backdropColor)) {
 | |
|     const borderRadius = toTRBLCorners(opts.borderRadius);
 | |
|     const padding = toPadding(opts.backdropPadding);
 | |
|     ctx.fillStyle = backdropColor;
 | |
|     const backdropLeft = left - padding.left;
 | |
|     const backdropTop = top - padding.top;
 | |
|     const backdropWidth = right - left + padding.width;
 | |
|     const backdropHeight = bottom - top + padding.height;
 | |
|     if (Object.values(borderRadius).some((v2) => v2 !== 0)) {
 | |
|       ctx.beginPath();
 | |
|       addRoundedRectPath(ctx, {
 | |
|         x: backdropLeft,
 | |
|         y: backdropTop,
 | |
|         w: backdropWidth,
 | |
|         h: backdropHeight,
 | |
|         radius: borderRadius
 | |
|       });
 | |
|       ctx.fill();
 | |
|     } else {
 | |
|       ctx.fillRect(backdropLeft, backdropTop, backdropWidth, backdropHeight);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function drawPointLabels(scale, labelCount) {
 | |
|   const { ctx, options: { pointLabels } } = scale;
 | |
|   for (let i2 = labelCount - 1; i2 >= 0; i2--) {
 | |
|     const item = scale._pointLabelItems[i2];
 | |
|     if (!item.visible) {
 | |
|       continue;
 | |
|     }
 | |
|     const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i2));
 | |
|     drawPointLabelBox(ctx, optsAtIndex, item);
 | |
|     const plFont = toFont(optsAtIndex.font);
 | |
|     const { x: x2, y: y2, textAlign } = item;
 | |
|     renderText(ctx, scale._pointLabels[i2], x2, y2 + plFont.lineHeight / 2, plFont, {
 | |
|       color: optsAtIndex.color,
 | |
|       textAlign,
 | |
|       textBaseline: "middle"
 | |
|     });
 | |
|   }
 | |
| }
 | |
| function pathRadiusLine(scale, radius, circular, labelCount) {
 | |
|   const { ctx } = scale;
 | |
|   if (circular) {
 | |
|     ctx.arc(scale.xCenter, scale.yCenter, radius, 0, TAU);
 | |
|   } else {
 | |
|     let pointPosition = scale.getPointPosition(0, radius);
 | |
|     ctx.moveTo(pointPosition.x, pointPosition.y);
 | |
|     for (let i2 = 1; i2 < labelCount; i2++) {
 | |
|       pointPosition = scale.getPointPosition(i2, radius);
 | |
|       ctx.lineTo(pointPosition.x, pointPosition.y);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function drawRadiusLine(scale, gridLineOpts, radius, labelCount, borderOpts) {
 | |
|   const ctx = scale.ctx;
 | |
|   const circular = gridLineOpts.circular;
 | |
|   const { color: color2, lineWidth } = gridLineOpts;
 | |
|   if (!circular && !labelCount || !color2 || !lineWidth || radius < 0) {
 | |
|     return;
 | |
|   }
 | |
|   ctx.save();
 | |
|   ctx.strokeStyle = color2;
 | |
|   ctx.lineWidth = lineWidth;
 | |
|   ctx.setLineDash(borderOpts.dash || []);
 | |
|   ctx.lineDashOffset = borderOpts.dashOffset;
 | |
|   ctx.beginPath();
 | |
|   pathRadiusLine(scale, radius, circular, labelCount);
 | |
|   ctx.closePath();
 | |
|   ctx.stroke();
 | |
|   ctx.restore();
 | |
| }
 | |
| function createPointLabelContext(parent, index, label) {
 | |
|   return createContext(parent, {
 | |
|     label,
 | |
|     index,
 | |
|     type: "pointLabel"
 | |
|   });
 | |
| }
 | |
| var RadialLinearScale = class extends LinearScaleBase {
 | |
|   constructor(cfg) {
 | |
|     super(cfg);
 | |
|     this.xCenter = void 0;
 | |
|     this.yCenter = void 0;
 | |
|     this.drawingArea = void 0;
 | |
|     this._pointLabels = [];
 | |
|     this._pointLabelItems = [];
 | |
|   }
 | |
|   setDimensions() {
 | |
|     const padding = this._padding = toPadding(getTickBackdropHeight(this.options) / 2);
 | |
|     const w2 = this.width = this.maxWidth - padding.width;
 | |
|     const h6 = this.height = this.maxHeight - padding.height;
 | |
|     this.xCenter = Math.floor(this.left + w2 / 2 + padding.left);
 | |
|     this.yCenter = Math.floor(this.top + h6 / 2 + padding.top);
 | |
|     this.drawingArea = Math.floor(Math.min(w2, h6) / 2);
 | |
|   }
 | |
|   determineDataLimits() {
 | |
|     const { min, max } = this.getMinMax(false);
 | |
|     this.min = isNumberFinite(min) && !isNaN(min) ? min : 0;
 | |
|     this.max = isNumberFinite(max) && !isNaN(max) ? max : 0;
 | |
|     this.handleTickRangeOptions();
 | |
|   }
 | |
|   computeTickLimit() {
 | |
|     return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));
 | |
|   }
 | |
|   generateTickLabels(ticks) {
 | |
|     LinearScaleBase.prototype.generateTickLabels.call(this, ticks);
 | |
|     this._pointLabels = this.getLabels().map((value, index) => {
 | |
|       const label = callback(this.options.pointLabels.callback, [
 | |
|         value,
 | |
|         index
 | |
|       ], this);
 | |
|       return label || label === 0 ? label : "";
 | |
|     }).filter((v2, i2) => this.chart.getDataVisibility(i2));
 | |
|   }
 | |
|   fit() {
 | |
|     const opts = this.options;
 | |
|     if (opts.display && opts.pointLabels.display) {
 | |
|       fitWithPointLabels(this);
 | |
|     } else {
 | |
|       this.setCenterPoint(0, 0, 0, 0);
 | |
|     }
 | |
|   }
 | |
|   setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {
 | |
|     this.xCenter += Math.floor((leftMovement - rightMovement) / 2);
 | |
|     this.yCenter += Math.floor((topMovement - bottomMovement) / 2);
 | |
|     this.drawingArea -= Math.min(this.drawingArea / 2, Math.max(leftMovement, rightMovement, topMovement, bottomMovement));
 | |
|   }
 | |
|   getIndexAngle(index) {
 | |
|     const angleMultiplier = TAU / (this._pointLabels.length || 1);
 | |
|     const startAngle = this.options.startAngle || 0;
 | |
|     return _normalizeAngle(index * angleMultiplier + toRadians(startAngle));
 | |
|   }
 | |
|   getDistanceFromCenterForValue(value) {
 | |
|     if (isNullOrUndef(value)) {
 | |
|       return NaN;
 | |
|     }
 | |
|     const scalingFactor = this.drawingArea / (this.max - this.min);
 | |
|     if (this.options.reverse) {
 | |
|       return (this.max - value) * scalingFactor;
 | |
|     }
 | |
|     return (value - this.min) * scalingFactor;
 | |
|   }
 | |
|   getValueForDistanceFromCenter(distance) {
 | |
|     if (isNullOrUndef(distance)) {
 | |
|       return NaN;
 | |
|     }
 | |
|     const scaledDistance = distance / (this.drawingArea / (this.max - this.min));
 | |
|     return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;
 | |
|   }
 | |
|   getPointLabelContext(index) {
 | |
|     const pointLabels = this._pointLabels || [];
 | |
|     if (index >= 0 && index < pointLabels.length) {
 | |
|       const pointLabel = pointLabels[index];
 | |
|       return createPointLabelContext(this.getContext(), index, pointLabel);
 | |
|     }
 | |
|   }
 | |
|   getPointPosition(index, distanceFromCenter, additionalAngle = 0) {
 | |
|     const angle = this.getIndexAngle(index) - HALF_PI + additionalAngle;
 | |
|     return {
 | |
|       x: Math.cos(angle) * distanceFromCenter + this.xCenter,
 | |
|       y: Math.sin(angle) * distanceFromCenter + this.yCenter,
 | |
|       angle
 | |
|     };
 | |
|   }
 | |
|   getPointPositionForValue(index, value) {
 | |
|     return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
 | |
|   }
 | |
|   getBasePosition(index) {
 | |
|     return this.getPointPositionForValue(index || 0, this.getBaseValue());
 | |
|   }
 | |
|   getPointLabelPosition(index) {
 | |
|     const { left, top, right, bottom } = this._pointLabelItems[index];
 | |
|     return {
 | |
|       left,
 | |
|       top,
 | |
|       right,
 | |
|       bottom
 | |
|     };
 | |
|   }
 | |
|   drawBackground() {
 | |
|     const { backgroundColor, grid: { circular } } = this.options;
 | |
|     if (backgroundColor) {
 | |
|       const ctx = this.ctx;
 | |
|       ctx.save();
 | |
|       ctx.beginPath();
 | |
|       pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this._pointLabels.length);
 | |
|       ctx.closePath();
 | |
|       ctx.fillStyle = backgroundColor;
 | |
|       ctx.fill();
 | |
|       ctx.restore();
 | |
|     }
 | |
|   }
 | |
|   drawGrid() {
 | |
|     const ctx = this.ctx;
 | |
|     const opts = this.options;
 | |
|     const { angleLines, grid, border } = opts;
 | |
|     const labelCount = this._pointLabels.length;
 | |
|     let i2, offset, position;
 | |
|     if (opts.pointLabels.display) {
 | |
|       drawPointLabels(this, labelCount);
 | |
|     }
 | |
|     if (grid.display) {
 | |
|       this.ticks.forEach((tick, index) => {
 | |
|         if (index !== 0 || index === 0 && this.min < 0) {
 | |
|           offset = this.getDistanceFromCenterForValue(tick.value);
 | |
|           const context = this.getContext(index);
 | |
|           const optsAtIndex = grid.setContext(context);
 | |
|           const optsAtIndexBorder = border.setContext(context);
 | |
|           drawRadiusLine(this, optsAtIndex, offset, labelCount, optsAtIndexBorder);
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|     if (angleLines.display) {
 | |
|       ctx.save();
 | |
|       for (i2 = labelCount - 1; i2 >= 0; i2--) {
 | |
|         const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i2));
 | |
|         const { color: color2, lineWidth } = optsAtIndex;
 | |
|         if (!lineWidth || !color2) {
 | |
|           continue;
 | |
|         }
 | |
|         ctx.lineWidth = lineWidth;
 | |
|         ctx.strokeStyle = color2;
 | |
|         ctx.setLineDash(optsAtIndex.borderDash);
 | |
|         ctx.lineDashOffset = optsAtIndex.borderDashOffset;
 | |
|         offset = this.getDistanceFromCenterForValue(opts.reverse ? this.min : this.max);
 | |
|         position = this.getPointPosition(i2, offset);
 | |
|         ctx.beginPath();
 | |
|         ctx.moveTo(this.xCenter, this.yCenter);
 | |
|         ctx.lineTo(position.x, position.y);
 | |
|         ctx.stroke();
 | |
|       }
 | |
|       ctx.restore();
 | |
|     }
 | |
|   }
 | |
|   drawBorder() {
 | |
|   }
 | |
|   drawLabels() {
 | |
|     const ctx = this.ctx;
 | |
|     const opts = this.options;
 | |
|     const tickOpts = opts.ticks;
 | |
|     if (!tickOpts.display) {
 | |
|       return;
 | |
|     }
 | |
|     const startAngle = this.getIndexAngle(0);
 | |
|     let offset, width;
 | |
|     ctx.save();
 | |
|     ctx.translate(this.xCenter, this.yCenter);
 | |
|     ctx.rotate(startAngle);
 | |
|     ctx.textAlign = "center";
 | |
|     ctx.textBaseline = "middle";
 | |
|     this.ticks.forEach((tick, index) => {
 | |
|       if (index === 0 && this.min >= 0 && !opts.reverse) {
 | |
|         return;
 | |
|       }
 | |
|       const optsAtIndex = tickOpts.setContext(this.getContext(index));
 | |
|       const tickFont = toFont(optsAtIndex.font);
 | |
|       offset = this.getDistanceFromCenterForValue(this.ticks[index].value);
 | |
|       if (optsAtIndex.showLabelBackdrop) {
 | |
|         ctx.font = tickFont.string;
 | |
|         width = ctx.measureText(tick.label).width;
 | |
|         ctx.fillStyle = optsAtIndex.backdropColor;
 | |
|         const padding = toPadding(optsAtIndex.backdropPadding);
 | |
|         ctx.fillRect(-width / 2 - padding.left, -offset - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height);
 | |
|       }
 | |
|       renderText(ctx, tick.label, 0, -offset, tickFont, {
 | |
|         color: optsAtIndex.color,
 | |
|         strokeColor: optsAtIndex.textStrokeColor,
 | |
|         strokeWidth: optsAtIndex.textStrokeWidth
 | |
|       });
 | |
|     });
 | |
|     ctx.restore();
 | |
|   }
 | |
|   drawTitle() {
 | |
|   }
 | |
| };
 | |
| __publicField(RadialLinearScale, "id", "radialLinear");
 | |
| __publicField(RadialLinearScale, "defaults", {
 | |
|   display: true,
 | |
|   animate: true,
 | |
|   position: "chartArea",
 | |
|   angleLines: {
 | |
|     display: true,
 | |
|     lineWidth: 1,
 | |
|     borderDash: [],
 | |
|     borderDashOffset: 0
 | |
|   },
 | |
|   grid: {
 | |
|     circular: false
 | |
|   },
 | |
|   startAngle: 0,
 | |
|   ticks: {
 | |
|     showLabelBackdrop: true,
 | |
|     callback: Ticks.formatters.numeric
 | |
|   },
 | |
|   pointLabels: {
 | |
|     backdropColor: void 0,
 | |
|     backdropPadding: 2,
 | |
|     display: true,
 | |
|     font: {
 | |
|       size: 10
 | |
|     },
 | |
|     callback(label) {
 | |
|       return label;
 | |
|     },
 | |
|     padding: 5,
 | |
|     centerPointLabels: false
 | |
|   }
 | |
| });
 | |
| __publicField(RadialLinearScale, "defaultRoutes", {
 | |
|   "angleLines.color": "borderColor",
 | |
|   "pointLabels.color": "color",
 | |
|   "ticks.color": "color"
 | |
| });
 | |
| __publicField(RadialLinearScale, "descriptors", {
 | |
|   angleLines: {
 | |
|     _fallback: "grid"
 | |
|   }
 | |
| });
 | |
| var INTERVALS = {
 | |
|   millisecond: {
 | |
|     common: true,
 | |
|     size: 1,
 | |
|     steps: 1e3
 | |
|   },
 | |
|   second: {
 | |
|     common: true,
 | |
|     size: 1e3,
 | |
|     steps: 60
 | |
|   },
 | |
|   minute: {
 | |
|     common: true,
 | |
|     size: 6e4,
 | |
|     steps: 60
 | |
|   },
 | |
|   hour: {
 | |
|     common: true,
 | |
|     size: 36e5,
 | |
|     steps: 24
 | |
|   },
 | |
|   day: {
 | |
|     common: true,
 | |
|     size: 864e5,
 | |
|     steps: 30
 | |
|   },
 | |
|   week: {
 | |
|     common: false,
 | |
|     size: 6048e5,
 | |
|     steps: 4
 | |
|   },
 | |
|   month: {
 | |
|     common: true,
 | |
|     size: 2628e6,
 | |
|     steps: 12
 | |
|   },
 | |
|   quarter: {
 | |
|     common: false,
 | |
|     size: 7884e6,
 | |
|     steps: 4
 | |
|   },
 | |
|   year: {
 | |
|     common: true,
 | |
|     size: 3154e7
 | |
|   }
 | |
| };
 | |
| var UNITS = /* @__PURE__ */ Object.keys(INTERVALS);
 | |
| function sorter(a2, b2) {
 | |
|   return a2 - b2;
 | |
| }
 | |
| function parse2(scale, input) {
 | |
|   if (isNullOrUndef(input)) {
 | |
|     return null;
 | |
|   }
 | |
|   const adapter = scale._adapter;
 | |
|   const { parser, round: round2, isoWeekday } = scale._parseOpts;
 | |
|   let value = input;
 | |
|   if (typeof parser === "function") {
 | |
|     value = parser(value);
 | |
|   }
 | |
|   if (!isNumberFinite(value)) {
 | |
|     value = typeof parser === "string" ? adapter.parse(value, parser) : adapter.parse(value);
 | |
|   }
 | |
|   if (value === null) {
 | |
|     return null;
 | |
|   }
 | |
|   if (round2) {
 | |
|     value = round2 === "week" && (isNumber(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, "isoWeek", isoWeekday) : adapter.startOf(value, round2);
 | |
|   }
 | |
|   return +value;
 | |
| }
 | |
| function determineUnitForAutoTicks(minUnit, min, max, capacity) {
 | |
|   const ilen = UNITS.length;
 | |
|   for (let i2 = UNITS.indexOf(minUnit); i2 < ilen - 1; ++i2) {
 | |
|     const interval = INTERVALS[UNITS[i2]];
 | |
|     const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER;
 | |
|     if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {
 | |
|       return UNITS[i2];
 | |
|     }
 | |
|   }
 | |
|   return UNITS[ilen - 1];
 | |
| }
 | |
| function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {
 | |
|   for (let i2 = UNITS.length - 1; i2 >= UNITS.indexOf(minUnit); i2--) {
 | |
|     const unit = UNITS[i2];
 | |
|     if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) {
 | |
|       return unit;
 | |
|     }
 | |
|   }
 | |
|   return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];
 | |
| }
 | |
| function determineMajorUnit(unit) {
 | |
|   for (let i2 = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i2 < ilen; ++i2) {
 | |
|     if (INTERVALS[UNITS[i2]].common) {
 | |
|       return UNITS[i2];
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function addTick(ticks, time, timestamps) {
 | |
|   if (!timestamps) {
 | |
|     ticks[time] = true;
 | |
|   } else if (timestamps.length) {
 | |
|     const { lo, hi } = _lookup(timestamps, time);
 | |
|     const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi];
 | |
|     ticks[timestamp] = true;
 | |
|   }
 | |
| }
 | |
| function setMajorTicks(scale, ticks, map3, majorUnit) {
 | |
|   const adapter = scale._adapter;
 | |
|   const first = +adapter.startOf(ticks[0].value, majorUnit);
 | |
|   const last = ticks[ticks.length - 1].value;
 | |
|   let major, index;
 | |
|   for (major = first; major <= last; major = +adapter.add(major, 1, majorUnit)) {
 | |
|     index = map3[major];
 | |
|     if (index >= 0) {
 | |
|       ticks[index].major = true;
 | |
|     }
 | |
|   }
 | |
|   return ticks;
 | |
| }
 | |
| function ticksFromTimestamps(scale, values, majorUnit) {
 | |
|   const ticks = [];
 | |
|   const map3 = {};
 | |
|   const ilen = values.length;
 | |
|   let i2, value;
 | |
|   for (i2 = 0; i2 < ilen; ++i2) {
 | |
|     value = values[i2];
 | |
|     map3[value] = i2;
 | |
|     ticks.push({
 | |
|       value,
 | |
|       major: false
 | |
|     });
 | |
|   }
 | |
|   return ilen === 0 || !majorUnit ? ticks : setMajorTicks(scale, ticks, map3, majorUnit);
 | |
| }
 | |
| var TimeScale = class extends Scale {
 | |
|   constructor(props) {
 | |
|     super(props);
 | |
|     this._cache = {
 | |
|       data: [],
 | |
|       labels: [],
 | |
|       all: []
 | |
|     };
 | |
|     this._unit = "day";
 | |
|     this._majorUnit = void 0;
 | |
|     this._offsets = {};
 | |
|     this._normalized = false;
 | |
|     this._parseOpts = void 0;
 | |
|   }
 | |
|   init(scaleOpts, opts = {}) {
 | |
|     const time = scaleOpts.time || (scaleOpts.time = {});
 | |
|     const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date);
 | |
|     adapter.init(opts);
 | |
|     mergeIf(time.displayFormats, adapter.formats());
 | |
|     this._parseOpts = {
 | |
|       parser: time.parser,
 | |
|       round: time.round,
 | |
|       isoWeekday: time.isoWeekday
 | |
|     };
 | |
|     super.init(scaleOpts);
 | |
|     this._normalized = opts.normalized;
 | |
|   }
 | |
|   parse(raw, index) {
 | |
|     if (raw === void 0) {
 | |
|       return null;
 | |
|     }
 | |
|     return parse2(this, raw);
 | |
|   }
 | |
|   beforeLayout() {
 | |
|     super.beforeLayout();
 | |
|     this._cache = {
 | |
|       data: [],
 | |
|       labels: [],
 | |
|       all: []
 | |
|     };
 | |
|   }
 | |
|   determineDataLimits() {
 | |
|     const options = this.options;
 | |
|     const adapter = this._adapter;
 | |
|     const unit = options.time.unit || "day";
 | |
|     let { min, max, minDefined, maxDefined } = this.getUserBounds();
 | |
|     function _applyBounds(bounds) {
 | |
|       if (!minDefined && !isNaN(bounds.min)) {
 | |
|         min = Math.min(min, bounds.min);
 | |
|       }
 | |
|       if (!maxDefined && !isNaN(bounds.max)) {
 | |
|         max = Math.max(max, bounds.max);
 | |
|       }
 | |
|     }
 | |
|     if (!minDefined || !maxDefined) {
 | |
|       _applyBounds(this._getLabelBounds());
 | |
|       if (options.bounds !== "ticks" || options.ticks.source !== "labels") {
 | |
|         _applyBounds(this.getMinMax(false));
 | |
|       }
 | |
|     }
 | |
|     min = isNumberFinite(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit);
 | |
|     max = isNumberFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;
 | |
|     this.min = Math.min(min, max - 1);
 | |
|     this.max = Math.max(min + 1, max);
 | |
|   }
 | |
|   _getLabelBounds() {
 | |
|     const arr = this.getLabelTimestamps();
 | |
|     let min = Number.POSITIVE_INFINITY;
 | |
|     let max = Number.NEGATIVE_INFINITY;
 | |
|     if (arr.length) {
 | |
|       min = arr[0];
 | |
|       max = arr[arr.length - 1];
 | |
|     }
 | |
|     return {
 | |
|       min,
 | |
|       max
 | |
|     };
 | |
|   }
 | |
|   buildTicks() {
 | |
|     const options = this.options;
 | |
|     const timeOpts = options.time;
 | |
|     const tickOpts = options.ticks;
 | |
|     const timestamps = tickOpts.source === "labels" ? this.getLabelTimestamps() : this._generate();
 | |
|     if (options.bounds === "ticks" && timestamps.length) {
 | |
|       this.min = this._userMin || timestamps[0];
 | |
|       this.max = this._userMax || timestamps[timestamps.length - 1];
 | |
|     }
 | |
|     const min = this.min;
 | |
|     const max = this.max;
 | |
|     const ticks = _filterBetween(timestamps, min, max);
 | |
|     this._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min)) : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));
 | |
|     this._majorUnit = !tickOpts.major.enabled || this._unit === "year" ? void 0 : determineMajorUnit(this._unit);
 | |
|     this.initOffsets(timestamps);
 | |
|     if (options.reverse) {
 | |
|       ticks.reverse();
 | |
|     }
 | |
|     return ticksFromTimestamps(this, ticks, this._majorUnit);
 | |
|   }
 | |
|   afterAutoSkip() {
 | |
|     if (this.options.offsetAfterAutoskip) {
 | |
|       this.initOffsets(this.ticks.map((tick) => +tick.value));
 | |
|     }
 | |
|   }
 | |
|   initOffsets(timestamps = []) {
 | |
|     let start = 0;
 | |
|     let end = 0;
 | |
|     let first, last;
 | |
|     if (this.options.offset && timestamps.length) {
 | |
|       first = this.getDecimalForValue(timestamps[0]);
 | |
|       if (timestamps.length === 1) {
 | |
|         start = 1 - first;
 | |
|       } else {
 | |
|         start = (this.getDecimalForValue(timestamps[1]) - first) / 2;
 | |
|       }
 | |
|       last = this.getDecimalForValue(timestamps[timestamps.length - 1]);
 | |
|       if (timestamps.length === 1) {
 | |
|         end = last;
 | |
|       } else {
 | |
|         end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;
 | |
|       }
 | |
|     }
 | |
|     const limit = timestamps.length < 3 ? 0.5 : 0.25;
 | |
|     start = _limitValue(start, 0, limit);
 | |
|     end = _limitValue(end, 0, limit);
 | |
|     this._offsets = {
 | |
|       start,
 | |
|       end,
 | |
|       factor: 1 / (start + 1 + end)
 | |
|     };
 | |
|   }
 | |
|   _generate() {
 | |
|     const adapter = this._adapter;
 | |
|     const min = this.min;
 | |
|     const max = this.max;
 | |
|     const options = this.options;
 | |
|     const timeOpts = options.time;
 | |
|     const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));
 | |
|     const stepSize = valueOrDefault(options.ticks.stepSize, 1);
 | |
|     const weekday = minor === "week" ? timeOpts.isoWeekday : false;
 | |
|     const hasWeekday = isNumber(weekday) || weekday === true;
 | |
|     const ticks = {};
 | |
|     let first = min;
 | |
|     let time, count;
 | |
|     if (hasWeekday) {
 | |
|       first = +adapter.startOf(first, "isoWeek", weekday);
 | |
|     }
 | |
|     first = +adapter.startOf(first, hasWeekday ? "day" : minor);
 | |
|     if (adapter.diff(max, min, minor) > 1e5 * stepSize) {
 | |
|       throw new Error(min + " and " + max + " are too far apart with stepSize of " + stepSize + " " + minor);
 | |
|     }
 | |
|     const timestamps = options.ticks.source === "data" && this.getDataTimestamps();
 | |
|     for (time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++) {
 | |
|       addTick(ticks, time, timestamps);
 | |
|     }
 | |
|     if (time === max || options.bounds === "ticks" || count === 1) {
 | |
|       addTick(ticks, time, timestamps);
 | |
|     }
 | |
|     return Object.keys(ticks).sort(sorter).map((x2) => +x2);
 | |
|   }
 | |
|   getLabelForValue(value) {
 | |
|     const adapter = this._adapter;
 | |
|     const timeOpts = this.options.time;
 | |
|     if (timeOpts.tooltipFormat) {
 | |
|       return adapter.format(value, timeOpts.tooltipFormat);
 | |
|     }
 | |
|     return adapter.format(value, timeOpts.displayFormats.datetime);
 | |
|   }
 | |
|   format(value, format) {
 | |
|     const options = this.options;
 | |
|     const formats = options.time.displayFormats;
 | |
|     const unit = this._unit;
 | |
|     const fmt = format || formats[unit];
 | |
|     return this._adapter.format(value, fmt);
 | |
|   }
 | |
|   _tickFormatFunction(time, index, ticks, format) {
 | |
|     const options = this.options;
 | |
|     const formatter = options.ticks.callback;
 | |
|     if (formatter) {
 | |
|       return callback(formatter, [
 | |
|         time,
 | |
|         index,
 | |
|         ticks
 | |
|       ], this);
 | |
|     }
 | |
|     const formats = options.time.displayFormats;
 | |
|     const unit = this._unit;
 | |
|     const majorUnit = this._majorUnit;
 | |
|     const minorFormat = unit && formats[unit];
 | |
|     const majorFormat = majorUnit && formats[majorUnit];
 | |
|     const tick = ticks[index];
 | |
|     const major = majorUnit && majorFormat && tick && tick.major;
 | |
|     return this._adapter.format(time, format || (major ? majorFormat : minorFormat));
 | |
|   }
 | |
|   generateTickLabels(ticks) {
 | |
|     let i2, ilen, tick;
 | |
|     for (i2 = 0, ilen = ticks.length; i2 < ilen; ++i2) {
 | |
|       tick = ticks[i2];
 | |
|       tick.label = this._tickFormatFunction(tick.value, i2, ticks);
 | |
|     }
 | |
|   }
 | |
|   getDecimalForValue(value) {
 | |
|     return value === null ? NaN : (value - this.min) / (this.max - this.min);
 | |
|   }
 | |
|   getPixelForValue(value) {
 | |
|     const offsets = this._offsets;
 | |
|     const pos = this.getDecimalForValue(value);
 | |
|     return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);
 | |
|   }
 | |
|   getValueForPixel(pixel) {
 | |
|     const offsets = this._offsets;
 | |
|     const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
 | |
|     return this.min + pos * (this.max - this.min);
 | |
|   }
 | |
|   _getLabelSize(label) {
 | |
|     const ticksOpts = this.options.ticks;
 | |
|     const tickLabelWidth = this.ctx.measureText(label).width;
 | |
|     const angle = toRadians(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);
 | |
|     const cosRotation = Math.cos(angle);
 | |
|     const sinRotation = Math.sin(angle);
 | |
|     const tickFontSize = this._resolveTickFontOptions(0).size;
 | |
|     return {
 | |
|       w: tickLabelWidth * cosRotation + tickFontSize * sinRotation,
 | |
|       h: tickLabelWidth * sinRotation + tickFontSize * cosRotation
 | |
|     };
 | |
|   }
 | |
|   _getLabelCapacity(exampleTime) {
 | |
|     const timeOpts = this.options.time;
 | |
|     const displayFormats = timeOpts.displayFormats;
 | |
|     const format = displayFormats[timeOpts.unit] || displayFormats.millisecond;
 | |
|     const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [
 | |
|       exampleTime
 | |
|     ], this._majorUnit), format);
 | |
|     const size = this._getLabelSize(exampleLabel);
 | |
|     const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;
 | |
|     return capacity > 0 ? capacity : 1;
 | |
|   }
 | |
|   getDataTimestamps() {
 | |
|     let timestamps = this._cache.data || [];
 | |
|     let i2, ilen;
 | |
|     if (timestamps.length) {
 | |
|       return timestamps;
 | |
|     }
 | |
|     const metas = this.getMatchingVisibleMetas();
 | |
|     if (this._normalized && metas.length) {
 | |
|       return this._cache.data = metas[0].controller.getAllParsedValues(this);
 | |
|     }
 | |
|     for (i2 = 0, ilen = metas.length; i2 < ilen; ++i2) {
 | |
|       timestamps = timestamps.concat(metas[i2].controller.getAllParsedValues(this));
 | |
|     }
 | |
|     return this._cache.data = this.normalize(timestamps);
 | |
|   }
 | |
|   getLabelTimestamps() {
 | |
|     const timestamps = this._cache.labels || [];
 | |
|     let i2, ilen;
 | |
|     if (timestamps.length) {
 | |
|       return timestamps;
 | |
|     }
 | |
|     const labels = this.getLabels();
 | |
|     for (i2 = 0, ilen = labels.length; i2 < ilen; ++i2) {
 | |
|       timestamps.push(parse2(this, labels[i2]));
 | |
|     }
 | |
|     return this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps);
 | |
|   }
 | |
|   normalize(values) {
 | |
|     return _arrayUnique(values.sort(sorter));
 | |
|   }
 | |
| };
 | |
| __publicField(TimeScale, "id", "time");
 | |
| __publicField(TimeScale, "defaults", {
 | |
|   bounds: "data",
 | |
|   adapters: {},
 | |
|   time: {
 | |
|     parser: false,
 | |
|     unit: false,
 | |
|     round: false,
 | |
|     isoWeekday: false,
 | |
|     minUnit: "millisecond",
 | |
|     displayFormats: {}
 | |
|   },
 | |
|   ticks: {
 | |
|     source: "auto",
 | |
|     callback: false,
 | |
|     major: {
 | |
|       enabled: false
 | |
|     }
 | |
|   }
 | |
| });
 | |
| function interpolate3(table, val, reverse) {
 | |
|   let lo = 0;
 | |
|   let hi = table.length - 1;
 | |
|   let prevSource, nextSource, prevTarget, nextTarget;
 | |
|   if (reverse) {
 | |
|     if (val >= table[lo].pos && val <= table[hi].pos) {
 | |
|       ({ lo, hi } = _lookupByKey(table, "pos", val));
 | |
|     }
 | |
|     ({ pos: prevSource, time: prevTarget } = table[lo]);
 | |
|     ({ pos: nextSource, time: nextTarget } = table[hi]);
 | |
|   } else {
 | |
|     if (val >= table[lo].time && val <= table[hi].time) {
 | |
|       ({ lo, hi } = _lookupByKey(table, "time", val));
 | |
|     }
 | |
|     ({ time: prevSource, pos: prevTarget } = table[lo]);
 | |
|     ({ time: nextSource, pos: nextTarget } = table[hi]);
 | |
|   }
 | |
|   const span = nextSource - prevSource;
 | |
|   return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget;
 | |
| }
 | |
| var TimeSeriesScale = class extends TimeScale {
 | |
|   constructor(props) {
 | |
|     super(props);
 | |
|     this._table = [];
 | |
|     this._minPos = void 0;
 | |
|     this._tableRange = void 0;
 | |
|   }
 | |
|   initOffsets() {
 | |
|     const timestamps = this._getTimestampsForTable();
 | |
|     const table = this._table = this.buildLookupTable(timestamps);
 | |
|     this._minPos = interpolate3(table, this.min);
 | |
|     this._tableRange = interpolate3(table, this.max) - this._minPos;
 | |
|     super.initOffsets(timestamps);
 | |
|   }
 | |
|   buildLookupTable(timestamps) {
 | |
|     const { min, max } = this;
 | |
|     const items = [];
 | |
|     const table = [];
 | |
|     let i2, ilen, prev, curr, next;
 | |
|     for (i2 = 0, ilen = timestamps.length; i2 < ilen; ++i2) {
 | |
|       curr = timestamps[i2];
 | |
|       if (curr >= min && curr <= max) {
 | |
|         items.push(curr);
 | |
|       }
 | |
|     }
 | |
|     if (items.length < 2) {
 | |
|       return [
 | |
|         {
 | |
|           time: min,
 | |
|           pos: 0
 | |
|         },
 | |
|         {
 | |
|           time: max,
 | |
|           pos: 1
 | |
|         }
 | |
|       ];
 | |
|     }
 | |
|     for (i2 = 0, ilen = items.length; i2 < ilen; ++i2) {
 | |
|       next = items[i2 + 1];
 | |
|       prev = items[i2 - 1];
 | |
|       curr = items[i2];
 | |
|       if (Math.round((next + prev) / 2) !== curr) {
 | |
|         table.push({
 | |
|           time: curr,
 | |
|           pos: i2 / (ilen - 1)
 | |
|         });
 | |
|       }
 | |
|     }
 | |
|     return table;
 | |
|   }
 | |
|   _generate() {
 | |
|     const min = this.min;
 | |
|     const max = this.max;
 | |
|     let timestamps = super.getDataTimestamps();
 | |
|     if (!timestamps.includes(min) || !timestamps.length) {
 | |
|       timestamps.splice(0, 0, min);
 | |
|     }
 | |
|     if (!timestamps.includes(max) || timestamps.length === 1) {
 | |
|       timestamps.push(max);
 | |
|     }
 | |
|     return timestamps.sort((a2, b2) => a2 - b2);
 | |
|   }
 | |
|   _getTimestampsForTable() {
 | |
|     let timestamps = this._cache.all || [];
 | |
|     if (timestamps.length) {
 | |
|       return timestamps;
 | |
|     }
 | |
|     const data = this.getDataTimestamps();
 | |
|     const label = this.getLabelTimestamps();
 | |
|     if (data.length && label.length) {
 | |
|       timestamps = this.normalize(data.concat(label));
 | |
|     } else {
 | |
|       timestamps = data.length ? data : label;
 | |
|     }
 | |
|     timestamps = this._cache.all = timestamps;
 | |
|     return timestamps;
 | |
|   }
 | |
|   getDecimalForValue(value) {
 | |
|     return (interpolate3(this._table, value) - this._minPos) / this._tableRange;
 | |
|   }
 | |
|   getValueForPixel(pixel) {
 | |
|     const offsets = this._offsets;
 | |
|     const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
 | |
|     return interpolate3(this._table, decimal * this._tableRange + this._minPos, true);
 | |
|   }
 | |
| };
 | |
| __publicField(TimeSeriesScale, "id", "timeseries");
 | |
| __publicField(TimeSeriesScale, "defaults", TimeScale.defaults);
 | |
| 
 | |
| // node_modules/.pnpm/gridjs@6.2.0/node_modules/gridjs/dist/gridjs.module.js
 | |
| function t2(t3, n2) {
 | |
|   for (var e2 = 0; e2 < n2.length; e2++) {
 | |
|     var r2 = n2[e2];
 | |
|     r2.enumerable = r2.enumerable || false, r2.configurable = true, "value" in r2 && (r2.writable = true), Object.defineProperty(t3, "symbol" == typeof (o2 = function(t4, n3) {
 | |
|       if ("object" != typeof t4 || null === t4) return t4;
 | |
|       var e3 = t4[Symbol.toPrimitive];
 | |
|       if (void 0 !== e3) {
 | |
|         var r3 = e3.call(t4, "string");
 | |
|         if ("object" != typeof r3) return r3;
 | |
|         throw new TypeError("@@toPrimitive must return a primitive value.");
 | |
|       }
 | |
|       return String(t4);
 | |
|     }(r2.key)) ? o2 : String(o2), r2);
 | |
|   }
 | |
|   var o2;
 | |
| }
 | |
| function n(n2, e2, r2) {
 | |
|   return e2 && t2(n2.prototype, e2), r2 && t2(n2, r2), Object.defineProperty(n2, "prototype", { writable: false }), n2;
 | |
| }
 | |
| function e() {
 | |
|   return e = Object.assign ? Object.assign.bind() : function(t3) {
 | |
|     for (var n2 = 1; n2 < arguments.length; n2++) {
 | |
|       var e2 = arguments[n2];
 | |
|       for (var r2 in e2) Object.prototype.hasOwnProperty.call(e2, r2) && (t3[r2] = e2[r2]);
 | |
|     }
 | |
|     return t3;
 | |
|   }, e.apply(this, arguments);
 | |
| }
 | |
| function r(t3, n2) {
 | |
|   t3.prototype = Object.create(n2.prototype), t3.prototype.constructor = t3, o(t3, n2);
 | |
| }
 | |
| function o(t3, n2) {
 | |
|   return o = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(t4, n3) {
 | |
|     return t4.__proto__ = n3, t4;
 | |
|   }, o(t3, n2);
 | |
| }
 | |
| function i(t3) {
 | |
|   if (void 0 === t3) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
 | |
|   return t3;
 | |
| }
 | |
| function u(t3, n2) {
 | |
|   (null == n2 || n2 > t3.length) && (n2 = t3.length);
 | |
|   for (var e2 = 0, r2 = new Array(n2); e2 < n2; e2++) r2[e2] = t3[e2];
 | |
|   return r2;
 | |
| }
 | |
| function s(t3, n2) {
 | |
|   var e2 = "undefined" != typeof Symbol && t3[Symbol.iterator] || t3["@@iterator"];
 | |
|   if (e2) return (e2 = e2.call(t3)).next.bind(e2);
 | |
|   if (Array.isArray(t3) || (e2 = function(t4, n3) {
 | |
|     if (t4) {
 | |
|       if ("string" == typeof t4) return u(t4, n3);
 | |
|       var e3 = Object.prototype.toString.call(t4).slice(8, -1);
 | |
|       return "Object" === e3 && t4.constructor && (e3 = t4.constructor.name), "Map" === e3 || "Set" === e3 ? Array.from(t4) : "Arguments" === e3 || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e3) ? u(t4, n3) : void 0;
 | |
|     }
 | |
|   }(t3)) || n2 && t3 && "number" == typeof t3.length) {
 | |
|     e2 && (t3 = e2);
 | |
|     var r2 = 0;
 | |
|     return function() {
 | |
|       return r2 >= t3.length ? { done: true } : { done: false, value: t3[r2++] };
 | |
|     };
 | |
|   }
 | |
|   throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
 | |
| }
 | |
| var a;
 | |
| !function(t3) {
 | |
|   t3[t3.Init = 0] = "Init", t3[t3.Loading = 1] = "Loading", t3[t3.Loaded = 2] = "Loaded", t3[t3.Rendered = 3] = "Rendered", t3[t3.Error = 4] = "Error";
 | |
| }(a || (a = {}));
 | |
| var l;
 | |
| var c;
 | |
| var f;
 | |
| var p;
 | |
| var d;
 | |
| var h;
 | |
| var _;
 | |
| var m = {};
 | |
| var v = [];
 | |
| var y = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
 | |
| function g(t3, n2) {
 | |
|   for (var e2 in n2) t3[e2] = n2[e2];
 | |
|   return t3;
 | |
| }
 | |
| function b(t3) {
 | |
|   var n2 = t3.parentNode;
 | |
|   n2 && n2.removeChild(t3);
 | |
| }
 | |
| function w(t3, n2, e2) {
 | |
|   var r2, o2, i2, u2 = {};
 | |
|   for (i2 in n2) "key" == i2 ? r2 = n2[i2] : "ref" == i2 ? o2 = n2[i2] : u2[i2] = n2[i2];
 | |
|   if (arguments.length > 2 && (u2.children = arguments.length > 3 ? l.call(arguments, 2) : e2), "function" == typeof t3 && null != t3.defaultProps) for (i2 in t3.defaultProps) void 0 === u2[i2] && (u2[i2] = t3.defaultProps[i2]);
 | |
|   return x(t3, u2, r2, o2, null);
 | |
| }
 | |
| function x(t3, n2, e2, r2, o2) {
 | |
|   var i2 = { type: t3, props: n2, key: e2, ref: r2, __k: null, __: null, __b: 0, __e: null, __d: void 0, __c: null, __h: null, constructor: void 0, __v: null == o2 ? ++f : o2 };
 | |
|   return null == o2 && null != c.vnode && c.vnode(i2), i2;
 | |
| }
 | |
| function S(t3) {
 | |
|   return t3.children;
 | |
| }
 | |
| function N(t3, n2) {
 | |
|   this.props = t3, this.context = n2;
 | |
| }
 | |
| function P(t3, n2) {
 | |
|   if (null == n2) return t3.__ ? P(t3.__, t3.__.__k.indexOf(t3) + 1) : null;
 | |
|   for (var e2; n2 < t3.__k.length; n2++) if (null != (e2 = t3.__k[n2]) && null != e2.__e) return e2.__e;
 | |
|   return "function" == typeof t3.type ? P(t3) : null;
 | |
| }
 | |
| function C(t3) {
 | |
|   var n2, e2;
 | |
|   if (null != (t3 = t3.__) && null != t3.__c) {
 | |
|     for (t3.__e = t3.__c.base = null, n2 = 0; n2 < t3.__k.length; n2++) if (null != (e2 = t3.__k[n2]) && null != e2.__e) {
 | |
|       t3.__e = t3.__c.base = e2.__e;
 | |
|       break;
 | |
|     }
 | |
|     return C(t3);
 | |
|   }
 | |
| }
 | |
| function E(t3) {
 | |
|   (!t3.__d && (t3.__d = true) && d.push(t3) && !I.__r++ || h !== c.debounceRendering) && ((h = c.debounceRendering) || setTimeout)(I);
 | |
| }
 | |
| function I() {
 | |
|   for (var t3; I.__r = d.length; ) t3 = d.sort(function(t4, n2) {
 | |
|     return t4.__v.__b - n2.__v.__b;
 | |
|   }), d = [], t3.some(function(t4) {
 | |
|     var n2, e2, r2, o2, i2, u2;
 | |
|     t4.__d && (i2 = (o2 = (n2 = t4).__v).__e, (u2 = n2.__P) && (e2 = [], (r2 = g({}, o2)).__v = o2.__v + 1, M(u2, o2, r2, n2.__n, void 0 !== u2.ownerSVGElement, null != o2.__h ? [i2] : null, e2, null == i2 ? P(o2) : i2, o2.__h), F(e2, o2), o2.__e != i2 && C(o2)));
 | |
|   });
 | |
| }
 | |
| function T(t3, n2, e2, r2, o2, i2, u2, s2, a2, l2) {
 | |
|   var c2, f2, p2, d2, h6, _2, y2, g2 = r2 && r2.__k || v, b2 = g2.length;
 | |
|   for (e2.__k = [], c2 = 0; c2 < n2.length; c2++) if (null != (d2 = e2.__k[c2] = null == (d2 = n2[c2]) || "boolean" == typeof d2 ? null : "string" == typeof d2 || "number" == typeof d2 || "bigint" == typeof d2 ? x(null, d2, null, null, d2) : Array.isArray(d2) ? x(S, { children: d2 }, null, null, null) : d2.__b > 0 ? x(d2.type, d2.props, d2.key, d2.ref ? d2.ref : null, d2.__v) : d2)) {
 | |
|     if (d2.__ = e2, d2.__b = e2.__b + 1, null === (p2 = g2[c2]) || p2 && d2.key == p2.key && d2.type === p2.type) g2[c2] = void 0;
 | |
|     else for (f2 = 0; f2 < b2; f2++) {
 | |
|       if ((p2 = g2[f2]) && d2.key == p2.key && d2.type === p2.type) {
 | |
|         g2[f2] = void 0;
 | |
|         break;
 | |
|       }
 | |
|       p2 = null;
 | |
|     }
 | |
|     M(t3, d2, p2 = p2 || m, o2, i2, u2, s2, a2, l2), h6 = d2.__e, (f2 = d2.ref) && p2.ref != f2 && (y2 || (y2 = []), p2.ref && y2.push(p2.ref, null, d2), y2.push(f2, d2.__c || h6, d2)), null != h6 ? (null == _2 && (_2 = h6), "function" == typeof d2.type && d2.__k === p2.__k ? d2.__d = a2 = L(d2, a2, t3) : a2 = A(t3, d2, p2, g2, h6, a2), "function" == typeof e2.type && (e2.__d = a2)) : a2 && p2.__e == a2 && a2.parentNode != t3 && (a2 = P(p2));
 | |
|   }
 | |
|   for (e2.__e = _2, c2 = b2; c2--; ) null != g2[c2] && W(g2[c2], g2[c2]);
 | |
|   if (y2) for (c2 = 0; c2 < y2.length; c2++) U(y2[c2], y2[++c2], y2[++c2]);
 | |
| }
 | |
| function L(t3, n2, e2) {
 | |
|   for (var r2, o2 = t3.__k, i2 = 0; o2 && i2 < o2.length; i2++) (r2 = o2[i2]) && (r2.__ = t3, n2 = "function" == typeof r2.type ? L(r2, n2, e2) : A(e2, r2, r2, o2, r2.__e, n2));
 | |
|   return n2;
 | |
| }
 | |
| function A(t3, n2, e2, r2, o2, i2) {
 | |
|   var u2, s2, a2;
 | |
|   if (void 0 !== n2.__d) u2 = n2.__d, n2.__d = void 0;
 | |
|   else if (null == e2 || o2 != i2 || null == o2.parentNode) t: if (null == i2 || i2.parentNode !== t3) t3.appendChild(o2), u2 = null;
 | |
|   else {
 | |
|     for (s2 = i2, a2 = 0; (s2 = s2.nextSibling) && a2 < r2.length; a2 += 1) if (s2 == o2) break t;
 | |
|     t3.insertBefore(o2, i2), u2 = i2;
 | |
|   }
 | |
|   return void 0 !== u2 ? u2 : o2.nextSibling;
 | |
| }
 | |
| function O(t3, n2, e2) {
 | |
|   "-" === n2[0] ? t3.setProperty(n2, e2) : t3[n2] = null == e2 ? "" : "number" != typeof e2 || y.test(n2) ? e2 : e2 + "px";
 | |
| }
 | |
| function H(t3, n2, e2, r2, o2) {
 | |
|   var i2;
 | |
|   t: if ("style" === n2) if ("string" == typeof e2) t3.style.cssText = e2;
 | |
|   else {
 | |
|     if ("string" == typeof r2 && (t3.style.cssText = r2 = ""), r2) for (n2 in r2) e2 && n2 in e2 || O(t3.style, n2, "");
 | |
|     if (e2) for (n2 in e2) r2 && e2[n2] === r2[n2] || O(t3.style, n2, e2[n2]);
 | |
|   }
 | |
|   else if ("o" === n2[0] && "n" === n2[1]) i2 = n2 !== (n2 = n2.replace(/Capture$/, "")), n2 = n2.toLowerCase() in t3 ? n2.toLowerCase().slice(2) : n2.slice(2), t3.l || (t3.l = {}), t3.l[n2 + i2] = e2, e2 ? r2 || t3.addEventListener(n2, i2 ? D : j, i2) : t3.removeEventListener(n2, i2 ? D : j, i2);
 | |
|   else if ("dangerouslySetInnerHTML" !== n2) {
 | |
|     if (o2) n2 = n2.replace(/xlink(H|:h)/, "h").replace(/sName$/, "s");
 | |
|     else if ("href" !== n2 && "list" !== n2 && "form" !== n2 && "tabIndex" !== n2 && "download" !== n2 && n2 in t3) try {
 | |
|       t3[n2] = null == e2 ? "" : e2;
 | |
|       break t;
 | |
|     } catch (t4) {
 | |
|     }
 | |
|     "function" == typeof e2 || (null == e2 || false === e2 && -1 == n2.indexOf("-") ? t3.removeAttribute(n2) : t3.setAttribute(n2, e2));
 | |
|   }
 | |
| }
 | |
| function j(t3) {
 | |
|   this.l[t3.type + false](c.event ? c.event(t3) : t3);
 | |
| }
 | |
| function D(t3) {
 | |
|   this.l[t3.type + true](c.event ? c.event(t3) : t3);
 | |
| }
 | |
| function M(t3, n2, e2, r2, o2, i2, u2, s2, a2) {
 | |
|   var l2, f2, p2, d2, h6, _2, m2, v2, y2, b2, w2, x2, k, P2, C2, E2 = n2.type;
 | |
|   if (void 0 !== n2.constructor) return null;
 | |
|   null != e2.__h && (a2 = e2.__h, s2 = n2.__e = e2.__e, n2.__h = null, i2 = [s2]), (l2 = c.__b) && l2(n2);
 | |
|   try {
 | |
|     t: if ("function" == typeof E2) {
 | |
|       if (v2 = n2.props, y2 = (l2 = E2.contextType) && r2[l2.__c], b2 = l2 ? y2 ? y2.props.value : l2.__ : r2, e2.__c ? m2 = (f2 = n2.__c = e2.__c).__ = f2.__E : ("prototype" in E2 && E2.prototype.render ? n2.__c = f2 = new E2(v2, b2) : (n2.__c = f2 = new N(v2, b2), f2.constructor = E2, f2.render = B), y2 && y2.sub(f2), f2.props = v2, f2.state || (f2.state = {}), f2.context = b2, f2.__n = r2, p2 = f2.__d = true, f2.__h = [], f2._sb = []), null == f2.__s && (f2.__s = f2.state), null != E2.getDerivedStateFromProps && (f2.__s == f2.state && (f2.__s = g({}, f2.__s)), g(f2.__s, E2.getDerivedStateFromProps(v2, f2.__s))), d2 = f2.props, h6 = f2.state, p2) null == E2.getDerivedStateFromProps && null != f2.componentWillMount && f2.componentWillMount(), null != f2.componentDidMount && f2.__h.push(f2.componentDidMount);
 | |
|       else {
 | |
|         if (null == E2.getDerivedStateFromProps && v2 !== d2 && null != f2.componentWillReceiveProps && f2.componentWillReceiveProps(v2, b2), !f2.__e && null != f2.shouldComponentUpdate && false === f2.shouldComponentUpdate(v2, f2.__s, b2) || n2.__v === e2.__v) {
 | |
|           for (f2.props = v2, f2.state = f2.__s, n2.__v !== e2.__v && (f2.__d = false), f2.__v = n2, n2.__e = e2.__e, n2.__k = e2.__k, n2.__k.forEach(function(t4) {
 | |
|             t4 && (t4.__ = n2);
 | |
|           }), w2 = 0; w2 < f2._sb.length; w2++) f2.__h.push(f2._sb[w2]);
 | |
|           f2._sb = [], f2.__h.length && u2.push(f2);
 | |
|           break t;
 | |
|         }
 | |
|         null != f2.componentWillUpdate && f2.componentWillUpdate(v2, f2.__s, b2), null != f2.componentDidUpdate && f2.__h.push(function() {
 | |
|           f2.componentDidUpdate(d2, h6, _2);
 | |
|         });
 | |
|       }
 | |
|       if (f2.context = b2, f2.props = v2, f2.__v = n2, f2.__P = t3, x2 = c.__r, k = 0, "prototype" in E2 && E2.prototype.render) {
 | |
|         for (f2.state = f2.__s, f2.__d = false, x2 && x2(n2), l2 = f2.render(f2.props, f2.state, f2.context), P2 = 0; P2 < f2._sb.length; P2++) f2.__h.push(f2._sb[P2]);
 | |
|         f2._sb = [];
 | |
|       } else do {
 | |
|         f2.__d = false, x2 && x2(n2), l2 = f2.render(f2.props, f2.state, f2.context), f2.state = f2.__s;
 | |
|       } while (f2.__d && ++k < 25);
 | |
|       f2.state = f2.__s, null != f2.getChildContext && (r2 = g(g({}, r2), f2.getChildContext())), p2 || null == f2.getSnapshotBeforeUpdate || (_2 = f2.getSnapshotBeforeUpdate(d2, h6)), C2 = null != l2 && l2.type === S && null == l2.key ? l2.props.children : l2, T(t3, Array.isArray(C2) ? C2 : [C2], n2, e2, r2, o2, i2, u2, s2, a2), f2.base = n2.__e, n2.__h = null, f2.__h.length && u2.push(f2), m2 && (f2.__E = f2.__ = null), f2.__e = false;
 | |
|     } else null == i2 && n2.__v === e2.__v ? (n2.__k = e2.__k, n2.__e = e2.__e) : n2.__e = R(e2.__e, n2, e2, r2, o2, i2, u2, a2);
 | |
|     (l2 = c.diffed) && l2(n2);
 | |
|   } catch (t4) {
 | |
|     n2.__v = null, (a2 || null != i2) && (n2.__e = s2, n2.__h = !!a2, i2[i2.indexOf(s2)] = null), c.__e(t4, n2, e2);
 | |
|   }
 | |
| }
 | |
| function F(t3, n2) {
 | |
|   c.__c && c.__c(n2, t3), t3.some(function(n3) {
 | |
|     try {
 | |
|       t3 = n3.__h, n3.__h = [], t3.some(function(t4) {
 | |
|         t4.call(n3);
 | |
|       });
 | |
|     } catch (t4) {
 | |
|       c.__e(t4, n3.__v);
 | |
|     }
 | |
|   });
 | |
| }
 | |
| function R(t3, n2, e2, r2, o2, i2, u2, s2) {
 | |
|   var a2, c2, f2, p2 = e2.props, d2 = n2.props, h6 = n2.type, _2 = 0;
 | |
|   if ("svg" === h6 && (o2 = true), null != i2) {
 | |
|     for (; _2 < i2.length; _2++) if ((a2 = i2[_2]) && "setAttribute" in a2 == !!h6 && (h6 ? a2.localName === h6 : 3 === a2.nodeType)) {
 | |
|       t3 = a2, i2[_2] = null;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   if (null == t3) {
 | |
|     if (null === h6) return document.createTextNode(d2);
 | |
|     t3 = o2 ? document.createElementNS("http://www.w3.org/2000/svg", h6) : document.createElement(h6, d2.is && d2), i2 = null, s2 = false;
 | |
|   }
 | |
|   if (null === h6) p2 === d2 || s2 && t3.data === d2 || (t3.data = d2);
 | |
|   else {
 | |
|     if (i2 = i2 && l.call(t3.childNodes), c2 = (p2 = e2.props || m).dangerouslySetInnerHTML, f2 = d2.dangerouslySetInnerHTML, !s2) {
 | |
|       if (null != i2) for (p2 = {}, _2 = 0; _2 < t3.attributes.length; _2++) p2[t3.attributes[_2].name] = t3.attributes[_2].value;
 | |
|       (f2 || c2) && (f2 && (c2 && f2.__html == c2.__html || f2.__html === t3.innerHTML) || (t3.innerHTML = f2 && f2.__html || ""));
 | |
|     }
 | |
|     if (function(t4, n3, e3, r3, o3) {
 | |
|       var i3;
 | |
|       for (i3 in e3) "children" === i3 || "key" === i3 || i3 in n3 || H(t4, i3, null, e3[i3], r3);
 | |
|       for (i3 in n3) o3 && "function" != typeof n3[i3] || "children" === i3 || "key" === i3 || "value" === i3 || "checked" === i3 || e3[i3] === n3[i3] || H(t4, i3, n3[i3], e3[i3], r3);
 | |
|     }(t3, d2, p2, o2, s2), f2) n2.__k = [];
 | |
|     else if (_2 = n2.props.children, T(t3, Array.isArray(_2) ? _2 : [_2], n2, e2, r2, o2 && "foreignObject" !== h6, i2, u2, i2 ? i2[0] : e2.__k && P(e2, 0), s2), null != i2) for (_2 = i2.length; _2--; ) null != i2[_2] && b(i2[_2]);
 | |
|     s2 || ("value" in d2 && void 0 !== (_2 = d2.value) && (_2 !== t3.value || "progress" === h6 && !_2 || "option" === h6 && _2 !== p2.value) && H(t3, "value", _2, p2.value, false), "checked" in d2 && void 0 !== (_2 = d2.checked) && _2 !== t3.checked && H(t3, "checked", _2, p2.checked, false));
 | |
|   }
 | |
|   return t3;
 | |
| }
 | |
| function U(t3, n2, e2) {
 | |
|   try {
 | |
|     "function" == typeof t3 ? t3(n2) : t3.current = n2;
 | |
|   } catch (t4) {
 | |
|     c.__e(t4, e2);
 | |
|   }
 | |
| }
 | |
| function W(t3, n2, e2) {
 | |
|   var r2, o2;
 | |
|   if (c.unmount && c.unmount(t3), (r2 = t3.ref) && (r2.current && r2.current !== t3.__e || U(r2, null, n2)), null != (r2 = t3.__c)) {
 | |
|     if (r2.componentWillUnmount) try {
 | |
|       r2.componentWillUnmount();
 | |
|     } catch (t4) {
 | |
|       c.__e(t4, n2);
 | |
|     }
 | |
|     r2.base = r2.__P = null, t3.__c = void 0;
 | |
|   }
 | |
|   if (r2 = t3.__k) for (o2 = 0; o2 < r2.length; o2++) r2[o2] && W(r2[o2], n2, e2 || "function" != typeof t3.type);
 | |
|   e2 || null == t3.__e || b(t3.__e), t3.__ = t3.__e = t3.__d = void 0;
 | |
| }
 | |
| function B(t3, n2, e2) {
 | |
|   return this.constructor(t3, e2);
 | |
| }
 | |
| function q(t3, n2, e2) {
 | |
|   var r2, o2, i2;
 | |
|   c.__ && c.__(t3, n2), o2 = (r2 = "function" == typeof e2) ? null : e2 && e2.__k || n2.__k, i2 = [], M(n2, t3 = (!r2 && e2 || n2).__k = w(S, null, [t3]), o2 || m, m, void 0 !== n2.ownerSVGElement, !r2 && e2 ? [e2] : o2 ? null : n2.firstChild ? l.call(n2.childNodes) : null, i2, !r2 && e2 ? e2 : o2 ? o2.__e : n2.firstChild, r2), F(i2, t3);
 | |
| }
 | |
| function z() {
 | |
|   return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(t3) {
 | |
|     var n2 = 16 * Math.random() | 0;
 | |
|     return ("x" == t3 ? n2 : 3 & n2 | 8).toString(16);
 | |
|   });
 | |
| }
 | |
| l = v.slice, c = { __e: function(t3, n2, e2, r2) {
 | |
|   for (var o2, i2, u2; n2 = n2.__; ) if ((o2 = n2.__c) && !o2.__) try {
 | |
|     if ((i2 = o2.constructor) && null != i2.getDerivedStateFromError && (o2.setState(i2.getDerivedStateFromError(t3)), u2 = o2.__d), null != o2.componentDidCatch && (o2.componentDidCatch(t3, r2 || {}), u2 = o2.__d), u2) return o2.__E = o2;
 | |
|   } catch (n3) {
 | |
|     t3 = n3;
 | |
|   }
 | |
|   throw t3;
 | |
| } }, f = 0, p = function(t3) {
 | |
|   return null != t3 && void 0 === t3.constructor;
 | |
| }, N.prototype.setState = function(t3, n2) {
 | |
|   var e2;
 | |
|   e2 = null != this.__s && this.__s !== this.state ? this.__s : this.__s = g({}, this.state), "function" == typeof t3 && (t3 = t3(g({}, e2), this.props)), t3 && g(e2, t3), null != t3 && this.__v && (n2 && this._sb.push(n2), E(this));
 | |
| }, N.prototype.forceUpdate = function(t3) {
 | |
|   this.__v && (this.__e = true, t3 && this.__h.push(t3), E(this));
 | |
| }, N.prototype.render = S, d = [], I.__r = 0, _ = 0;
 | |
| var V = /* @__PURE__ */ function() {
 | |
|   function t3(t4) {
 | |
|     this._id = void 0, this._id = t4 || z();
 | |
|   }
 | |
|   return n(t3, [{ key: "id", get: function() {
 | |
|     return this._id;
 | |
|   } }]), t3;
 | |
| }();
 | |
| function $(t3) {
 | |
|   return w(t3.parentElement || "span", { dangerouslySetInnerHTML: { __html: t3.content } });
 | |
| }
 | |
| function G(t3, n2) {
 | |
|   return w($, { content: t3, parentElement: n2 });
 | |
| }
 | |
| var K;
 | |
| var X = /* @__PURE__ */ function(t3) {
 | |
|   function n2(n3) {
 | |
|     var e3;
 | |
|     return (e3 = t3.call(this) || this).data = void 0, e3.update(n3), e3;
 | |
|   }
 | |
|   r(n2, t3);
 | |
|   var e2 = n2.prototype;
 | |
|   return e2.cast = function(t4) {
 | |
|     return t4 instanceof HTMLElement ? G(t4.outerHTML) : t4;
 | |
|   }, e2.update = function(t4) {
 | |
|     return this.data = this.cast(t4), this;
 | |
|   }, n2;
 | |
| }(V);
 | |
| var Z = /* @__PURE__ */ function(t3) {
 | |
|   function e2(n2) {
 | |
|     var e3;
 | |
|     return (e3 = t3.call(this) || this)._cells = void 0, e3.cells = n2 || [], e3;
 | |
|   }
 | |
|   r(e2, t3);
 | |
|   var o2 = e2.prototype;
 | |
|   return o2.cell = function(t4) {
 | |
|     return this._cells[t4];
 | |
|   }, o2.toArray = function() {
 | |
|     return this.cells.map(function(t4) {
 | |
|       return t4.data;
 | |
|     });
 | |
|   }, e2.fromCells = function(t4) {
 | |
|     return new e2(t4.map(function(t5) {
 | |
|       return new X(t5.data);
 | |
|     }));
 | |
|   }, n(e2, [{ key: "cells", get: function() {
 | |
|     return this._cells;
 | |
|   }, set: function(t4) {
 | |
|     this._cells = t4;
 | |
|   } }, { key: "length", get: function() {
 | |
|     return this.cells.length;
 | |
|   } }]), e2;
 | |
| }(V);
 | |
| var J = /* @__PURE__ */ function(t3) {
 | |
|   function e2(n2) {
 | |
|     var e3;
 | |
|     return (e3 = t3.call(this) || this)._rows = void 0, e3._length = void 0, e3.rows = n2 instanceof Array ? n2 : n2 instanceof Z ? [n2] : [], e3;
 | |
|   }
 | |
|   return r(e2, t3), e2.prototype.toArray = function() {
 | |
|     return this.rows.map(function(t4) {
 | |
|       return t4.toArray();
 | |
|     });
 | |
|   }, e2.fromRows = function(t4) {
 | |
|     return new e2(t4.map(function(t5) {
 | |
|       return Z.fromCells(t5.cells);
 | |
|     }));
 | |
|   }, e2.fromArray = function(t4) {
 | |
|     return new e2((t4 = function(t5) {
 | |
|       return !t5[0] || t5[0] instanceof Array ? t5 : [t5];
 | |
|     }(t4)).map(function(t5) {
 | |
|       return new Z(t5.map(function(t6) {
 | |
|         return new X(t6);
 | |
|       }));
 | |
|     }));
 | |
|   }, n(e2, [{ key: "rows", get: function() {
 | |
|     return this._rows;
 | |
|   }, set: function(t4) {
 | |
|     this._rows = t4;
 | |
|   } }, { key: "length", get: function() {
 | |
|     return this._length || this.rows.length;
 | |
|   }, set: function(t4) {
 | |
|     this._length = t4;
 | |
|   } }]), e2;
 | |
| }(V);
 | |
| var Q = /* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|     this.callbacks = void 0;
 | |
|   }
 | |
|   var n2 = t3.prototype;
 | |
|   return n2.init = function(t4) {
 | |
|     this.callbacks || (this.callbacks = {}), t4 && !this.callbacks[t4] && (this.callbacks[t4] = []);
 | |
|   }, n2.listeners = function() {
 | |
|     return this.callbacks;
 | |
|   }, n2.on = function(t4, n3) {
 | |
|     return this.init(t4), this.callbacks[t4].push(n3), this;
 | |
|   }, n2.off = function(t4, n3) {
 | |
|     var e2 = t4;
 | |
|     return this.init(), this.callbacks[e2] && 0 !== this.callbacks[e2].length ? (this.callbacks[e2] = this.callbacks[e2].filter(function(t5) {
 | |
|       return t5 != n3;
 | |
|     }), this) : this;
 | |
|   }, n2.emit = function(t4) {
 | |
|     var n3 = arguments, e2 = t4;
 | |
|     return this.init(e2), this.callbacks[e2].length > 0 && (this.callbacks[e2].forEach(function(t5) {
 | |
|       return t5.apply(void 0, [].slice.call(n3, 1));
 | |
|     }), true);
 | |
|   }, t3;
 | |
| }();
 | |
| function Y(t3, n2) {
 | |
|   if (typeof t3 != typeof n2) return false;
 | |
|   if (null === t3 && null === n2) return true;
 | |
|   if ("object" != typeof t3) return t3 === n2;
 | |
|   if (Array.isArray(t3) && Array.isArray(n2)) {
 | |
|     if (t3.length !== n2.length) return false;
 | |
|     for (var e2 = 0; e2 < t3.length; e2++) if (!Y(t3[e2], n2[e2])) return false;
 | |
|     return true;
 | |
|   }
 | |
|   if (t3.hasOwnProperty("constructor") && n2.hasOwnProperty("constructor") && t3.hasOwnProperty("props") && n2.hasOwnProperty("props") && t3.hasOwnProperty("key") && n2.hasOwnProperty("key") && t3.hasOwnProperty("ref") && n2.hasOwnProperty("ref") && t3.hasOwnProperty("type") && n2.hasOwnProperty("type")) return Y(t3.props, n2.props);
 | |
|   var r2 = Object.keys(t3), o2 = Object.keys(n2);
 | |
|   if (r2.length !== o2.length) return false;
 | |
|   for (var i2 = 0, u2 = r2; i2 < u2.length; i2++) {
 | |
|     var s2 = u2[i2];
 | |
|     if (!n2.hasOwnProperty(s2) || !Y(t3[s2], n2[s2])) return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| !function(t3) {
 | |
|   t3[t3.Initiator = 0] = "Initiator", t3[t3.ServerFilter = 1] = "ServerFilter", t3[t3.ServerSort = 2] = "ServerSort", t3[t3.ServerLimit = 3] = "ServerLimit", t3[t3.Extractor = 4] = "Extractor", t3[t3.Transformer = 5] = "Transformer", t3[t3.Filter = 6] = "Filter", t3[t3.Sort = 7] = "Sort", t3[t3.Limit = 8] = "Limit";
 | |
| }(K || (K = {}));
 | |
| var tt = /* @__PURE__ */ function(t3) {
 | |
|   function o2(n2) {
 | |
|     var e2;
 | |
|     return (e2 = t3.call(this) || this).id = void 0, e2._props = void 0, e2._props = {}, e2.id = z(), n2 && e2.setProps(n2), e2;
 | |
|   }
 | |
|   r(o2, t3);
 | |
|   var i2 = o2.prototype;
 | |
|   return i2.process = function() {
 | |
|     var t4 = [].slice.call(arguments);
 | |
|     this.validateProps instanceof Function && this.validateProps.apply(this, t4), this.emit.apply(this, ["beforeProcess"].concat(t4));
 | |
|     var n2 = this._process.apply(this, t4);
 | |
|     return this.emit.apply(this, ["afterProcess"].concat(t4)), n2;
 | |
|   }, i2.setProps = function(t4) {
 | |
|     var n2 = e({}, this._props, t4);
 | |
|     return Y(n2, this._props) || (this._props = n2, this.emit("propsUpdated", this)), this;
 | |
|   }, n(o2, [{ key: "props", get: function() {
 | |
|     return this._props;
 | |
|   } }]), o2;
 | |
| }(Q);
 | |
| var nt = /* @__PURE__ */ function(t3) {
 | |
|   function e2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(e2, t3), e2.prototype._process = function(t4) {
 | |
|     return this.props.keyword ? (n2 = String(this.props.keyword).trim(), e3 = this.props.columns, r2 = this.props.ignoreHiddenColumns, o2 = t4, i2 = this.props.selector, n2 = n2.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), new J(o2.rows.filter(function(t5, o3) {
 | |
|       return t5.cells.some(function(t6, u2) {
 | |
|         if (!t6) return false;
 | |
|         if (r2 && e3 && e3[u2] && "object" == typeof e3[u2] && e3[u2].hidden) return false;
 | |
|         var s2 = "";
 | |
|         if ("function" == typeof i2) s2 = i2(t6.data, o3, u2);
 | |
|         else if ("object" == typeof t6.data) {
 | |
|           var a2 = t6.data;
 | |
|           a2 && a2.props && a2.props.content && (s2 = a2.props.content);
 | |
|         } else s2 = String(t6.data);
 | |
|         return new RegExp(n2, "gi").test(s2);
 | |
|       });
 | |
|     }))) : t4;
 | |
|     var n2, e3, r2, o2, i2;
 | |
|   }, n(e2, [{ key: "type", get: function() {
 | |
|     return K.Filter;
 | |
|   } }]), e2;
 | |
| }(tt);
 | |
| function et() {
 | |
|   var t3 = "gridjs";
 | |
|   return "" + t3 + [].slice.call(arguments).reduce(function(t4, n2) {
 | |
|     return t4 + "-" + n2;
 | |
|   }, "");
 | |
| }
 | |
| function rt() {
 | |
|   return [].slice.call(arguments).map(function(t3) {
 | |
|     return t3 ? t3.toString() : "";
 | |
|   }).filter(function(t3) {
 | |
|     return t3;
 | |
|   }).reduce(function(t3, n2) {
 | |
|     return (t3 || "") + " " + n2;
 | |
|   }, "").trim();
 | |
| }
 | |
| var ot;
 | |
| var it;
 | |
| var ut;
 | |
| var st;
 | |
| var at = /* @__PURE__ */ function(t3) {
 | |
|   function o2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(o2, t3), o2.prototype._process = function(t4) {
 | |
|     if (!this.props.keyword) return t4;
 | |
|     var n2 = {};
 | |
|     return this.props.url && (n2.url = this.props.url(t4.url, this.props.keyword)), this.props.body && (n2.body = this.props.body(t4.body, this.props.keyword)), e({}, t4, n2);
 | |
|   }, n(o2, [{ key: "type", get: function() {
 | |
|     return K.ServerFilter;
 | |
|   } }]), o2;
 | |
| }(tt);
 | |
| var lt = 0;
 | |
| var ct = [];
 | |
| var ft = [];
 | |
| var pt = c.__b;
 | |
| var dt = c.__r;
 | |
| var ht = c.diffed;
 | |
| var _t = c.__c;
 | |
| var mt = c.unmount;
 | |
| function vt(t3, n2) {
 | |
|   c.__h && c.__h(it, t3, lt || n2), lt = 0;
 | |
|   var e2 = it.__H || (it.__H = { __: [], __h: [] });
 | |
|   return t3 >= e2.__.length && e2.__.push({ __V: ft }), e2.__[t3];
 | |
| }
 | |
| function yt(t3) {
 | |
|   return lt = 1, function(t4, n2, e2) {
 | |
|     var r2 = vt(ot++, 2);
 | |
|     if (r2.t = t4, !r2.__c && (r2.__ = [Et(void 0, n2), function(t5) {
 | |
|       var n3 = r2.__N ? r2.__N[0] : r2.__[0], e3 = r2.t(n3, t5);
 | |
|       n3 !== e3 && (r2.__N = [e3, r2.__[1]], r2.__c.setState({}));
 | |
|     }], r2.__c = it, !it.u)) {
 | |
|       it.u = true;
 | |
|       var o2 = it.shouldComponentUpdate;
 | |
|       it.shouldComponentUpdate = function(t5, n3, e3) {
 | |
|         if (!r2.__c.__H) return true;
 | |
|         var i2 = r2.__c.__H.__.filter(function(t6) {
 | |
|           return t6.__c;
 | |
|         });
 | |
|         if (i2.every(function(t6) {
 | |
|           return !t6.__N;
 | |
|         })) return !o2 || o2.call(this, t5, n3, e3);
 | |
|         var u2 = false;
 | |
|         return i2.forEach(function(t6) {
 | |
|           if (t6.__N) {
 | |
|             var n4 = t6.__[0];
 | |
|             t6.__ = t6.__N, t6.__N = void 0, n4 !== t6.__[0] && (u2 = true);
 | |
|           }
 | |
|         }), !(!u2 && r2.__c.props === t5) && (!o2 || o2.call(this, t5, n3, e3));
 | |
|       };
 | |
|     }
 | |
|     return r2.__N || r2.__;
 | |
|   }(Et, t3);
 | |
| }
 | |
| function gt(t3, n2) {
 | |
|   var e2 = vt(ot++, 3);
 | |
|   !c.__s && Ct(e2.__H, n2) && (e2.__ = t3, e2.i = n2, it.__H.__h.push(e2));
 | |
| }
 | |
| function bt(t3) {
 | |
|   return lt = 5, wt(function() {
 | |
|     return { current: t3 };
 | |
|   }, []);
 | |
| }
 | |
| function wt(t3, n2) {
 | |
|   var e2 = vt(ot++, 7);
 | |
|   return Ct(e2.__H, n2) ? (e2.__V = t3(), e2.i = n2, e2.__h = t3, e2.__V) : e2.__;
 | |
| }
 | |
| function xt() {
 | |
|   for (var t3; t3 = ct.shift(); ) if (t3.__P && t3.__H) try {
 | |
|     t3.__H.__h.forEach(Nt), t3.__H.__h.forEach(Pt), t3.__H.__h = [];
 | |
|   } catch (n2) {
 | |
|     t3.__H.__h = [], c.__e(n2, t3.__v);
 | |
|   }
 | |
| }
 | |
| c.__b = function(t3) {
 | |
|   it = null, pt && pt(t3);
 | |
| }, c.__r = function(t3) {
 | |
|   dt && dt(t3), ot = 0;
 | |
|   var n2 = (it = t3.__c).__H;
 | |
|   n2 && (ut === it ? (n2.__h = [], it.__h = [], n2.__.forEach(function(t4) {
 | |
|     t4.__N && (t4.__ = t4.__N), t4.__V = ft, t4.__N = t4.i = void 0;
 | |
|   })) : (n2.__h.forEach(Nt), n2.__h.forEach(Pt), n2.__h = [])), ut = it;
 | |
| }, c.diffed = function(t3) {
 | |
|   ht && ht(t3);
 | |
|   var n2 = t3.__c;
 | |
|   n2 && n2.__H && (n2.__H.__h.length && (1 !== ct.push(n2) && st === c.requestAnimationFrame || ((st = c.requestAnimationFrame) || St)(xt)), n2.__H.__.forEach(function(t4) {
 | |
|     t4.i && (t4.__H = t4.i), t4.__V !== ft && (t4.__ = t4.__V), t4.i = void 0, t4.__V = ft;
 | |
|   })), ut = it = null;
 | |
| }, c.__c = function(t3, n2) {
 | |
|   n2.some(function(t4) {
 | |
|     try {
 | |
|       t4.__h.forEach(Nt), t4.__h = t4.__h.filter(function(t5) {
 | |
|         return !t5.__ || Pt(t5);
 | |
|       });
 | |
|     } catch (e2) {
 | |
|       n2.some(function(t5) {
 | |
|         t5.__h && (t5.__h = []);
 | |
|       }), n2 = [], c.__e(e2, t4.__v);
 | |
|     }
 | |
|   }), _t && _t(t3, n2);
 | |
| }, c.unmount = function(t3) {
 | |
|   mt && mt(t3);
 | |
|   var n2, e2 = t3.__c;
 | |
|   e2 && e2.__H && (e2.__H.__.forEach(function(t4) {
 | |
|     try {
 | |
|       Nt(t4);
 | |
|     } catch (t5) {
 | |
|       n2 = t5;
 | |
|     }
 | |
|   }), e2.__H = void 0, n2 && c.__e(n2, e2.__v));
 | |
| };
 | |
| var kt = "function" == typeof requestAnimationFrame;
 | |
| function St(t3) {
 | |
|   var n2, e2 = function() {
 | |
|     clearTimeout(r2), kt && cancelAnimationFrame(n2), setTimeout(t3);
 | |
|   }, r2 = setTimeout(e2, 100);
 | |
|   kt && (n2 = requestAnimationFrame(e2));
 | |
| }
 | |
| function Nt(t3) {
 | |
|   var n2 = it, e2 = t3.__c;
 | |
|   "function" == typeof e2 && (t3.__c = void 0, e2()), it = n2;
 | |
| }
 | |
| function Pt(t3) {
 | |
|   var n2 = it;
 | |
|   t3.__c = t3.__(), it = n2;
 | |
| }
 | |
| function Ct(t3, n2) {
 | |
|   return !t3 || t3.length !== n2.length || n2.some(function(n3, e2) {
 | |
|     return n3 !== t3[e2];
 | |
|   });
 | |
| }
 | |
| function Et(t3, n2) {
 | |
|   return "function" == typeof n2 ? n2(t3) : n2;
 | |
| }
 | |
| function It() {
 | |
|   return function(t3) {
 | |
|     var n2 = it.context[t3.__c], e2 = vt(ot++, 9);
 | |
|     return e2.c = t3, n2 ? (null == e2.__ && (e2.__ = true, n2.sub(it)), n2.props.value) : t3.__;
 | |
|   }(fn);
 | |
| }
 | |
| var Tt = { search: { placeholder: "Type a keyword..." }, sort: { sortAsc: "Sort column ascending", sortDesc: "Sort column descending" }, pagination: { previous: "Previous", next: "Next", navigate: function(t3, n2) {
 | |
|   return "Page " + t3 + " of " + n2;
 | |
| }, page: function(t3) {
 | |
|   return "Page " + t3;
 | |
| }, showing: "Showing", of: "of", to: "to", results: "results" }, loading: "Loading...", noRecordsFound: "No matching records found", error: "An error happened while fetching the data" };
 | |
| var Lt = /* @__PURE__ */ function() {
 | |
|   function t3(t4) {
 | |
|     this._language = void 0, this._defaultLanguage = void 0, this._language = t4, this._defaultLanguage = Tt;
 | |
|   }
 | |
|   var n2 = t3.prototype;
 | |
|   return n2.getString = function(t4, n3) {
 | |
|     if (!n3 || !t4) return null;
 | |
|     var e2 = t4.split("."), r2 = e2[0];
 | |
|     if (n3[r2]) {
 | |
|       var o2 = n3[r2];
 | |
|       return "string" == typeof o2 ? function() {
 | |
|         return o2;
 | |
|       } : "function" == typeof o2 ? o2 : this.getString(e2.slice(1).join("."), o2);
 | |
|     }
 | |
|     return null;
 | |
|   }, n2.translate = function(t4) {
 | |
|     var n3, e2 = this.getString(t4, this._language);
 | |
|     return (n3 = e2 || this.getString(t4, this._defaultLanguage)) ? n3.apply(void 0, [].slice.call(arguments, 1)) : t4;
 | |
|   }, t3;
 | |
| }();
 | |
| function At() {
 | |
|   var t3 = It();
 | |
|   return function(n2) {
 | |
|     var e2;
 | |
|     return (e2 = t3.translator).translate.apply(e2, [n2].concat([].slice.call(arguments, 1)));
 | |
|   };
 | |
| }
 | |
| var Ot = function(t3) {
 | |
|   return function(n2) {
 | |
|     return e({}, n2, { search: { keyword: t3 } });
 | |
|   };
 | |
| };
 | |
| function Ht() {
 | |
|   return It().store;
 | |
| }
 | |
| function jt(t3) {
 | |
|   var n2 = Ht(), e2 = yt(t3(n2.getState())), r2 = e2[0], o2 = e2[1];
 | |
|   return gt(function() {
 | |
|     return n2.subscribe(function() {
 | |
|       var e3 = t3(n2.getState());
 | |
|       r2 !== e3 && o2(e3);
 | |
|     });
 | |
|   }, []), r2;
 | |
| }
 | |
| function Dt() {
 | |
|   var t3, n2 = yt(void 0), e2 = n2[0], r2 = n2[1], o2 = It(), i2 = o2.search, u2 = At(), s2 = Ht().dispatch, a2 = jt(function(t4) {
 | |
|     return t4.search;
 | |
|   });
 | |
|   gt(function() {
 | |
|     e2 && e2.setProps({ keyword: null == a2 ? void 0 : a2.keyword });
 | |
|   }, [a2, e2]), gt(function() {
 | |
|     r2(i2.server ? new at({ keyword: i2.keyword, url: i2.server.url, body: i2.server.body }) : new nt({ keyword: i2.keyword, columns: o2.header && o2.header.columns, ignoreHiddenColumns: i2.ignoreHiddenColumns || void 0 === i2.ignoreHiddenColumns, selector: i2.selector })), i2.keyword && s2(Ot(i2.keyword));
 | |
|   }, [i2]), gt(function() {
 | |
|     if (e2) return o2.pipeline.register(e2), function() {
 | |
|       return o2.pipeline.unregister(e2);
 | |
|     };
 | |
|   }, [o2, e2]);
 | |
|   var l2, c2, f2, p2 = function(t4, n3) {
 | |
|     return lt = 8, wt(function() {
 | |
|       return t4;
 | |
|     }, n3);
 | |
|   }((l2 = function(t4) {
 | |
|     t4.target instanceof HTMLInputElement && s2(Ot(t4.target.value));
 | |
|   }, c2 = e2 instanceof at ? i2.debounceTimeout || 250 : 0, function() {
 | |
|     var t4 = arguments;
 | |
|     return new Promise(function(n3) {
 | |
|       f2 && clearTimeout(f2), f2 = setTimeout(function() {
 | |
|         return n3(l2.apply(void 0, [].slice.call(t4)));
 | |
|       }, c2);
 | |
|     });
 | |
|   }), [i2, e2]);
 | |
|   return w("div", { className: et(rt("search", null == (t3 = o2.className) ? void 0 : t3.search)) }, w("input", { type: "search", placeholder: u2("search.placeholder"), "aria-label": u2("search.placeholder"), onInput: p2, className: rt(et("input"), et("search", "input")), defaultValue: (null == a2 ? void 0 : a2.keyword) || "" }));
 | |
| }
 | |
| var Mt = /* @__PURE__ */ function(t3) {
 | |
|   function e2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   r(e2, t3);
 | |
|   var o2 = e2.prototype;
 | |
|   return o2.validateProps = function() {
 | |
|     if (isNaN(Number(this.props.limit)) || isNaN(Number(this.props.page))) throw Error("Invalid parameters passed");
 | |
|   }, o2._process = function(t4) {
 | |
|     var n2 = this.props.page;
 | |
|     return new J(t4.rows.slice(n2 * this.props.limit, (n2 + 1) * this.props.limit));
 | |
|   }, n(e2, [{ key: "type", get: function() {
 | |
|     return K.Limit;
 | |
|   } }]), e2;
 | |
| }(tt);
 | |
| var Ft = /* @__PURE__ */ function(t3) {
 | |
|   function o2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(o2, t3), o2.prototype._process = function(t4) {
 | |
|     var n2 = {};
 | |
|     return this.props.url && (n2.url = this.props.url(t4.url, this.props.page, this.props.limit)), this.props.body && (n2.body = this.props.body(t4.body, this.props.page, this.props.limit)), e({}, t4, n2);
 | |
|   }, n(o2, [{ key: "type", get: function() {
 | |
|     return K.ServerLimit;
 | |
|   } }]), o2;
 | |
| }(tt);
 | |
| function Rt() {
 | |
|   var t3 = It(), n2 = t3.pagination, e2 = n2.server, r2 = n2.summary, o2 = void 0 === r2 || r2, i2 = n2.nextButton, u2 = void 0 === i2 || i2, s2 = n2.prevButton, a2 = void 0 === s2 || s2, l2 = n2.buttonsCount, c2 = void 0 === l2 ? 3 : l2, f2 = n2.limit, p2 = void 0 === f2 ? 10 : f2, d2 = n2.page, h6 = void 0 === d2 ? 0 : d2, _2 = n2.resetPageOnUpdate, m2 = void 0 === _2 || _2, v2 = bt(null), y2 = yt(h6), g2 = y2[0], b2 = y2[1], x2 = yt(0), k = x2[0], N2 = x2[1], P2 = At();
 | |
|   gt(function() {
 | |
|     return e2 ? (v2.current = new Ft({ limit: p2, page: g2, url: e2.url, body: e2.body }), t3.pipeline.register(v2.current)) : (v2.current = new Mt({ limit: p2, page: g2 }), t3.pipeline.register(v2.current)), v2.current instanceof Ft ? t3.pipeline.on("afterProcess", function(t4) {
 | |
|       return N2(t4.length);
 | |
|     }) : v2.current instanceof Mt && v2.current.on("beforeProcess", function(t4) {
 | |
|       return N2(t4.length);
 | |
|     }), t3.pipeline.on("updated", C2), t3.pipeline.on("error", function() {
 | |
|       N2(0), b2(0);
 | |
|     }), function() {
 | |
|       t3.pipeline.unregister(v2.current), t3.pipeline.off("updated", C2);
 | |
|     };
 | |
|   }, []);
 | |
|   var C2 = function(t4) {
 | |
|     m2 && t4 !== v2.current && (b2(0), 0 !== v2.current.props.page && v2.current.setProps({ page: 0 }));
 | |
|   }, E2 = function() {
 | |
|     return Math.ceil(k / p2);
 | |
|   }, I2 = function(t4) {
 | |
|     if (t4 >= E2() || t4 < 0 || t4 === g2) return null;
 | |
|     b2(t4), v2.current.setProps({ page: t4 });
 | |
|   };
 | |
|   return w("div", { className: rt(et("pagination"), t3.className.pagination) }, w(S, null, o2 && k > 0 && w("div", { role: "status", "aria-live": "polite", className: rt(et("summary"), t3.className.paginationSummary), title: P2("pagination.navigate", g2 + 1, E2()) }, P2("pagination.showing"), " ", w("b", null, P2("" + (g2 * p2 + 1))), " ", P2("pagination.to"), " ", w("b", null, P2("" + Math.min((g2 + 1) * p2, k))), " ", P2("pagination.of"), " ", w("b", null, P2("" + k)), " ", P2("pagination.results"))), w("div", { className: et("pages") }, a2 && w("button", { tabIndex: 0, role: "button", disabled: 0 === g2, onClick: function() {
 | |
|     return I2(g2 - 1);
 | |
|   }, title: P2("pagination.previous"), "aria-label": P2("pagination.previous"), className: rt(t3.className.paginationButton, t3.className.paginationButtonPrev) }, P2("pagination.previous")), function() {
 | |
|     if (c2 <= 0) return null;
 | |
|     var n3 = Math.min(E2(), c2), e3 = Math.min(g2, Math.floor(n3 / 2));
 | |
|     return g2 + Math.floor(n3 / 2) >= E2() && (e3 = n3 - (E2() - g2)), w(S, null, E2() > n3 && g2 - e3 > 0 && w(S, null, w("button", { tabIndex: 0, role: "button", onClick: function() {
 | |
|       return I2(0);
 | |
|     }, title: P2("pagination.firstPage"), "aria-label": P2("pagination.firstPage"), className: t3.className.paginationButton }, P2("1")), w("button", { tabIndex: -1, className: rt(et("spread"), t3.className.paginationButton) }, "...")), Array.from(Array(n3).keys()).map(function(t4) {
 | |
|       return g2 + (t4 - e3);
 | |
|     }).map(function(n4) {
 | |
|       return w("button", { tabIndex: 0, role: "button", onClick: function() {
 | |
|         return I2(n4);
 | |
|       }, className: rt(g2 === n4 ? rt(et("currentPage"), t3.className.paginationButtonCurrent) : null, t3.className.paginationButton), title: P2("pagination.page", n4 + 1), "aria-label": P2("pagination.page", n4 + 1) }, P2("" + (n4 + 1)));
 | |
|     }), E2() > n3 && E2() > g2 + e3 + 1 && w(S, null, w("button", { tabIndex: -1, className: rt(et("spread"), t3.className.paginationButton) }, "..."), w("button", { tabIndex: 0, role: "button", onClick: function() {
 | |
|       return I2(E2() - 1);
 | |
|     }, title: P2("pagination.page", E2()), "aria-label": P2("pagination.page", E2()), className: t3.className.paginationButton }, P2("" + E2()))));
 | |
|   }(), u2 && w("button", { tabIndex: 0, role: "button", disabled: E2() === g2 + 1 || 0 === E2(), onClick: function() {
 | |
|     return I2(g2 + 1);
 | |
|   }, title: P2("pagination.next"), "aria-label": P2("pagination.next"), className: rt(t3.className.paginationButton, t3.className.paginationButtonNext) }, P2("pagination.next"))));
 | |
| }
 | |
| function Ut(t3, n2) {
 | |
|   return "string" == typeof t3 ? t3.indexOf("%") > -1 ? n2 / 100 * parseInt(t3, 10) : parseInt(t3, 10) : t3;
 | |
| }
 | |
| function Wt(t3) {
 | |
|   return t3 ? Math.floor(t3) + "px" : "";
 | |
| }
 | |
| function Bt(t3) {
 | |
|   var n2 = t3.tableRef.cloneNode(true);
 | |
|   return n2.style.position = "absolute", n2.style.width = "100%", n2.style.zIndex = "-2147483640", n2.style.visibility = "hidden", w("div", { ref: function(t4) {
 | |
|     t4 && t4.appendChild(n2);
 | |
|   } });
 | |
| }
 | |
| function qt(t3) {
 | |
|   if (!t3) return "";
 | |
|   var n2 = t3.split(" ");
 | |
|   return 1 === n2.length && /([a-z][A-Z])+/g.test(t3) ? t3 : n2.map(function(t4, n3) {
 | |
|     return 0 == n3 ? t4.toLowerCase() : t4.charAt(0).toUpperCase() + t4.slice(1).toLowerCase();
 | |
|   }).join("");
 | |
| }
 | |
| var zt;
 | |
| var Vt = new (/* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|   }
 | |
|   var n2 = t3.prototype;
 | |
|   return n2.format = function(t4, n3) {
 | |
|     return "[Grid.js] [" + n3.toUpperCase() + "]: " + t4;
 | |
|   }, n2.error = function(t4, n3) {
 | |
|     void 0 === n3 && (n3 = false);
 | |
|     var e2 = this.format(t4, "error");
 | |
|     if (n3) throw Error(e2);
 | |
|     console.error(e2);
 | |
|   }, n2.warn = function(t4) {
 | |
|     console.warn(this.format(t4, "warn"));
 | |
|   }, n2.info = function(t4) {
 | |
|     console.info(this.format(t4, "info"));
 | |
|   }, t3;
 | |
| }())();
 | |
| !function(t3) {
 | |
|   t3[t3.Header = 0] = "Header", t3[t3.Footer = 1] = "Footer", t3[t3.Cell = 2] = "Cell";
 | |
| }(zt || (zt = {}));
 | |
| var $t = /* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|     this.plugins = void 0, this.plugins = [];
 | |
|   }
 | |
|   var n2 = t3.prototype;
 | |
|   return n2.get = function(t4) {
 | |
|     return this.plugins.find(function(n3) {
 | |
|       return n3.id === t4;
 | |
|     });
 | |
|   }, n2.add = function(t4) {
 | |
|     return t4.id ? this.get(t4.id) ? (Vt.error("Duplicate plugin ID: " + t4.id), this) : (this.plugins.push(t4), this) : (Vt.error("Plugin ID cannot be empty"), this);
 | |
|   }, n2.remove = function(t4) {
 | |
|     var n3 = this.get(t4);
 | |
|     return n3 && this.plugins.splice(this.plugins.indexOf(n3), 1), this;
 | |
|   }, n2.list = function(t4) {
 | |
|     var n3;
 | |
|     return n3 = null != t4 || null != t4 ? this.plugins.filter(function(n4) {
 | |
|       return n4.position === t4;
 | |
|     }) : this.plugins, n3.sort(function(t5, n4) {
 | |
|       return t5.order && n4.order ? t5.order - n4.order : 1;
 | |
|     });
 | |
|   }, t3;
 | |
| }();
 | |
| function Gt(t3) {
 | |
|   var n2 = this, r2 = It();
 | |
|   if (t3.pluginId) {
 | |
|     var o2 = r2.plugin.get(t3.pluginId);
 | |
|     return o2 ? w(S, {}, w(o2.component, e({ plugin: o2 }, t3.props))) : null;
 | |
|   }
 | |
|   return void 0 !== t3.position ? w(S, {}, r2.plugin.list(t3.position).map(function(t4) {
 | |
|     return w(t4.component, e({ plugin: t4 }, n2.props.props));
 | |
|   })) : null;
 | |
| }
 | |
| var Kt = /* @__PURE__ */ function(t3) {
 | |
|   function o2() {
 | |
|     var n2;
 | |
|     return (n2 = t3.call(this) || this)._columns = void 0, n2._columns = [], n2;
 | |
|   }
 | |
|   r(o2, t3);
 | |
|   var i2 = o2.prototype;
 | |
|   return i2.adjustWidth = function(t4, n2, r2) {
 | |
|     var i3 = t4.container, u2 = t4.autoWidth;
 | |
|     if (!i3) return this;
 | |
|     var a2 = i3.clientWidth, l2 = {};
 | |
|     n2.current && u2 && (q(w(Bt, { tableRef: n2.current }), r2.current), l2 = function(t5) {
 | |
|       var n3 = t5.querySelector("table");
 | |
|       if (!n3) return {};
 | |
|       var r3 = n3.className, o3 = n3.style.cssText;
 | |
|       n3.className = r3 + " " + et("shadowTable"), n3.style.tableLayout = "auto", n3.style.width = "auto", n3.style.padding = "0", n3.style.margin = "0", n3.style.border = "none", n3.style.outline = "none";
 | |
|       var i4 = Array.from(n3.parentNode.querySelectorAll("thead th")).reduce(function(t6, n4) {
 | |
|         var r4;
 | |
|         return n4.style.width = n4.clientWidth + "px", e(((r4 = {})[n4.getAttribute("data-column-id")] = { minWidth: n4.clientWidth }, r4), t6);
 | |
|       }, {});
 | |
|       return n3.className = r3, n3.style.cssText = o3, n3.style.tableLayout = "auto", Array.from(n3.parentNode.querySelectorAll("thead th")).reduce(function(t6, n4) {
 | |
|         return t6[n4.getAttribute("data-column-id")].width = n4.clientWidth, t6;
 | |
|       }, i4);
 | |
|     }(r2.current));
 | |
|     for (var c2, f2 = s(o2.tabularFormat(this.columns).reduce(function(t5, n3) {
 | |
|       return t5.concat(n3);
 | |
|     }, [])); !(c2 = f2()).done; ) {
 | |
|       var p2 = c2.value;
 | |
|       p2.columns && p2.columns.length > 0 || (!p2.width && u2 ? p2.id in l2 && (p2.width = Wt(l2[p2.id].width), p2.minWidth = Wt(l2[p2.id].minWidth)) : p2.width = Wt(Ut(p2.width, a2)));
 | |
|     }
 | |
|     return n2.current && u2 && q(null, r2.current), this;
 | |
|   }, i2.setSort = function(t4, n2) {
 | |
|     for (var r2, o3 = s(n2 || this.columns || []); !(r2 = o3()).done; ) {
 | |
|       var i3 = r2.value;
 | |
|       i3.columns && i3.columns.length > 0 ? i3.sort = void 0 : void 0 === i3.sort && t4 ? i3.sort = {} : i3.sort ? "object" == typeof i3.sort && (i3.sort = e({}, i3.sort)) : i3.sort = void 0, i3.columns && this.setSort(t4, i3.columns);
 | |
|     }
 | |
|   }, i2.setResizable = function(t4, n2) {
 | |
|     for (var e2, r2 = s(n2 || this.columns || []); !(e2 = r2()).done; ) {
 | |
|       var o3 = e2.value;
 | |
|       void 0 === o3.resizable && (o3.resizable = t4), o3.columns && this.setResizable(t4, o3.columns);
 | |
|     }
 | |
|   }, i2.setID = function(t4) {
 | |
|     for (var n2, e2 = s(t4 || this.columns || []); !(n2 = e2()).done; ) {
 | |
|       var r2 = n2.value;
 | |
|       r2.id || "string" != typeof r2.name || (r2.id = qt(r2.name)), r2.id || Vt.error('Could not find a valid ID for one of the columns. Make sure a valid "id" is set for all columns.'), r2.columns && this.setID(r2.columns);
 | |
|     }
 | |
|   }, i2.populatePlugins = function(t4, n2) {
 | |
|     for (var r2, o3 = s(n2); !(r2 = o3()).done; ) {
 | |
|       var i3 = r2.value;
 | |
|       void 0 !== i3.plugin && t4.add(e({ id: i3.id }, i3.plugin, { position: zt.Cell }));
 | |
|     }
 | |
|   }, o2.fromColumns = function(t4) {
 | |
|     for (var n2, e2 = new o2(), r2 = s(t4); !(n2 = r2()).done; ) {
 | |
|       var i3 = n2.value;
 | |
|       if ("string" == typeof i3 || p(i3)) e2.columns.push({ name: i3 });
 | |
|       else if ("object" == typeof i3) {
 | |
|         var u2 = i3;
 | |
|         u2.columns && (u2.columns = o2.fromColumns(u2.columns).columns), "object" == typeof u2.plugin && void 0 === u2.data && (u2.data = null), e2.columns.push(i3);
 | |
|       }
 | |
|     }
 | |
|     return e2;
 | |
|   }, o2.createFromConfig = function(t4) {
 | |
|     var n2 = new o2();
 | |
|     return t4.from ? n2.columns = o2.fromHTMLTable(t4.from).columns : t4.columns ? n2.columns = o2.fromColumns(t4.columns).columns : !t4.data || "object" != typeof t4.data[0] || t4.data[0] instanceof Array || (n2.columns = Object.keys(t4.data[0]).map(function(t5) {
 | |
|       return { name: t5 };
 | |
|     })), n2.columns.length ? (n2.setID(), n2.setSort(t4.sort), n2.setResizable(t4.resizable), n2.populatePlugins(t4.plugin, n2.columns), n2) : null;
 | |
|   }, o2.fromHTMLTable = function(t4) {
 | |
|     for (var n2, e2 = new o2(), r2 = s(t4.querySelector("thead").querySelectorAll("th")); !(n2 = r2()).done; ) {
 | |
|       var i3 = n2.value;
 | |
|       e2.columns.push({ name: i3.innerHTML, width: i3.width });
 | |
|     }
 | |
|     return e2;
 | |
|   }, o2.tabularFormat = function(t4) {
 | |
|     var n2 = [], e2 = t4 || [], r2 = [];
 | |
|     if (e2 && e2.length) {
 | |
|       n2.push(e2);
 | |
|       for (var o3, i3 = s(e2); !(o3 = i3()).done; ) {
 | |
|         var u2 = o3.value;
 | |
|         u2.columns && u2.columns.length && (r2 = r2.concat(u2.columns));
 | |
|       }
 | |
|       r2.length && (n2 = n2.concat(this.tabularFormat(r2)));
 | |
|     }
 | |
|     return n2;
 | |
|   }, o2.leafColumns = function(t4) {
 | |
|     var n2 = [], e2 = t4 || [];
 | |
|     if (e2 && e2.length) for (var r2, o3 = s(e2); !(r2 = o3()).done; ) {
 | |
|       var i3 = r2.value;
 | |
|       i3.columns && 0 !== i3.columns.length || n2.push(i3), i3.columns && (n2 = n2.concat(this.leafColumns(i3.columns)));
 | |
|     }
 | |
|     return n2;
 | |
|   }, o2.maximumDepth = function(t4) {
 | |
|     return this.tabularFormat([t4]).length - 1;
 | |
|   }, n(o2, [{ key: "columns", get: function() {
 | |
|     return this._columns;
 | |
|   }, set: function(t4) {
 | |
|     this._columns = t4;
 | |
|   } }, { key: "visibleColumns", get: function() {
 | |
|     return this._columns.filter(function(t4) {
 | |
|       return !t4.hidden;
 | |
|     });
 | |
|   } }]), o2;
 | |
| }(V);
 | |
| var Xt = function() {
 | |
| };
 | |
| var Zt = /* @__PURE__ */ function(t3) {
 | |
|   function n2(n3) {
 | |
|     var e3;
 | |
|     return (e3 = t3.call(this) || this).data = void 0, e3.set(n3), e3;
 | |
|   }
 | |
|   r(n2, t3);
 | |
|   var e2 = n2.prototype;
 | |
|   return e2.get = function() {
 | |
|     try {
 | |
|       return Promise.resolve(this.data()).then(function(t4) {
 | |
|         return { data: t4, total: t4.length };
 | |
|       });
 | |
|     } catch (t4) {
 | |
|       return Promise.reject(t4);
 | |
|     }
 | |
|   }, e2.set = function(t4) {
 | |
|     return t4 instanceof Array ? this.data = function() {
 | |
|       return t4;
 | |
|     } : t4 instanceof Function && (this.data = t4), this;
 | |
|   }, n2;
 | |
| }(Xt);
 | |
| var Jt = /* @__PURE__ */ function(t3) {
 | |
|   function n2(n3) {
 | |
|     var e2;
 | |
|     return (e2 = t3.call(this) || this).options = void 0, e2.options = n3, e2;
 | |
|   }
 | |
|   r(n2, t3);
 | |
|   var o2 = n2.prototype;
 | |
|   return o2.handler = function(t4) {
 | |
|     return "function" == typeof this.options.handle ? this.options.handle(t4) : t4.ok ? t4.json() : (Vt.error("Could not fetch data: " + t4.status + " - " + t4.statusText, true), null);
 | |
|   }, o2.get = function(t4) {
 | |
|     var n3 = e({}, this.options, t4);
 | |
|     return "function" == typeof n3.data ? n3.data(n3) : fetch(n3.url, n3).then(this.handler.bind(this)).then(function(t5) {
 | |
|       return { data: n3.then(t5), total: "function" == typeof n3.total ? n3.total(t5) : void 0 };
 | |
|     });
 | |
|   }, n2;
 | |
| }(Xt);
 | |
| var Qt = /* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|   }
 | |
|   return t3.createFromConfig = function(t4) {
 | |
|     var n2 = null;
 | |
|     return t4.data && (n2 = new Zt(t4.data)), t4.from && (n2 = new Zt(this.tableElementToArray(t4.from)), t4.from.style.display = "none"), t4.server && (n2 = new Jt(t4.server)), n2 || Vt.error("Could not determine the storage type", true), n2;
 | |
|   }, t3.tableElementToArray = function(t4) {
 | |
|     for (var n2, e2, r2 = [], o2 = s(t4.querySelector("tbody").querySelectorAll("tr")); !(n2 = o2()).done; ) {
 | |
|       for (var i2, u2 = [], a2 = s(n2.value.querySelectorAll("td")); !(i2 = a2()).done; ) {
 | |
|         var l2 = i2.value;
 | |
|         1 === l2.childNodes.length && l2.childNodes[0].nodeType === Node.TEXT_NODE ? u2.push((e2 = l2.innerHTML, new DOMParser().parseFromString(e2, "text/html").documentElement.textContent)) : u2.push(G(l2.innerHTML));
 | |
|       }
 | |
|       r2.push(u2);
 | |
|     }
 | |
|     return r2;
 | |
|   }, t3;
 | |
| }();
 | |
| var Yt = "undefined" != typeof Symbol ? Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator")) : "@@iterator";
 | |
| function tn(t3, n2, e2) {
 | |
|   if (!t3.s) {
 | |
|     if (e2 instanceof nn) {
 | |
|       if (!e2.s) return void (e2.o = tn.bind(null, t3, n2));
 | |
|       1 & n2 && (n2 = e2.s), e2 = e2.v;
 | |
|     }
 | |
|     if (e2 && e2.then) return void e2.then(tn.bind(null, t3, n2), tn.bind(null, t3, 2));
 | |
|     t3.s = n2, t3.v = e2;
 | |
|     var r2 = t3.o;
 | |
|     r2 && r2(t3);
 | |
|   }
 | |
| }
 | |
| var nn = /* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|   }
 | |
|   return t3.prototype.then = function(n2, e2) {
 | |
|     var r2 = new t3(), o2 = this.s;
 | |
|     if (o2) {
 | |
|       var i2 = 1 & o2 ? n2 : e2;
 | |
|       if (i2) {
 | |
|         try {
 | |
|           tn(r2, 1, i2(this.v));
 | |
|         } catch (t4) {
 | |
|           tn(r2, 2, t4);
 | |
|         }
 | |
|         return r2;
 | |
|       }
 | |
|       return this;
 | |
|     }
 | |
|     return this.o = function(t4) {
 | |
|       try {
 | |
|         var o3 = t4.v;
 | |
|         1 & t4.s ? tn(r2, 1, n2 ? n2(o3) : o3) : e2 ? tn(r2, 1, e2(o3)) : tn(r2, 2, o3);
 | |
|       } catch (t5) {
 | |
|         tn(r2, 2, t5);
 | |
|       }
 | |
|     }, r2;
 | |
|   }, t3;
 | |
| }();
 | |
| function en(t3) {
 | |
|   return t3 instanceof nn && 1 & t3.s;
 | |
| }
 | |
| var rn = /* @__PURE__ */ function(t3) {
 | |
|   function e2(n2) {
 | |
|     var e3;
 | |
|     return (e3 = t3.call(this) || this)._steps = /* @__PURE__ */ new Map(), e3.cache = /* @__PURE__ */ new Map(), e3.lastProcessorIndexUpdated = -1, n2 && n2.forEach(function(t4) {
 | |
|       return e3.register(t4);
 | |
|     }), e3;
 | |
|   }
 | |
|   r(e2, t3);
 | |
|   var o2 = e2.prototype;
 | |
|   return o2.clearCache = function() {
 | |
|     this.cache = /* @__PURE__ */ new Map(), this.lastProcessorIndexUpdated = -1;
 | |
|   }, o2.register = function(t4, n2) {
 | |
|     if (void 0 === n2 && (n2 = null), !t4) throw Error("Processor is not defined");
 | |
|     if (null === t4.type) throw Error("Processor type is not defined");
 | |
|     if (this.findProcessorIndexByID(t4.id) > -1) throw Error("Processor ID " + t4.id + " is already defined");
 | |
|     return t4.on("propsUpdated", this.processorPropsUpdated.bind(this)), this.addProcessorByPriority(t4, n2), this.afterRegistered(t4), t4;
 | |
|   }, o2.tryRegister = function(t4, n2) {
 | |
|     void 0 === n2 && (n2 = null);
 | |
|     try {
 | |
|       return this.register(t4, n2);
 | |
|     } catch (t5) {
 | |
|     }
 | |
|   }, o2.unregister = function(t4) {
 | |
|     if (t4 && -1 !== this.findProcessorIndexByID(t4.id)) {
 | |
|       var n2 = this._steps.get(t4.type);
 | |
|       n2 && n2.length && (this._steps.set(t4.type, n2.filter(function(n3) {
 | |
|         return n3 != t4;
 | |
|       })), this.emit("updated", t4));
 | |
|     }
 | |
|   }, o2.addProcessorByPriority = function(t4, n2) {
 | |
|     var e3 = this._steps.get(t4.type);
 | |
|     if (!e3) {
 | |
|       var r2 = [];
 | |
|       this._steps.set(t4.type, r2), e3 = r2;
 | |
|     }
 | |
|     if (null === n2 || n2 < 0) e3.push(t4);
 | |
|     else if (e3[n2]) {
 | |
|       var o3 = e3.slice(0, n2 - 1), i2 = e3.slice(n2 + 1);
 | |
|       this._steps.set(t4.type, o3.concat(t4).concat(i2));
 | |
|     } else e3[n2] = t4;
 | |
|   }, o2.getStepsByType = function(t4) {
 | |
|     return this.steps.filter(function(n2) {
 | |
|       return n2.type === t4;
 | |
|     });
 | |
|   }, o2.getSortedProcessorTypes = function() {
 | |
|     return Object.keys(K).filter(function(t4) {
 | |
|       return !isNaN(Number(t4));
 | |
|     }).map(function(t4) {
 | |
|       return Number(t4);
 | |
|     });
 | |
|   }, o2.process = function(t4) {
 | |
|     try {
 | |
|       var n2 = function(t5) {
 | |
|         return e3.lastProcessorIndexUpdated = o3.length, e3.emit("afterProcess", i2), i2;
 | |
|       }, e3 = this, r2 = e3.lastProcessorIndexUpdated, o3 = e3.steps, i2 = t4, u2 = function(t5, n3) {
 | |
|         try {
 | |
|           var u3 = function(t6, n4, e4) {
 | |
|             if ("function" == typeof t6[Yt]) {
 | |
|               var r3, o4, i3, u4 = t6[Yt]();
 | |
|               if (function t7(e5) {
 | |
|                 try {
 | |
|                   for (; !(r3 = u4.next()).done; ) if ((e5 = n4(r3.value)) && e5.then) {
 | |
|                     if (!en(e5)) return void e5.then(t7, i3 || (i3 = tn.bind(null, o4 = new nn(), 2)));
 | |
|                     e5 = e5.v;
 | |
|                   }
 | |
|                   o4 ? tn(o4, 1, e5) : o4 = e5;
 | |
|                 } catch (t8) {
 | |
|                   tn(o4 || (o4 = new nn()), 2, t8);
 | |
|                 }
 | |
|               }(), u4.return) {
 | |
|                 var s2 = function(t7) {
 | |
|                   try {
 | |
|                     r3.done || u4.return();
 | |
|                   } catch (t8) {
 | |
|                   }
 | |
|                   return t7;
 | |
|                 };
 | |
|                 if (o4 && o4.then) return o4.then(s2, function(t7) {
 | |
|                   throw s2(t7);
 | |
|                 });
 | |
|                 s2();
 | |
|               }
 | |
|               return o4;
 | |
|             }
 | |
|             if (!("length" in t6)) throw new TypeError("Object is not iterable");
 | |
|             for (var a2 = [], l2 = 0; l2 < t6.length; l2++) a2.push(t6[l2]);
 | |
|             return function(t7, n5, e5) {
 | |
|               var r4, o5, i4 = -1;
 | |
|               return function e6(u5) {
 | |
|                 try {
 | |
|                   for (; ++i4 < t7.length; ) if ((u5 = n5(i4)) && u5.then) {
 | |
|                     if (!en(u5)) return void u5.then(e6, o5 || (o5 = tn.bind(null, r4 = new nn(), 2)));
 | |
|                     u5 = u5.v;
 | |
|                   }
 | |
|                   r4 ? tn(r4, 1, u5) : r4 = u5;
 | |
|                 } catch (t8) {
 | |
|                   tn(r4 || (r4 = new nn()), 2, t8);
 | |
|                 }
 | |
|               }(), r4;
 | |
|             }(a2, function(t7) {
 | |
|               return n4(a2[t7]);
 | |
|             });
 | |
|           }(o3, function(t6) {
 | |
|             var n4 = e3.findProcessorIndexByID(t6.id), o4 = function() {
 | |
|               if (n4 >= r2) return Promise.resolve(t6.process(i2)).then(function(n5) {
 | |
|                 e3.cache.set(t6.id, i2 = n5);
 | |
|               });
 | |
|               i2 = e3.cache.get(t6.id);
 | |
|             }();
 | |
|             if (o4 && o4.then) return o4.then(function() {
 | |
|             });
 | |
|           });
 | |
|         } catch (t6) {
 | |
|           return n3(t6);
 | |
|         }
 | |
|         return u3 && u3.then ? u3.then(void 0, n3) : u3;
 | |
|       }(0, function(t5) {
 | |
|         throw Vt.error(t5), e3.emit("error", i2), t5;
 | |
|       });
 | |
|       return Promise.resolve(u2 && u2.then ? u2.then(n2) : n2());
 | |
|     } catch (t5) {
 | |
|       return Promise.reject(t5);
 | |
|     }
 | |
|   }, o2.findProcessorIndexByID = function(t4) {
 | |
|     return this.steps.findIndex(function(n2) {
 | |
|       return n2.id == t4;
 | |
|     });
 | |
|   }, o2.setLastProcessorIndex = function(t4) {
 | |
|     var n2 = this.findProcessorIndexByID(t4.id);
 | |
|     this.lastProcessorIndexUpdated > n2 && (this.lastProcessorIndexUpdated = n2);
 | |
|   }, o2.processorPropsUpdated = function(t4) {
 | |
|     this.setLastProcessorIndex(t4), this.emit("propsUpdated"), this.emit("updated", t4);
 | |
|   }, o2.afterRegistered = function(t4) {
 | |
|     this.setLastProcessorIndex(t4), this.emit("afterRegister"), this.emit("updated", t4);
 | |
|   }, n(e2, [{ key: "steps", get: function() {
 | |
|     for (var t4, n2 = [], e3 = s(this.getSortedProcessorTypes()); !(t4 = e3()).done; ) {
 | |
|       var r2 = this._steps.get(t4.value);
 | |
|       r2 && r2.length && (n2 = n2.concat(r2));
 | |
|     }
 | |
|     return n2.filter(function(t5) {
 | |
|       return t5;
 | |
|     });
 | |
|   } }]), e2;
 | |
| }(Q);
 | |
| var on = /* @__PURE__ */ function(t3) {
 | |
|   function e2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(e2, t3), e2.prototype._process = function(t4) {
 | |
|     try {
 | |
|       return Promise.resolve(this.props.storage.get(t4));
 | |
|     } catch (t5) {
 | |
|       return Promise.reject(t5);
 | |
|     }
 | |
|   }, n(e2, [{ key: "type", get: function() {
 | |
|     return K.Extractor;
 | |
|   } }]), e2;
 | |
| }(tt);
 | |
| var un = /* @__PURE__ */ function(t3) {
 | |
|   function e2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(e2, t3), e2.prototype._process = function(t4) {
 | |
|     var n2 = J.fromArray(t4.data);
 | |
|     return n2.length = t4.total, n2;
 | |
|   }, n(e2, [{ key: "type", get: function() {
 | |
|     return K.Transformer;
 | |
|   } }]), e2;
 | |
| }(tt);
 | |
| var sn = /* @__PURE__ */ function(t3) {
 | |
|   function o2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(o2, t3), o2.prototype._process = function() {
 | |
|     return Object.entries(this.props.serverStorageOptions).filter(function(t4) {
 | |
|       return "function" != typeof t4[1];
 | |
|     }).reduce(function(t4, n2) {
 | |
|       var r2;
 | |
|       return e({}, t4, ((r2 = {})[n2[0]] = n2[1], r2));
 | |
|     }, {});
 | |
|   }, n(o2, [{ key: "type", get: function() {
 | |
|     return K.Initiator;
 | |
|   } }]), o2;
 | |
| }(tt);
 | |
| var an = /* @__PURE__ */ function(t3) {
 | |
|   function e2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   r(e2, t3);
 | |
|   var o2 = e2.prototype;
 | |
|   return o2.castData = function(t4) {
 | |
|     if (!t4 || !t4.length) return [];
 | |
|     if (!this.props.header || !this.props.header.columns) return t4;
 | |
|     var n2 = Kt.leafColumns(this.props.header.columns);
 | |
|     return t4[0] instanceof Array ? t4.map(function(t5) {
 | |
|       var e3 = 0;
 | |
|       return n2.map(function(n3, r2) {
 | |
|         return void 0 !== n3.data ? (e3++, "function" == typeof n3.data ? n3.data(t5) : n3.data) : t5[r2 - e3];
 | |
|       });
 | |
|     }) : "object" != typeof t4[0] || t4[0] instanceof Array ? [] : t4.map(function(t5) {
 | |
|       return n2.map(function(n3, e3) {
 | |
|         return void 0 !== n3.data ? "function" == typeof n3.data ? n3.data(t5) : n3.data : n3.id ? t5[n3.id] : (Vt.error("Could not find the correct cell for column at position " + e3 + ".\n                          Make sure either 'id' or 'selector' is defined for all columns."), null);
 | |
|       });
 | |
|     });
 | |
|   }, o2._process = function(t4) {
 | |
|     return { data: this.castData(t4.data), total: t4.total };
 | |
|   }, n(e2, [{ key: "type", get: function() {
 | |
|     return K.Transformer;
 | |
|   } }]), e2;
 | |
| }(tt);
 | |
| var ln = /* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|   }
 | |
|   return t3.createFromConfig = function(t4) {
 | |
|     var n2 = new rn();
 | |
|     return t4.storage instanceof Jt && n2.register(new sn({ serverStorageOptions: t4.server })), n2.register(new on({ storage: t4.storage })), n2.register(new an({ header: t4.header })), n2.register(new un()), n2;
 | |
|   }, t3;
 | |
| }();
 | |
| var cn = function(t3) {
 | |
|   var n2 = this;
 | |
|   this.state = void 0, this.listeners = [], this.isDispatching = false, this.getState = function() {
 | |
|     return n2.state;
 | |
|   }, this.getListeners = function() {
 | |
|     return n2.listeners;
 | |
|   }, this.dispatch = function(t4) {
 | |
|     if ("function" != typeof t4) throw new Error("Reducer is not a function");
 | |
|     if (n2.isDispatching) throw new Error("Reducers may not dispatch actions");
 | |
|     n2.isDispatching = true;
 | |
|     var e2 = n2.state;
 | |
|     try {
 | |
|       n2.state = t4(n2.state);
 | |
|     } finally {
 | |
|       n2.isDispatching = false;
 | |
|     }
 | |
|     for (var r2, o2 = s(n2.listeners); !(r2 = o2()).done; ) (0, r2.value)(n2.state, e2);
 | |
|     return n2.state;
 | |
|   }, this.subscribe = function(t4) {
 | |
|     if ("function" != typeof t4) throw new Error("Listener is not a function");
 | |
|     return n2.listeners = [].concat(n2.listeners, [t4]), function() {
 | |
|       return n2.listeners = n2.listeners.filter(function(n3) {
 | |
|         return n3 !== t4;
 | |
|       });
 | |
|     };
 | |
|   }, this.state = t3;
 | |
| };
 | |
| var fn = function(t3, n2) {
 | |
|   var e2 = { __c: n2 = "__cC" + _++, __: null, Consumer: function(t4, n3) {
 | |
|     return t4.children(n3);
 | |
|   }, Provider: function(t4) {
 | |
|     var e3, r2;
 | |
|     return this.getChildContext || (e3 = [], (r2 = {})[n2] = this, this.getChildContext = function() {
 | |
|       return r2;
 | |
|     }, this.shouldComponentUpdate = function(t5) {
 | |
|       this.props.value !== t5.value && e3.some(E);
 | |
|     }, this.sub = function(t5) {
 | |
|       e3.push(t5);
 | |
|       var n3 = t5.componentWillUnmount;
 | |
|       t5.componentWillUnmount = function() {
 | |
|         e3.splice(e3.indexOf(t5), 1), n3 && n3.call(t5);
 | |
|       };
 | |
|     }), t4.children;
 | |
|   } };
 | |
|   return e2.Provider.__ = e2.Consumer.contextType = e2;
 | |
| }();
 | |
| var pn = /* @__PURE__ */ function() {
 | |
|   function t3() {
 | |
|     Object.assign(this, t3.defaultConfig());
 | |
|   }
 | |
|   var n2 = t3.prototype;
 | |
|   return n2.assign = function(t4) {
 | |
|     return Object.assign(this, t4);
 | |
|   }, n2.update = function(n3) {
 | |
|     return n3 ? (this.assign(t3.fromPartialConfig(e({}, this, n3))), this) : this;
 | |
|   }, t3.defaultConfig = function() {
 | |
|     return { store: new cn({ status: a.Init, header: void 0, data: null }), plugin: new $t(), tableRef: { current: null }, width: "100%", height: "auto", processingThrottleMs: 100, autoWidth: true, style: {}, className: {} };
 | |
|   }, t3.fromPartialConfig = function(n3) {
 | |
|     var e2 = new t3().assign(n3);
 | |
|     return "boolean" == typeof n3.sort && n3.sort && e2.assign({ sort: { multiColumn: true } }), e2.assign({ header: Kt.createFromConfig(e2) }), e2.assign({ storage: Qt.createFromConfig(e2) }), e2.assign({ pipeline: ln.createFromConfig(e2) }), e2.assign({ translator: new Lt(e2.language) }), e2.plugin = new $t(), e2.search && e2.plugin.add({ id: "search", position: zt.Header, component: Dt }), e2.pagination && e2.plugin.add({ id: "pagination", position: zt.Footer, component: Rt }), e2.plugins && e2.plugins.forEach(function(t4) {
 | |
|       return e2.plugin.add(t4);
 | |
|     }), e2;
 | |
|   }, t3;
 | |
| }();
 | |
| function dn(t3) {
 | |
|   var n2, r2 = It();
 | |
|   return w("td", e({ role: t3.role, colSpan: t3.colSpan, "data-column-id": t3.column && t3.column.id, className: rt(et("td"), t3.className, r2.className.td), style: e({}, t3.style, r2.style.td), onClick: function(n3) {
 | |
|     t3.messageCell || r2.eventEmitter.emit("cellClick", n3, t3.cell, t3.column, t3.row);
 | |
|   } }, (n2 = t3.column) ? "function" == typeof n2.attributes ? n2.attributes(t3.cell.data, t3.row, t3.column) : n2.attributes : {}), t3.column && "function" == typeof t3.column.formatter ? t3.column.formatter(t3.cell.data, t3.row, t3.column) : t3.column && t3.column.plugin ? w(Gt, { pluginId: t3.column.id, props: { column: t3.column, cell: t3.cell, row: t3.row } }) : t3.cell.data);
 | |
| }
 | |
| function hn(t3) {
 | |
|   var n2 = It(), e2 = jt(function(t4) {
 | |
|     return t4.header;
 | |
|   });
 | |
|   return w("tr", { className: rt(et("tr"), n2.className.tr), onClick: function(e3) {
 | |
|     t3.messageRow || n2.eventEmitter.emit("rowClick", e3, t3.row);
 | |
|   } }, t3.children ? t3.children : t3.row.cells.map(function(n3, r2) {
 | |
|     var o2 = function(t4) {
 | |
|       if (e2) {
 | |
|         var n4 = Kt.leafColumns(e2.columns);
 | |
|         if (n4) return n4[t4];
 | |
|       }
 | |
|       return null;
 | |
|     }(r2);
 | |
|     return o2 && o2.hidden ? null : w(dn, { key: n3.id, cell: n3, row: t3.row, column: o2 });
 | |
|   }));
 | |
| }
 | |
| function _n(t3) {
 | |
|   return w(hn, { messageRow: true }, w(dn, { role: "alert", colSpan: t3.colSpan, messageCell: true, cell: new X(t3.message), className: rt(et("message"), t3.className ? t3.className : null) }));
 | |
| }
 | |
| function mn() {
 | |
|   var t3 = It(), n2 = jt(function(t4) {
 | |
|     return t4.data;
 | |
|   }), e2 = jt(function(t4) {
 | |
|     return t4.status;
 | |
|   }), r2 = jt(function(t4) {
 | |
|     return t4.header;
 | |
|   }), o2 = At(), i2 = function() {
 | |
|     return r2 ? r2.visibleColumns.length : 0;
 | |
|   };
 | |
|   return w("tbody", { className: rt(et("tbody"), t3.className.tbody) }, n2 && n2.rows.map(function(t4) {
 | |
|     return w(hn, { key: t4.id, row: t4 });
 | |
|   }), e2 === a.Loading && (!n2 || 0 === n2.length) && w(_n, { message: o2("loading"), colSpan: i2(), className: rt(et("loading"), t3.className.loading) }), e2 === a.Rendered && n2 && 0 === n2.length && w(_n, { message: o2("noRecordsFound"), colSpan: i2(), className: rt(et("notfound"), t3.className.notfound) }), e2 === a.Error && w(_n, { message: o2("error"), colSpan: i2(), className: rt(et("error"), t3.className.error) }));
 | |
| }
 | |
| var vn = /* @__PURE__ */ function(t3) {
 | |
|   function e2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   r(e2, t3);
 | |
|   var o2 = e2.prototype;
 | |
|   return o2.validateProps = function() {
 | |
|     for (var t4, n2 = s(this.props.columns); !(t4 = n2()).done; ) {
 | |
|       var e3 = t4.value;
 | |
|       void 0 === e3.direction && (e3.direction = 1), 1 !== e3.direction && -1 !== e3.direction && Vt.error("Invalid sort direction " + e3.direction);
 | |
|     }
 | |
|   }, o2.compare = function(t4, n2) {
 | |
|     return t4 > n2 ? 1 : t4 < n2 ? -1 : 0;
 | |
|   }, o2.compareWrapper = function(t4, n2) {
 | |
|     for (var e3, r2 = 0, o3 = s(this.props.columns); !(e3 = o3()).done; ) {
 | |
|       var i2 = e3.value;
 | |
|       if (0 !== r2) break;
 | |
|       var u2 = t4.cells[i2.index].data, a2 = n2.cells[i2.index].data;
 | |
|       r2 |= "function" == typeof i2.compare ? i2.compare(u2, a2) * i2.direction : this.compare(u2, a2) * i2.direction;
 | |
|     }
 | |
|     return r2;
 | |
|   }, o2._process = function(t4) {
 | |
|     var n2 = [].concat(t4.rows);
 | |
|     n2.sort(this.compareWrapper.bind(this));
 | |
|     var e3 = new J(n2);
 | |
|     return e3.length = t4.length, e3;
 | |
|   }, n(e2, [{ key: "type", get: function() {
 | |
|     return K.Sort;
 | |
|   } }]), e2;
 | |
| }(tt);
 | |
| var yn = function(t3, n2, r2, o2) {
 | |
|   return function(i2) {
 | |
|     var u2, s2 = null != (u2 = i2.sort) && u2.columns ? i2.sort.columns.map(function(t4) {
 | |
|       return e({}, t4);
 | |
|     }) : [], a2 = s2.length, l2 = s2.find(function(n3) {
 | |
|       return n3.index === t3;
 | |
|     }), c2 = false, f2 = false, p2 = false, d2 = false;
 | |
|     if (void 0 !== l2 ? r2 ? -1 === l2.direction ? p2 = true : d2 = true : 1 === a2 ? d2 = true : a2 > 1 && (f2 = true, c2 = true) : 0 === a2 ? c2 = true : a2 > 0 && !r2 ? (c2 = true, f2 = true) : a2 > 0 && r2 && (c2 = true), f2 && (s2 = []), c2) s2.push({ index: t3, direction: n2, compare: o2 });
 | |
|     else if (d2) {
 | |
|       var h6 = s2.indexOf(l2);
 | |
|       s2[h6].direction = n2;
 | |
|     } else if (p2) {
 | |
|       var _2 = s2.indexOf(l2);
 | |
|       s2.splice(_2, 1);
 | |
|     }
 | |
|     return e({}, i2, { sort: { columns: s2 } });
 | |
|   };
 | |
| };
 | |
| var gn = function(t3, n2, r2) {
 | |
|   return function(o2) {
 | |
|     var i2 = (o2.sort ? [].concat(o2.sort.columns) : []).find(function(n3) {
 | |
|       return n3.index === t3;
 | |
|     });
 | |
|     return e({}, o2, i2 ? yn(t3, 1 === i2.direction ? -1 : 1, n2, r2)(o2) : yn(t3, 1, n2, r2)(o2));
 | |
|   };
 | |
| };
 | |
| var bn = /* @__PURE__ */ function(t3) {
 | |
|   function o2() {
 | |
|     return t3.apply(this, arguments) || this;
 | |
|   }
 | |
|   return r(o2, t3), o2.prototype._process = function(t4) {
 | |
|     var n2 = {};
 | |
|     return this.props.url && (n2.url = this.props.url(t4.url, this.props.columns)), this.props.body && (n2.body = this.props.body(t4.body, this.props.columns)), e({}, t4, n2);
 | |
|   }, n(o2, [{ key: "type", get: function() {
 | |
|     return K.ServerSort;
 | |
|   } }]), o2;
 | |
| }(tt);
 | |
| function wn(t3) {
 | |
|   var n2 = It(), r2 = Ht().dispatch, o2 = At(), i2 = yt(0), u2 = i2[0], s2 = i2[1], a2 = n2.sort, l2 = jt(function(t4) {
 | |
|     return t4.sort;
 | |
|   }), c2 = "object" == typeof (null == a2 ? void 0 : a2.server) ? K.ServerSort : K.Sort, f2 = function() {
 | |
|     var t4 = n2.pipeline.getStepsByType(c2);
 | |
|     if (t4.length) return t4[0];
 | |
|   };
 | |
|   return gt(function() {
 | |
|     var t4 = f2() || (c2 === K.ServerSort ? new bn(e({ columns: l2 ? l2.columns : [] }, a2.server)) : new vn({ columns: l2 ? l2.columns : [] }));
 | |
|     return n2.pipeline.tryRegister(t4), function() {
 | |
|       return n2.pipeline.unregister(t4);
 | |
|     };
 | |
|   }, [n2]), gt(function() {
 | |
|     if (l2) {
 | |
|       var n3, e2 = l2.columns.find(function(n4) {
 | |
|         return n4.index === t3.index;
 | |
|       });
 | |
|       e2 ? (0 === u2 && (e2.direction = null != (n3 = t3.direction) ? n3 : 1), s2(e2.direction)) : s2(0);
 | |
|     }
 | |
|   }, [l2]), gt(function() {
 | |
|     var t4 = f2();
 | |
|     t4 && l2 && t4.setProps({ columns: l2.columns });
 | |
|   }, [l2]), w("button", { tabIndex: -1, "aria-label": o2("sort.sort" + (1 === u2 ? "Desc" : "Asc")), title: o2("sort.sort" + (1 === u2 ? "Desc" : "Asc")), className: rt(et("sort"), et("sort", /* @__PURE__ */ function(t4) {
 | |
|     return 1 === t4 ? "asc" : -1 === t4 ? "desc" : "neutral";
 | |
|   }(u2)), n2.className.sort), onClick: function(n3) {
 | |
|     n3.preventDefault(), n3.stopPropagation(), r2(gn(t3.index, true === n3.shiftKey && a2.multiColumn, t3.compare));
 | |
|   } });
 | |
| }
 | |
| var xn = function(t3, n2) {
 | |
|   var e2;
 | |
|   void 0 === n2 && (n2 = 100);
 | |
|   var r2 = Date.now(), o2 = function() {
 | |
|     r2 = Date.now(), t3.apply(void 0, [].slice.call(arguments));
 | |
|   };
 | |
|   return function() {
 | |
|     var t4 = [].slice.call(arguments), i2 = Date.now(), u2 = i2 - r2;
 | |
|     u2 >= n2 ? o2.apply(void 0, t4) : (e2 && clearTimeout(e2), e2 = setTimeout(function() {
 | |
|       o2.apply(void 0, t4), e2 = null;
 | |
|     }, n2 - u2));
 | |
|   };
 | |
| };
 | |
| function kn(t3) {
 | |
|   var n2, e2 = function(t4) {
 | |
|     return t4 instanceof MouseEvent ? Math.floor(t4.pageX) : Math.floor(t4.changedTouches[0].pageX);
 | |
|   }, r2 = function(r3) {
 | |
|     r3.stopPropagation();
 | |
|     var u2 = parseInt(t3.thRef.current.style.width, 10) - e2(r3);
 | |
|     n2 = xn(function(t4) {
 | |
|       return o2(t4, u2);
 | |
|     }, 10), document.addEventListener("mouseup", i2), document.addEventListener("touchend", i2), document.addEventListener("mousemove", n2), document.addEventListener("touchmove", n2);
 | |
|   }, o2 = function(n3, r3) {
 | |
|     n3.stopPropagation();
 | |
|     var o3 = t3.thRef.current;
 | |
|     r3 + e2(n3) >= parseInt(o3.style.minWidth, 10) && (o3.style.width = r3 + e2(n3) + "px");
 | |
|   }, i2 = function t4(e3) {
 | |
|     e3.stopPropagation(), document.removeEventListener("mouseup", t4), document.removeEventListener("mousemove", n2), document.removeEventListener("touchmove", n2), document.removeEventListener("touchend", t4);
 | |
|   };
 | |
|   return w("div", { className: rt(et("th"), et("resizable")), onMouseDown: r2, onTouchStart: r2, onClick: function(t4) {
 | |
|     return t4.stopPropagation();
 | |
|   } });
 | |
| }
 | |
| function Sn(t3) {
 | |
|   var n2 = It(), r2 = bt(null), o2 = yt({}), i2 = o2[0], u2 = o2[1], s2 = Ht().dispatch;
 | |
|   gt(function() {
 | |
|     if (n2.fixedHeader && r2.current) {
 | |
|       var t4 = r2.current.offsetTop;
 | |
|       "number" == typeof t4 && u2({ top: t4 });
 | |
|     }
 | |
|   }, [r2]);
 | |
|   var a2, l2 = function() {
 | |
|     return null != t3.column.sort;
 | |
|   }, c2 = function(e2) {
 | |
|     e2.stopPropagation(), l2() && s2(gn(t3.index, true === e2.shiftKey && n2.sort.multiColumn, t3.column.sort.compare));
 | |
|   };
 | |
|   return w("th", e({ ref: r2, "data-column-id": t3.column && t3.column.id, className: rt(et("th"), l2() ? et("th", "sort") : null, n2.fixedHeader ? et("th", "fixed") : null, n2.className.th), onClick: c2, style: e({}, n2.style.th, { minWidth: t3.column.minWidth, width: t3.column.width }, i2, t3.style), onKeyDown: function(t4) {
 | |
|     l2() && 13 === t4.which && c2(t4);
 | |
|   }, rowSpan: t3.rowSpan > 1 ? t3.rowSpan : void 0, colSpan: t3.colSpan > 1 ? t3.colSpan : void 0 }, (a2 = t3.column) ? "function" == typeof a2.attributes ? a2.attributes(null, null, t3.column) : a2.attributes : {}, l2() ? { tabIndex: 0 } : {}), w("div", { className: et("th", "content") }, void 0 !== t3.column.name ? t3.column.name : void 0 !== t3.column.plugin ? w(Gt, { pluginId: t3.column.plugin.id, props: { column: t3.column } }) : null), l2() && w(wn, e({ index: t3.index }, t3.column.sort)), t3.column.resizable && t3.index < n2.header.visibleColumns.length - 1 && w(kn, { column: t3.column, thRef: r2 }));
 | |
| }
 | |
| function Nn() {
 | |
|   var t3, n2 = It(), e2 = jt(function(t4) {
 | |
|     return t4.header;
 | |
|   });
 | |
|   return e2 ? w("thead", { key: e2.id, className: rt(et("thead"), n2.className.thead) }, (t3 = Kt.tabularFormat(e2.columns)).map(function(n3, r2) {
 | |
|     return function(t4, n4, r3) {
 | |
|       var o2 = Kt.leafColumns(e2.columns);
 | |
|       return w(hn, null, t4.map(function(t5) {
 | |
|         return t5.hidden ? null : function(t6, n5, e3, r4) {
 | |
|           var o3 = function(t7, n6, e4) {
 | |
|             var r5 = Kt.maximumDepth(t7), o4 = e4 - n6;
 | |
|             return { rowSpan: Math.floor(o4 - r5 - r5 / o4), colSpan: t7.columns && t7.columns.length || 1 };
 | |
|           }(t6, n5, r4);
 | |
|           return w(Sn, { column: t6, index: e3, colSpan: o3.colSpan, rowSpan: o3.rowSpan });
 | |
|         }(t5, n4, o2.indexOf(t5), r3);
 | |
|       }));
 | |
|     }(n3, r2, t3.length);
 | |
|   })) : null;
 | |
| }
 | |
| var Pn = function(t3) {
 | |
|   return function(n2) {
 | |
|     return e({}, n2, { header: t3 });
 | |
|   };
 | |
| };
 | |
| function Cn() {
 | |
|   var t3 = It(), n2 = bt(null), r2 = Ht().dispatch;
 | |
|   return gt(function() {
 | |
|     n2 && r2(/* @__PURE__ */ function(t4) {
 | |
|       return function(n3) {
 | |
|         return e({}, n3, { tableRef: t4 });
 | |
|       };
 | |
|     }(n2));
 | |
|   }, [n2]), w("table", { ref: n2, role: "grid", className: rt(et("table"), t3.className.table), style: e({}, t3.style.table, { height: t3.height }) }, w(Nn, null), w(mn, null));
 | |
| }
 | |
| function En() {
 | |
|   var t3 = yt(true), n2 = t3[0], r2 = t3[1], o2 = bt(null), i2 = It();
 | |
|   return gt(function() {
 | |
|     0 === o2.current.children.length && r2(false);
 | |
|   }, [o2]), n2 ? w("div", { ref: o2, className: rt(et("head"), i2.className.header), style: e({}, i2.style.header) }, w(Gt, { position: zt.Header })) : null;
 | |
| }
 | |
| function In() {
 | |
|   var t3 = bt(null), n2 = yt(true), r2 = n2[0], o2 = n2[1], i2 = It();
 | |
|   return gt(function() {
 | |
|     0 === t3.current.children.length && o2(false);
 | |
|   }, [t3]), r2 ? w("div", { ref: t3, className: rt(et("footer"), i2.className.footer), style: e({}, i2.style.footer) }, w(Gt, { position: zt.Footer })) : null;
 | |
| }
 | |
| function Tn() {
 | |
|   var t3 = It(), n2 = Ht().dispatch, r2 = jt(function(t4) {
 | |
|     return t4.status;
 | |
|   }), o2 = jt(function(t4) {
 | |
|     return t4.data;
 | |
|   }), i2 = jt(function(t4) {
 | |
|     return t4.tableRef;
 | |
|   }), u2 = { current: null }, s2 = xn(function() {
 | |
|     try {
 | |
|       n2(function(t4) {
 | |
|         return e({}, t4, { status: a.Loading });
 | |
|       });
 | |
|       var r3 = function(r4, o3) {
 | |
|         try {
 | |
|           var i3 = Promise.resolve(t3.pipeline.process()).then(function(t4) {
 | |
|             n2(/* @__PURE__ */ function(t5) {
 | |
|               return function(n3) {
 | |
|                 return t5 ? e({}, n3, { data: t5, status: a.Loaded }) : n3;
 | |
|               };
 | |
|             }(t4)), setTimeout(function() {
 | |
|               n2(function(t5) {
 | |
|                 return t5.status === a.Loaded ? e({}, t5, { status: a.Rendered }) : t5;
 | |
|               });
 | |
|             }, 0);
 | |
|           });
 | |
|         } catch (t4) {
 | |
|           return o3(t4);
 | |
|         }
 | |
|         return i3 && i3.then ? i3.then(void 0, o3) : i3;
 | |
|       }(0, function(t4) {
 | |
|         Vt.error(t4), n2(function(t5) {
 | |
|           return e({}, t5, { data: null, status: a.Error });
 | |
|         });
 | |
|       });
 | |
|       return Promise.resolve(r3 && r3.then ? r3.then(function() {
 | |
|       }) : void 0);
 | |
|     } catch (t4) {
 | |
|       return Promise.reject(t4);
 | |
|     }
 | |
|   }, t3.processingThrottleMs);
 | |
|   return gt(function() {
 | |
|     return n2(Pn(t3.header)), s2(), t3.pipeline.on("updated", s2), function() {
 | |
|       return t3.pipeline.off("updated", s2);
 | |
|     };
 | |
|   }, []), gt(function() {
 | |
|     t3.header && r2 === a.Loaded && null != o2 && o2.length && n2(Pn(t3.header.adjustWidth(t3, i2, u2)));
 | |
|   }, [o2, t3, u2]), w("div", { role: "complementary", className: rt("gridjs", et("container"), r2 === a.Loading ? et("loading") : null, t3.className.container), style: e({}, t3.style.container, { width: t3.width }) }, r2 === a.Loading && w("div", { className: et("loading-bar") }), w(En, null), w("div", { className: et("wrapper"), style: { height: t3.height } }, w(Cn, null)), w(In, null), w("div", { ref: u2, id: "gridjs-temp", className: et("temp") }));
 | |
| }
 | |
| var Ln = /* @__PURE__ */ function(t3) {
 | |
|   function n2(n3) {
 | |
|     var e3;
 | |
|     return (e3 = t3.call(this) || this).config = void 0, e3.plugin = void 0, e3.config = new pn().assign({ instance: i(e3), eventEmitter: i(e3) }).update(n3), e3.plugin = e3.config.plugin, e3;
 | |
|   }
 | |
|   r(n2, t3);
 | |
|   var e2 = n2.prototype;
 | |
|   return e2.updateConfig = function(t4) {
 | |
|     return this.config.update(t4), this;
 | |
|   }, e2.createElement = function() {
 | |
|     return w(fn.Provider, { value: this.config, children: w(Tn, {}) });
 | |
|   }, e2.forceRender = function() {
 | |
|     return this.config && this.config.container || Vt.error("Container is empty. Make sure you call render() before forceRender()", true), this.destroy(), q(this.createElement(), this.config.container), this;
 | |
|   }, e2.destroy = function() {
 | |
|     this.config.pipeline.clearCache(), q(null, this.config.container);
 | |
|   }, e2.render = function(t4) {
 | |
|     return t4 || Vt.error("Container element cannot be null", true), t4.childNodes.length > 0 ? (Vt.error("The container element " + t4 + " is not empty. Make sure the container is empty and call render() again"), this) : (this.config.container = t4, q(this.createElement(), t4), this);
 | |
|   }, n2;
 | |
| }(Q);
 | |
| 
 | |
| // src/gui/statistics.tsx
 | |
| var import_path = __toESM(require("path"));
 | |
| var import_vhtml = __toESM(require_vhtml());
 | |
| Chart.register(
 | |
|   BarElement,
 | |
|   BarController,
 | |
|   plugin_legend,
 | |
|   plugin_title,
 | |
|   plugin_tooltip,
 | |
|   plugin_subtitle,
 | |
|   CategoryScale,
 | |
|   LinearScale,
 | |
|   PieController,
 | |
|   ArcElement
 | |
| );
 | |
| var StatisticsView = class {
 | |
|   constructor(containerEl, osrCore) {
 | |
|     this.containerEl = containerEl;
 | |
|     this.osrCore = osrCore;
 | |
|   }
 | |
|   render() {
 | |
|     this.containerEl.style.textAlign = "center";
 | |
|     this.containerEl.innerHTML += /* @__PURE__ */ (0, import_vhtml.default)("select", { id: "sr-chart-period" }, /* @__PURE__ */ (0, import_vhtml.default)("option", { value: "month", selected: true }, t("MONTH")), /* @__PURE__ */ (0, import_vhtml.default)("option", { value: "quarter" }, t("QUARTER")), /* @__PURE__ */ (0, import_vhtml.default)("option", { value: "year" }, t("YEAR")), /* @__PURE__ */ (0, import_vhtml.default)("option", { value: "lifetime" }, t("LIFETIME")));
 | |
|     const cardStats = this.osrCore.cardStats;
 | |
|     let maxN = cardStats.delayedDays.getMaxValue();
 | |
|     for (let dueOffset = 0; dueOffset <= maxN; dueOffset++) {
 | |
|       cardStats.delayedDays.clearCountIfMissing(dueOffset);
 | |
|     }
 | |
|     const dueDatesFlashcardsCopy = { 0: 0 };
 | |
|     for (const [dueOffset, dueCount] of getTypedObjectEntries(cardStats.delayedDays.dict)) {
 | |
|       if (dueOffset <= 0) {
 | |
|         dueDatesFlashcardsCopy[0] += dueCount;
 | |
|       } else {
 | |
|         dueDatesFlashcardsCopy[dueOffset] = dueCount;
 | |
|       }
 | |
|     }
 | |
|     const scheduledCount = cardStats.youngCount + cardStats.matureCount;
 | |
|     maxN = Math.max(maxN, 1);
 | |
|     this.containerEl.innerHTML += /* @__PURE__ */ (0, import_vhtml.default)("div", null, /* @__PURE__ */ (0, import_vhtml.default)("canvas", { id: "forecastChart" }), /* @__PURE__ */ (0, import_vhtml.default)("span", { id: "forecastChartSummary" }), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("canvas", { id: "intervalsChart" }), /* @__PURE__ */ (0, import_vhtml.default)("span", { id: "intervalsChartSummary" }), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("canvas", { id: "easesChart" }), /* @__PURE__ */ (0, import_vhtml.default)("span", { id: "easesChartSummary" }), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("canvas", { id: "cardTypesChart" }), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("span", { id: "cardTypesChartSummary" }), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("br", null), /* @__PURE__ */ (0, import_vhtml.default)("h1", null, "Notes"), /* @__PURE__ */ (0, import_vhtml.default)("div", { id: "noteStats" }));
 | |
|     this.forecastChart = createStatsChart(
 | |
|       "bar",
 | |
|       "forecastChart",
 | |
|       t("FORECAST"),
 | |
|       t("FORECAST_DESC"),
 | |
|       Object.keys(dueDatesFlashcardsCopy),
 | |
|       Object.values(dueDatesFlashcardsCopy),
 | |
|       t("REVIEWS_PER_DAY", { avg: (scheduledCount / maxN).toFixed(1) }),
 | |
|       t("SCHEDULED"),
 | |
|       t("DAYS"),
 | |
|       t("NUMBER_OF_CARDS")
 | |
|     );
 | |
|     maxN = cardStats.intervals.getMaxValue();
 | |
|     for (let interval = 0; interval <= maxN; interval++) {
 | |
|       cardStats.intervals.clearCountIfMissing(interval);
 | |
|     }
 | |
|     const averageInterval = textInterval(
 | |
|       Math.round(
 | |
|         cardStats.intervals.getTotalOfValueMultiplyCount() / scheduledCount * 10
 | |
|       ) / 10 || 0,
 | |
|       false
 | |
|     ), longestInterval = textInterval(cardStats.intervals.getMaxValue(), false);
 | |
|     this.intervalsChart = createStatsChart(
 | |
|       "bar",
 | |
|       "intervalsChart",
 | |
|       t("INTERVALS"),
 | |
|       t("INTERVALS_DESC"),
 | |
|       Object.keys(cardStats.intervals.dict),
 | |
|       Object.values(cardStats.intervals.dict),
 | |
|       t("INTERVALS_SUMMARY", { avg: averageInterval, longest: longestInterval }),
 | |
|       t("COUNT"),
 | |
|       t("DAYS"),
 | |
|       t("NUMBER_OF_CARDS")
 | |
|     );
 | |
|     const eases = getKeysPreserveType(cardStats.eases.dict);
 | |
|     for (let ease = Math.min(...eases); ease <= Math.max(...eases); ease++) {
 | |
|       cardStats.eases.clearCountIfMissing(ease);
 | |
|     }
 | |
|     const averageEase = Math.round(cardStats.eases.getTotalOfValueMultiplyCount() / scheduledCount) || 0;
 | |
|     this.easesChart = createStatsChart(
 | |
|       "bar",
 | |
|       "easesChart",
 | |
|       t("EASES"),
 | |
|       "",
 | |
|       Object.keys(cardStats.eases.dict),
 | |
|       Object.values(cardStats.eases.dict),
 | |
|       t("EASES_SUMMARY", { avgEase: averageEase }),
 | |
|       t("COUNT"),
 | |
|       t("EASES"),
 | |
|       t("NUMBER_OF_CARDS")
 | |
|     );
 | |
|     const totalCardsCount = this.osrCore.reviewableDeckTree.getDistinctCardCount(
 | |
|       2 /* All */,
 | |
|       true
 | |
|     );
 | |
|     this.cardTypesChart = createStatsChart(
 | |
|       "pie",
 | |
|       "cardTypesChart",
 | |
|       t("CARD_TYPES"),
 | |
|       t("CARD_TYPES_DESC"),
 | |
|       [
 | |
|         `${t("CARD_TYPE_NEW")} - ${Math.round(cardStats.newCount / totalCardsCount * 100)}%`,
 | |
|         `${t("CARD_TYPE_YOUNG")} - ${Math.round(
 | |
|           cardStats.youngCount / totalCardsCount * 100
 | |
|         )}%`,
 | |
|         `${t("CARD_TYPE_MATURE")} - ${Math.round(
 | |
|           cardStats.matureCount / totalCardsCount * 100
 | |
|         )}%`
 | |
|       ],
 | |
|       [cardStats.newCount, cardStats.youngCount, cardStats.matureCount],
 | |
|       t("CARD_TYPES_SUMMARY", { totalCardsCount })
 | |
|     );
 | |
|     const noteEases = mapRecord(
 | |
|       SrsAlgorithm.getInstance().noteStats().dict,
 | |
|       (key, value) => [
 | |
|         import_path.default.parse(key).name,
 | |
|         Math.round(value)
 | |
|       ]
 | |
|     );
 | |
|     this.noteStatsGrid = new Ln({
 | |
|       columns: [
 | |
|         {
 | |
|           name: t("NOTE")
 | |
|         },
 | |
|         {
 | |
|           name: t("EASE"),
 | |
|           sort: true,
 | |
|           width: "200px"
 | |
|         }
 | |
|       ],
 | |
|       search: true,
 | |
|       autoWidth: false,
 | |
|       data: Object.entries(noteEases).sort((a2, b2) => b2[1] - a2[1]),
 | |
|       pagination: {
 | |
|         limit: 10,
 | |
|         summary: false
 | |
|       },
 | |
|       language: {
 | |
|         search: {
 | |
|           placeholder: t("SEARCH")
 | |
|         },
 | |
|         pagination: {
 | |
|           previous: t("PREVIOUS"),
 | |
|           next: t("NEXT")
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.noteStatsGrid.render(document.getElementById("noteStats"));
 | |
|   }
 | |
|   destroy() {
 | |
|     this.forecastChart.destroy();
 | |
|     this.intervalsChart.destroy();
 | |
|     this.easesChart.destroy();
 | |
|     this.cardTypesChart.destroy();
 | |
|     this.noteStatsGrid.destroy();
 | |
|   }
 | |
| };
 | |
| function createStatsChart(type, canvasId, title, subtitle, labels, data, summary, seriesTitle = "", xAxisTitle = "", yAxisTitle = "") {
 | |
|   const style = getComputedStyle(document.body);
 | |
|   const textColor = style.getPropertyValue("--text-normal");
 | |
|   let scales = {}, backgroundColor = ["#2196f3"];
 | |
|   if (type !== "pie") {
 | |
|     scales = {
 | |
|       x: {
 | |
|         title: {
 | |
|           display: true,
 | |
|           text: xAxisTitle,
 | |
|           color: textColor
 | |
|         }
 | |
|       },
 | |
|       y: {
 | |
|         title: {
 | |
|           display: true,
 | |
|           text: yAxisTitle,
 | |
|           color: textColor
 | |
|         }
 | |
|       }
 | |
|     };
 | |
|   } else {
 | |
|     backgroundColor = ["#2196f3", "#4caf50", "green"];
 | |
|   }
 | |
|   const shouldFilter = canvasId === "forecastChart" || canvasId === "intervalsChart";
 | |
|   const statsChart = new Chart(document.getElementById(canvasId), {
 | |
|     type,
 | |
|     data: {
 | |
|       labels: shouldFilter ? labels.slice(0, 31) : labels,
 | |
|       datasets: [
 | |
|         {
 | |
|           label: seriesTitle,
 | |
|           backgroundColor,
 | |
|           data: shouldFilter ? data.slice(0, 31) : data
 | |
|         }
 | |
|       ]
 | |
|     },
 | |
|     options: {
 | |
|       scales,
 | |
|       plugins: {
 | |
|         title: {
 | |
|           display: true,
 | |
|           text: title,
 | |
|           font: {
 | |
|             size: 22
 | |
|           },
 | |
|           color: textColor
 | |
|         },
 | |
|         subtitle: {
 | |
|           display: true,
 | |
|           text: subtitle,
 | |
|           font: {
 | |
|             size: 16,
 | |
|             style: "italic"
 | |
|           },
 | |
|           color: textColor
 | |
|         },
 | |
|         legend: {
 | |
|           display: false
 | |
|         }
 | |
|       },
 | |
|       aspectRatio: 2
 | |
|     }
 | |
|   });
 | |
|   if (shouldFilter) {
 | |
|     const chartPeriodEl = document.getElementById("sr-chart-period");
 | |
|     chartPeriodEl.addEventListener("click", () => {
 | |
|       let filteredLabels, filteredData;
 | |
|       const chartPeriod = chartPeriodEl.value;
 | |
|       if (chartPeriod === "month") {
 | |
|         filteredLabels = labels.slice(0, 31);
 | |
|         filteredData = data.slice(0, 31);
 | |
|       } else if (chartPeriod === "quarter") {
 | |
|         filteredLabels = labels.slice(0, 91);
 | |
|         filteredData = data.slice(0, 91);
 | |
|       } else if (chartPeriod === "year") {
 | |
|         filteredLabels = labels.slice(0, 366);
 | |
|         filteredData = data.slice(0, 366);
 | |
|       } else {
 | |
|         filteredLabels = labels;
 | |
|         filteredData = data;
 | |
|       }
 | |
|       statsChart.data.labels = filteredLabels;
 | |
|       statsChart.data.datasets[0] = {
 | |
|         label: seriesTitle,
 | |
|         backgroundColor,
 | |
|         data: filteredData
 | |
|       };
 | |
|       statsChart.update();
 | |
|     });
 | |
|   }
 | |
|   document.getElementById(`${canvasId}Summary`).innerText = summary;
 | |
|   return statsChart;
 | |
| }
 | |
| 
 | |
| // src/gui/tabs.tsx
 | |
| var import_obsidian5 = require("obsidian");
 | |
| var import_vhtml2 = __toESM(require_vhtml());
 | |
| function createTabs(containerElement, tabs, activateTabId) {
 | |
|   const tabHeader = containerElement.createEl("div", {
 | |
|     attr: { class: "sr-tab-header" }
 | |
|   });
 | |
|   const tabContentContainers = {};
 | |
|   const tabButtons = {};
 | |
|   const tabStructure = {
 | |
|     header: tabHeader,
 | |
|     // Indicate that the first tab is active.
 | |
|     // This does not affect what tab is active in practice, it just reports the active tab.
 | |
|     activeTabId: Object.keys(tabs)[0],
 | |
|     buttons: tabButtons,
 | |
|     contentContainers: tabContentContainers,
 | |
|     contentGeneratorPromises: {}
 | |
|   };
 | |
|   let firstButton;
 | |
|   for (const tabId in tabs) {
 | |
|     const tab = tabs[tabId];
 | |
|     const button = tabHeader.createEl("button", {
 | |
|       attr: {
 | |
|         class: "sr-tab-header-button",
 | |
|         activateTab: "sr-tab-" + tabId
 | |
|       }
 | |
|     });
 | |
|     button.onclick = function(event) {
 | |
|       var _a;
 | |
|       const tabButton = this;
 | |
|       let maxWidth = 0;
 | |
|       let maxHeight = 0;
 | |
|       const tabHeader2 = tabButton.parentElement;
 | |
|       if (null === tabHeader2) {
 | |
|         throw new Error("Tab header is missing. Did not get a parent from tab button.");
 | |
|       }
 | |
|       const containerElement2 = tabHeader2.parentElement;
 | |
|       if (null === containerElement2) {
 | |
|         throw new Error(
 | |
|           "Container element is missing. Did not get a parent from tab header."
 | |
|         );
 | |
|       }
 | |
|       const tabContents = containerElement2.findAll("div.sr-tab-content");
 | |
|       const isMainSettingsModal = containerElement2.hasClass("vertical-tab-content");
 | |
|       for (const index in tabContents) {
 | |
|         const tabContent2 = tabContents[index];
 | |
|         if (!isMainSettingsModal) {
 | |
|           tabContent2.addClass("sr-tab-active");
 | |
|           if (tabContent2.offsetHeight > maxHeight) {
 | |
|             maxHeight = tabContent2.offsetHeight;
 | |
|           }
 | |
|           if (tabContent2.offsetWidth > maxWidth) {
 | |
|             maxWidth = tabContent2.offsetWidth;
 | |
|           }
 | |
|         }
 | |
|         tabContent2.removeClass("sr-tab-active");
 | |
|       }
 | |
|       const adjacentTabButtons = tabHeader2.findAll(".sr-tab-header-button");
 | |
|       for (const index in adjacentTabButtons) {
 | |
|         const tabButton2 = adjacentTabButtons[index];
 | |
|         tabButton2.removeClass("sr-tab-active");
 | |
|       }
 | |
|       tabButton.addClass("sr-tab-active");
 | |
|       const activateTabAttribute = tabButton.attributes.getNamedItem("activateTab");
 | |
|       if (null === activateTabAttribute) {
 | |
|         throw new Error("Tab button has no 'activateTab' HTML attribute! Murr!");
 | |
|       }
 | |
|       const activateTabId2 = activateTabAttribute.value;
 | |
|       const tabContent = document.getElementById(activateTabId2);
 | |
|       if (null === tabContent) {
 | |
|         throw new Error(
 | |
|           "No tab content was found with activate_tab_id '" + activateTabId2 + "'! Hmph!"
 | |
|         );
 | |
|       }
 | |
|       tabContent.addClass("sr-tab-active");
 | |
|       tabStructure.activeTabId = activateTabId2.replace(/^sr-tab-/, "");
 | |
|       (_a = tabContent.find(".sr-focus-element-on-tab-opening")) == null ? void 0 : _a.focus();
 | |
|       if (!isMainSettingsModal) {
 | |
|         tabContent.style.width = maxWidth + "px";
 | |
|         tabContent.style.height = maxHeight + "px";
 | |
|       }
 | |
|       event.preventDefault();
 | |
|     };
 | |
|     if (tab.icon) (0, import_obsidian5.setIcon)(button, tab.icon);
 | |
|     button.insertAdjacentHTML("beforeend", /* @__PURE__ */ (0, import_vhtml2.default)("span", { style: "padding-left: 5px;" }, tab.title));
 | |
|     tabButtons[tabId] = button;
 | |
|     tabContentContainers[tabId] = containerElement.createEl("div", {
 | |
|       attr: { class: "sr-tab-content", id: "sr-tab-" + tabId }
 | |
|     });
 | |
|     tabStructure.contentGeneratorPromises[tabId] = tab.contentGenerator(
 | |
|       tabContentContainers[tabId]
 | |
|     );
 | |
|     if (void 0 === firstButton) {
 | |
|       firstButton = button;
 | |
|     }
 | |
|   }
 | |
|   tabButtons[activateTabId].click();
 | |
|   return tabStructure;
 | |
| }
 | |
| 
 | |
| // src/gui/settings.tsx
 | |
| var applyDebounceTimer = 0;
 | |
| function applySettingsUpdate(callback2) {
 | |
|   clearTimeout(applyDebounceTimer);
 | |
|   applyDebounceTimer = window.setTimeout(callback2, 512);
 | |
| }
 | |
| var SRSettingTab = class extends import_obsidian6.PluginSettingTab {
 | |
|   constructor(app, plugin) {
 | |
|     super(app, plugin);
 | |
|     this.lastPosition = {
 | |
|       scrollPosition: 0,
 | |
|       tabName: "main-flashcards"
 | |
|     };
 | |
|     this.plugin = plugin;
 | |
|   }
 | |
|   display() {
 | |
|     const { containerEl } = this;
 | |
|     containerEl.empty();
 | |
|     const header = containerEl.createEl("h4", {
 | |
|       text: `${t("SETTINGS_HEADER")}`
 | |
|     });
 | |
|     header.addClass("sr-centered");
 | |
|     this.tabStructure = createTabs(
 | |
|       containerEl,
 | |
|       {
 | |
|         "main-flashcards": {
 | |
|           title: t("FLASHCARDS"),
 | |
|           icon: "SpacedRepIcon",
 | |
|           contentGenerator: (containerElement) => this.tabFlashcards(containerElement)
 | |
|         },
 | |
|         "main-notes": {
 | |
|           title: t("NOTES"),
 | |
|           icon: "book-text",
 | |
|           contentGenerator: (containerElement) => this.tabNotes(containerElement)
 | |
|         },
 | |
|         "main-algorithm": {
 | |
|           title: t("SCHEDULING"),
 | |
|           icon: "calendar",
 | |
|           contentGenerator: (containerElement) => this.tabScheduling(containerElement)
 | |
|         },
 | |
|         "main-ui-preferences": {
 | |
|           title: t("UI"),
 | |
|           icon: "presentation",
 | |
|           contentGenerator: (containerElement) => this.tabUiPreferences(containerElement)
 | |
|         },
 | |
|         "main-statistics": {
 | |
|           title: t("STATS_TITLE"),
 | |
|           icon: "bar-chart-3",
 | |
|           contentGenerator: async (containerElement) => {
 | |
|             if (this.plugin.osrAppCore.cardStats == null) {
 | |
|               await this.plugin.sync();
 | |
|             }
 | |
|             this.statistics = new StatisticsView(
 | |
|               containerElement,
 | |
|               this.plugin.osrAppCore
 | |
|             );
 | |
|             this.statistics.render();
 | |
|           }
 | |
|         },
 | |
|         "main-help": {
 | |
|           title: t("HELP"),
 | |
|           icon: "badge-help",
 | |
|           contentGenerator: (containerElement) => this.tabHelp(containerElement)
 | |
|         }
 | |
|       },
 | |
|       this.lastPosition.tabName
 | |
|     );
 | |
|     this.tabStructure.contentGeneratorPromises[this.tabStructure.activeTabId].then(() => {
 | |
|       this.rememberLastPosition(containerEl);
 | |
|     });
 | |
|   }
 | |
|   hide() {
 | |
|     this.statistics.destroy();
 | |
|     this.containerEl.empty();
 | |
|   }
 | |
|   async tabFlashcards(containerEl) {
 | |
|     containerEl.createEl("h3", { text: t("GROUP_TAGS_FOLDERS") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("FLASHCARD_TAGS")).setDesc(t("FLASHCARD_TAGS_DESC")).addTextArea(
 | |
|       (text) => text.setValue(this.plugin.data.settings.flashcardTags.join(" ")).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.flashcardTags = value.split(/\s+/);
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("CONVERT_FOLDERS_TO_DECKS")).setDesc(t("CONVERT_FOLDERS_TO_DECKS_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.convertFoldersToDecks).onChange(async (value) => {
 | |
|         this.plugin.data.settings.convertFoldersToDecks = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     this.createSettingFoldersToIgnore(containerEl);
 | |
|     containerEl.createEl("h3", { text: t("GROUP_FLASHCARD_REVIEW") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("BURY_SIBLINGS_TILL_NEXT_DAY")).setDesc(t("BURY_SIBLINGS_TILL_NEXT_DAY_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.burySiblingCards).onChange(async (value) => {
 | |
|         this.plugin.data.settings.burySiblingCards = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("REVIEW_CARD_ORDER_WITHIN_DECK")).addDropdown(
 | |
|       (dropdown) => dropdown.addOptions({
 | |
|         NewFirstSequential: t("REVIEW_CARD_ORDER_NEW_FIRST_SEQUENTIAL"),
 | |
|         DueFirstSequential: t("REVIEW_CARD_ORDER_DUE_FIRST_SEQUENTIAL"),
 | |
|         NewFirstRandom: t("REVIEW_CARD_ORDER_NEW_FIRST_RANDOM"),
 | |
|         DueFirstRandom: t("REVIEW_CARD_ORDER_DUE_FIRST_RANDOM"),
 | |
|         EveryCardRandomDeckAndCard: t("REVIEW_CARD_ORDER_RANDOM_DECK_AND_CARD")
 | |
|       }).setValue(this.plugin.data.settings.flashcardCardOrder).onChange(async (value) => {
 | |
|         this.plugin.data.settings.flashcardCardOrder = value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       })
 | |
|     );
 | |
|     const deckOrderEnabled = this.plugin.data.settings.flashcardCardOrder != "EveryCardRandomDeckAndCard";
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("REVIEW_DECK_ORDER")).addDropdown(
 | |
|       (dropdown) => dropdown.addOptions(
 | |
|         deckOrderEnabled ? {
 | |
|           // eslint-disable-next-line camelcase
 | |
|           PrevDeckComplete_Sequential: t(
 | |
|             "REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL"
 | |
|           ),
 | |
|           // eslint-disable-next-line camelcase
 | |
|           PrevDeckComplete_Random: t(
 | |
|             "REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM"
 | |
|           )
 | |
|         } : {
 | |
|           EveryCardRandomDeckAndCard: t(
 | |
|             "REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD"
 | |
|           )
 | |
|         }
 | |
|       ).setValue(
 | |
|         deckOrderEnabled ? this.plugin.data.settings.flashcardDeckOrder : "EveryCardRandomDeckAndCard"
 | |
|       ).setDisabled(!deckOrderEnabled).onChange(async (value) => {
 | |
|         this.plugin.data.settings.flashcardDeckOrder = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("h3", { text: t("GROUP_FLASHCARD_SEPARATORS") });
 | |
|     const convertHighlightsToClozesEl = new import_obsidian6.Setting(containerEl).setName(
 | |
|       t("CONVERT_HIGHLIGHTS_TO_CLOZES")
 | |
|     );
 | |
|     convertHighlightsToClozesEl.descEl.insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CONVERT_HIGHLIGHTS_TO_CLOZES_DESC", { defaultPattern: "==[123;;]answer[;;hint]==" })
 | |
|     );
 | |
|     convertHighlightsToClozesEl.addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.convertHighlightsToClozes).onChange(async (value) => {
 | |
|         const defaultHightlightPattern = "==[123;;]answer[;;hint]==";
 | |
|         const clozePatternSet = new Set(this.plugin.data.settings.clozePatterns);
 | |
|         if (value) {
 | |
|           clozePatternSet.add(defaultHightlightPattern);
 | |
|         } else {
 | |
|           clozePatternSet.delete(defaultHightlightPattern);
 | |
|         }
 | |
|         this.plugin.data.settings.clozePatterns = [...clozePatternSet];
 | |
|         this.plugin.data.settings.convertHighlightsToClozes = value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       })
 | |
|     );
 | |
|     const convertBoldTextToClozesEl = new import_obsidian6.Setting(containerEl).setName(
 | |
|       t("CONVERT_BOLD_TEXT_TO_CLOZES")
 | |
|     );
 | |
|     convertBoldTextToClozesEl.descEl.insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CONVERT_BOLD_TEXT_TO_CLOZES_DESC", { defaultPattern: "**[123;;]answer[;;hint]**" })
 | |
|     );
 | |
|     convertBoldTextToClozesEl.addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.convertBoldTextToClozes).onChange(async (value) => {
 | |
|         const defaultBoldPattern = "**[123;;]answer[;;hint]**";
 | |
|         const clozePatternSet = new Set(this.plugin.data.settings.clozePatterns);
 | |
|         if (value) {
 | |
|           clozePatternSet.add(defaultBoldPattern);
 | |
|         } else {
 | |
|           clozePatternSet.delete(defaultBoldPattern);
 | |
|         }
 | |
|         this.plugin.data.settings.clozePatterns = [...clozePatternSet];
 | |
|         this.plugin.data.settings.convertBoldTextToClozes = value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       })
 | |
|     );
 | |
|     const convertCurlyBracketsToClozesEl = new import_obsidian6.Setting(containerEl).setName(
 | |
|       t("CONVERT_CURLY_BRACKETS_TO_CLOZES")
 | |
|     );
 | |
|     convertCurlyBracketsToClozesEl.descEl.insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CONVERT_CURLY_BRACKETS_TO_CLOZES_DESC", {
 | |
|         defaultPattern: "{{[123;;]answer[;;hint]}}"
 | |
|       })
 | |
|     );
 | |
|     convertCurlyBracketsToClozesEl.addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.convertCurlyBracketsToClozes).onChange(async (value) => {
 | |
|         const defaultCurlyBracketsPattern = "{{[123;;]answer[;;hint]}}";
 | |
|         const clozePatternSet = new Set(this.plugin.data.settings.clozePatterns);
 | |
|         if (value) {
 | |
|           clozePatternSet.add(defaultCurlyBracketsPattern);
 | |
|         } else {
 | |
|           clozePatternSet.delete(defaultCurlyBracketsPattern);
 | |
|         }
 | |
|         this.plugin.data.settings.clozePatterns = [...clozePatternSet];
 | |
|         this.plugin.data.settings.convertCurlyBracketsToClozes = value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       })
 | |
|     );
 | |
|     const clozePatternsEl = new import_obsidian6.Setting(containerEl).setName(t("CLOZE_PATTERNS"));
 | |
|     clozePatternsEl.descEl.insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CLOZE_PATTERNS_DESC", {
 | |
|         docsUrl: "https://www.stephenmwangi.com/obsidian-spaced-repetition/flashcards/cloze-cards/#cloze-types"
 | |
|       })
 | |
|     );
 | |
|     clozePatternsEl.addTextArea(
 | |
|       (text) => text.setPlaceholder(
 | |
|         "Example:\n==[123;;]answer[;;hint]==\n**[123;;]answer[;;hint]**\n{{[123;;]answer[;;hint]}}"
 | |
|       ).setValue(this.plugin.data.settings.clozePatterns.join("\n")).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           const defaultHightlightPattern = "==[123;;]answer[;;hint]==";
 | |
|           const defaultBoldPattern = "**[123;;]answer[;;hint]**";
 | |
|           const defaultCurlyBracketsPattern = "{{[123;;]answer[;;hint]}}";
 | |
|           const clozePatternSet = new Set(
 | |
|             value.split(/\n+/).map((v2) => v2.trim()).filter((v2) => v2)
 | |
|           );
 | |
|           if (clozePatternSet.has(defaultHightlightPattern)) {
 | |
|             this.plugin.data.settings.convertHighlightsToClozes = true;
 | |
|           } else {
 | |
|             this.plugin.data.settings.convertHighlightsToClozes = false;
 | |
|           }
 | |
|           if (clozePatternSet.has(defaultBoldPattern)) {
 | |
|             this.plugin.data.settings.convertBoldTextToClozes = true;
 | |
|           } else {
 | |
|             this.plugin.data.settings.convertBoldTextToClozes = false;
 | |
|           }
 | |
|           if (clozePatternSet.has(defaultCurlyBracketsPattern)) {
 | |
|             this.plugin.data.settings.convertCurlyBracketsToClozes = true;
 | |
|           } else {
 | |
|             this.plugin.data.settings.convertCurlyBracketsToClozes = false;
 | |
|           }
 | |
|           this.plugin.data.settings.clozePatterns = [...clozePatternSet];
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("INLINE_CARDS_SEPARATOR")).setDesc(t("FIX_SEPARATORS_MANUALLY_WARNING")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.singleLineCardSeparator).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.singleLineCardSeparator = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.singleLineCardSeparator = DEFAULT_SETTINGS.singleLineCardSeparator;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("INLINE_REVERSED_CARDS_SEPARATOR")).setDesc(t("FIX_SEPARATORS_MANUALLY_WARNING")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.singleLineReversedCardSeparator).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.singleLineReversedCardSeparator = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.singleLineReversedCardSeparator = DEFAULT_SETTINGS.singleLineReversedCardSeparator;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("MULTILINE_CARDS_SEPARATOR")).setDesc(t("FIX_SEPARATORS_MANUALLY_WARNING")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.multilineCardSeparator).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.multilineCardSeparator = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.multilineCardSeparator = DEFAULT_SETTINGS.multilineCardSeparator;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("MULTILINE_REVERSED_CARDS_SEPARATOR")).setDesc(t("FIX_SEPARATORS_MANUALLY_WARNING")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.multilineReversedCardSeparator).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.multilineReversedCardSeparator = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.multilineReversedCardSeparator = DEFAULT_SETTINGS.multilineReversedCardSeparator;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("MULTILINE_CARDS_END_MARKER")).setDesc(t("FIX_SEPARATORS_MANUALLY_WARNING")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.multilineCardEndMarker).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.multilineCardEndMarker = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.multilineCardEndMarker = DEFAULT_SETTINGS.multilineCardEndMarker;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   async tabNotes(containerEl) {
 | |
|     containerEl.createEl("h3", { text: t("GROUP_TAGS_FOLDERS") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("TAGS_TO_REVIEW")).setDesc(t("TAGS_TO_REVIEW_DESC")).addTextArea(
 | |
|       (text) => text.setValue(this.plugin.data.settings.tagsToReview.join(" ")).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.tagsToReview = value.split(/\s+/);
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     );
 | |
|     this.createSettingFoldersToIgnore(containerEl);
 | |
|     containerEl.createEl("h3", { text: t("NOTES_REVIEW_QUEUE") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("AUTO_NEXT_NOTE")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.autoNextNote).onChange(async (value) => {
 | |
|         this.plugin.data.settings.autoNextNote = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("OPEN_RANDOM_NOTE")).setDesc(t("OPEN_RANDOM_NOTE_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.openRandomNote).onChange(async (value) => {
 | |
|         this.plugin.data.settings.openRandomNote = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("REVIEW_PANE_ON_STARTUP")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.enableNoteReviewPaneOnStartup).onChange(async (value) => {
 | |
|         this.plugin.data.settings.enableNoteReviewPaneOnStartup = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("MAX_N_DAYS_REVIEW_QUEUE")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.maxNDaysNotesReviewQueue.toString()).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           const numValue = Number.parseInt(value);
 | |
|           if (!isNaN(numValue)) {
 | |
|             if (numValue < 1) {
 | |
|               new import_obsidian6.Notice(t("MIN_ONE_DAY"));
 | |
|               text.setValue(
 | |
|                 this.plugin.data.settings.maxNDaysNotesReviewQueue.toString()
 | |
|               );
 | |
|               return;
 | |
|             }
 | |
|             this.plugin.data.settings.maxNDaysNotesReviewQueue = numValue;
 | |
|             await this.plugin.savePluginData();
 | |
|           } else {
 | |
|             new import_obsidian6.Notice(t("VALID_NUMBER_WARNING"));
 | |
|           }
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.maxNDaysNotesReviewQueue = DEFAULT_SETTINGS.maxNDaysNotesReviewQueue;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   async createSettingFoldersToIgnore(containerEl) {
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("FOLDERS_TO_IGNORE")).setDesc(t("FOLDERS_TO_IGNORE_DESC")).addTextArea(
 | |
|       (text) => text.setValue(this.plugin.data.settings.noteFoldersToIgnore.join("\n")).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.noteFoldersToIgnore = value.split(/\n+/).map((v2) => v2.trim()).filter((v2) => v2);
 | |
|           await this.plugin.savePluginData();
 | |
|           this.display();
 | |
|         });
 | |
|       })
 | |
|     );
 | |
|   }
 | |
|   async tabUiPreferences(containerEl) {
 | |
|     containerEl.createEl("h3", { text: t("OBSIDIAN_INTEGRATION") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("OPEN_IN_TAB")).setDesc(t("OPEN_IN_TAB_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.openViewInNewTab).onChange(async (value) => {
 | |
|         if (value) {
 | |
|           this.plugin.registerSRFocusListener();
 | |
|         } else {
 | |
|           this.plugin.tabViewManager.closeAllTabViews();
 | |
|           this.plugin.removeSRFocusListener();
 | |
|         }
 | |
|         this.plugin.data.settings.openViewInNewTab = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("SHOW_RIBBON_ICON")).setDesc(t("SHOW_RIBBON_ICON_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.showRibbonIcon).onChange(async (value) => {
 | |
|         this.plugin.data.settings.showRibbonIcon = value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.plugin.showRibbonIcon(value);
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("SHOW_STATUS_BAR")).setDesc(t("SHOW_STATUS_BAR_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.showStatusBar).onChange(async (value) => {
 | |
|         this.plugin.data.settings.showStatusBar = value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.plugin.showStatusBar(value);
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("ENABLE_FILE_MENU_REVIEW_OPTIONS")).setDesc(t("ENABLE_FILE_MENU_REVIEW_OPTIONS_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(!this.plugin.data.settings.disableFileMenuReviewOptions).onChange(async (value) => {
 | |
|         this.plugin.data.settings.disableFileMenuReviewOptions = !value;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.plugin.showFileMenuItems(value);
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("h3", { text: t("FLASHCARDS") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("INITIALLY_EXPAND_SUBDECKS_IN_TREE")).setDesc(t("INITIALLY_EXPAND_SUBDECKS_IN_TREE_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.initiallyExpandAllSubdecksInTree).onChange(async (value) => {
 | |
|         this.plugin.data.settings.initiallyExpandAllSubdecksInTree = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("SHOW_CARD_CONTEXT")).setDesc(t("SHOW_CARD_CONTEXT_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.showContextInCards).onChange(async (value) => {
 | |
|         this.plugin.data.settings.showContextInCards = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("SHOW_INTERVAL_IN_REVIEW_BUTTONS")).setDesc(t("SHOW_INTERVAL_IN_REVIEW_BUTTONS_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.showIntervalInReviewButtons).onChange(async (value) => {
 | |
|         this.plugin.data.settings.showIntervalInReviewButtons = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("CARD_MODAL_HEIGHT_PERCENT")).setDesc(t("CARD_MODAL_SIZE_PERCENT_DESC")).addSlider(
 | |
|       (slider) => slider.setLimits(10, 100, 5).setValue(this.plugin.data.settings.flashcardHeightPercentage).setDynamicTooltip().onChange(async (value) => {
 | |
|         this.plugin.data.settings.flashcardHeightPercentage = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.flashcardHeightPercentage = DEFAULT_SETTINGS.flashcardHeightPercentage;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("CARD_MODAL_WIDTH_PERCENT")).setDesc(t("CARD_MODAL_SIZE_PERCENT_DESC")).addSlider(
 | |
|       (slider) => slider.setLimits(10, 100, 5).setValue(this.plugin.data.settings.flashcardWidthPercentage).setDynamicTooltip().onChange(async (value) => {
 | |
|         this.plugin.data.settings.flashcardWidthPercentage = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.flashcardWidthPercentage = DEFAULT_SETTINGS.flashcardWidthPercentage;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     containerEl.createEl("h3", { text: t("GROUP_FLASHCARDS_NOTES") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("FLASHCARD_EASY_LABEL")).setDesc(t("FLASHCARD_EASY_DESC")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.flashcardEasyText).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.flashcardEasyText = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.flashcardEasyText = DEFAULT_SETTINGS.flashcardEasyText;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("FLASHCARD_GOOD_LABEL")).setDesc(t("FLASHCARD_GOOD_DESC")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.flashcardGoodText).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.flashcardGoodText = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.flashcardGoodText = DEFAULT_SETTINGS.flashcardGoodText;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("FLASHCARD_HARD_LABEL")).setDesc(t("FLASHCARD_HARD_DESC")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.flashcardHardText).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           this.plugin.data.settings.flashcardHardText = value;
 | |
|           await this.plugin.savePluginData();
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.flashcardHardText = DEFAULT_SETTINGS.flashcardHardText;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("REVIEW_BUTTON_DELAY")).setDesc(t("REVIEW_BUTTON_DELAY_DESC")).addSlider(
 | |
|       (slider) => slider.setLimits(0, 5e3, 100).setValue(this.plugin.data.settings.reviewButtonDelay).setDynamicTooltip().onChange(async (value) => {
 | |
|         this.plugin.data.settings.reviewButtonDelay = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.reviewButtonDelay = DEFAULT_SETTINGS.reviewButtonDelay;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   async tabScheduling(containerEl) {
 | |
|     containerEl.createEl("h3", { text: t("ALGORITHM") });
 | |
|     const algoSettingEl = new import_obsidian6.Setting(containerEl).setName(t("ALGORITHM"));
 | |
|     algoSettingEl.descEl.insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CHECK_ALGORITHM_WIKI", {
 | |
|         algoUrl: "https://www.stephenmwangi.com/obsidian-spaced-repetition/algorithms/"
 | |
|       })
 | |
|     );
 | |
|     algoSettingEl.addDropdown(
 | |
|       (dropdown) => dropdown.addOptions({
 | |
|         "SM-2-OSR": t("SM2_OSR_VARIANT")
 | |
|       }).setValue(this.plugin.data.settings.algorithm).onChange(async (value) => {
 | |
|         this.plugin.data.settings.algorithm = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("BASE_EASE")).setDesc(t("BASE_EASE_DESC")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.baseEase.toString()).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           const numValue = Number.parseInt(value);
 | |
|           if (!isNaN(numValue)) {
 | |
|             if (numValue < 130) {
 | |
|               new import_obsidian6.Notice(t("BASE_EASE_MIN_WARNING"));
 | |
|               text.setValue(this.plugin.data.settings.baseEase.toString());
 | |
|               return;
 | |
|             }
 | |
|             this.plugin.data.settings.baseEase = numValue;
 | |
|             await this.plugin.savePluginData();
 | |
|           } else {
 | |
|             new import_obsidian6.Notice(t("VALID_NUMBER_WARNING"));
 | |
|           }
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.baseEase = DEFAULT_SETTINGS.baseEase;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("LAPSE_INTERVAL_CHANGE")).setDesc(t("LAPSE_INTERVAL_CHANGE_DESC")).addSlider(
 | |
|       (slider) => slider.setLimits(1, 99, 1).setValue(this.plugin.data.settings.lapsesIntervalChange * 100).setDynamicTooltip().onChange(async (value) => {
 | |
|         this.plugin.data.settings.lapsesIntervalChange = value / 100;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.lapsesIntervalChange = DEFAULT_SETTINGS.lapsesIntervalChange;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("EASY_BONUS")).setDesc(t("EASY_BONUS_DESC")).addText(
 | |
|       (text) => text.setValue((this.plugin.data.settings.easyBonus * 100).toString()).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           const numValue = Number.parseInt(value) / 100;
 | |
|           if (!isNaN(numValue)) {
 | |
|             if (numValue < 1) {
 | |
|               new import_obsidian6.Notice(t("EASY_BONUS_MIN_WARNING"));
 | |
|               text.setValue(
 | |
|                 (this.plugin.data.settings.easyBonus * 100).toString()
 | |
|               );
 | |
|               return;
 | |
|             }
 | |
|             this.plugin.data.settings.easyBonus = numValue;
 | |
|             await this.plugin.savePluginData();
 | |
|           } else {
 | |
|             new import_obsidian6.Notice(t("VALID_NUMBER_WARNING"));
 | |
|           }
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.easyBonus = DEFAULT_SETTINGS.easyBonus;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("LOAD_BALANCE")).setDesc(t("LOAD_BALANCE_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.loadBalance).onChange(async (value) => {
 | |
|         this.plugin.data.settings.loadBalance = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("MAX_INTERVAL")).setDesc(t("MAX_INTERVAL_DESC")).addText(
 | |
|       (text) => text.setValue(this.plugin.data.settings.maximumInterval.toString()).onChange((value) => {
 | |
|         applySettingsUpdate(async () => {
 | |
|           const numValue = Number.parseInt(value);
 | |
|           if (!isNaN(numValue)) {
 | |
|             if (numValue < 1) {
 | |
|               new import_obsidian6.Notice(t("MAX_INTERVAL_MIN_WARNING"));
 | |
|               text.setValue(
 | |
|                 this.plugin.data.settings.maximumInterval.toString()
 | |
|               );
 | |
|               return;
 | |
|             }
 | |
|             this.plugin.data.settings.maximumInterval = numValue;
 | |
|             await this.plugin.savePluginData();
 | |
|           } else {
 | |
|             new import_obsidian6.Notice(t("VALID_NUMBER_WARNING"));
 | |
|           }
 | |
|         });
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.maximumInterval = DEFAULT_SETTINGS.maximumInterval;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("MAX_LINK_CONTRIB")).setDesc(t("MAX_LINK_CONTRIB_DESC")).addSlider(
 | |
|       (slider) => slider.setLimits(0, 100, 1).setValue(this.plugin.data.settings.maxLinkFactor * 100).setDynamicTooltip().onChange(async (value) => {
 | |
|         this.plugin.data.settings.maxLinkFactor = value / 100;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     ).addExtraButton((button) => {
 | |
|       button.setIcon("reset").setTooltip(t("RESET_DEFAULT")).onClick(async () => {
 | |
|         this.plugin.data.settings.maxLinkFactor = DEFAULT_SETTINGS.maxLinkFactor;
 | |
|         await this.plugin.savePluginData();
 | |
|         this.display();
 | |
|       });
 | |
|     });
 | |
|     containerEl.createEl("h3", { text: t("GROUP_DATA_STORAGE") });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("GROUP_DATA_STORAGE")).setDesc(t("GROUP_DATA_STORAGE_DESC")).addDropdown(
 | |
|       (dropdown) => dropdown.addOptions({
 | |
|         NOTES: t("STORE_IN_NOTES")
 | |
|       }).setValue(this.plugin.data.settings.dataStore).onChange(async (value) => {
 | |
|         this.plugin.data.settings.dataStore = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("INLINE_SCHEDULING_COMMENTS")).setDesc(t("INLINE_SCHEDULING_COMMENTS_DESC")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.cardCommentOnSameLine).onChange(async (value) => {
 | |
|         this.plugin.data.settings.cardCommentOnSameLine = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|   }
 | |
|   async tabHelp(containerEl) {
 | |
|     containerEl.createEl("h3", { text: `${t("HELP")}` });
 | |
|     containerEl.createEl("p").insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CHECK_WIKI", {
 | |
|         wikiUrl: "https://www.stephenmwangi.com/obsidian-spaced-repetition/"
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("p").insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("GITHUB_DISCUSSIONS", {
 | |
|         discussionsUrl: "https://github.com/st3v3nmw/obsidian-spaced-repetition/discussions/"
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("p").insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("GITHUB_ISSUES", {
 | |
|         issuesUrl: "https://github.com/st3v3nmw/obsidian-spaced-repetition/issues/"
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("h3", { text: `${t("LOGGING")}` });
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("DISPLAY_SCHEDULING_DEBUG_INFO")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.showSchedulingDebugMessages).onChange(async (value) => {
 | |
|         this.plugin.data.settings.showSchedulingDebugMessages = value;
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     new import_obsidian6.Setting(containerEl).setName(t("DISPLAY_PARSER_DEBUG_INFO")).addToggle(
 | |
|       (toggle) => toggle.setValue(this.plugin.data.settings.showParserDebugMessages).onChange(async (value) => {
 | |
|         this.plugin.data.settings.showParserDebugMessages = value;
 | |
|         setDebugParser(this.plugin.data.settings.showParserDebugMessages);
 | |
|         await this.plugin.savePluginData();
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("h3", { text: t("GROUP_CONTRIBUTING") });
 | |
|     containerEl.createEl("p").insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("GITHUB_SOURCE_CODE", {
 | |
|         githubProjectUrl: "https://github.com/st3v3nmw/obsidian-spaced-repetition"
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("p").insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("CODE_CONTRIBUTION_INFO", {
 | |
|         codeContributionUrl: "https://www.stephenmwangi.com/obsidian-spaced-repetition/contributing/#code"
 | |
|       })
 | |
|     );
 | |
|     containerEl.createEl("p").insertAdjacentHTML(
 | |
|       "beforeend",
 | |
|       t("TRANSLATION_CONTRIBUTION_INFO", {
 | |
|         translationContributionUrl: "https://www.stephenmwangi.com/obsidian-spaced-repetition/contributing/#translating"
 | |
|       })
 | |
|     );
 | |
|   }
 | |
|   rememberLastPosition(containerElement) {
 | |
|     const lastPosition = this.lastPosition;
 | |
|     this.tabStructure.buttons[lastPosition.tabName].click();
 | |
|     containerElement.scrollTo({
 | |
|       top: this.lastPosition.scrollPosition,
 | |
|       behavior: "auto"
 | |
|     });
 | |
|     containerElement.addEventListener("scroll", (_2) => {
 | |
|       this.lastPosition.scrollPosition = containerElement.scrollTop;
 | |
|     });
 | |
|     for (const tabName in this.tabStructure.buttons) {
 | |
|       const button = this.tabStructure.buttons[tabName];
 | |
|       button.onClickEvent((_2) => {
 | |
|         lastPosition.tabName = tabName;
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/sidebar.tsx
 | |
| var OsrSidebar = class {
 | |
|   get app() {
 | |
|     return this.plugin.app;
 | |
|   }
 | |
|   constructor(plugin, settings, nextNoteReviewHandler) {
 | |
|     this.plugin = plugin;
 | |
|     this.settings = settings;
 | |
|     this.nextNoteReviewHandler = nextNoteReviewHandler;
 | |
|   }
 | |
|   redraw() {
 | |
|     this.reviewQueueListView.redraw();
 | |
|   }
 | |
|   getActiveLeaf(type) {
 | |
|     const leaves = this.app.workspace.getLeavesOfType(type);
 | |
|     if (leaves.length == 0) {
 | |
|       return this.app.workspace.getRightLeaf(false);
 | |
|     }
 | |
|     return leaves[0];
 | |
|   }
 | |
|   init() {
 | |
|     this.plugin.registerView(REVIEW_QUEUE_VIEW_TYPE, (leaf) => {
 | |
|       return this.reviewQueueListView = new ReviewQueueListView(
 | |
|         leaf,
 | |
|         this.nextNoteReviewHandler,
 | |
|         this.settings
 | |
|       );
 | |
|     });
 | |
|   }
 | |
|   async activateReviewQueueViewPanel() {
 | |
|     if (this.settings.enableNoteReviewPaneOnStartup) {
 | |
|       await this.getActiveLeaf(REVIEW_QUEUE_VIEW_TYPE).setViewState({
 | |
|         type: REVIEW_QUEUE_VIEW_TYPE,
 | |
|         active: true
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   async openReviewQueueView() {
 | |
|     const reviewQueueLeaf = this.getActiveLeaf(REVIEW_QUEUE_VIEW_TYPE);
 | |
|     this.app.workspace.revealLeaf(reviewQueueLeaf);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/sr-modal.tsx
 | |
| var import_obsidian10 = require("obsidian");
 | |
| 
 | |
| // src/gui/card-ui.tsx
 | |
| var import_moment4 = __toESM(require_moment());
 | |
| var import_obsidian8 = require("obsidian");
 | |
| 
 | |
| // src/utils/renderers.ts
 | |
| var import_obsidian7 = require("obsidian");
 | |
| var RenderMarkdownWrapper = class {
 | |
|   constructor(app, plugin, notePath) {
 | |
|     this.app = app;
 | |
|     this.notePath = notePath;
 | |
|     this.plugin = plugin;
 | |
|   }
 | |
|   // slightly modified version of the renderMarkdown function in
 | |
|   // https://github.com/mgmeyers/obsidian-kanban/blob/main/src/KanbanView.tsx
 | |
|   async renderMarkdownWrapper(markdownString, containerEl, textDirection, recursiveDepth = 0) {
 | |
|     if (recursiveDepth > 4) return;
 | |
|     let el;
 | |
|     if (textDirection == 2 /* Rtl */) {
 | |
|       el = containerEl.createDiv();
 | |
|       el.setAttribute("dir", "rtl");
 | |
|     } else el = containerEl;
 | |
|     import_obsidian7.MarkdownRenderer.render(this.app, markdownString, el, this.notePath, this.plugin);
 | |
|     el.findAll(".internal-embed").forEach((el2) => {
 | |
|       const link2 = this.parseLink(el2.getAttribute("src"));
 | |
|       if (!link2.target) {
 | |
|         el2.innerText = link2.text;
 | |
|       } else if (link2.target instanceof import_obsidian7.TFile) {
 | |
|         if (link2.target.extension !== "md") {
 | |
|           this.embedMediaFile(el2, link2.target);
 | |
|         } else {
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   parseLink(src) {
 | |
|     const linkComponentsRegex = /^(?<file>[^#^]+)?(?:#(?!\^)(?<heading>.+)|#\^(?<blockId>.+)|#)?$/;
 | |
|     const matched = typeof src === "string" && src.match(linkComponentsRegex);
 | |
|     const file = matched.groups.file || this.notePath;
 | |
|     const target = this.plugin.app.metadataCache.getFirstLinkpathDest(file, this.notePath);
 | |
|     return {
 | |
|       text: matched[0],
 | |
|       file: matched.groups.file,
 | |
|       heading: matched.groups.heading,
 | |
|       blockId: matched.groups.blockId,
 | |
|       target
 | |
|     };
 | |
|   }
 | |
|   embedMediaFile(el, target) {
 | |
|     el.innerText = "";
 | |
|     if (IMAGE_FORMATS.includes(target.extension)) {
 | |
|       el.createEl(
 | |
|         "img",
 | |
|         {
 | |
|           attr: {
 | |
|             src: this.plugin.app.vault.getResourcePath(target)
 | |
|           }
 | |
|         },
 | |
|         (img) => {
 | |
|           if (el.hasAttribute("width"))
 | |
|             img.setAttribute("width", el.getAttribute("width"));
 | |
|           else img.setAttribute("width", "100%");
 | |
|           if (el.hasAttribute("alt")) img.setAttribute("alt", el.getAttribute("alt"));
 | |
|           el.addEventListener(
 | |
|             "click",
 | |
|             (ev) => ev.target.style.minWidth = ev.target.style.minWidth === "100%" ? null : "100%"
 | |
|           );
 | |
|         }
 | |
|       );
 | |
|       el.addClasses(["image-embed", "is-loaded"]);
 | |
|     } else if (AUDIO_FORMATS.includes(target.extension) || VIDEO_FORMATS.includes(target.extension)) {
 | |
|       el.createEl(
 | |
|         AUDIO_FORMATS.includes(target.extension) ? "audio" : "video",
 | |
|         {
 | |
|           attr: {
 | |
|             controls: "",
 | |
|             src: this.plugin.app.vault.getResourcePath(target)
 | |
|           }
 | |
|         },
 | |
|         (audio) => {
 | |
|           if (el.hasAttribute("alt")) audio.setAttribute("alt", el.getAttribute("alt"));
 | |
|         }
 | |
|       );
 | |
|       el.addClasses(["media-embed", "is-loaded"]);
 | |
|     } else {
 | |
|       el.innerText = target.path;
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/card-ui.tsx
 | |
| var CardUI = class {
 | |
|   constructor(app, plugin, settings, reviewSequencer, reviewMode, view, backToDeck, editClickHandler) {
 | |
|     this.totalCardsInSession = 0;
 | |
|     this.totalDecksInSession = 0;
 | |
|     this.currentDeckTotalCardsInQueue = 0;
 | |
|     this._keydownHandler = (e2) => {
 | |
|       if (document.activeElement.nodeName === "TEXTAREA" || this.mode === 3 /* Closed */ || !this.plugin.getSRInFocusState()) {
 | |
|         return;
 | |
|       }
 | |
|       const consumeKeyEvent = () => {
 | |
|         e2.preventDefault();
 | |
|         e2.stopPropagation();
 | |
|       };
 | |
|       switch (e2.code) {
 | |
|         case "KeyS":
 | |
|           this._skipCurrentCard();
 | |
|           consumeKeyEvent();
 | |
|           break;
 | |
|         case "Space":
 | |
|           if (this.mode === 1 /* Front */) {
 | |
|             this._showAnswer();
 | |
|             consumeKeyEvent();
 | |
|           } else if (this.mode === 2 /* Back */) {
 | |
|             this._processReview(1 /* Good */);
 | |
|             consumeKeyEvent();
 | |
|           }
 | |
|           break;
 | |
|         case "Enter":
 | |
|         case "NumpadEnter":
 | |
|           if (this.mode !== 1 /* Front */) {
 | |
|             break;
 | |
|           }
 | |
|           this._showAnswer();
 | |
|           consumeKeyEvent();
 | |
|           break;
 | |
|         case "Numpad1":
 | |
|         case "Digit1":
 | |
|           if (this.mode !== 2 /* Back */) {
 | |
|             break;
 | |
|           }
 | |
|           this._processReview(2 /* Hard */);
 | |
|           consumeKeyEvent();
 | |
|           break;
 | |
|         case "Numpad2":
 | |
|         case "Digit2":
 | |
|           if (this.mode !== 2 /* Back */) {
 | |
|             break;
 | |
|           }
 | |
|           this._processReview(1 /* Good */);
 | |
|           consumeKeyEvent();
 | |
|           break;
 | |
|         case "Numpad3":
 | |
|         case "Digit3":
 | |
|           if (this.mode !== 2 /* Back */) {
 | |
|             break;
 | |
|           }
 | |
|           this._processReview(0 /* Easy */);
 | |
|           consumeKeyEvent();
 | |
|           break;
 | |
|         case "Numpad0":
 | |
|         case "Digit0":
 | |
|           if (this.mode !== 2 /* Back */) {
 | |
|             break;
 | |
|           }
 | |
|           this._processReview(3 /* Reset */);
 | |
|           consumeKeyEvent();
 | |
|           break;
 | |
|         default:
 | |
|           break;
 | |
|       }
 | |
|     };
 | |
|     this.app = app;
 | |
|     this.plugin = plugin;
 | |
|     this.settings = settings;
 | |
|     this.reviewSequencer = reviewSequencer;
 | |
|     this.reviewMode = reviewMode;
 | |
|     this.backToDeck = backToDeck;
 | |
|     this.editClickHandler = editClickHandler;
 | |
|     this.view = view;
 | |
|     this.chosenDeck = null;
 | |
|     this.init();
 | |
|   }
 | |
|   // #region -> public methods
 | |
|   /**
 | |
|    * Initializes all static elements in the FlashcardView
 | |
|    */
 | |
|   init() {
 | |
|     this.view.addClasses(["sr-flashcard", "sr-is-hidden"]);
 | |
|     this.controls = this.view.createDiv();
 | |
|     this.controls.addClass("sr-controls");
 | |
|     this._createCardControls();
 | |
|     this._createInfoSection();
 | |
|     this.content = this.view.createDiv();
 | |
|     this.content.addClass("sr-content");
 | |
|     this.response = this.view.createDiv();
 | |
|     this.response.addClass("sr-response");
 | |
|     this._createResponseButtons();
 | |
|   }
 | |
|   /**
 | |
|    * Shows the FlashcardView if it is hidden
 | |
|    */
 | |
|   async show(chosenDeck) {
 | |
|     if (!this.view.hasClass("sr-is-hidden")) {
 | |
|       return;
 | |
|     }
 | |
|     this.chosenDeck = chosenDeck;
 | |
|     const deckStats = this.reviewSequencer.getDeckStats(chosenDeck.getTopicPath());
 | |
|     this.totalCardsInSession = deckStats.cardsInQueueCount;
 | |
|     this.totalDecksInSession = deckStats.decksInQueueOfThisDeckCount;
 | |
|     await this._drawContent();
 | |
|     this.view.removeClass("sr-is-hidden");
 | |
|     document.addEventListener("keydown", this._keydownHandler);
 | |
|   }
 | |
|   /**
 | |
|    * Refreshes all dynamic elements
 | |
|    */
 | |
|   async refresh() {
 | |
|     await this._drawContent();
 | |
|   }
 | |
|   /**
 | |
|    * Hides the FlashcardView if it is visible
 | |
|    */
 | |
|   hide() {
 | |
|     if (this.view.hasClass("sr-is-hidden")) {
 | |
|       return;
 | |
|     }
 | |
|     document.removeEventListener("keydown", this._keydownHandler);
 | |
|     this.view.addClass("sr-is-hidden");
 | |
|   }
 | |
|   /**
 | |
|    * Closes the FlashcardView
 | |
|    */
 | |
|   close() {
 | |
|     this.hide();
 | |
|     document.removeEventListener("keydown", this._keydownHandler);
 | |
|   }
 | |
|   // #region -> Functions & helpers
 | |
|   async _drawContent() {
 | |
|     this.resetButton.disabled = true;
 | |
|     this.mode = 1 /* Front */;
 | |
|     this.previousDeck = this.currentDeck;
 | |
|     this.currentDeck = this.reviewSequencer.currentDeck;
 | |
|     if (this.previousDeck !== this.currentDeck) {
 | |
|       const currentDeckStats = this.reviewSequencer.getDeckStats(
 | |
|         this.currentDeck.getTopicPath()
 | |
|       );
 | |
|       this.currentDeckTotalCardsInQueue = currentDeckStats.cardsInQueueOfThisDeckCount;
 | |
|     }
 | |
|     this._updateInfoBar(this.chosenDeck, this.currentDeck);
 | |
|     this.content.empty();
 | |
|     const wrapper = new RenderMarkdownWrapper(
 | |
|       this.app,
 | |
|       this.plugin,
 | |
|       this._currentNote.filePath
 | |
|     );
 | |
|     await wrapper.renderMarkdownWrapper(
 | |
|       this._currentCard.front.trimStart(),
 | |
|       this.content,
 | |
|       this._currentQuestion.questionText.textDirection
 | |
|     );
 | |
|     this.content.scrollTop = 0;
 | |
|     this._resetResponseButtons();
 | |
|   }
 | |
|   get _currentCard() {
 | |
|     return this.reviewSequencer.currentCard;
 | |
|   }
 | |
|   get _currentQuestion() {
 | |
|     return this.reviewSequencer.currentQuestion;
 | |
|   }
 | |
|   get _currentNote() {
 | |
|     return this.reviewSequencer.currentNote;
 | |
|   }
 | |
|   async _processReview(response) {
 | |
|     const timeNow = (0, import_moment4.now)();
 | |
|     if (this.lastPressed && timeNow - this.lastPressed < this.plugin.data.settings.reviewButtonDelay) {
 | |
|       return;
 | |
|     }
 | |
|     this.lastPressed = timeNow;
 | |
|     await this.reviewSequencer.processReview(response);
 | |
|     await this._showNextCard();
 | |
|   }
 | |
|   async _showNextCard() {
 | |
|     if (this._currentCard != null) await this.refresh();
 | |
|     else this.backToDeck();
 | |
|   }
 | |
|   // #region -> Controls
 | |
|   _createCardControls() {
 | |
|     this._createEditButton();
 | |
|     this._createResetButton();
 | |
|     this._createCardInfoButton();
 | |
|     this._createSkipButton();
 | |
|   }
 | |
|   _createEditButton() {
 | |
|     this.editButton = this.controls.createEl("button");
 | |
|     this.editButton.addClasses(["sr-button", "sr-edit-button"]);
 | |
|     (0, import_obsidian8.setIcon)(this.editButton, "edit");
 | |
|     this.editButton.setAttribute("aria-label", t("EDIT_CARD"));
 | |
|     this.editButton.addEventListener("click", async () => {
 | |
|       this.editClickHandler();
 | |
|     });
 | |
|   }
 | |
|   _createResetButton() {
 | |
|     this.resetButton = this.controls.createEl("button");
 | |
|     this.resetButton.addClasses(["sr-button", "sr-reset-button"]);
 | |
|     (0, import_obsidian8.setIcon)(this.resetButton, "refresh-cw");
 | |
|     this.resetButton.setAttribute("aria-label", t("RESET_CARD_PROGRESS"));
 | |
|     this.resetButton.addEventListener("click", () => {
 | |
|       this._processReview(3 /* Reset */);
 | |
|     });
 | |
|   }
 | |
|   _createCardInfoButton() {
 | |
|     this.infoButton = this.controls.createEl("button");
 | |
|     this.infoButton.addClasses(["sr-button", "sr-info-button"]);
 | |
|     (0, import_obsidian8.setIcon)(this.infoButton, "info");
 | |
|     this.infoButton.setAttribute("aria-label", "View Card Info");
 | |
|     this.infoButton.addEventListener("click", async () => {
 | |
|       this._displayCurrentCardInfoNotice();
 | |
|     });
 | |
|   }
 | |
|   _createSkipButton() {
 | |
|     this.skipButton = this.controls.createEl("button");
 | |
|     this.skipButton.addClasses(["sr-button", "sr-skip-button"]);
 | |
|     (0, import_obsidian8.setIcon)(this.skipButton, "chevrons-right");
 | |
|     this.skipButton.setAttribute("aria-label", t("SKIP"));
 | |
|     this.skipButton.addEventListener("click", () => {
 | |
|       this._skipCurrentCard();
 | |
|     });
 | |
|   }
 | |
|   async _skipCurrentCard() {
 | |
|     this.reviewSequencer.skipCurrentCard();
 | |
|     await this._showNextCard();
 | |
|   }
 | |
|   _displayCurrentCardInfoNotice() {
 | |
|     var _a;
 | |
|     const schedule = this._currentCard.scheduleInfo;
 | |
|     const currentEaseStr = t("CURRENT_EASE_HELP_TEXT") + ((_a = schedule == null ? void 0 : schedule.latestEase) != null ? _a : t("NEW"));
 | |
|     const currentIntervalStr = t("CURRENT_INTERVAL_HELP_TEXT") + textInterval(schedule == null ? void 0 : schedule.interval, false);
 | |
|     const generatedFromStr = t("CARD_GENERATED_FROM", {
 | |
|       notePath: this._currentQuestion.note.filePath
 | |
|     });
 | |
|     new import_obsidian8.Notice(currentEaseStr + "\n" + currentIntervalStr + "\n" + generatedFromStr);
 | |
|   }
 | |
|   // #region -> Deck Info
 | |
|   _createInfoSection() {
 | |
|     this.infoSection = this.view.createDiv();
 | |
|     this.infoSection.addClass("sr-info-section");
 | |
|     this.deckProgressInfo = this.infoSection.createDiv();
 | |
|     this.deckProgressInfo.addClass("sr-deck-progress-info");
 | |
|     this.chosenDeckInfo = this.deckProgressInfo.createDiv();
 | |
|     this.chosenDeckInfo.addClass("sr-chosen-deck-info");
 | |
|     this.chosenDeckName = this.chosenDeckInfo.createDiv();
 | |
|     this.chosenDeckName.addClass("sr-chosen-deck-name");
 | |
|     this.chosenDeckCounterWrapper = this.chosenDeckInfo.createDiv();
 | |
|     this.chosenDeckCounterWrapper.addClass("sr-chosen-deck-counter-wrapper");
 | |
|     this.chosenDeckCounterDivider = this.chosenDeckCounterWrapper.createDiv();
 | |
|     this.chosenDeckCounterDivider.addClass("sr-chosen-deck-counter-divider");
 | |
|     this.chosenDeckCardCounterWrapper = this.chosenDeckCounterWrapper.createDiv();
 | |
|     this.chosenDeckCardCounterWrapper.addClass("sr-chosen-deck-card-counter-wrapper");
 | |
|     this.chosenDeckCardCounter = this.chosenDeckCardCounterWrapper.createDiv();
 | |
|     this.chosenDeckCardCounter.addClass("sr-chosen-deck-card-counter");
 | |
|     this.chosenDeckCardCounterIcon = this.chosenDeckCardCounterWrapper.createDiv();
 | |
|     this.chosenDeckCardCounterIcon.addClass("sr-chosen-deck-card-counter-icon");
 | |
|     (0, import_obsidian8.setIcon)(this.chosenDeckCardCounterIcon, "credit-card");
 | |
|     this.chosenDeckSubDeckCounterWrapper = this.chosenDeckCounterWrapper.createDiv();
 | |
|     this.chosenDeckSubDeckCounterWrapper.addClass("sr-is-hidden");
 | |
|     this.chosenDeckSubDeckCounterWrapper.addClass("sr-chosen-deck-subdeck-counter-wrapper");
 | |
|     this.chosenDeckSubDeckCounter = this.chosenDeckSubDeckCounterWrapper.createDiv();
 | |
|     this.chosenDeckSubDeckCounter.addClass("sr-chosen-deck-subdeck-counter");
 | |
|     this.chosenDeckSubDeckCounterIcon = this.chosenDeckSubDeckCounterWrapper.createDiv();
 | |
|     this.chosenDeckSubDeckCounterIcon.addClass("sr-chosen-deck-subdeck-counter-icon");
 | |
|     (0, import_obsidian8.setIcon)(this.chosenDeckSubDeckCounterIcon, "layers");
 | |
|     this.currentDeckInfo = this.deckProgressInfo.createDiv();
 | |
|     this.currentDeckInfo.addClass("sr-is-hidden");
 | |
|     this.currentDeckInfo.addClass("sr-current-deck-info");
 | |
|     this.currentDeckName = this.currentDeckInfo.createDiv();
 | |
|     this.currentDeckName.addClass("sr-current-deck-name");
 | |
|     this.currentDeckCounterWrapper = this.currentDeckInfo.createDiv();
 | |
|     this.currentDeckCounterWrapper.addClass("sr-current-deck-counter-wrapper");
 | |
|     this.currentDeckCounterDivider = this.currentDeckCounterWrapper.createDiv();
 | |
|     this.currentDeckCounterDivider.addClass("sr-current-deck-counter-divider");
 | |
|     this.currentDeckCardCounterWrapper = this.currentDeckCounterWrapper.createDiv();
 | |
|     this.currentDeckCardCounterWrapper.addClass("sr-current-deck-card-counter-wrapper");
 | |
|     this.currentDeckCardCounter = this.currentDeckCardCounterWrapper.createDiv();
 | |
|     this.currentDeckCardCounter.addClass("sr-current-deck-card-counter");
 | |
|     this.currentDeckCardCounterIcon = this.currentDeckCardCounterWrapper.createDiv();
 | |
|     this.currentDeckCardCounterIcon.addClass("sr-current-deck-card-counter-icon");
 | |
|     (0, import_obsidian8.setIcon)(this.currentDeckCardCounterIcon, "credit-card");
 | |
|     if (this.settings.showContextInCards) {
 | |
|       this.cardContext = this.infoSection.createDiv();
 | |
|       this.cardContext.addClass("sr-context");
 | |
|     }
 | |
|   }
 | |
|   _updateInfoBar(chosenDeck, currentDeck) {
 | |
|     this._updateChosenDeckInfo(chosenDeck);
 | |
|     this._updateCurrentDeckInfo(chosenDeck, currentDeck);
 | |
|     this._updateCardContext();
 | |
|   }
 | |
|   _updateChosenDeckInfo(chosenDeck) {
 | |
|     const chosenDeckStats = this.reviewSequencer.getDeckStats(chosenDeck.getTopicPath());
 | |
|     this.chosenDeckName.setText(`${chosenDeck.deckName}`);
 | |
|     this.chosenDeckCardCounter.setText(
 | |
|       `${this.totalCardsInSession - chosenDeckStats.cardsInQueueCount}/${this.totalCardsInSession}`
 | |
|     );
 | |
|     if (chosenDeck.subdecks.length === 0) {
 | |
|       if (!this.chosenDeckSubDeckCounterWrapper.hasClass("sr-is-hidden")) {
 | |
|         this.chosenDeckSubDeckCounterWrapper.addClass("sr-is-hidden");
 | |
|       }
 | |
|       return;
 | |
|     }
 | |
|     if (this.chosenDeckSubDeckCounterWrapper.hasClass("sr-is-hidden")) {
 | |
|       this.chosenDeckSubDeckCounterWrapper.removeClass("sr-is-hidden");
 | |
|     }
 | |
|     this.chosenDeckSubDeckCounter.setText(
 | |
|       `${this.totalDecksInSession - chosenDeckStats.decksInQueueOfThisDeckCount}/${this.totalDecksInSession}`
 | |
|     );
 | |
|   }
 | |
|   _updateCurrentDeckInfo(chosenDeck, currentDeck) {
 | |
|     if (chosenDeck.subdecks.length === 0) {
 | |
|       if (!this.currentDeckInfo.hasClass("sr-is-hidden")) {
 | |
|         this.currentDeckInfo.addClass("sr-is-hidden");
 | |
|       }
 | |
|       return;
 | |
|     }
 | |
|     if (this.currentDeckInfo.hasClass("sr-is-hidden")) {
 | |
|       this.currentDeckInfo.removeClass("sr-is-hidden");
 | |
|     }
 | |
|     this.currentDeckName.setText(`${currentDeck.deckName}`);
 | |
|     const isRandomMode = this.settings.flashcardCardOrder === "EveryCardRandomDeckAndCard";
 | |
|     if (!isRandomMode) {
 | |
|       const currentDeckStats = this.reviewSequencer.getDeckStats(currentDeck.getTopicPath());
 | |
|       this.currentDeckCardCounter.setText(
 | |
|         `${this.currentDeckTotalCardsInQueue - currentDeckStats.cardsInQueueOfThisDeckCount}/${this.currentDeckTotalCardsInQueue}`
 | |
|       );
 | |
|     }
 | |
|   }
 | |
|   _updateCardContext() {
 | |
|     if (!this.settings.showContextInCards) {
 | |
|       this.cardContext.setText("");
 | |
|       return;
 | |
|     }
 | |
|     this.cardContext.setText(
 | |
|       ` ${this._formatQuestionContextText(this._currentQuestion.questionContext)}`
 | |
|     );
 | |
|   }
 | |
|   _formatQuestionContextText(questionContext) {
 | |
|     const separator = " > ";
 | |
|     let result = this._currentNote.file.basename;
 | |
|     questionContext.forEach((context) => {
 | |
|       if (context.startsWith("[[") && context.endsWith("]]")) {
 | |
|         context = context.replace("[[", "").replace("]]", "");
 | |
|         if (context.contains("|")) {
 | |
|           context = context.split("|")[1];
 | |
|         }
 | |
|       }
 | |
|       result += separator + context;
 | |
|     });
 | |
|     return result;
 | |
|   }
 | |
|   // #region -> Response
 | |
|   _createResponseButtons() {
 | |
|     this._createShowAnswerButton();
 | |
|     this._createHardButton();
 | |
|     this._createGoodButton();
 | |
|     this._createEasyButton();
 | |
|   }
 | |
|   _resetResponseButtons() {
 | |
|     this.answerButton.removeClass("sr-is-hidden");
 | |
|     this.hardButton.addClass("sr-is-hidden");
 | |
|     this.goodButton.addClass("sr-is-hidden");
 | |
|     this.easyButton.addClass("sr-is-hidden");
 | |
|   }
 | |
|   _createShowAnswerButton() {
 | |
|     this.answerButton = this.response.createEl("button");
 | |
|     this.answerButton.addClasses(["sr-response-button", "sr-show-answer-button", "sr-bg-blue"]);
 | |
|     this.answerButton.setText(t("SHOW_ANSWER"));
 | |
|     this.answerButton.addEventListener("click", () => {
 | |
|       this._showAnswer();
 | |
|     });
 | |
|   }
 | |
|   _createHardButton() {
 | |
|     this.hardButton = this.response.createEl("button");
 | |
|     this.hardButton.addClasses([
 | |
|       "sr-response-button",
 | |
|       "sr-hard-button",
 | |
|       "sr-bg-red",
 | |
|       "sr-is-hidden"
 | |
|     ]);
 | |
|     this.hardButton.setText(this.settings.flashcardHardText);
 | |
|     this.hardButton.addEventListener("click", () => {
 | |
|       this._processReview(2 /* Hard */);
 | |
|     });
 | |
|   }
 | |
|   _createGoodButton() {
 | |
|     this.goodButton = this.response.createEl("button");
 | |
|     this.goodButton.addClasses([
 | |
|       "sr-response-button",
 | |
|       "sr-good-button",
 | |
|       "sr-bg-blue",
 | |
|       "sr-is-hidden"
 | |
|     ]);
 | |
|     this.goodButton.setText(this.settings.flashcardGoodText);
 | |
|     this.goodButton.addEventListener("click", () => {
 | |
|       this._processReview(1 /* Good */);
 | |
|     });
 | |
|   }
 | |
|   _createEasyButton() {
 | |
|     this.easyButton = this.response.createEl("button");
 | |
|     this.easyButton.addClasses([
 | |
|       "sr-response-button",
 | |
|       "sr-hard-button",
 | |
|       "sr-bg-green",
 | |
|       "sr-is-hidden"
 | |
|     ]);
 | |
|     this.easyButton.setText(this.settings.flashcardEasyText);
 | |
|     this.easyButton.addEventListener("click", () => {
 | |
|       this._processReview(0 /* Easy */);
 | |
|     });
 | |
|   }
 | |
|   _setupEaseButton(button, buttonName, reviewResponse) {
 | |
|     const schedule = this.reviewSequencer.determineCardSchedule(
 | |
|       reviewResponse,
 | |
|       this._currentCard
 | |
|     );
 | |
|     const interval = schedule.interval;
 | |
|     if (this.settings.showIntervalInReviewButtons) {
 | |
|       if (import_obsidian8.Platform.isMobile) {
 | |
|         button.setText(textInterval(interval, true));
 | |
|       } else {
 | |
|         button.setText(`${buttonName} - ${textInterval(interval, false)}`);
 | |
|       }
 | |
|     } else {
 | |
|       button.setText(buttonName);
 | |
|     }
 | |
|   }
 | |
|   _showAnswer() {
 | |
|     const timeNow = (0, import_moment4.now)();
 | |
|     if (this.lastPressed && timeNow - this.lastPressed < this.plugin.data.settings.reviewButtonDelay) {
 | |
|       return;
 | |
|     }
 | |
|     this.lastPressed = timeNow;
 | |
|     this.mode = 2 /* Back */;
 | |
|     this.resetButton.disabled = false;
 | |
|     if (this._currentQuestion.questionType !== 4 /* Cloze */) {
 | |
|       const hr = document.createElement("hr");
 | |
|       this.content.appendChild(hr);
 | |
|     } else {
 | |
|       this.content.empty();
 | |
|     }
 | |
|     const wrapper = new RenderMarkdownWrapper(
 | |
|       this.app,
 | |
|       this.plugin,
 | |
|       this._currentNote.filePath
 | |
|     );
 | |
|     wrapper.renderMarkdownWrapper(
 | |
|       this._currentCard.back,
 | |
|       this.content,
 | |
|       this._currentQuestion.questionText.textDirection
 | |
|     );
 | |
|     this.answerButton.addClass("sr-is-hidden");
 | |
|     this.hardButton.removeClass("sr-is-hidden");
 | |
|     this.easyButton.removeClass("sr-is-hidden");
 | |
|     if (this.reviewMode === 0 /* Cram */) {
 | |
|       this.response.addClass("is-cram");
 | |
|       this.hardButton.setText(`${this.settings.flashcardHardText}`);
 | |
|       this.easyButton.setText(`${this.settings.flashcardEasyText}`);
 | |
|     } else {
 | |
|       this.goodButton.removeClass("sr-is-hidden");
 | |
|       this._setupEaseButton(
 | |
|         this.hardButton,
 | |
|         this.settings.flashcardHardText,
 | |
|         2 /* Hard */
 | |
|       );
 | |
|       this._setupEaseButton(
 | |
|         this.goodButton,
 | |
|         this.settings.flashcardGoodText,
 | |
|         1 /* Good */
 | |
|       );
 | |
|       this._setupEaseButton(
 | |
|         this.easyButton,
 | |
|         this.settings.flashcardEasyText,
 | |
|         0 /* Easy */
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/deck-ui.tsx
 | |
| var import_vhtml3 = __toESM(require_vhtml());
 | |
| var DeckUI = class {
 | |
|   constructor(plugin, settings, reviewSequencer, view, startReviewOfDeck) {
 | |
|     this.plugin = plugin;
 | |
|     this.settings = settings;
 | |
|     this.reviewSequencer = reviewSequencer;
 | |
|     this.view = view;
 | |
|     this.startReviewOfDeck = startReviewOfDeck;
 | |
|     this.init();
 | |
|   }
 | |
|   /**
 | |
|    * Initializes all static elements in the DeckListView
 | |
|    */
 | |
|   init() {
 | |
|     this.view.addClasses(["sr-deck-list", "sr-is-hidden"]);
 | |
|     this.header = this.view.createDiv();
 | |
|     this.header.addClass("sr-header");
 | |
|     this.title = this.header.createDiv();
 | |
|     this.title.addClass("sr-title");
 | |
|     this.title.setText(t("DECKS"));
 | |
|     this.stats = this.header.createDiv();
 | |
|     this.stats.addClass("sr-header-stats-container");
 | |
|     this._createHeaderStats();
 | |
|     this.headerDivider = this.view.createEl("hr");
 | |
|     this.content = this.view.createDiv();
 | |
|     this.content.addClass("sr-content");
 | |
|   }
 | |
|   /**
 | |
|    * Shows the DeckListView & rerenders dynamic elements
 | |
|    */
 | |
|   show() {
 | |
|     this.mode = 0 /* Deck */;
 | |
|     this._createHeaderStats();
 | |
|     this.content.empty();
 | |
|     for (const deck of this.reviewSequencer.originalDeckTree.subdecks) {
 | |
|       this._createTree(deck, this.content);
 | |
|     }
 | |
|     if (this.view.hasClass("sr-is-hidden")) {
 | |
|       this.view.removeClass("sr-is-hidden");
 | |
|     }
 | |
|   }
 | |
|   /**
 | |
|    * Hides the DeckListView
 | |
|    */
 | |
|   hide() {
 | |
|     if (!this.view.hasClass("sr-is-hidden")) {
 | |
|       this.view.addClass("sr-is-hidden");
 | |
|     }
 | |
|   }
 | |
|   /**
 | |
|    * Closes the DeckListView
 | |
|    */
 | |
|   close() {
 | |
|     this.hide();
 | |
|   }
 | |
|   // -> Header
 | |
|   _createHeaderStats() {
 | |
|     const statistics = this.reviewSequencer.getDeckStats(TopicPath.emptyPath);
 | |
|     this.stats.empty();
 | |
|     this._createHeaderStatsContainer(t("DUE_CARDS"), statistics.dueCount, "sr-bg-green");
 | |
|     this._createHeaderStatsContainer(t("NEW_CARDS"), statistics.newCount, "sr-bg-blue");
 | |
|     this._createHeaderStatsContainer(t("TOTAL_CARDS"), statistics.totalCount, "sr-bg-red");
 | |
|   }
 | |
|   _createHeaderStatsContainer(statsLable, statsNumber, statsClass) {
 | |
|     const statsContainer = this.stats.createDiv();
 | |
|     statsContainer.ariaLabel = statsLable;
 | |
|     statsContainer.addClasses([
 | |
|       "tag-pane-tag-count",
 | |
|       "tree-item-flair",
 | |
|       "sr-header-stats-count",
 | |
|       statsClass
 | |
|     ]);
 | |
|     const lable = statsContainer.createDiv();
 | |
|     lable.setText(statsLable + ":");
 | |
|     const number = statsContainer.createDiv();
 | |
|     number.setText(statsNumber.toString());
 | |
|   }
 | |
|   // -> Tree content
 | |
|   _createTree(deck, container) {
 | |
|     const deckTree = container.createDiv("tree-item sr-tree-item-container");
 | |
|     const deckTreeSelf = deckTree.createDiv(
 | |
|       "tree-item-self tag-pane-tag is-clickable sr-tree-item-row"
 | |
|     );
 | |
|     const shouldBeInitiallyExpanded = this.settings.initiallyExpandAllSubdecksInTree;
 | |
|     let collapsed = !shouldBeInitiallyExpanded;
 | |
|     let collapseIconEl = null;
 | |
|     if (deck.subdecks.length > 0) {
 | |
|       collapseIconEl = deckTreeSelf.createDiv("tree-item-icon collapse-icon");
 | |
|       collapseIconEl.innerHTML = COLLAPSE_ICON;
 | |
|       collapseIconEl.childNodes[0].style.transform = collapsed ? "rotate(-90deg)" : "";
 | |
|     }
 | |
|     const deckTreeInner = deckTreeSelf.createDiv("tree-item-inner");
 | |
|     const deckTreeInnerText = deckTreeInner.createDiv("tag-pane-tag-text");
 | |
|     deckTreeInnerText.innerHTML += /* @__PURE__ */ (0, import_vhtml3.default)("span", { class: "tag-pane-tag-self" }, deck.deckName);
 | |
|     const deckTreeOuter = deckTreeSelf.createDiv();
 | |
|     deckTreeOuter.addClasses(["tree-item-flair-outer", "sr-tree-stats-container"]);
 | |
|     const deckStats = this.reviewSequencer.getDeckStats(deck.getTopicPath());
 | |
|     this._createStats(deckStats, deckTreeOuter);
 | |
|     const deckTreeChildren = deckTree.createDiv("tree-item-children");
 | |
|     deckTreeChildren.style.display = collapsed ? "none" : "block";
 | |
|     if (deck.subdecks.length > 0) {
 | |
|       collapseIconEl.addEventListener("click", (e2) => {
 | |
|         if (collapsed) {
 | |
|           collapseIconEl.childNodes[0].style.transform = "";
 | |
|           deckTreeChildren.style.display = "block";
 | |
|         } else {
 | |
|           collapseIconEl.childNodes[0].style.transform = "rotate(-90deg)";
 | |
|           deckTreeChildren.style.display = "none";
 | |
|         }
 | |
|         e2.stopPropagation();
 | |
|         collapsed = !collapsed;
 | |
|       });
 | |
|     }
 | |
|     deckTreeSelf.addEventListener("click", () => {
 | |
|       this.startReviewOfDeck(deck);
 | |
|     });
 | |
|     for (const subdeck of deck.subdecks) {
 | |
|       this._createTree(subdeck, deckTreeChildren);
 | |
|     }
 | |
|   }
 | |
|   _createStats(statistics, statsWrapper) {
 | |
|     statsWrapper.empty();
 | |
|     this._createStatsContainer(
 | |
|       t("DUE_CARDS"),
 | |
|       statistics.dueCount,
 | |
|       "sr-bg-green",
 | |
|       statsWrapper
 | |
|     );
 | |
|     this._createStatsContainer(t("NEW_CARDS"), statistics.newCount, "sr-bg-blue", statsWrapper);
 | |
|     this._createStatsContainer(
 | |
|       t("TOTAL_CARDS"),
 | |
|       statistics.totalCount,
 | |
|       "sr-bg-red",
 | |
|       statsWrapper
 | |
|     );
 | |
|   }
 | |
|   _createStatsContainer(statsLable, statsNumber, statsClass, statsWrapper) {
 | |
|     const statsContainer = statsWrapper.createDiv();
 | |
|     statsContainer.ariaLabel = statsLable;
 | |
|     statsContainer.addClasses([
 | |
|       "tag-pane-tag-count",
 | |
|       "tree-item-flair",
 | |
|       "sr-tree-stats-count",
 | |
|       statsClass
 | |
|     ]);
 | |
|     statsContainer.setText(statsNumber.toString());
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/edit-modal.tsx
 | |
| var import_obsidian9 = require("obsidian");
 | |
| var FlashcardEditModal = class _FlashcardEditModal extends import_obsidian9.Modal {
 | |
|   constructor(app, existingText, textDirection) {
 | |
|     super(app);
 | |
|     this.didSaveChanges = false;
 | |
|     // -> Functions & helpers
 | |
|     this.saveClickCallback = (_2) => this.save();
 | |
|     this.cancelClickCallback = (_2) => this.cancel();
 | |
|     this.saveOnEnterCallback = (evt) => {
 | |
|       if ((evt.ctrlKey || evt.metaKey) && evt.key === "Enter") {
 | |
|         evt.preventDefault();
 | |
|         this.save();
 | |
|       }
 | |
|     };
 | |
|     this.modalText = existingText;
 | |
|     this.changedText = existingText;
 | |
|     this.textDirection = textDirection;
 | |
|     this.waitForClose = new Promise((resolve2, reject) => {
 | |
|       this.resolvePromise = resolve2;
 | |
|       this.rejectPromise = reject;
 | |
|     });
 | |
|     this.modalEl.addClasses(["sr-modal", "sr-edit-modal"]);
 | |
|     this.init();
 | |
|     this.open();
 | |
|   }
 | |
|   static Prompt(app, placeholder, textDirection) {
 | |
|     const newPromptModal = new _FlashcardEditModal(app, placeholder, textDirection);
 | |
|     return newPromptModal.waitForClose;
 | |
|   }
 | |
|   /**
 | |
|    * Initializes all components of the EditModal
 | |
|    */
 | |
|   init() {
 | |
|     var _a;
 | |
|     this.contentEl.empty();
 | |
|     this.contentEl.addClass("sr-edit-view");
 | |
|     this.title = this.contentEl.createDiv();
 | |
|     this.title.setText(t("EDIT_CARD"));
 | |
|     this.title.addClass("sr-title");
 | |
|     this.textArea = this.contentEl.createEl("textarea");
 | |
|     this.textArea.addClass("sr-input");
 | |
|     this.textArea.setText((_a = this.modalText) != null ? _a : "");
 | |
|     this.textArea.addEventListener("keydown", this.saveOnEnterCallback);
 | |
|     if (this.textDirection == 2 /* Rtl */) {
 | |
|       this.textArea.setAttribute("dir", "rtl");
 | |
|     }
 | |
|     this._createResponse(this.contentEl);
 | |
|   }
 | |
|   /**
 | |
|    * Opens the EditModal
 | |
|    */
 | |
|   onOpen() {
 | |
|     super.onOpen();
 | |
|     this.textArea.focus();
 | |
|   }
 | |
|   /**
 | |
|    * Closes the EditModal
 | |
|    */
 | |
|   onClose() {
 | |
|     super.onClose();
 | |
|     this.resolveInput();
 | |
|     this.removeInputListener();
 | |
|   }
 | |
|   save() {
 | |
|     this.didSaveChanges = true;
 | |
|     this.changedText = this.textArea.value;
 | |
|     this.close();
 | |
|   }
 | |
|   cancel() {
 | |
|     this.close();
 | |
|   }
 | |
|   resolveInput() {
 | |
|     if (!this.didSaveChanges) this.rejectPromise(t("NO_INPUT"));
 | |
|     else this.resolvePromise(this.changedText);
 | |
|   }
 | |
|   removeInputListener() {
 | |
|     this.textArea.removeEventListener("keydown", this.saveOnEnterCallback);
 | |
|   }
 | |
|   // -> Response section
 | |
|   _createResponseButton(container, text, colorClass, callback2) {
 | |
|     const button = container.createEl("button");
 | |
|     button.addClasses(["sr-response-button", colorClass]);
 | |
|     button.setText(text);
 | |
|     button.addEventListener("click", callback2);
 | |
|   }
 | |
|   _createResponse(mainContentContainer) {
 | |
|     const response = mainContentContainer.createDiv();
 | |
|     response.addClass("sr-response");
 | |
|     this._createResponseButton(response, t("CANCEL"), "sr-bg-red", this.cancelClickCallback);
 | |
|     this._createResponseButton(response, "", "sr-spacer", () => {
 | |
|     });
 | |
|     this._createResponseButton(response, t("SAVE"), "sr-bg-green", this.saveClickCallback);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/sr-modal.tsx
 | |
| var FlashcardModal = class extends import_obsidian10.Modal {
 | |
|   constructor(app, plugin, settings, reviewSequencer, reviewMode) {
 | |
|     super(app);
 | |
|     this.plugin = plugin;
 | |
|     this.settings = settings;
 | |
|     this.reviewSequencer = reviewSequencer;
 | |
|     this.reviewMode = reviewMode;
 | |
|     this.modalEl.style.height = this.settings.flashcardHeightPercentage + "%";
 | |
|     this.modalEl.style.maxHeight = this.settings.flashcardHeightPercentage + "%";
 | |
|     this.modalEl.style.width = this.settings.flashcardWidthPercentage + "%";
 | |
|     this.modalEl.style.maxWidth = this.settings.flashcardWidthPercentage + "%";
 | |
|     this.modalEl.setAttribute("id", "sr-modal");
 | |
|     if (this.settings.flashcardHeightPercentage >= 100 || this.settings.flashcardWidthPercentage >= 100) {
 | |
|       this.modalEl.style.borderRadius = "0";
 | |
|     }
 | |
|     this.contentEl.addClass("sr-modal-content");
 | |
|     this.deckView = new DeckUI(
 | |
|       this.plugin,
 | |
|       this.settings,
 | |
|       this.reviewSequencer,
 | |
|       this.contentEl.createDiv(),
 | |
|       this._startReviewOfDeck.bind(this)
 | |
|     );
 | |
|     this.flashcardView = new CardUI(
 | |
|       this.app,
 | |
|       this.plugin,
 | |
|       this.settings,
 | |
|       this.reviewSequencer,
 | |
|       this.reviewMode,
 | |
|       this.contentEl.createDiv(),
 | |
|       this._showDecksList.bind(this),
 | |
|       this._doEditQuestionText.bind(this)
 | |
|     );
 | |
|   }
 | |
|   onOpen() {
 | |
|     this._createBackButton();
 | |
|     this._showDecksList();
 | |
|   }
 | |
|   onClose() {
 | |
|     this.plugin.setSRViewInFocus(false);
 | |
|     this.mode = 3 /* Closed */;
 | |
|     this.deckView.close();
 | |
|     this.flashcardView.close();
 | |
|   }
 | |
|   _showDecksList() {
 | |
|     this._hideFlashcard();
 | |
|     this.deckView.show();
 | |
|   }
 | |
|   _hideDecksList() {
 | |
|     this.deckView.hide();
 | |
|   }
 | |
|   _showFlashcard(deck) {
 | |
|     this._hideDecksList();
 | |
|     this.flashcardView.show(deck);
 | |
|   }
 | |
|   _hideFlashcard() {
 | |
|     this.flashcardView.hide();
 | |
|   }
 | |
|   _startReviewOfDeck(deck) {
 | |
|     this.reviewSequencer.setCurrentDeck(deck.getTopicPath());
 | |
|     if (this.reviewSequencer.hasCurrentCard) {
 | |
|       this._showFlashcard(deck);
 | |
|       this.backButton.removeClass("sr-is-hidden");
 | |
|     } else {
 | |
|       this._showDecksList();
 | |
|     }
 | |
|   }
 | |
|   async _doEditQuestionText() {
 | |
|     const currentQ = this.reviewSequencer.currentQuestion;
 | |
|     const textPrompt = currentQ.questionText.actualQuestion;
 | |
|     const editModal = FlashcardEditModal.Prompt(
 | |
|       this.app,
 | |
|       textPrompt,
 | |
|       currentQ.questionText.textDirection
 | |
|     );
 | |
|     editModal.then(async (modifiedCardText) => {
 | |
|       this.reviewSequencer.updateCurrentQuestionText(modifiedCardText);
 | |
|     }).catch((reason) => console.log(reason));
 | |
|   }
 | |
|   _createBackButton() {
 | |
|     this.backButton = this.modalEl.createDiv();
 | |
|     this.backButton.addClasses(["sr-back-button", "sr-is-hidden"]);
 | |
|     (0, import_obsidian10.setIcon)(this.backButton, "arrow-left");
 | |
|     this.backButton.setAttribute("aria-label", t("BACK"));
 | |
|     this.backButton.addEventListener("click", () => {
 | |
|       this.backButton.addClass("sr-is-hidden");
 | |
|       this._showDecksList();
 | |
|     });
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/sr-tab-view.tsx
 | |
| var import_obsidian11 = require("obsidian");
 | |
| var SRTabView = class extends import_obsidian11.ItemView {
 | |
|   constructor(leaf, plugin, loadReviewSequencerData) {
 | |
|     super(leaf);
 | |
|     this.openErrorCount = 0;
 | |
|     this.plugin = plugin;
 | |
|     this.settings = plugin.data.settings;
 | |
|     this.loadReviewSequencerData = loadReviewSequencerData;
 | |
|     const viewContent = this.containerEl.getElementsByClassName("view-content");
 | |
|     if (viewContent.length > 0) {
 | |
|       this.viewContainerEl = viewContent[0];
 | |
|       this.viewContainerEl.addClass("sr-tab-view");
 | |
|       this.viewContentEl = this.viewContainerEl.createDiv("sr-tab-view-content");
 | |
|       this.viewContentEl.style.height = this.settings.flashcardHeightPercentage + "%";
 | |
|       this.viewContentEl.style.maxHeight = this.settings.flashcardHeightPercentage + "%";
 | |
|       this.viewContentEl.style.width = this.settings.flashcardWidthPercentage + "%";
 | |
|       this.viewContentEl.style.maxWidth = this.settings.flashcardWidthPercentage + "%";
 | |
|       this.viewContainerEl.appendChild(this.viewContentEl);
 | |
|     }
 | |
|   }
 | |
|   /**
 | |
|    * Returns the view type identifier for the SRTabView.
 | |
|    *
 | |
|    * @returns {string} The view type identifier.
 | |
|    */
 | |
|   getViewType() {
 | |
|     return SR_TAB_VIEW;
 | |
|   }
 | |
|   /**
 | |
|    * Retrieves the icon identifier for the SRTabView.
 | |
|    *
 | |
|    * @returns {string} The tab icon identifier.
 | |
|    */
 | |
|   getIcon() {
 | |
|     return "SpacedRepIcon";
 | |
|   }
 | |
|   /**
 | |
|    * Returns the display text for the SRTabView.
 | |
|    *
 | |
|    * @returns {string} The display text for the SRTabView.
 | |
|    */
 | |
|   getDisplayText() {
 | |
|     return "Spaced Repetition";
 | |
|   }
 | |
|   /**
 | |
|    * Initializes the SRTabView when opened by loading the review sequencer data
 | |
|    * and setting up the deck and flashcard views if they are not already initialized.
 | |
|    * Catches and logs errors that occur during the initial loading process.
 | |
|    */
 | |
|   async onOpen() {
 | |
|     try {
 | |
|       this._createBackButton();
 | |
|       const loadedData = await this.loadReviewSequencerData();
 | |
|       this.reviewSequencer = loadedData.reviewSequencer;
 | |
|       this.reviewMode = loadedData.mode;
 | |
|       if (this.deckView === void 0) {
 | |
|         this.deckView = new DeckUI(
 | |
|           this.plugin,
 | |
|           this.settings,
 | |
|           this.reviewSequencer,
 | |
|           this.viewContentEl.createDiv(),
 | |
|           this._startReviewOfDeck.bind(this)
 | |
|         );
 | |
|       }
 | |
|       if (this.flashcardView === void 0) {
 | |
|         this.flashcardView = new CardUI(
 | |
|           this.app,
 | |
|           this.plugin,
 | |
|           this.settings,
 | |
|           this.reviewSequencer,
 | |
|           this.reviewMode,
 | |
|           this.viewContentEl.createDiv(),
 | |
|           this._showDecksList.bind(this),
 | |
|           this._doEditQuestionText.bind(this)
 | |
|         );
 | |
|       }
 | |
|       this._showDecksList();
 | |
|     } catch (e2) {
 | |
|       if (this.openErrorCount > 0) {
 | |
|         console.error(e2);
 | |
|       }
 | |
|       this.openErrorCount++;
 | |
|     }
 | |
|   }
 | |
|   /**
 | |
|    * Closes the SRTabView by shutting down any active deck or flashcard views.
 | |
|    * Ensures that resources associated with these views are properly released.
 | |
|    */
 | |
|   async onClose() {
 | |
|     if (this.deckView) this.deckView.close();
 | |
|     if (this.flashcardView) this.flashcardView.close();
 | |
|   }
 | |
|   _showDecksList() {
 | |
|     this._hideFlashcard();
 | |
|     this.deckView.show();
 | |
|   }
 | |
|   _hideDecksList() {
 | |
|     this.deckView.hide();
 | |
|   }
 | |
|   _showFlashcard(deck) {
 | |
|     this._hideDecksList();
 | |
|     this.flashcardView.show(deck);
 | |
|   }
 | |
|   _hideFlashcard() {
 | |
|     this.flashcardView.hide();
 | |
|   }
 | |
|   _startReviewOfDeck(deck) {
 | |
|     this.reviewSequencer.setCurrentDeck(deck.getTopicPath());
 | |
|     if (this.reviewSequencer.hasCurrentCard) {
 | |
|       this.backButton.removeClass("sr-is-hidden");
 | |
|       this._showFlashcard(deck);
 | |
|     } else {
 | |
|       this._showDecksList();
 | |
|     }
 | |
|   }
 | |
|   async _doEditQuestionText() {
 | |
|     const currentQ = this.reviewSequencer.currentQuestion;
 | |
|     const textPrompt = currentQ.questionText.actualQuestion;
 | |
|     const editModal = FlashcardEditModal.Prompt(
 | |
|       this.app,
 | |
|       textPrompt,
 | |
|       currentQ.questionText.textDirection
 | |
|     );
 | |
|     editModal.then(async (modifiedCardText) => {
 | |
|       this.reviewSequencer.updateCurrentQuestionText(modifiedCardText);
 | |
|     }).catch((reason) => console.log(reason));
 | |
|   }
 | |
|   _createBackButton() {
 | |
|     this.backButton = this.viewContentEl.createDiv();
 | |
|     this.backButton.addClasses(["sr-back-button", "sr-is-hidden"]);
 | |
|     (0, import_obsidian11.setIcon)(this.backButton, "arrow-left");
 | |
|     this.backButton.setAttribute("aria-label", t("BACK"));
 | |
|     this.backButton.addEventListener("click", () => {
 | |
|       this.backButton.addClass("sr-is-hidden");
 | |
|       this._showDecksList();
 | |
|     });
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/gui/tab-view-manager.tsx
 | |
| var TabViewManager = class {
 | |
|   // Add any needed resourced
 | |
|   constructor(plugin) {
 | |
|     // Add any new other tab view types to this, then they'll be automatically registered
 | |
|     this.tabViewTypes = [
 | |
|       {
 | |
|         type: SR_TAB_VIEW,
 | |
|         viewCreator: (leaf) => new SRTabView(leaf, this.plugin, async () => {
 | |
|           if (this.shouldOpenSingeNoteTabView) {
 | |
|             const singleNoteDeckData = await this.plugin.getPreparedDecksForSingleNoteReview(
 | |
|               this.chosenSingleNoteForTabbedView,
 | |
|               this.chosenReviewModeForTabbedView
 | |
|             );
 | |
|             return this.plugin.getPreparedReviewSequencer(
 | |
|               singleNoteDeckData.deckTree,
 | |
|               singleNoteDeckData.remainingDeckTree,
 | |
|               singleNoteDeckData.mode
 | |
|             );
 | |
|           }
 | |
|           const fullDeckTree = this.osrAppCore.reviewableDeckTree;
 | |
|           const remainingDeckTree = this.chosenReviewModeForTabbedView === 0 /* Cram */ ? this.osrAppCore.reviewableDeckTree : this.osrAppCore.remainingDeckTree;
 | |
|           return this.plugin.getPreparedReviewSequencer(
 | |
|             fullDeckTree,
 | |
|             remainingDeckTree,
 | |
|             this.chosenReviewModeForTabbedView
 | |
|           );
 | |
|         })
 | |
|       }
 | |
|     ];
 | |
|     this.plugin = plugin;
 | |
|     this.shouldOpenSingeNoteTabView = false;
 | |
|     this.registerAllTabViews();
 | |
|   }
 | |
|   /**
 | |
|    * Opens the Spaced Repetition tab view in the application.
 | |
|    *
 | |
|    * This method sets up the necessary state for the tab view and invokes the
 | |
|    * internal method to open the tab view with the specified parameters.
 | |
|    *
 | |
|    * @param osrAppCore - The core application instance used for managing reviewable decks.
 | |
|    * @param reviewMode - The mode of flashcard review.
 | |
|    * @param singleNote - Optional parameter specifying a single note to review.
 | |
|    *                     If provided, the tab view will focus on this note.
 | |
|    *
 | |
|    * @returns {Promise<void>} - A promise that resolves when the tab view is opened.
 | |
|    */
 | |
|   async openSRTabView(osrAppCore, reviewMode, singleNote) {
 | |
|     this.osrAppCore = osrAppCore;
 | |
|     this.chosenReviewModeForTabbedView = reviewMode;
 | |
|     this.shouldOpenSingeNoteTabView = singleNote !== void 0;
 | |
|     if (singleNote) this.chosenSingleNoteForTabbedView = singleNote;
 | |
|     await this.openTabView(SR_TAB_VIEW, true);
 | |
|   }
 | |
|   /**
 | |
|    * Closes all open tab views in the application.
 | |
|    *
 | |
|    * This method iterates over all registered tab view types and detaches
 | |
|    * their corresponding leaves from the workspace, effectively closing them.
 | |
|    */
 | |
|   closeAllTabViews() {
 | |
|     this.forEachTabViewType((viewType) => {
 | |
|       this.plugin.app.workspace.detachLeavesOfType(viewType.type);
 | |
|     });
 | |
|   }
 | |
|   forEachTabViewType(callback2) {
 | |
|     this.tabViewTypes.forEach((type) => callback2(type));
 | |
|   }
 | |
|   registerAllTabViews() {
 | |
|     this.forEachTabViewType(
 | |
|       (viewType) => this.plugin.registerView(viewType.type, viewType.viewCreator)
 | |
|     );
 | |
|   }
 | |
|   async openTabView(type, newLeaf) {
 | |
|     const { workspace } = this.plugin.app;
 | |
|     let leaf = null;
 | |
|     const leaves = workspace.getLeavesOfType(type);
 | |
|     if (leaves.length > 0) {
 | |
|       leaf = leaves[0];
 | |
|     } else {
 | |
|       leaf = workspace.getLeaf(newLeaf);
 | |
|       if (leaf !== null) {
 | |
|         await leaf.setViewState({ type, active: true });
 | |
|       }
 | |
|     }
 | |
|     if (leaf !== null) {
 | |
|       workspace.revealLeaf(leaf);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/icons/app-icon.ts
 | |
| var import_obsidian12 = require("obsidian");
 | |
| function appIcon() {
 | |
|   (0, import_obsidian12.addIcon)(
 | |
|     "SpacedRepIcon",
 | |
|     `<path fill="currentColor" stroke="currentColor" d="M 88.960938 17.257812 L 47.457031 17.257812 C 45.679688 17.257812 44.230469 18.703125 44.230469 20.484375 L 44.230469 86.558594 C 44.230469 88.335938 45.679688 89.785156 47.457031 89.785156 L 88.960938 89.785156 C 90.738281 89.785156 92.1875 88.335938 92.1875 86.558594 L 92.1875 20.484375 C 92.1875 18.703125 90.738281 17.257812 88.960938 17.257812 Z M 88.28125 85.878906 L 48.136719 85.878906 L 48.136719 21.164062 L 88.28125 21.164062 Z M 88.28125 85.878906 "/>
 | |
|         <path fill="currentColor" stroke="currentColor"  d="M 88.960938 9.445312 L 61.667969 9.445312 C 59.925781 3.816406 54.011719 0.515625 48.269531 2.054688 L 8.183594 12.796875 C 2.304688 14.371094 -1.199219 20.4375 0.378906 26.316406 L 17.476562 90.140625 C 18.796875 95.066406 23.269531 98.324219 28.144531 98.324219 C 29.085938 98.324219 30.046875 98.199219 31 97.945312 L 40.765625 95.328125 C 42.625 96.75 44.941406 97.597656 47.457031 97.597656 L 88.960938 97.597656 C 95.046875 97.597656 100 92.644531 100 86.558594 L 100 20.484375 C 100 14.398438 95.046875 9.445312 88.960938 9.445312 Z M 29.988281 94.171875 C 26.1875 95.191406 22.269531 92.925781 21.25 89.128906 L 4.152344 25.304688 C 3.132812 21.507812 5.394531 17.585938 9.195312 16.570312 L 49.28125 5.828125 C 52.578125 4.945312 55.960938 6.53125 57.464844 9.445312 L 47.457031 9.445312 C 41.371094 9.445312 36.417969 14.398438 36.417969 20.484375 L 36.417969 86.558594 C 36.417969 88.558594 36.957031 90.433594 37.890625 92.054688 Z M 96.09375 86.558594 C 96.09375 90.492188 92.894531 93.691406 88.960938 93.691406 L 47.457031 93.691406 C 43.523438 93.691406 40.324219 90.492188 40.324219 86.558594 L 40.324219 20.484375 C 40.324219 16.550781 43.523438 13.351562 47.457031 13.351562 L 88.960938 13.351562 C 92.894531 13.351562 96.09375 16.550781 96.09375 20.484375 Z M 96.09375 86.558594 "/>
 | |
|         <path fill="currentColor" stroke="currentColor"  d="M 54.101562 53.09375 L 60.070312 57.410156 L 57.789062 64.378906 C 56.90625 67.074219 59.996094 69.320312 62.285156 67.648438 L 68.210938 63.324219 L 74.132812 67.648438 C 76.421875 69.320312 79.511719 67.074219 78.628906 64.378906 L 76.347656 57.410156 L 82.320312 53.09375 C 84.613281 51.433594 83.441406 47.804688 80.605469 47.804688 L 73.242188 47.804688 L 70.988281 40.839844 C 70.117188 38.144531 66.300781 38.144531 65.429688 40.839844 L 63.179688 47.804688 L 55.8125 47.804688 C 52.980469 47.804688 51.804688 51.433594 54.101562 53.09375 Z M 54.101562 53.09375 "/>
 | |
|         `
 | |
|   );
 | |
| }
 | |
| 
 | |
| // src/next-note-review-handler.ts
 | |
| var import_obsidian14 = require("obsidian");
 | |
| 
 | |
| // src/gui/review-deck-selection-modal.tsx
 | |
| var import_obsidian13 = require("obsidian");
 | |
| var ReviewDeckSelectionModal = class extends import_obsidian13.FuzzySuggestModal {
 | |
|   constructor(app, deckKeys) {
 | |
|     super(app);
 | |
|     this.deckKeys = [];
 | |
|     this.deckKeys = deckKeys;
 | |
|   }
 | |
|   getItems() {
 | |
|     return this.deckKeys;
 | |
|   }
 | |
|   getItemText(item) {
 | |
|     return item;
 | |
|   }
 | |
|   onChooseItem(deckKey, _2) {
 | |
|     this.close();
 | |
|     this.submitCallback(deckKey);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/next-note-review-handler.ts
 | |
| var NextNoteReviewHandler = class {
 | |
|   get lastSelectedReviewDeck() {
 | |
|     return this._lastSelectedReviewDeck;
 | |
|   }
 | |
|   get noteReviewQueue() {
 | |
|     return this._noteReviewQueue;
 | |
|   }
 | |
|   constructor(app, settings, noteReviewQueue) {
 | |
|     this.app = app;
 | |
|     this.settings = settings;
 | |
|     this._noteReviewQueue = noteReviewQueue;
 | |
|   }
 | |
|   async autoReviewNextNote() {
 | |
|     if (this.settings.autoNextNote) {
 | |
|       if (!this._lastSelectedReviewDeck) {
 | |
|         const reviewDeckKeys = this._noteReviewQueue.reviewDeckNameList;
 | |
|         if (reviewDeckKeys.length > 0) this._lastSelectedReviewDeck = reviewDeckKeys[0];
 | |
|         else {
 | |
|           new import_obsidian14.Notice(t("ALL_CAUGHT_UP"));
 | |
|           return;
 | |
|         }
 | |
|       }
 | |
|       this.reviewNextNote(this._lastSelectedReviewDeck);
 | |
|     }
 | |
|   }
 | |
|   async reviewNextNoteModal() {
 | |
|     const reviewDeckNames = this._noteReviewQueue.reviewDeckNameList;
 | |
|     if (reviewDeckNames.length === 1) {
 | |
|       this.reviewNextNote(reviewDeckNames[0]);
 | |
|     } else {
 | |
|       const deckSelectionModal = new ReviewDeckSelectionModal(this.app, reviewDeckNames);
 | |
|       deckSelectionModal.submitCallback = (deckKey) => this.reviewNextNote(deckKey);
 | |
|       deckSelectionModal.open();
 | |
|     }
 | |
|   }
 | |
|   async reviewNextNote(deckKey) {
 | |
|     if (!this._noteReviewQueue.reviewDeckNameList.contains(deckKey)) {
 | |
|       new import_obsidian14.Notice(t("NO_DECK_EXISTS", { deckName: deckKey }));
 | |
|       return;
 | |
|     }
 | |
|     this._lastSelectedReviewDeck = deckKey;
 | |
|     const deck = this._noteReviewQueue.reviewDecks.get(deckKey);
 | |
|     const notefile = deck.determineNextNote(this.settings.openRandomNote);
 | |
|     if (notefile) {
 | |
|       await this.openNote(deckKey, notefile.tfile);
 | |
|     } else {
 | |
|       new import_obsidian14.Notice(t("ALL_CAUGHT_UP"));
 | |
|     }
 | |
|   }
 | |
|   async openNote(deckName, file) {
 | |
|     this._lastSelectedReviewDeck = deckName;
 | |
|     await this.app.workspace.getLeaf().openFile(file);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/note-review-deck.ts
 | |
| var SchedNote = class {
 | |
|   constructor(note, dueUnix) {
 | |
|     this.note = note;
 | |
|     this.dueUnix = dueUnix;
 | |
|   }
 | |
|   isDue(todayUnix) {
 | |
|     return this.dueUnix <= todayUnix;
 | |
|   }
 | |
| };
 | |
| var NoteReviewDeck = class {
 | |
|   constructor(name) {
 | |
|     this._newNotes = [];
 | |
|     this._scheduledNotes = [];
 | |
|     this._dueNotesCount = 0;
 | |
|     this._deckName = name;
 | |
|     this._activeFolders = /* @__PURE__ */ new Set([this._deckName, t("TODAY")]);
 | |
|   }
 | |
|   get deckName() {
 | |
|     return this._deckName;
 | |
|   }
 | |
|   get newNotes() {
 | |
|     return this._newNotes;
 | |
|   }
 | |
|   get scheduledNotes() {
 | |
|     return this._scheduledNotes;
 | |
|   }
 | |
|   get dueNotesCount() {
 | |
|     return this._dueNotesCount;
 | |
|   }
 | |
|   get activeFolders() {
 | |
|     return this._activeFolders;
 | |
|   }
 | |
|   calcDueNotesCount(todayUnix) {
 | |
|     this._dueNotesCount = 0;
 | |
|     this.scheduledNotes.forEach((scheduledNote) => {
 | |
|       if (scheduledNote.isDue(todayUnix)) {
 | |
|         this._dueNotesCount++;
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   sortNotesByDateAndImportance(pageranks) {
 | |
|     this._newNotes = this.newNotes.sort(
 | |
|       (a2, b2) => (pageranks[b2.path] || 0) - (pageranks[a2.path] || 0)
 | |
|     );
 | |
|     this._scheduledNotes = this.scheduledNotes.sort((a2, b2) => {
 | |
|       const result = a2.dueUnix - b2.dueUnix;
 | |
|       if (result != 0) {
 | |
|         return result;
 | |
|       }
 | |
|       return (pageranks[b2.note.path] || 0) - (pageranks[a2.note.path] || 0);
 | |
|     });
 | |
|   }
 | |
|   determineNextNote(openRandomNote) {
 | |
|     const todayUnix = globalDateProvider.today.valueOf();
 | |
|     const dueNotes = this.scheduledNotes.filter((note) => note.isDue(todayUnix));
 | |
|     if (dueNotes.length > 0) {
 | |
|       const index = openRandomNote ? globalRandomNumberProvider.getInteger(0, dueNotes.length - 1) : 0;
 | |
|       return dueNotes[index].note;
 | |
|     }
 | |
|     if (this.newNotes.length > 0) {
 | |
|       const index = openRandomNote ? globalRandomNumberProvider.getInteger(0, this.newNotes.length - 1) : 0;
 | |
|       return this.newNotes[index];
 | |
|     }
 | |
|     return null;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/note-review-queue.ts
 | |
| var NoteReviewQueue = class {
 | |
|   get reviewDecks() {
 | |
|     return this._reviewDecks;
 | |
|   }
 | |
|   get dueNotesCount() {
 | |
|     return this._dueNotesCount;
 | |
|   }
 | |
|   get reviewDeckNameList() {
 | |
|     return [...this._reviewDecks.keys()];
 | |
|   }
 | |
|   init() {
 | |
|     this._reviewDecks = /* @__PURE__ */ new Map();
 | |
|   }
 | |
|   calcDueNotesCount(todayUnix) {
 | |
|     this._dueNotesCount = 0;
 | |
|     this._reviewDecks.forEach((reviewDeck) => {
 | |
|       reviewDeck.calcDueNotesCount(todayUnix);
 | |
|       this._dueNotesCount += reviewDeck.dueNotesCount;
 | |
|     });
 | |
|   }
 | |
|   addNoteToQueue(noteFile, noteSchedule, matchedNoteTags) {
 | |
|     for (const matchedNoteTag of matchedNoteTags) {
 | |
|       if (!this.reviewDecks.has(matchedNoteTag)) {
 | |
|         this.reviewDecks.set(matchedNoteTag, new NoteReviewDeck(matchedNoteTag));
 | |
|       }
 | |
|     }
 | |
|     if (noteSchedule == null) {
 | |
|       for (const matchedNoteTag of matchedNoteTags) {
 | |
|         this.reviewDecks.get(matchedNoteTag).newNotes.push(noteFile);
 | |
|       }
 | |
|     } else {
 | |
|       for (const matchedNoteTag of matchedNoteTags) {
 | |
|         this.reviewDecks.get(matchedNoteTag).scheduledNotes.push(new SchedNote(noteFile, noteSchedule.dueDateAsUnix));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   updateScheduleInfo(note, scheduleInfo) {
 | |
|     this.reviewDecks.forEach((reviewDeck) => {
 | |
|       let wasDueInDeck = false;
 | |
|       for (const scheduledNote of reviewDeck.scheduledNotes) {
 | |
|         if (scheduledNote.note.path === note.path) {
 | |
|           scheduledNote.dueUnix = scheduleInfo.dueDate.valueOf();
 | |
|           wasDueInDeck = true;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       if (!wasDueInDeck) {
 | |
|         reviewDeck.newNotes.splice(
 | |
|           reviewDeck.newNotes.findIndex((newNote) => newNote.path === note.path),
 | |
|           1
 | |
|         );
 | |
|         reviewDeck.scheduledNotes.push(new SchedNote(note, scheduleInfo.dueDate.valueOf()));
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/plugin-data.ts
 | |
| var DEFAULT_DATA = {
 | |
|   settings: DEFAULT_SETTINGS,
 | |
|   buryDate: "",
 | |
|   buryList: [],
 | |
|   historyDeck: null
 | |
| };
 | |
| 
 | |
| // src/question-postponement-list.ts
 | |
| var QuestionPostponementList = class {
 | |
|   constructor(plugin, settings, list) {
 | |
|     this.plugin = plugin;
 | |
|     this.settings = settings;
 | |
|     this.list = list;
 | |
|   }
 | |
|   async clearIfNewDay(data) {
 | |
|     const now2 = window.moment(Date.now());
 | |
|     const todayDate = now2.format("YYYY-MM-DD");
 | |
|     const isNewDay = todayDate !== data.buryDate;
 | |
|     if (isNewDay) {
 | |
|       data.buryDate = todayDate;
 | |
|       this.clear();
 | |
|       await this.write();
 | |
|     }
 | |
|   }
 | |
|   clear() {
 | |
|     this.list.splice(0);
 | |
|   }
 | |
|   add(question) {
 | |
|     if (!this.includes(question)) this.list.push(question.questionText.textHash);
 | |
|   }
 | |
|   includes(question) {
 | |
|     return this.list.includes(question.questionText.textHash);
 | |
|   }
 | |
|   async write() {
 | |
|     if (this.plugin == null) return;
 | |
|     await this.plugin.savePluginData();
 | |
|   }
 | |
| };
 | |
| 
 | |
| // src/main.ts
 | |
| var SRPlugin = class _SRPlugin extends import_obsidian15.Plugin {
 | |
|   constructor() {
 | |
|     super(...arguments);
 | |
|     this.ribbonIcon = null;
 | |
|     this.statusBar = null;
 | |
|     this.isSRInFocus = false;
 | |
|   }
 | |
|   async onload() {
 | |
|     this.tabViewManager = new TabViewManager(this);
 | |
|     this.app.workspace.onLayoutReady(async () => {
 | |
|       this.tabViewManager.closeAllTabViews();
 | |
|     });
 | |
|     await this.loadPluginData();
 | |
|     const noteReviewQueue = new NoteReviewQueue();
 | |
|     this.nextNoteReviewHandler = new NextNoteReviewHandler(
 | |
|       this.app,
 | |
|       this.data.settings,
 | |
|       noteReviewQueue
 | |
|     );
 | |
|     this.osrSidebar = new OsrSidebar(this, this.data.settings, this.nextNoteReviewHandler);
 | |
|     this.osrSidebar.init();
 | |
|     this.app.workspace.onLayoutReady(async () => {
 | |
|       await this.osrSidebar.activateReviewQueueViewPanel();
 | |
|       setTimeout(async () => {
 | |
|         if (!this.osrAppCore.syncLock) {
 | |
|           await this.sync();
 | |
|         }
 | |
|       }, 2e3);
 | |
|     });
 | |
|     const questionPostponementList = new QuestionPostponementList(
 | |
|       this,
 | |
|       this.data.settings,
 | |
|       this.data.buryList
 | |
|     );
 | |
|     const osrNoteLinkInfoFinder = new ObsidianVaultNoteLinkInfoFinder(this.app.metadataCache);
 | |
|     this.osrAppCore = new OsrAppCore(this.app);
 | |
|     this.osrAppCore.init(
 | |
|       questionPostponementList,
 | |
|       osrNoteLinkInfoFinder,
 | |
|       this.data.settings,
 | |
|       this.onOsrVaultDataChanged.bind(this),
 | |
|       noteReviewQueue
 | |
|     );
 | |
|     appIcon();
 | |
|     this.showStatusBar(this.data.settings.showStatusBar);
 | |
|     this.showRibbonIcon(this.data.settings.showRibbonIcon);
 | |
|     this.showFileMenuItems(!this.data.settings.disableFileMenuReviewOptions);
 | |
|     this.addPluginCommands();
 | |
|     this.addSettingTab(new SRSettingTab(this.app, this));
 | |
|     this.registerSRFocusListener();
 | |
|   }
 | |
|   showFileMenuItems(status) {
 | |
|     if (this.fileMenuHandler === void 0) {
 | |
|       this.fileMenuHandler = (menu, fileish) => {
 | |
|         if (fileish instanceof import_obsidian15.TFile && fileish.extension === "md") {
 | |
|           menu.addItem((item) => {
 | |
|             item.setTitle(
 | |
|               t("REVIEW_DIFFICULTY_FILE_MENU", {
 | |
|                 difficulty: this.data.settings.flashcardEasyText
 | |
|               })
 | |
|             ).setIcon("SpacedRepIcon").onClick(() => {
 | |
|               this.saveNoteReviewResponse(fileish, 0 /* Easy */);
 | |
|             });
 | |
|           });
 | |
|           menu.addItem((item) => {
 | |
|             item.setTitle(
 | |
|               t("REVIEW_DIFFICULTY_FILE_MENU", {
 | |
|                 difficulty: this.data.settings.flashcardGoodText
 | |
|               })
 | |
|             ).setIcon("SpacedRepIcon").onClick(() => {
 | |
|               this.saveNoteReviewResponse(fileish, 1 /* Good */);
 | |
|             });
 | |
|           });
 | |
|           menu.addItem((item) => {
 | |
|             item.setTitle(
 | |
|               t("REVIEW_DIFFICULTY_FILE_MENU", {
 | |
|                 difficulty: this.data.settings.flashcardHardText
 | |
|               })
 | |
|             ).setIcon("SpacedRepIcon").onClick(() => {
 | |
|               this.saveNoteReviewResponse(fileish, 2 /* Hard */);
 | |
|             });
 | |
|           });
 | |
|         }
 | |
|       };
 | |
|     }
 | |
|     if (status) {
 | |
|       this.registerEvent(this.app.workspace.on("file-menu", this.fileMenuHandler));
 | |
|     } else {
 | |
|       this.app.workspace.off("file-menu", this.fileMenuHandler);
 | |
|     }
 | |
|   }
 | |
|   addPluginCommands() {
 | |
|     this.addCommand({
 | |
|       id: "srs-note-review-open-note",
 | |
|       name: t("OPEN_NOTE_FOR_REVIEW"),
 | |
|       callback: async () => {
 | |
|         if (!this.osrAppCore.syncLock) {
 | |
|           await this.sync();
 | |
|           this.nextNoteReviewHandler.reviewNextNoteModal();
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-note-review-easy",
 | |
|       name: t("REVIEW_NOTE_DIFFICULTY_CMD", {
 | |
|         difficulty: this.data.settings.flashcardEasyText
 | |
|       }),
 | |
|       callback: () => {
 | |
|         const openFile = this.app.workspace.getActiveFile();
 | |
|         if (openFile && openFile.extension === "md") {
 | |
|           this.saveNoteReviewResponse(openFile, 0 /* Easy */);
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-note-review-good",
 | |
|       name: t("REVIEW_NOTE_DIFFICULTY_CMD", {
 | |
|         difficulty: this.data.settings.flashcardGoodText
 | |
|       }),
 | |
|       callback: () => {
 | |
|         const openFile = this.app.workspace.getActiveFile();
 | |
|         if (openFile && openFile.extension === "md") {
 | |
|           this.saveNoteReviewResponse(openFile, 1 /* Good */);
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-note-review-hard",
 | |
|       name: t("REVIEW_NOTE_DIFFICULTY_CMD", {
 | |
|         difficulty: this.data.settings.flashcardHardText
 | |
|       }),
 | |
|       callback: () => {
 | |
|         const openFile = this.app.workspace.getActiveFile();
 | |
|         if (openFile && openFile.extension === "md") {
 | |
|           this.saveNoteReviewResponse(openFile, 2 /* Hard */);
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-review-flashcards",
 | |
|       name: t("REVIEW_ALL_CARDS"),
 | |
|       callback: async () => {
 | |
|         if (this.osrAppCore.syncLock) {
 | |
|           return;
 | |
|         }
 | |
|         await this.sync();
 | |
|         if (this.data.settings.openViewInNewTab) {
 | |
|           this.tabViewManager.openSRTabView(this.osrAppCore, 1 /* Review */);
 | |
|         } else {
 | |
|           this.openFlashcardModal(
 | |
|             this.osrAppCore.reviewableDeckTree,
 | |
|             this.osrAppCore.remainingDeckTree,
 | |
|             1 /* Review */
 | |
|           );
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-cram-flashcards",
 | |
|       name: t("CRAM_ALL_CARDS"),
 | |
|       callback: async () => {
 | |
|         await this.sync();
 | |
|         if (this.data.settings.openViewInNewTab) {
 | |
|           this.tabViewManager.openSRTabView(this.osrAppCore, 0 /* Cram */);
 | |
|         } else {
 | |
|           this.openFlashcardModal(
 | |
|             this.osrAppCore.reviewableDeckTree,
 | |
|             this.osrAppCore.reviewableDeckTree,
 | |
|             0 /* Cram */
 | |
|           );
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-review-flashcards-in-note",
 | |
|       name: t("REVIEW_CARDS_IN_NOTE"),
 | |
|       callback: async () => {
 | |
|         const openFile = this.app.workspace.getActiveFile();
 | |
|         if (!openFile || openFile.extension !== "md") {
 | |
|           return;
 | |
|         }
 | |
|         if (this.data.settings.openViewInNewTab) {
 | |
|           this.tabViewManager.openSRTabView(
 | |
|             this.osrAppCore,
 | |
|             1 /* Review */,
 | |
|             openFile
 | |
|           );
 | |
|         } else {
 | |
|           this.openFlashcardModalForSingleNote(openFile, 1 /* Review */);
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-cram-flashcards-in-note",
 | |
|       name: t("CRAM_CARDS_IN_NOTE"),
 | |
|       callback: async () => {
 | |
|         const openFile = this.app.workspace.getActiveFile();
 | |
|         if (!openFile || openFile.extension !== "md") {
 | |
|           return;
 | |
|         }
 | |
|         if (this.data.settings.openViewInNewTab) {
 | |
|           this.tabViewManager.openSRTabView(
 | |
|             this.osrAppCore,
 | |
|             0 /* Cram */,
 | |
|             openFile
 | |
|           );
 | |
|         } else {
 | |
|           this.openFlashcardModalForSingleNote(openFile, 0 /* Cram */);
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|     this.addCommand({
 | |
|       id: "srs-open-review-queue-view",
 | |
|       name: t("OPEN_REVIEW_QUEUE_VIEW"),
 | |
|       callback: async () => {
 | |
|         await this.osrSidebar.openReviewQueueView();
 | |
|       }
 | |
|     });
 | |
|   }
 | |
|   onunload() {
 | |
|     this.app.workspace.getLeavesOfType(REVIEW_QUEUE_VIEW_TYPE).forEach((leaf) => leaf.detach());
 | |
|     this.tabViewManager.closeAllTabViews();
 | |
|   }
 | |
|   getPreparedReviewSequencer(fullDeckTree, remainingDeckTree, reviewMode) {
 | |
|     const deckIterator = _SRPlugin.createDeckTreeIterator(this.data.settings);
 | |
|     const reviewSequencer = new FlashcardReviewSequencer(
 | |
|       reviewMode,
 | |
|       deckIterator,
 | |
|       this.data.settings,
 | |
|       SrsAlgorithm.getInstance(),
 | |
|       this.osrAppCore.questionPostponementList,
 | |
|       this.osrAppCore.dueDateFlashcardHistogram
 | |
|     );
 | |
|     reviewSequencer.setDeckTree(fullDeckTree, remainingDeckTree);
 | |
|     return { reviewSequencer, mode: reviewMode };
 | |
|   }
 | |
|   async getPreparedDecksForSingleNoteReview(file, mode) {
 | |
|     const note = await this.loadNote(file);
 | |
|     const deckTree = new Deck2("root", null);
 | |
|     note.appendCardsToDeck(deckTree);
 | |
|     const remainingDeckTree = DeckTreeFilter.filterForRemainingCards(
 | |
|       this.osrAppCore.questionPostponementList,
 | |
|       deckTree,
 | |
|       mode
 | |
|     );
 | |
|     return { deckTree, remainingDeckTree, mode };
 | |
|   }
 | |
|   registerSRFocusListener() {
 | |
|     this.registerEvent(
 | |
|       this.app.workspace.on("active-leaf-change", this.handleFocusChange.bind(this))
 | |
|     );
 | |
|   }
 | |
|   removeSRFocusListener() {
 | |
|     this.setSRViewInFocus(false);
 | |
|     this.app.workspace.off("active-leaf-change", this.handleFocusChange.bind(this));
 | |
|   }
 | |
|   handleFocusChange(leaf) {
 | |
|     this.setSRViewInFocus(leaf !== null && leaf.view instanceof SRTabView);
 | |
|   }
 | |
|   setSRViewInFocus(value) {
 | |
|     this.isSRInFocus = value;
 | |
|   }
 | |
|   getSRInFocusState() {
 | |
|     return this.isSRInFocus;
 | |
|   }
 | |
|   async openFlashcardModalForSingleNote(noteFile, reviewMode) {
 | |
|     const singleNoteDeckData = await this.getPreparedDecksForSingleNoteReview(
 | |
|       noteFile,
 | |
|       reviewMode
 | |
|     );
 | |
|     this.openFlashcardModal(
 | |
|       singleNoteDeckData.deckTree,
 | |
|       singleNoteDeckData.remainingDeckTree,
 | |
|       reviewMode
 | |
|     );
 | |
|   }
 | |
|   openFlashcardModal(fullDeckTree, remainingDeckTree, reviewMode) {
 | |
|     const reviewSequencerData = this.getPreparedReviewSequencer(
 | |
|       fullDeckTree,
 | |
|       remainingDeckTree,
 | |
|       reviewMode
 | |
|     );
 | |
|     this.setSRViewInFocus(true);
 | |
|     new FlashcardModal(
 | |
|       this.app,
 | |
|       this,
 | |
|       this.data.settings,
 | |
|       reviewSequencerData.reviewSequencer,
 | |
|       reviewSequencerData.mode
 | |
|     ).open();
 | |
|   }
 | |
|   static createDeckTreeIterator(settings) {
 | |
|     let cardOrder = CardOrder[settings.flashcardCardOrder];
 | |
|     if (cardOrder === void 0) cardOrder = 2 /* DueFirstSequential */;
 | |
|     let deckOrder = DeckOrder[settings.flashcardDeckOrder];
 | |
|     if (deckOrder === void 0) deckOrder = 0 /* PrevDeckComplete_Sequential */;
 | |
|     const iteratorOrder = {
 | |
|       deckOrder,
 | |
|       cardOrder
 | |
|     };
 | |
|     return new DeckTreeIterator(iteratorOrder, null);
 | |
|   }
 | |
|   async sync() {
 | |
|     if (this.osrAppCore.syncLock) {
 | |
|       return;
 | |
|     }
 | |
|     const now2 = window.moment(Date.now());
 | |
|     this.osrAppCore.defaultTextDirection = this.getObsidianRtlSetting();
 | |
|     await this.osrAppCore.loadVault();
 | |
|     if (this.data.settings.showSchedulingDebugMessages) {
 | |
|       console.log(`SR: ${t("DECKS")}`, this.osrAppCore.reviewableDeckTree);
 | |
|       console.log(
 | |
|         "SR: " + t("SYNC_TIME_TAKEN", {
 | |
|           t: Date.now() - now2.valueOf()
 | |
|         })
 | |
|       );
 | |
|     }
 | |
|   }
 | |
|   onOsrVaultDataChanged() {
 | |
|     this.statusBar.setText(
 | |
|       t("STATUS_BAR", {
 | |
|         dueNotesCount: this.osrAppCore.noteReviewQueue.dueNotesCount,
 | |
|         dueFlashcardsCount: this.osrAppCore.remainingDeckTree.getCardCount(
 | |
|           2 /* All */,
 | |
|           true
 | |
|         )
 | |
|       })
 | |
|     );
 | |
|     if (this.data.settings.enableNoteReviewPaneOnStartup) this.osrSidebar.redraw();
 | |
|   }
 | |
|   async loadNote(noteFile) {
 | |
|     const loader = new NoteFileLoader(this.data.settings);
 | |
|     const srFile = this.createSrTFile(noteFile);
 | |
|     const folderTopicPath = TopicPath.getFolderPathFromFilename(
 | |
|       srFile,
 | |
|       this.data.settings
 | |
|     );
 | |
|     const note = await loader.load(
 | |
|       this.createSrTFile(noteFile),
 | |
|       this.getObsidianRtlSetting(),
 | |
|       folderTopicPath
 | |
|     );
 | |
|     if (note.hasChanged) {
 | |
|       note.writeNoteFile(this.data.settings);
 | |
|     }
 | |
|     return note;
 | |
|   }
 | |
|   getObsidianRtlSetting() {
 | |
|     const v2 = this.app.vault.getConfig("rightToLeft");
 | |
|     return convertToStringOrEmpty(v2) == "true" ? 2 /* Rtl */ : 1 /* Ltr */;
 | |
|   }
 | |
|   async saveNoteReviewResponse(note, response) {
 | |
|     const noteSrTFile = this.createSrTFile(note);
 | |
|     if (SettingsUtil.isPathInNoteIgnoreFolder(this.data.settings, note.path)) {
 | |
|       new import_obsidian15.Notice(t("NOTE_IN_IGNORED_FOLDER"));
 | |
|       return;
 | |
|     }
 | |
|     const tags = noteSrTFile.getAllTagsFromCache();
 | |
|     if (!SettingsUtil.isAnyTagANoteReviewTag(this.data.settings, tags)) {
 | |
|       new import_obsidian15.Notice(t("PLEASE_TAG_NOTE"));
 | |
|       return;
 | |
|     }
 | |
|     await this.osrAppCore.saveNoteReviewResponse(noteSrTFile, response, this.data.settings);
 | |
|     new import_obsidian15.Notice(t("RESPONSE_RECEIVED"));
 | |
|     if (this.data.settings.autoNextNote) {
 | |
|       this.nextNoteReviewHandler.autoReviewNextNote();
 | |
|     }
 | |
|   }
 | |
|   createSrTFile(note) {
 | |
|     return new SrTFile(this.app.vault, this.app.metadataCache, note);
 | |
|   }
 | |
|   async loadPluginData() {
 | |
|     const loadedData = await this.loadData();
 | |
|     if (loadedData == null ? void 0 : loadedData.settings) upgradeSettings(loadedData.settings);
 | |
|     this.data = Object.assign({}, DEFAULT_DATA, loadedData);
 | |
|     this.data.settings = Object.assign({}, DEFAULT_SETTINGS, this.data.settings);
 | |
|     setDebugParser(this.data.settings.showParserDebugMessages);
 | |
|     this.setupDataStoreAndAlgorithmInstances(this.data.settings);
 | |
|   }
 | |
|   setupDataStoreAndAlgorithmInstances(settings) {
 | |
|     DataStore.instance = new StoreInNotes(settings);
 | |
|     SrsAlgorithm.instance = new SrsAlgorithmOsr(settings);
 | |
|     DataStoreAlgorithm.instance = new DataStoreInNoteAlgorithmOsr(settings);
 | |
|   }
 | |
|   async savePluginData() {
 | |
|     await this.saveData(this.data);
 | |
|   }
 | |
|   showRibbonIcon(status) {
 | |
|     if (!this.ribbonIcon) {
 | |
|       this.ribbonIcon = this.addRibbonIcon("SpacedRepIcon", t("REVIEW_CARDS"), async () => {
 | |
|         if (!this.osrAppCore.syncLock) {
 | |
|           await this.sync();
 | |
|           this.openFlashcardModal(
 | |
|             this.osrAppCore.reviewableDeckTree,
 | |
|             this.osrAppCore.remainingDeckTree,
 | |
|             1 /* Review */
 | |
|           );
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|     if (status) {
 | |
|       this.ribbonIcon.style.display = "";
 | |
|     } else {
 | |
|       this.ribbonIcon.style.display = "none";
 | |
|     }
 | |
|   }
 | |
|   showStatusBar(status) {
 | |
|     if (!this.statusBar) {
 | |
|       this.statusBar = this.addStatusBarItem();
 | |
|       this.statusBar.classList.add("mod-clickable");
 | |
|       this.statusBar.setAttribute("aria-label", t("OPEN_NOTE_FOR_REVIEW"));
 | |
|       this.statusBar.setAttribute("aria-label-position", "top");
 | |
|       this.statusBar.addEventListener("click", async () => {
 | |
|         if (!this.osrAppCore.syncLock) {
 | |
|           await this.sync();
 | |
|           this.nextNoteReviewHandler.reviewNextNoteModal();
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|     if (status) {
 | |
|       this.statusBar.style.display = "";
 | |
|     } else {
 | |
|       this.statusBar.style.display = "none";
 | |
|     }
 | |
|   }
 | |
| };
 | |
| /*! Bundled license information:
 | |
| 
 | |
| moment/moment.js:
 | |
|   (*! moment.js *)
 | |
|   (*! version : 2.30.1 *)
 | |
|   (*! authors : Tim Wood, Iskren Chernev, Moment.js contributors *)
 | |
|   (*! license : MIT *)
 | |
|   (*! momentjs.com *)
 | |
| 
 | |
| @kurkle/color/dist/color.esm.js:
 | |
|   (*!
 | |
|    * @kurkle/color v0.3.4
 | |
|    * https://github.com/kurkle/color#readme
 | |
|    * (c) 2024 Jukka Kurkela
 | |
|    * Released under the MIT License
 | |
|    *)
 | |
| 
 | |
| chart.js/dist/chunks/helpers.segment.js:
 | |
|   (*!
 | |
|    * Chart.js v4.4.8
 | |
|    * https://www.chartjs.org
 | |
|    * (c) 2025 Chart.js Contributors
 | |
|    * Released under the MIT License
 | |
|    *)
 | |
| 
 | |
| chart.js/dist/chart.js:
 | |
|   (*!
 | |
|    * Chart.js v4.4.8
 | |
|    * https://www.chartjs.org
 | |
|    * (c) 2025 Chart.js Contributors
 | |
|    * Released under the MIT License
 | |
|    *)
 | |
| */
 | |
| 
 | |
| 
 | |
| /* nosourcemap */ |