/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/

'use strict';

var obsidian = require('obsidian');

/******************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};

function createCommonjsModule(fn) {
  var module = { exports: {} };
	return fn(module, module.exports), module.exports;
}

var utils = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
exports.extend = extend;
exports.indexOf = indexOf;
exports.escapeExpression = escapeExpression;
exports.isEmpty = isEmpty;
exports.createFrame = createFrame;
exports.blockParams = blockParams;
exports.appendContextPath = appendContextPath;
var escape = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#x27;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

var badChars = /[&<>"'`=]/g,
    possible = /[&<>"'`=]/;

function escapeChar(chr) {
  return escape[chr];
}

function extend(obj /* , ...source */) {
  for (var i = 1; i < arguments.length; i++) {
    for (var key in arguments[i]) {
      if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
        obj[key] = arguments[i][key];
      }
    }
  }

  return obj;
}

var toString = Object.prototype.toString;

exports.toString = toString;
// Sourced from lodash
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
/* eslint-disable func-style */
var isFunction = function isFunction(value) {
  return typeof value === 'function';
};
// fallback for older versions of Chrome and Safari
/* istanbul ignore next */
if (isFunction(/x/)) {
  exports.isFunction = isFunction = function (value) {
    return typeof value === 'function' && toString.call(value) === '[object Function]';
  };
}
exports.isFunction = isFunction;

/* eslint-enable func-style */

/* istanbul ignore next */
var isArray = Array.isArray || function (value) {
  return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
};

exports.isArray = isArray;
// Older IE versions do not directly support indexOf so we must implement our own, sadly.

function indexOf(array, value) {
  for (var i = 0, len = array.length; i < len; i++) {
    if (array[i] === value) {
      return i;
    }
  }
  return -1;
}

function escapeExpression(string) {
  if (typeof string !== 'string') {
    // don't escape SafeStrings, since they're already safe
    if (string && string.toHTML) {
      return string.toHTML();
    } else if (string == null) {
      return '';
    } else if (!string) {
      return string + '';
    }

    // Force a string conversion as this will be done by the append regardless and
    // the regex test will do this transparently behind the scenes, causing issues if
    // an object's to string has escaped characters in it.
    string = '' + string;
  }

  if (!possible.test(string)) {
    return string;
  }
  return string.replace(badChars, escapeChar);
}

function isEmpty(value) {
  if (!value && value !== 0) {
    return true;
  } else if (isArray(value) && value.length === 0) {
    return true;
  } else {
    return false;
  }
}

function createFrame(object) {
  var frame = extend({}, object);
  frame._parent = object;
  return frame;
}

function blockParams(params, ids) {
  params.path = ids;
  return params;
}

function appendContextPath(contextPath, id) {
  return (contextPath ? contextPath + '.' : '') + id;
}

});

var exception = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
var errorProps = ['description', 'fileName', 'lineNumber', 'endLineNumber', 'message', 'name', 'number', 'stack'];

function Exception(message, node) {
  var loc = node && node.loc,
      line = undefined,
      endLineNumber = undefined,
      column = undefined,
      endColumn = undefined;

  if (loc) {
    line = loc.start.line;
    endLineNumber = loc.end.line;
    column = loc.start.column;
    endColumn = loc.end.column;

    message += ' - ' + line + ':' + column;
  }

  var tmp = Error.prototype.constructor.call(this, message);

  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
  for (var idx = 0; idx < errorProps.length; idx++) {
    this[errorProps[idx]] = tmp[errorProps[idx]];
  }

  /* istanbul ignore else */
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, Exception);
  }

  try {
    if (loc) {
      this.lineNumber = line;
      this.endLineNumber = endLineNumber;

      // Work around issue under safari where we can't directly set the column value
      /* istanbul ignore next */
      if (Object.defineProperty) {
        Object.defineProperty(this, 'column', {
          value: column,
          enumerable: true
        });
        Object.defineProperty(this, 'endColumn', {
          value: endColumn,
          enumerable: true
        });
      } else {
        this.column = column;
        this.endColumn = endColumn;
      }
    }
  } catch (nop) {
    /* Ignore if the browser is very particular */
  }
}

Exception.prototype = new Error();

exports['default'] = Exception;
module.exports = exports['default'];

});

var blockHelperMissing = createCommonjsModule(function (module, exports) {

exports.__esModule = true;



exports['default'] = function (instance) {
  instance.registerHelper('blockHelperMissing', function (context, options) {
    var inverse = options.inverse,
        fn = options.fn;

    if (context === true) {
      return fn(this);
    } else if (context === false || context == null) {
      return inverse(this);
    } else if (utils.isArray(context)) {
      if (context.length > 0) {
        if (options.ids) {
          options.ids = [options.name];
        }

        return instance.helpers.each(context, options);
      } else {
        return inverse(this);
      }
    } else {
      if (options.data && options.ids) {
        var data = utils.createFrame(options.data);
        data.contextPath = utils.appendContextPath(options.data.contextPath, options.name);
        options = { data: data };
      }

      return fn(context, options);
    }
  });
};

module.exports = exports['default'];

});

var each = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }





var _exception2 = _interopRequireDefault(exception);

exports['default'] = function (instance) {
  instance.registerHelper('each', function (context, options) {
    if (!options) {
      throw new _exception2['default']('Must pass iterator to #each');
    }

    var fn = options.fn,
        inverse = options.inverse,
        i = 0,
        ret = '',
        data = undefined,
        contextPath = undefined;

    if (options.data && options.ids) {
      contextPath = utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
    }

    if (utils.isFunction(context)) {
      context = context.call(this);
    }

    if (options.data) {
      data = utils.createFrame(options.data);
    }

    function execIteration(field, index, last) {
      if (data) {
        data.key = field;
        data.index = index;
        data.first = index === 0;
        data.last = !!last;

        if (contextPath) {
          data.contextPath = contextPath + field;
        }
      }

      ret = ret + fn(context[field], {
        data: data,
        blockParams: utils.blockParams([context[field], field], [contextPath + field, null])
      });
    }

    if (context && typeof context === 'object') {
      if (utils.isArray(context)) {
        for (var j = context.length; i < j; i++) {
          if (i in context) {
            execIteration(i, i, i === context.length - 1);
          }
        }
      } else if (typeof Symbol === 'function' && context[Symbol.iterator]) {
        var newContext = [];
        var iterator = context[Symbol.iterator]();
        for (var it = iterator.next(); !it.done; it = iterator.next()) {
          newContext.push(it.value);
        }
        context = newContext;
        for (var j = context.length; i < j; i++) {
          execIteration(i, i, i === context.length - 1);
        }
      } else {
        (function () {
          var priorKey = undefined;

          Object.keys(context).forEach(function (key) {
            // We're running the iterations one step out of sync so we can detect
            // the last iteration without have to scan the object twice and create
            // an itermediate keys array.
            if (priorKey !== undefined) {
              execIteration(priorKey, i - 1);
            }
            priorKey = key;
            i++;
          });
          if (priorKey !== undefined) {
            execIteration(priorKey, i - 1, true);
          }
        })();
      }
    }

    if (i === 0) {
      ret = inverse(this);
    }

    return ret;
  });
};

module.exports = exports['default'];

});

var helperMissing = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _exception2 = _interopRequireDefault(exception);

exports['default'] = function (instance) {
  instance.registerHelper('helperMissing', function () /* [args, ]options */{
    if (arguments.length === 1) {
      // A missing field in a {{foo}} construct.
      return undefined;
    } else {
      // Someone is actually trying to call something, blow up.
      throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
    }
  });
};

module.exports = exports['default'];

});

var _if = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }





var _exception2 = _interopRequireDefault(exception);

exports['default'] = function (instance) {
  instance.registerHelper('if', function (conditional, options) {
    if (arguments.length != 2) {
      throw new _exception2['default']('#if requires exactly one argument');
    }
    if (utils.isFunction(conditional)) {
      conditional = conditional.call(this);
    }

    // Default behavior is to render the positive path if the value is truthy and not empty.
    // The `includeZero` option may be set to treat the condtional as purely not empty based on the
    // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
    if (!options.hash.includeZero && !conditional || utils.isEmpty(conditional)) {
      return options.inverse(this);
    } else {
      return options.fn(this);
    }
  });

  instance.registerHelper('unless', function (conditional, options) {
    if (arguments.length != 2) {
      throw new _exception2['default']('#unless requires exactly one argument');
    }
    return instance.helpers['if'].call(this, conditional, {
      fn: options.inverse,
      inverse: options.fn,
      hash: options.hash
    });
  });
};

module.exports = exports['default'];

});

var log$1 = createCommonjsModule(function (module, exports) {

exports.__esModule = true;

exports['default'] = function (instance) {
  instance.registerHelper('log', function () /* message, options */{
    var args = [undefined],
        options = arguments[arguments.length - 1];
    for (var i = 0; i < arguments.length - 1; i++) {
      args.push(arguments[i]);
    }

    var level = 1;
    if (options.hash.level != null) {
      level = options.hash.level;
    } else if (options.data && options.data.level != null) {
      level = options.data.level;
    }
    args[0] = level;

    instance.log.apply(instance, args);
  });
};

module.exports = exports['default'];

});

var lookup = createCommonjsModule(function (module, exports) {

exports.__esModule = true;

exports['default'] = function (instance) {
  instance.registerHelper('lookup', function (obj, field, options) {
    if (!obj) {
      // Note for 5.0: Change to "obj == null" in 5.0
      return obj;
    }
    return options.lookupProperty(obj, field);
  });
};

module.exports = exports['default'];

});

var _with = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }





var _exception2 = _interopRequireDefault(exception);

exports['default'] = function (instance) {
  instance.registerHelper('with', function (context, options) {
    if (arguments.length != 2) {
      throw new _exception2['default']('#with requires exactly one argument');
    }
    if (utils.isFunction(context)) {
      context = context.call(this);
    }

    var fn = options.fn;

    if (!utils.isEmpty(context)) {
      var data = options.data;
      if (options.data && options.ids) {
        data = utils.createFrame(options.data);
        data.contextPath = utils.appendContextPath(options.data.contextPath, options.ids[0]);
      }

      return fn(context, {
        data: data,
        blockParams: utils.blockParams([context], [data && data.contextPath])
      });
    } else {
      return options.inverse(this);
    }
  });
};

module.exports = exports['default'];

});

var registerDefaultHelpers_1 = registerDefaultHelpers;
var moveHelperToHooks_1 = moveHelperToHooks;
// istanbul ignore next

function _interopRequireDefault$7(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _helpersBlockHelperMissing2 = _interopRequireDefault$7(blockHelperMissing);



var _helpersEach2 = _interopRequireDefault$7(each);



var _helpersHelperMissing2 = _interopRequireDefault$7(helperMissing);



var _helpersIf2 = _interopRequireDefault$7(_if);



var _helpersLog2 = _interopRequireDefault$7(log$1);



var _helpersLookup2 = _interopRequireDefault$7(lookup);



var _helpersWith2 = _interopRequireDefault$7(_with);

function registerDefaultHelpers(instance) {
  _helpersBlockHelperMissing2['default'](instance);
  _helpersEach2['default'](instance);
  _helpersHelperMissing2['default'](instance);
  _helpersIf2['default'](instance);
  _helpersLog2['default'](instance);
  _helpersLookup2['default'](instance);
  _helpersWith2['default'](instance);
}

function moveHelperToHooks(instance, helperName, keepHelper) {
  if (instance.helpers[helperName]) {
    instance.hooks[helperName] = instance.helpers[helperName];
    if (!keepHelper) {
      delete instance.helpers[helperName];
    }
  }
}


var helpers$1 = /*#__PURE__*/Object.defineProperty({
	registerDefaultHelpers: registerDefaultHelpers_1,
	moveHelperToHooks: moveHelperToHooks_1
}, '__esModule', {value: true});

var inline = createCommonjsModule(function (module, exports) {

exports.__esModule = true;



exports['default'] = function (instance) {
  instance.registerDecorator('inline', function (fn, props, container, options) {
    var ret = fn;
    if (!props.partials) {
      props.partials = {};
      ret = function (context, options) {
        // Create a new partials stack frame prior to exec.
        var original = container.partials;
        container.partials = utils.extend({}, original, props.partials);
        var ret = fn(context, options);
        container.partials = original;
        return ret;
      };
    }

    props.partials[options.args[0]] = options.fn;

    return ret;
  });
};

module.exports = exports['default'];

});

var registerDefaultDecorators_1 = registerDefaultDecorators;
// istanbul ignore next

function _interopRequireDefault$6(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _decoratorsInline2 = _interopRequireDefault$6(inline);

function registerDefaultDecorators(instance) {
  _decoratorsInline2['default'](instance);
}


var decorators = /*#__PURE__*/Object.defineProperty({
	registerDefaultDecorators: registerDefaultDecorators_1
}, '__esModule', {value: true});

var logger_1 = createCommonjsModule(function (module, exports) {

exports.__esModule = true;



var logger = {
  methodMap: ['debug', 'info', 'warn', 'error'],
  level: 'info',

  // Maps a given level value to the `methodMap` indexes above.
  lookupLevel: function lookupLevel(level) {
    if (typeof level === 'string') {
      var levelMap = utils.indexOf(logger.methodMap, level.toLowerCase());
      if (levelMap >= 0) {
        level = levelMap;
      } else {
        level = parseInt(level, 10);
      }
    }

    return level;
  },

  // Can be overridden in the host environment
  log: function log(level) {
    level = logger.lookupLevel(level);

    if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) {
      var method = logger.methodMap[level];
      // eslint-disable-next-line no-console
      if (!console[method]) {
        method = 'log';
      }

      for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        message[_key - 1] = arguments[_key];
      }

      console[method].apply(console, message); // eslint-disable-line no-console
    }
  }
};

exports['default'] = logger;
module.exports = exports['default'];

});

var createNewLookupObject_2 = createNewLookupObject;



/**
 * Create a new object with "null"-prototype to avoid truthy results on prototype properties.
 * The resulting object can be used with "object[property]" to check if a property exists
 * @param {...object} sources a varargs parameter of source objects that will be merged
 * @returns {object}
 */

function createNewLookupObject() {
  for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) {
    sources[_key] = arguments[_key];
  }

  return utils.extend.apply(undefined, [Object.create(null)].concat(sources));
}


var createNewLookupObject_1 = /*#__PURE__*/Object.defineProperty({
	createNewLookupObject: createNewLookupObject_2
}, '__esModule', {value: true});

var createProtoAccessControl_1 = createProtoAccessControl;
var resultIsAllowed_1 = resultIsAllowed;
var resetLoggedProperties_1 = resetLoggedProperties;
// istanbul ignore next

function _interopRequireDefault$5(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }





var _logger2$1 = _interopRequireDefault$5(logger_1);

var loggedProperties = Object.create(null);

function createProtoAccessControl(runtimeOptions) {
  var defaultMethodWhiteList = Object.create(null);
  defaultMethodWhiteList['constructor'] = false;
  defaultMethodWhiteList['__defineGetter__'] = false;
  defaultMethodWhiteList['__defineSetter__'] = false;
  defaultMethodWhiteList['__lookupGetter__'] = false;

  var defaultPropertyWhiteList = Object.create(null);
  // eslint-disable-next-line no-proto
  defaultPropertyWhiteList['__proto__'] = false;

  return {
    properties: {
      whitelist: createNewLookupObject_1.createNewLookupObject(defaultPropertyWhiteList, runtimeOptions.allowedProtoProperties),
      defaultValue: runtimeOptions.allowProtoPropertiesByDefault
    },
    methods: {
      whitelist: createNewLookupObject_1.createNewLookupObject(defaultMethodWhiteList, runtimeOptions.allowedProtoMethods),
      defaultValue: runtimeOptions.allowProtoMethodsByDefault
    }
  };
}

function resultIsAllowed(result, protoAccessControl, propertyName) {
  if (typeof result === 'function') {
    return checkWhiteList(protoAccessControl.methods, propertyName);
  } else {
    return checkWhiteList(protoAccessControl.properties, propertyName);
  }
}

function checkWhiteList(protoAccessControlForType, propertyName) {
  if (protoAccessControlForType.whitelist[propertyName] !== undefined) {
    return protoAccessControlForType.whitelist[propertyName] === true;
  }
  if (protoAccessControlForType.defaultValue !== undefined) {
    return protoAccessControlForType.defaultValue;
  }
  logUnexpecedPropertyAccessOnce(propertyName);
  return false;
}

function logUnexpecedPropertyAccessOnce(propertyName) {
  if (loggedProperties[propertyName] !== true) {
    loggedProperties[propertyName] = true;
    _logger2$1['default'].log('error', 'Handlebars: Access has been denied to resolve the property "' + propertyName + '" because it is not an "own property" of its parent.\n' + 'You can add a runtime option to disable the check or this warning:\n' + 'See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details');
  }
}

function resetLoggedProperties() {
  Object.keys(loggedProperties).forEach(function (propertyName) {
    delete loggedProperties[propertyName];
  });
}


var protoAccess = /*#__PURE__*/Object.defineProperty({
	createProtoAccessControl: createProtoAccessControl_1,
	resultIsAllowed: resultIsAllowed_1,
	resetLoggedProperties: resetLoggedProperties_1
}, '__esModule', {value: true});

var HandlebarsEnvironment_1 = HandlebarsEnvironment;
// istanbul ignore next

function _interopRequireDefault$4(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }





var _exception2$3 = _interopRequireDefault$4(exception);







var _logger2 = _interopRequireDefault$4(logger_1);



var VERSION = '4.7.8';
var VERSION_1 = VERSION;
var COMPILER_REVISION = 8;
var COMPILER_REVISION_1 = COMPILER_REVISION;
var LAST_COMPATIBLE_COMPILER_REVISION = 7;

var LAST_COMPATIBLE_COMPILER_REVISION_1 = LAST_COMPATIBLE_COMPILER_REVISION;
var REVISION_CHANGES = {
  1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
  2: '== 1.0.0-rc.3',
  3: '== 1.0.0-rc.4',
  4: '== 1.x.x',
  5: '== 2.0.0-alpha.x',
  6: '>= 2.0.0-beta.1',
  7: '>= 4.0.0 <4.3.0',
  8: '>= 4.3.0'
};

var REVISION_CHANGES_1 = REVISION_CHANGES;
var objectType = '[object Object]';

function HandlebarsEnvironment(helpers, partials, decorators$1) {
  this.helpers = helpers || {};
  this.partials = partials || {};
  this.decorators = decorators$1 || {};

  helpers$1.registerDefaultHelpers(this);
  decorators.registerDefaultDecorators(this);
}

HandlebarsEnvironment.prototype = {
  constructor: HandlebarsEnvironment,

  logger: _logger2['default'],
  log: _logger2['default'].log,

  registerHelper: function registerHelper(name, fn) {
    if (utils.toString.call(name) === objectType) {
      if (fn) {
        throw new _exception2$3['default']('Arg not supported with multiple helpers');
      }
      utils.extend(this.helpers, name);
    } else {
      this.helpers[name] = fn;
    }
  },
  unregisterHelper: function unregisterHelper(name) {
    delete this.helpers[name];
  },

  registerPartial: function registerPartial(name, partial) {
    if (utils.toString.call(name) === objectType) {
      utils.extend(this.partials, name);
    } else {
      if (typeof partial === 'undefined') {
        throw new _exception2$3['default']('Attempting to register a partial called "' + name + '" as undefined');
      }
      this.partials[name] = partial;
    }
  },
  unregisterPartial: function unregisterPartial(name) {
    delete this.partials[name];
  },

  registerDecorator: function registerDecorator(name, fn) {
    if (utils.toString.call(name) === objectType) {
      if (fn) {
        throw new _exception2$3['default']('Arg not supported with multiple decorators');
      }
      utils.extend(this.decorators, name);
    } else {
      this.decorators[name] = fn;
    }
  },
  unregisterDecorator: function unregisterDecorator(name) {
    delete this.decorators[name];
  },
  /**
   * Reset the memory of illegal property accesses that have already been logged.
   * @deprecated should only be used in handlebars test-cases
   */
  resetLoggedPropertyAccesses: function resetLoggedPropertyAccesses() {
    protoAccess.resetLoggedProperties();
  }
};

var log = _logger2['default'].log;

var log_1 = log;
var createFrame = utils.createFrame;
var logger = _logger2['default'];


var base$1 = /*#__PURE__*/Object.defineProperty({
	HandlebarsEnvironment: HandlebarsEnvironment_1,
	VERSION: VERSION_1,
	COMPILER_REVISION: COMPILER_REVISION_1,
	LAST_COMPATIBLE_COMPILER_REVISION: LAST_COMPATIBLE_COMPILER_REVISION_1,
	REVISION_CHANGES: REVISION_CHANGES_1,
	log: log_1,
	createFrame: createFrame,
	logger: logger
}, '__esModule', {value: true});

var safeString = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
function SafeString(string) {
  this.string = string;
}

SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
  return '' + this.string;
};

exports['default'] = SafeString;
module.exports = exports['default'];

});

var wrapHelper_2 = wrapHelper;

function wrapHelper(helper, transformOptionsFn) {
  if (typeof helper !== 'function') {
    // This should not happen, but apparently it does in https://github.com/wycats/handlebars.js/issues/1639
    // We try to make the wrapper least-invasive by not wrapping it, if the helper is not a function.
    return helper;
  }
  var wrapper = function wrapper() /* dynamic arguments */{
    var options = arguments[arguments.length - 1];
    arguments[arguments.length - 1] = transformOptionsFn(options);
    return helper.apply(this, arguments);
  };
  return wrapper;
}


var wrapHelper_1 = /*#__PURE__*/Object.defineProperty({
	wrapHelper: wrapHelper_2
}, '__esModule', {value: true});

var checkRevision_1 = checkRevision;
var template_1 = template;
var wrapProgram_1 = wrapProgram;
var resolvePartial_1 = resolvePartial;
var invokePartial_1 = invokePartial;
var noop_1 = noop;
// istanbul ignore next

function _interopRequireDefault$3(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

// istanbul ignore next

function _interopRequireWildcard$1(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }



var Utils = _interopRequireWildcard$1(utils);



var _exception2$2 = _interopRequireDefault$3(exception);









function checkRevision(compilerInfo) {
  var compilerRevision = compilerInfo && compilerInfo[0] || 1,
      currentRevision = base$1.COMPILER_REVISION;

  if (compilerRevision >= base$1.LAST_COMPATIBLE_COMPILER_REVISION && compilerRevision <= base$1.COMPILER_REVISION) {
    return;
  }

  if (compilerRevision < base$1.LAST_COMPATIBLE_COMPILER_REVISION) {
    var runtimeVersions = base$1.REVISION_CHANGES[currentRevision],
        compilerVersions = base$1.REVISION_CHANGES[compilerRevision];
    throw new _exception2$2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
  } else {
    // Use the embedded version info since the runtime doesn't know about this revision yet
    throw new _exception2$2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
  }
}

function template(templateSpec, env) {
  /* istanbul ignore next */
  if (!env) {
    throw new _exception2$2['default']('No environment passed to template');
  }
  if (!templateSpec || !templateSpec.main) {
    throw new _exception2$2['default']('Unknown template object: ' + typeof templateSpec);
  }

  templateSpec.main.decorator = templateSpec.main_d;

  // Note: Using env.VM references rather than local var references throughout this section to allow
  // for external users to override these as pseudo-supported APIs.
  env.VM.checkRevision(templateSpec.compiler);

  // backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0)
  var templateWasPrecompiledWithCompilerV7 = templateSpec.compiler && templateSpec.compiler[0] === 7;

  function invokePartialWrapper(partial, context, options) {
    if (options.hash) {
      context = Utils.extend({}, context, options.hash);
      if (options.ids) {
        options.ids[0] = true;
      }
    }
    partial = env.VM.resolvePartial.call(this, partial, context, options);

    var extendedOptions = Utils.extend({}, options, {
      hooks: this.hooks,
      protoAccessControl: this.protoAccessControl
    });

    var result = env.VM.invokePartial.call(this, partial, context, extendedOptions);

    if (result == null && env.compile) {
      options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
      result = options.partials[options.name](context, extendedOptions);
    }
    if (result != null) {
      if (options.indent) {
        var lines = result.split('\n');
        for (var i = 0, l = lines.length; i < l; i++) {
          if (!lines[i] && i + 1 === l) {
            break;
          }

          lines[i] = options.indent + lines[i];
        }
        result = lines.join('\n');
      }
      return result;
    } else {
      throw new _exception2$2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
    }
  }

  // Just add water
  var container = {
    strict: function strict(obj, name, loc) {
      if (!obj || !(name in obj)) {
        throw new _exception2$2['default']('"' + name + '" not defined in ' + obj, {
          loc: loc
        });
      }
      return container.lookupProperty(obj, name);
    },
    lookupProperty: function lookupProperty(parent, propertyName) {
      var result = parent[propertyName];
      if (result == null) {
        return result;
      }
      if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
        return result;
      }

      if (protoAccess.resultIsAllowed(result, container.protoAccessControl, propertyName)) {
        return result;
      }
      return undefined;
    },
    lookup: function lookup(depths, name) {
      var len = depths.length;
      for (var i = 0; i < len; i++) {
        var result = depths[i] && container.lookupProperty(depths[i], name);
        if (result != null) {
          return depths[i][name];
        }
      }
    },
    lambda: function lambda(current, context) {
      return typeof current === 'function' ? current.call(context) : current;
    },

    escapeExpression: Utils.escapeExpression,
    invokePartial: invokePartialWrapper,

    fn: function fn(i) {
      var ret = templateSpec[i];
      ret.decorator = templateSpec[i + '_d'];
      return ret;
    },

    programs: [],
    program: function program(i, data, declaredBlockParams, blockParams, depths) {
      var programWrapper = this.programs[i],
          fn = this.fn(i);
      if (data || depths || blockParams || declaredBlockParams) {
        programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
      } else if (!programWrapper) {
        programWrapper = this.programs[i] = wrapProgram(this, i, fn);
      }
      return programWrapper;
    },

    data: function data(value, depth) {
      while (value && depth--) {
        value = value._parent;
      }
      return value;
    },
    mergeIfNeeded: function mergeIfNeeded(param, common) {
      var obj = param || common;

      if (param && common && param !== common) {
        obj = Utils.extend({}, common, param);
      }

      return obj;
    },
    // An empty object to use as replacement for null-contexts
    nullContext: Object.seal({}),

    noop: env.VM.noop,
    compilerInfo: templateSpec.compiler
  };

  function ret(context) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

    var data = options.data;

    ret._setup(options);
    if (!options.partial && templateSpec.useData) {
      data = initData(context, data);
    }
    var depths = undefined,
        blockParams = templateSpec.useBlockParams ? [] : undefined;
    if (templateSpec.useDepths) {
      if (options.depths) {
        depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
      } else {
        depths = [context];
      }
    }

    function main(context /*, options*/) {
      return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
    }

    main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams);
    return main(context, options);
  }

  ret.isTop = true;

  ret._setup = function (options) {
    if (!options.partial) {
      var mergedHelpers = Utils.extend({}, env.helpers, options.helpers);
      wrapHelpersToPassLookupProperty(mergedHelpers, container);
      container.helpers = mergedHelpers;

      if (templateSpec.usePartial) {
        // Use mergeIfNeeded here to prevent compiling global partials multiple times
        container.partials = container.mergeIfNeeded(options.partials, env.partials);
      }
      if (templateSpec.usePartial || templateSpec.useDecorators) {
        container.decorators = Utils.extend({}, env.decorators, options.decorators);
      }

      container.hooks = {};
      container.protoAccessControl = protoAccess.createProtoAccessControl(options);

      var keepHelperInHelpers = options.allowCallsToHelperMissing || templateWasPrecompiledWithCompilerV7;
      helpers$1.moveHelperToHooks(container, 'helperMissing', keepHelperInHelpers);
      helpers$1.moveHelperToHooks(container, 'blockHelperMissing', keepHelperInHelpers);
    } else {
      container.protoAccessControl = options.protoAccessControl; // internal option
      container.helpers = options.helpers;
      container.partials = options.partials;
      container.decorators = options.decorators;
      container.hooks = options.hooks;
    }
  };

  ret._child = function (i, data, blockParams, depths) {
    if (templateSpec.useBlockParams && !blockParams) {
      throw new _exception2$2['default']('must pass block params');
    }
    if (templateSpec.useDepths && !depths) {
      throw new _exception2$2['default']('must pass parent depths');
    }

    return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
  };
  return ret;
}

function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
  function prog(context) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

    var currentDepths = depths;
    if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) {
      currentDepths = [context].concat(depths);
    }

    return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths);
  }

  prog = executeDecorators(fn, prog, container, depths, data, blockParams);

  prog.program = i;
  prog.depth = depths ? depths.length : 0;
  prog.blockParams = declaredBlockParams || 0;
  return prog;
}

/**
 * This is currently part of the official API, therefore implementation details should not be changed.
 */

function resolvePartial(partial, context, options) {
  if (!partial) {
    if (options.name === '@partial-block') {
      partial = options.data['partial-block'];
    } else {
      partial = options.partials[options.name];
    }
  } else if (!partial.call && !options.name) {
    // This is a dynamic partial that returned a string
    options.name = partial;
    partial = options.partials[partial];
  }
  return partial;
}

function invokePartial(partial, context, options) {
  // Use the current closure context to save the partial-block if this partial
  var currentPartialBlock = options.data && options.data['partial-block'];
  options.partial = true;
  if (options.ids) {
    options.data.contextPath = options.ids[0] || options.data.contextPath;
  }

  var partialBlock = undefined;
  if (options.fn && options.fn !== noop) {
    (function () {
      options.data = base$1.createFrame(options.data);
      // Wrapper function to get access to currentPartialBlock from the closure
      var fn = options.fn;
      partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) {
        var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

        // Restore the partial-block from the closure for the execution of the block
        // i.e. the part inside the block of the partial call.
        options.data = base$1.createFrame(options.data);
        options.data['partial-block'] = currentPartialBlock;
        return fn(context, options);
      };
      if (fn.partials) {
        options.partials = Utils.extend({}, options.partials, fn.partials);
      }
    })();
  }

  if (partial === undefined && partialBlock) {
    partial = partialBlock;
  }

  if (partial === undefined) {
    throw new _exception2$2['default']('The partial ' + options.name + ' could not be found');
  } else if (partial instanceof Function) {
    return partial(context, options);
  }
}

function noop() {
  return '';
}

function initData(context, data) {
  if (!data || !('root' in data)) {
    data = data ? base$1.createFrame(data) : {};
    data.root = context;
  }
  return data;
}

function executeDecorators(fn, prog, container, depths, data, blockParams) {
  if (fn.decorator) {
    var props = {};
    prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths);
    Utils.extend(prog, props);
  }
  return prog;
}

function wrapHelpersToPassLookupProperty(mergedHelpers, container) {
  Object.keys(mergedHelpers).forEach(function (helperName) {
    var helper = mergedHelpers[helperName];
    mergedHelpers[helperName] = passLookupPropertyOption(helper, container);
  });
}

function passLookupPropertyOption(helper, container) {
  var lookupProperty = container.lookupProperty;
  return wrapHelper_1.wrapHelper(helper, function (options) {
    return Utils.extend({ lookupProperty: lookupProperty }, options);
  });
}


var runtime = /*#__PURE__*/Object.defineProperty({
	checkRevision: checkRevision_1,
	template: template_1,
	wrapProgram: wrapProgram_1,
	resolvePartial: resolvePartial_1,
	invokePartial: invokePartial_1,
	noop: noop_1
}, '__esModule', {value: true});

/* global globalThis */

var noConflict = createCommonjsModule(function (module, exports) {

exports.__esModule = true;

exports['default'] = function (Handlebars) {
  /* istanbul ignore next */
  // https://mathiasbynens.be/notes/globalthis
  (function () {
    if (typeof globalThis === 'object') return;
    Object.prototype.__defineGetter__('__magic__', function () {
      return this;
    });
    __magic__.globalThis = __magic__; // eslint-disable-line no-undef
    delete Object.prototype.__magic__;
  })();

  var $Handlebars = globalThis.Handlebars;

  /* istanbul ignore next */
  Handlebars.noConflict = function () {
    if (globalThis.Handlebars === Handlebars) {
      globalThis.Handlebars = $Handlebars;
    }
    return Handlebars;
  };
};

module.exports = exports['default'];

});

var handlebars_runtime = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

// istanbul ignore next

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }



var base = _interopRequireWildcard(base$1);

// Each of these augment the Handlebars object. No need to setup here.
// (This is done to easily share code between commonjs and browse envs)



var _handlebarsSafeString2 = _interopRequireDefault(safeString);



var _handlebarsException2 = _interopRequireDefault(exception);



var Utils = _interopRequireWildcard(utils);



var runtime$1 = _interopRequireWildcard(runtime);



var _handlebarsNoConflict2 = _interopRequireDefault(noConflict);

// For compatibility and usage outside of module systems, make the Handlebars object a namespace
function create() {
  var hb = new base.HandlebarsEnvironment();

  Utils.extend(hb, base);
  hb.SafeString = _handlebarsSafeString2['default'];
  hb.Exception = _handlebarsException2['default'];
  hb.Utils = Utils;
  hb.escapeExpression = Utils.escapeExpression;

  hb.VM = runtime$1;
  hb.template = function (spec) {
    return runtime$1.template(spec, hb);
  };

  return hb;
}

var inst = create();
inst.create = create;

_handlebarsNoConflict2['default'](inst);

inst['default'] = inst;

exports['default'] = inst;
module.exports = exports['default'];

});

var ast = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
var AST = {
  // Public API used to evaluate derived attributes regarding AST nodes
  helpers: {
    // a mustache is definitely a helper if:
    // * it is an eligible helper, and
    // * it has at least one parameter or hash segment
    helperExpression: function helperExpression(node) {
      return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash);
    },

    scopedId: function scopedId(path) {
      return (/^\.|this\b/.test(path.original)
      );
    },

    // an ID is simple if it only has one part, and that part is not
    // `..` or `this`.
    simpleId: function simpleId(path) {
      return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
    }
  }
};

// Must be exported as an object rather than the root of the module as the jison lexer
// must modify the object to operate properly.
exports['default'] = AST;
module.exports = exports['default'];

});

var parser$1 = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
var handlebars = (function () {
    var parser = { trace: function trace() {},
        yy: {},
        symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 },
        terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" },
        productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 0], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]],
        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {

            var $0 = $$.length - 1;
            switch (yystate) {
                case 1:
                    return $$[$0 - 1];
                case 2:
                    this.$ = yy.prepareProgram($$[$0]);
                    break;
                case 3:
                    this.$ = $$[$0];
                    break;
                case 4:
                    this.$ = $$[$0];
                    break;
                case 5:
                    this.$ = $$[$0];
                    break;
                case 6:
                    this.$ = $$[$0];
                    break;
                case 7:
                    this.$ = $$[$0];
                    break;
                case 8:
                    this.$ = $$[$0];
                    break;
                case 9:
                    this.$ = {
                        type: 'CommentStatement',
                        value: yy.stripComment($$[$0]),
                        strip: yy.stripFlags($$[$0], $$[$0]),
                        loc: yy.locInfo(this._$)
                    };

                    break;
                case 10:
                    this.$ = {
                        type: 'ContentStatement',
                        original: $$[$0],
                        value: $$[$0],
                        loc: yy.locInfo(this._$)
                    };

                    break;
                case 11:
                    this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
                    break;
                case 12:
                    this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] };
                    break;
                case 13:
                    this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$);
                    break;
                case 14:
                    this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$);
                    break;
                case 15:
                    this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
                    break;
                case 16:
                    this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
                    break;
                case 17:
                    this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
                    break;
                case 18:
                    this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] };
                    break;
                case 19:
                    var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$),
                        program = yy.prepareProgram([inverse], $$[$0 - 1].loc);
                    program.chained = true;

                    this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true };

                    break;
                case 20:
                    this.$ = $$[$0];
                    break;
                case 21:
                    this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) };
                    break;
                case 22:
                    this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
                    break;
                case 23:
                    this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
                    break;
                case 24:
                    this.$ = {
                        type: 'PartialStatement',
                        name: $$[$0 - 3],
                        params: $$[$0 - 2],
                        hash: $$[$0 - 1],
                        indent: '',
                        strip: yy.stripFlags($$[$0 - 4], $$[$0]),
                        loc: yy.locInfo(this._$)
                    };

                    break;
                case 25:
                    this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
                    break;
                case 26:
                    this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) };
                    break;
                case 27:
                    this.$ = $$[$0];
                    break;
                case 28:
                    this.$ = $$[$0];
                    break;
                case 29:
                    this.$ = {
                        type: 'SubExpression',
                        path: $$[$0 - 3],
                        params: $$[$0 - 2],
                        hash: $$[$0 - 1],
                        loc: yy.locInfo(this._$)
                    };

                    break;
                case 30:
                    this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) };
                    break;
                case 31:
                    this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) };
                    break;
                case 32:
                    this.$ = yy.id($$[$0 - 1]);
                    break;
                case 33:
                    this.$ = $$[$0];
                    break;
                case 34:
                    this.$ = $$[$0];
                    break;
                case 35:
                    this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) };
                    break;
                case 36:
                    this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) };
                    break;
                case 37:
                    this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) };
                    break;
                case 38:
                    this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) };
                    break;
                case 39:
                    this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) };
                    break;
                case 40:
                    this.$ = $$[$0];
                    break;
                case 41:
                    this.$ = $$[$0];
                    break;
                case 42:
                    this.$ = yy.preparePath(true, $$[$0], this._$);
                    break;
                case 43:
                    this.$ = yy.preparePath(false, $$[$0], this._$);
                    break;
                case 44:
                    $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2];
                    break;
                case 45:
                    this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }];
                    break;
                case 46:
                    this.$ = [];
                    break;
                case 47:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 48:
                    this.$ = [];
                    break;
                case 49:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 50:
                    this.$ = [];
                    break;
                case 51:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 58:
                    this.$ = [];
                    break;
                case 59:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 64:
                    this.$ = [];
                    break;
                case 65:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 70:
                    this.$ = [];
                    break;
                case 71:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 78:
                    this.$ = [];
                    break;
                case 79:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 82:
                    this.$ = [];
                    break;
                case 83:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 86:
                    this.$ = [];
                    break;
                case 87:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 90:
                    this.$ = [];
                    break;
                case 91:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 94:
                    this.$ = [];
                    break;
                case 95:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 98:
                    this.$ = [$$[$0]];
                    break;
                case 99:
                    $$[$0 - 1].push($$[$0]);
                    break;
                case 100:
                    this.$ = [$$[$0]];
                    break;
                case 101:
                    $$[$0 - 1].push($$[$0]);
                    break;
            }
        },
        table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 15: [2, 48], 17: 39, 18: [2, 48] }, { 20: 41, 56: 40, 64: 42, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 44, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 45, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 41, 56: 48, 64: 42, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 49, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 50] }, { 72: [1, 35], 86: 51 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 52, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 53, 38: 55, 39: [1, 57], 43: 56, 44: [1, 58], 45: 54, 47: [2, 54] }, { 28: 59, 43: 60, 44: [1, 58], 47: [2, 56] }, { 13: 62, 15: [1, 20], 18: [1, 61] }, { 33: [2, 86], 57: 63, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 64, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 65, 47: [1, 66] }, { 30: 67, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 68, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 69, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 70, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 74, 33: [2, 80], 50: 71, 63: 72, 64: 75, 65: [1, 43], 69: 73, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 79] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 50] }, { 20: 74, 53: 80, 54: [2, 84], 63: 81, 64: 75, 65: [1, 43], 69: 82, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 83, 47: [1, 66] }, { 47: [2, 55] }, { 4: 84, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 85, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 86, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 87, 47: [1, 66] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 74, 33: [2, 88], 58: 88, 63: 89, 64: 75, 65: [1, 43], 69: 90, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 91, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 92, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 31: 93, 33: [2, 60], 63: 94, 64: 75, 65: [1, 43], 69: 95, 70: 76, 71: 77, 72: [1, 78], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 33: [2, 66], 36: 96, 63: 97, 64: 75, 65: [1, 43], 69: 98, 70: 76, 71: 77, 72: [1, 78], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 22: 99, 23: [2, 52], 63: 100, 64: 75, 65: [1, 43], 69: 101, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 33: [2, 92], 62: 102, 63: 103, 64: 75, 65: [1, 43], 69: 104, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 105] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 106, 72: [1, 107], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 108], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 109] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 55, 39: [1, 57], 43: 56, 44: [1, 58], 45: 111, 46: 110, 47: [2, 76] }, { 33: [2, 70], 40: 112, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 113] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 74, 63: 115, 64: 75, 65: [1, 43], 67: 114, 68: [2, 96], 69: 116, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 117] }, { 32: 118, 33: [2, 62], 74: 119, 75: [1, 120] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 121, 74: 122, 75: [1, 120] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 123] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 124] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 108] }, { 20: 74, 63: 125, 64: 75, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 74, 33: [2, 72], 41: 126, 63: 127, 64: 75, 65: [1, 43], 69: 128, 70: 76, 71: 77, 72: [1, 78], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 129] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 130] }, { 33: [2, 63] }, { 72: [1, 132], 76: 131 }, { 33: [1, 133] }, { 33: [2, 69] }, { 15: [2, 12], 18: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 134, 74: 135, 75: [1, 120] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 137], 77: [1, 136] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 138] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }],
        defaultActions: { 4: [2, 1], 54: [2, 55], 56: [2, 20], 60: [2, 57], 73: [2, 81], 82: [2, 85], 86: [2, 18], 90: [2, 89], 101: [2, 53], 104: [2, 93], 110: [2, 19], 111: [2, 77], 116: [2, 97], 119: [2, 63], 122: [2, 69], 135: [2, 75], 136: [2, 32] },
        parseError: function parseError(str, hash) {
            throw new Error(str);
        },
        parse: function parse(input) {
            var self = this,
                stack = [0],
                vstack = [null],
                lstack = [],
                table = this.table,
                yytext = "",
                yylineno = 0,
                yyleng = 0;
            this.lexer.setInput(input);
            this.lexer.yy = this.yy;
            this.yy.lexer = this.lexer;
            this.yy.parser = this;
            if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {};
            var yyloc = this.lexer.yylloc;
            lstack.push(yyloc);
            var ranges = this.lexer.options && this.lexer.options.ranges;
            if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError;
            function lex() {
                var token;
                token = self.lexer.lex() || 1;
                if (typeof token !== "number") {
                    token = self.symbols_[token] || token;
                }
                return token;
            }
            var symbol,
                state,
                action,
                r,
                yyval = {},
                p,
                len,
                newState,
                expected;
            while (true) {
                state = stack[stack.length - 1];
                if (this.defaultActions[state]) {
                    action = this.defaultActions[state];
                } else {
                    if (symbol === null || typeof symbol == "undefined") {
                        symbol = lex();
                    }
                    action = table[state] && table[state][symbol];
                }
                if (typeof action === "undefined" || !action.length || !action[0]) {
                    var errStr = "";
                    {
                        expected = [];
                        for (p in table[state]) if (this.terminals_[p] && p > 2) {
                            expected.push("'" + this.terminals_[p] + "'");
                        }
                        if (this.lexer.showPosition) {
                            errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
                        } else {
                            errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
                        }
                        this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
                    }
                }
                if (action[0] instanceof Array && action.length > 1) {
                    throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
                }
                switch (action[0]) {
                    case 1:
                        stack.push(symbol);
                        vstack.push(this.lexer.yytext);
                        lstack.push(this.lexer.yylloc);
                        stack.push(action[1]);
                        symbol = null;
                        {
                            yyleng = this.lexer.yyleng;
                            yytext = this.lexer.yytext;
                            yylineno = this.lexer.yylineno;
                            yyloc = this.lexer.yylloc;
                        }
                        break;
                    case 2:
                        len = this.productions_[action[1]][1];
                        yyval.$ = vstack[vstack.length - len];
                        yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column };
                        if (ranges) {
                            yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
                        }
                        r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
                        if (typeof r !== "undefined") {
                            return r;
                        }
                        if (len) {
                            stack = stack.slice(0, -1 * len * 2);
                            vstack = vstack.slice(0, -1 * len);
                            lstack = lstack.slice(0, -1 * len);
                        }
                        stack.push(this.productions_[action[1]][0]);
                        vstack.push(yyval.$);
                        lstack.push(yyval._$);
                        newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
                        stack.push(newState);
                        break;
                    case 3:
                        return true;
                }
            }
            return true;
        }
    };
    /* Jison generated lexer */
    var lexer = (function () {
        var lexer = { EOF: 1,
            parseError: function parseError(str, hash) {
                if (this.yy.parser) {
                    this.yy.parser.parseError(str, hash);
                } else {
                    throw new Error(str);
                }
            },
            setInput: function setInput(input) {
                this._input = input;
                this._more = this._less = this.done = false;
                this.yylineno = this.yyleng = 0;
                this.yytext = this.matched = this.match = '';
                this.conditionStack = ['INITIAL'];
                this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
                if (this.options.ranges) this.yylloc.range = [0, 0];
                this.offset = 0;
                return this;
            },
            input: function input() {
                var ch = this._input[0];
                this.yytext += ch;
                this.yyleng++;
                this.offset++;
                this.match += ch;
                this.matched += ch;
                var lines = ch.match(/(?:\r\n?|\n).*/g);
                if (lines) {
                    this.yylineno++;
                    this.yylloc.last_line++;
                } else {
                    this.yylloc.last_column++;
                }
                if (this.options.ranges) this.yylloc.range[1]++;

                this._input = this._input.slice(1);
                return ch;
            },
            unput: function unput(ch) {
                var len = ch.length;
                var lines = ch.split(/(?:\r\n?|\n)/g);

                this._input = ch + this._input;
                this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
                //this.yyleng -= len;
                this.offset -= len;
                var oldLines = this.match.split(/(?:\r\n?|\n)/g);
                this.match = this.match.substr(0, this.match.length - 1);
                this.matched = this.matched.substr(0, this.matched.length - 1);

                if (lines.length - 1) this.yylineno -= lines.length - 1;
                var r = this.yylloc.range;

                this.yylloc = { first_line: this.yylloc.first_line,
                    last_line: this.yylineno + 1,
                    first_column: this.yylloc.first_column,
                    last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
                };

                if (this.options.ranges) {
                    this.yylloc.range = [r[0], r[0] + this.yyleng - len];
                }
                return this;
            },
            more: function more() {
                this._more = true;
                return this;
            },
            less: function less(n) {
                this.unput(this.match.slice(n));
            },
            pastInput: function pastInput() {
                var past = this.matched.substr(0, this.matched.length - this.match.length);
                return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
            },
            upcomingInput: function upcomingInput() {
                var next = this.match;
                if (next.length < 20) {
                    next += this._input.substr(0, 20 - next.length);
                }
                return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
            },
            showPosition: function showPosition() {
                var pre = this.pastInput();
                var c = new Array(pre.length + 1).join("-");
                return pre + this.upcomingInput() + "\n" + c + "^";
            },
            next: function next() {
                if (this.done) {
                    return this.EOF;
                }
                if (!this._input) this.done = true;

                var token, match, tempMatch, index, lines;
                if (!this._more) {
                    this.yytext = '';
                    this.match = '';
                }
                var rules = this._currentRules();
                for (var i = 0; i < rules.length; i++) {
                    tempMatch = this._input.match(this.rules[rules[i]]);
                    if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
                        match = tempMatch;
                        index = i;
                        if (!this.options.flex) break;
                    }
                }
                if (match) {
                    lines = match[0].match(/(?:\r\n?|\n).*/g);
                    if (lines) this.yylineno += lines.length;
                    this.yylloc = { first_line: this.yylloc.last_line,
                        last_line: this.yylineno + 1,
                        first_column: this.yylloc.last_column,
                        last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length };
                    this.yytext += match[0];
                    this.match += match[0];
                    this.matches = match;
                    this.yyleng = this.yytext.length;
                    if (this.options.ranges) {
                        this.yylloc.range = [this.offset, this.offset += this.yyleng];
                    }
                    this._more = false;
                    this._input = this._input.slice(match[0].length);
                    this.matched += match[0];
                    token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
                    if (this.done && this._input) this.done = false;
                    if (token) return token;else return;
                }
                if (this._input === "") {
                    return this.EOF;
                } else {
                    return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno });
                }
            },
            lex: function lex() {
                var r = this.next();
                if (typeof r !== 'undefined') {
                    return r;
                } else {
                    return this.lex();
                }
            },
            begin: function begin(condition) {
                this.conditionStack.push(condition);
            },
            popState: function popState() {
                return this.conditionStack.pop();
            },
            _currentRules: function _currentRules() {
                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
            },
            topState: function topState() {
                return this.conditionStack[this.conditionStack.length - 2];
            },
            pushState: function begin(condition) {
                this.begin(condition);
            } };
        lexer.options = {};
        lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {

            function strip(start, end) {
                return yy_.yytext = yy_.yytext.substring(start, yy_.yyleng - end + start);
            }
            switch ($avoiding_name_collisions) {
                case 0:
                    if (yy_.yytext.slice(-2) === "\\\\") {
                        strip(0, 1);
                        this.begin("mu");
                    } else if (yy_.yytext.slice(-1) === "\\") {
                        strip(0, 1);
                        this.begin("emu");
                    } else {
                        this.begin("mu");
                    }
                    if (yy_.yytext) return 15;

                    break;
                case 1:
                    return 15;
                case 2:
                    this.popState();
                    return 15;
                case 3:
                    this.begin('raw');return 15;
                case 4:
                    this.popState();
                    // Should be using `this.topState()` below, but it currently
                    // returns the second top instead of the first top. Opened an
                    // issue about it at https://github.com/zaach/jison/issues/291
                    if (this.conditionStack[this.conditionStack.length - 1] === 'raw') {
                        return 15;
                    } else {
                        strip(5, 9);
                        return 'END_RAW_BLOCK';
                    }
                case 5:
                    return 15;
                case 6:
                    this.popState();
                    return 14;
                case 7:
                    return 65;
                case 8:
                    return 68;
                case 9:
                    return 19;
                case 10:
                    this.popState();
                    this.begin('raw');
                    return 23;
                case 11:
                    return 55;
                case 12:
                    return 60;
                case 13:
                    return 29;
                case 14:
                    return 47;
                case 15:
                    this.popState();return 44;
                case 16:
                    this.popState();return 44;
                case 17:
                    return 34;
                case 18:
                    return 39;
                case 19:
                    return 51;
                case 20:
                    return 48;
                case 21:
                    this.unput(yy_.yytext);
                    this.popState();
                    this.begin('com');

                    break;
                case 22:
                    this.popState();
                    return 14;
                case 23:
                    return 48;
                case 24:
                    return 73;
                case 25:
                    return 72;
                case 26:
                    return 72;
                case 27:
                    return 87;
                case 28:
                    // ignore whitespace
                    break;
                case 29:
                    this.popState();return 54;
                case 30:
                    this.popState();return 33;
                case 31:
                    yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80;
                case 32:
                    yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80;
                case 33:
                    return 85;
                case 34:
                    return 82;
                case 35:
                    return 82;
                case 36:
                    return 83;
                case 37:
                    return 84;
                case 38:
                    return 81;
                case 39:
                    return 75;
                case 40:
                    return 77;
                case 41:
                    return 72;
                case 42:
                    yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72;
                case 43:
                    return 'INVALID';
                case 44:
                    return 5;
            }
        };
        lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]+?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/];
        lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } };
        return lexer;
    })();
    parser.lexer = lexer;
    function Parser() {
        this.yy = {};
    }Parser.prototype = parser;parser.Parser = Parser;
    return new Parser();
})();exports["default"] = handlebars;
module.exports = exports["default"];

});

var visitor = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _exception2 = _interopRequireDefault(exception);

function Visitor() {
  this.parents = [];
}

Visitor.prototype = {
  constructor: Visitor,
  mutating: false,

  // Visits a given value. If mutating, will replace the value if necessary.
  acceptKey: function acceptKey(node, name) {
    var value = this.accept(node[name]);
    if (this.mutating) {
      // Hacky sanity check: This may have a few false positives for type for the helper
      // methods but will generally do the right thing without a lot of overhead.
      if (value && !Visitor.prototype[value.type]) {
        throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
      }
      node[name] = value;
    }
  },

  // Performs an accept operation with added sanity check to ensure
  // required keys are not removed.
  acceptRequired: function acceptRequired(node, name) {
    this.acceptKey(node, name);

    if (!node[name]) {
      throw new _exception2['default'](node.type + ' requires ' + name);
    }
  },

  // Traverses a given array. If mutating, empty respnses will be removed
  // for child elements.
  acceptArray: function acceptArray(array) {
    for (var i = 0, l = array.length; i < l; i++) {
      this.acceptKey(array, i);

      if (!array[i]) {
        array.splice(i, 1);
        i--;
        l--;
      }
    }
  },

  accept: function accept(object) {
    if (!object) {
      return;
    }

    /* istanbul ignore next: Sanity code */
    if (!this[object.type]) {
      throw new _exception2['default']('Unknown type: ' + object.type, object);
    }

    if (this.current) {
      this.parents.unshift(this.current);
    }
    this.current = object;

    var ret = this[object.type](object);

    this.current = this.parents.shift();

    if (!this.mutating || ret) {
      return ret;
    } else if (ret !== false) {
      return object;
    }
  },

  Program: function Program(program) {
    this.acceptArray(program.body);
  },

  MustacheStatement: visitSubExpression,
  Decorator: visitSubExpression,

  BlockStatement: visitBlock,
  DecoratorBlock: visitBlock,

  PartialStatement: visitPartial,
  PartialBlockStatement: function PartialBlockStatement(partial) {
    visitPartial.call(this, partial);

    this.acceptKey(partial, 'program');
  },

  ContentStatement: function ContentStatement() /* content */{},
  CommentStatement: function CommentStatement() /* comment */{},

  SubExpression: visitSubExpression,

  PathExpression: function PathExpression() /* path */{},

  StringLiteral: function StringLiteral() /* string */{},
  NumberLiteral: function NumberLiteral() /* number */{},
  BooleanLiteral: function BooleanLiteral() /* bool */{},
  UndefinedLiteral: function UndefinedLiteral() /* literal */{},
  NullLiteral: function NullLiteral() /* literal */{},

  Hash: function Hash(hash) {
    this.acceptArray(hash.pairs);
  },
  HashPair: function HashPair(pair) {
    this.acceptRequired(pair, 'value');
  }
};

function visitSubExpression(mustache) {
  this.acceptRequired(mustache, 'path');
  this.acceptArray(mustache.params);
  this.acceptKey(mustache, 'hash');
}
function visitBlock(block) {
  visitSubExpression.call(this, block);

  this.acceptKey(block, 'program');
  this.acceptKey(block, 'inverse');
}
function visitPartial(partial) {
  this.acceptRequired(partial, 'name');
  this.acceptArray(partial.params);
  this.acceptKey(partial, 'hash');
}

exports['default'] = Visitor;
module.exports = exports['default'];

});

var whitespaceControl = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _visitor2 = _interopRequireDefault(visitor);

function WhitespaceControl() {
  var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

  this.options = options;
}
WhitespaceControl.prototype = new _visitor2['default']();

WhitespaceControl.prototype.Program = function (program) {
  var doStandalone = !this.options.ignoreStandalone;

  var isRoot = !this.isRootSeen;
  this.isRootSeen = true;

  var body = program.body;
  for (var i = 0, l = body.length; i < l; i++) {
    var current = body[i],
        strip = this.accept(current);

    if (!strip) {
      continue;
    }

    var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
        _isNextWhitespace = isNextWhitespace(body, i, isRoot),
        openStandalone = strip.openStandalone && _isPrevWhitespace,
        closeStandalone = strip.closeStandalone && _isNextWhitespace,
        inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;

    if (strip.close) {
      omitRight(body, i, true);
    }
    if (strip.open) {
      omitLeft(body, i, true);
    }

    if (doStandalone && inlineStandalone) {
      omitRight(body, i);

      if (omitLeft(body, i)) {
        // If we are on a standalone node, save the indent info for partials
        if (current.type === 'PartialStatement') {
          // Pull out the whitespace from the final line
          current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1];
        }
      }
    }
    if (doStandalone && openStandalone) {
      omitRight((current.program || current.inverse).body);

      // Strip out the previous content node if it's whitespace only
      omitLeft(body, i);
    }
    if (doStandalone && closeStandalone) {
      // Always strip the next node
      omitRight(body, i);

      omitLeft((current.inverse || current.program).body);
    }
  }

  return program;
};

WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) {
  this.accept(block.program);
  this.accept(block.inverse);

  // Find the inverse program that is involed with whitespace stripping.
  var program = block.program || block.inverse,
      inverse = block.program && block.inverse,
      firstInverse = inverse,
      lastInverse = inverse;

  if (inverse && inverse.chained) {
    firstInverse = inverse.body[0].program;

    // Walk the inverse chain to find the last inverse that is actually in the chain.
    while (lastInverse.chained) {
      lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
    }
  }

  var strip = {
    open: block.openStrip.open,
    close: block.closeStrip.close,

    // Determine the standalone candiacy. Basically flag our content as being possibly standalone
    // so our parent can determine if we actually are standalone
    openStandalone: isNextWhitespace(program.body),
    closeStandalone: isPrevWhitespace((firstInverse || program).body)
  };

  if (block.openStrip.close) {
    omitRight(program.body, null, true);
  }

  if (inverse) {
    var inverseStrip = block.inverseStrip;

    if (inverseStrip.open) {
      omitLeft(program.body, null, true);
    }

    if (inverseStrip.close) {
      omitRight(firstInverse.body, null, true);
    }
    if (block.closeStrip.open) {
      omitLeft(lastInverse.body, null, true);
    }

    // Find standalone else statments
    if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) {
      omitLeft(program.body);
      omitRight(firstInverse.body);
    }
  } else if (block.closeStrip.open) {
    omitLeft(program.body, null, true);
  }

  return strip;
};

WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) {
  return mustache.strip;
};

WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) {
  /* istanbul ignore next */
  var strip = node.strip || {};
  return {
    inlineStandalone: true,
    open: strip.open,
    close: strip.close
  };
};

function isPrevWhitespace(body, i, isRoot) {
  if (i === undefined) {
    i = body.length;
  }

  // Nodes that end with newlines are considered whitespace (but are special
  // cased for strip operations)
  var prev = body[i - 1],
      sibling = body[i - 2];
  if (!prev) {
    return isRoot;
  }

  if (prev.type === 'ContentStatement') {
    return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original);
  }
}
function isNextWhitespace(body, i, isRoot) {
  if (i === undefined) {
    i = -1;
  }

  var next = body[i + 1],
      sibling = body[i + 2];
  if (!next) {
    return isRoot;
  }

  if (next.type === 'ContentStatement') {
    return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original);
  }
}

// Marks the node to the right of the position as omitted.
// I.e. {{foo}}' ' will mark the ' ' node as omitted.
//
// If i is undefined, then the first child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
function omitRight(body, i, multiple) {
  var current = body[i == null ? 0 : i + 1];
  if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) {
    return;
  }

  var original = current.value;
  current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, '');
  current.rightStripped = current.value !== original;
}

// Marks the node to the left of the position as omitted.
// I.e. ' '{{foo}} will mark the ' ' node as omitted.
//
// If i is undefined then the last child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
function omitLeft(body, i, multiple) {
  var current = body[i == null ? body.length - 1 : i - 1];
  if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) {
    return;
  }

  // We omit the last node if it's whitespace only and not preceded by a non-content node.
  var original = current.value;
  current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, '');
  current.leftStripped = current.value !== original;
  return current.leftStripped;
}

exports['default'] = WhitespaceControl;
module.exports = exports['default'];

});

var SourceLocation_1 = SourceLocation;
var id_1 = id;
var stripFlags_1 = stripFlags;
var stripComment_1 = stripComment;
var preparePath_1 = preparePath;
var prepareMustache_1 = prepareMustache;
var prepareRawBlock_1 = prepareRawBlock;
var prepareBlock_1 = prepareBlock;
var prepareProgram_1 = prepareProgram;
var preparePartialBlock_1 = preparePartialBlock;
// istanbul ignore next

function _interopRequireDefault$2(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _exception2$1 = _interopRequireDefault$2(exception);

function validateClose(open, close) {
  close = close.path ? close.path.original : close;

  if (open.path.original !== close) {
    var errorNode = { loc: open.path.loc };

    throw new _exception2$1['default'](open.path.original + " doesn't match " + close, errorNode);
  }
}

function SourceLocation(source, locInfo) {
  this.source = source;
  this.start = {
    line: locInfo.first_line,
    column: locInfo.first_column
  };
  this.end = {
    line: locInfo.last_line,
    column: locInfo.last_column
  };
}

function id(token) {
  if (/^\[.*\]$/.test(token)) {
    return token.substring(1, token.length - 1);
  } else {
    return token;
  }
}

function stripFlags(open, close) {
  return {
    open: open.charAt(2) === '~',
    close: close.charAt(close.length - 3) === '~'
  };
}

function stripComment(comment) {
  return comment.replace(/^\{\{~?!-?-?/, '').replace(/-?-?~?\}\}$/, '');
}

function preparePath(data, parts, loc) {
  loc = this.locInfo(loc);

  var original = data ? '@' : '',
      dig = [],
      depth = 0;

  for (var i = 0, l = parts.length; i < l; i++) {
    var part = parts[i].part,

    // If we have [] syntax then we do not treat path references as operators,
    // i.e. foo.[this] resolves to approximately context.foo['this']
    isLiteral = parts[i].original !== part;
    original += (parts[i].separator || '') + part;

    if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
      if (dig.length > 0) {
        throw new _exception2$1['default']('Invalid path: ' + original, { loc: loc });
      } else if (part === '..') {
        depth++;
      }
    } else {
      dig.push(part);
    }
  }

  return {
    type: 'PathExpression',
    data: data,
    depth: depth,
    parts: dig,
    original: original,
    loc: loc
  };
}

function prepareMustache(path, params, hash, open, strip, locInfo) {
  // Must use charAt to support IE pre-10
  var escapeFlag = open.charAt(3) || open.charAt(2),
      escaped = escapeFlag !== '{' && escapeFlag !== '&';

  var decorator = /\*/.test(open);
  return {
    type: decorator ? 'Decorator' : 'MustacheStatement',
    path: path,
    params: params,
    hash: hash,
    escaped: escaped,
    strip: strip,
    loc: this.locInfo(locInfo)
  };
}

function prepareRawBlock(openRawBlock, contents, close, locInfo) {
  validateClose(openRawBlock, close);

  locInfo = this.locInfo(locInfo);
  var program = {
    type: 'Program',
    body: contents,
    strip: {},
    loc: locInfo
  };

  return {
    type: 'BlockStatement',
    path: openRawBlock.path,
    params: openRawBlock.params,
    hash: openRawBlock.hash,
    program: program,
    openStrip: {},
    inverseStrip: {},
    closeStrip: {},
    loc: locInfo
  };
}

function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
  if (close && close.path) {
    validateClose(openBlock, close);
  }

  var decorator = /\*/.test(openBlock.open);

  program.blockParams = openBlock.blockParams;

  var inverse = undefined,
      inverseStrip = undefined;

  if (inverseAndProgram) {
    if (decorator) {
      throw new _exception2$1['default']('Unexpected inverse block on decorator', inverseAndProgram);
    }

    if (inverseAndProgram.chain) {
      inverseAndProgram.program.body[0].closeStrip = close.strip;
    }

    inverseStrip = inverseAndProgram.strip;
    inverse = inverseAndProgram.program;
  }

  if (inverted) {
    inverted = inverse;
    inverse = program;
    program = inverted;
  }

  return {
    type: decorator ? 'DecoratorBlock' : 'BlockStatement',
    path: openBlock.path,
    params: openBlock.params,
    hash: openBlock.hash,
    program: program,
    inverse: inverse,
    openStrip: openBlock.strip,
    inverseStrip: inverseStrip,
    closeStrip: close && close.strip,
    loc: this.locInfo(locInfo)
  };
}

function prepareProgram(statements, loc) {
  if (!loc && statements.length) {
    var firstLoc = statements[0].loc,
        lastLoc = statements[statements.length - 1].loc;

    /* istanbul ignore else */
    if (firstLoc && lastLoc) {
      loc = {
        source: firstLoc.source,
        start: {
          line: firstLoc.start.line,
          column: firstLoc.start.column
        },
        end: {
          line: lastLoc.end.line,
          column: lastLoc.end.column
        }
      };
    }
  }

  return {
    type: 'Program',
    body: statements,
    strip: {},
    loc: loc
  };
}

function preparePartialBlock(open, program, close, locInfo) {
  validateClose(open, close);

  return {
    type: 'PartialBlockStatement',
    name: open.path,
    params: open.params,
    hash: open.hash,
    program: program,
    openStrip: open.strip,
    closeStrip: close && close.strip,
    loc: this.locInfo(locInfo)
  };
}


var helpers = /*#__PURE__*/Object.defineProperty({
	SourceLocation: SourceLocation_1,
	id: id_1,
	stripFlags: stripFlags_1,
	stripComment: stripComment_1,
	preparePath: preparePath_1,
	prepareMustache: prepareMustache_1,
	prepareRawBlock: prepareRawBlock_1,
	prepareBlock: prepareBlock_1,
	prepareProgram: prepareProgram_1,
	preparePartialBlock: preparePartialBlock_1
}, '__esModule', {value: true});

var parseWithoutProcessing_1 = parseWithoutProcessing;
var parse_1 = parse;
// istanbul ignore next

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }

// istanbul ignore next

function _interopRequireDefault$1(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _parser2 = _interopRequireDefault$1(parser$1);



var _whitespaceControl2 = _interopRequireDefault$1(whitespaceControl);



var Helpers = _interopRequireWildcard(helpers);



var parser = _parser2['default'];

var yy = {};
utils.extend(yy, Helpers);

function parseWithoutProcessing(input, options) {
  // Just return if an already-compiled AST was passed in.
  if (input.type === 'Program') {
    return input;
  }

  _parser2['default'].yy = yy;

  // Altering the shared object here, but this is ok as parser is a sync operation
  yy.locInfo = function (locInfo) {
    return new yy.SourceLocation(options && options.srcName, locInfo);
  };

  var ast = _parser2['default'].parse(input);

  return ast;
}

function parse(input, options) {
  var ast = parseWithoutProcessing(input, options);
  var strip = new _whitespaceControl2['default'](options);

  return strip.accept(ast);
}


var base = /*#__PURE__*/Object.defineProperty({
	parseWithoutProcessing: parseWithoutProcessing_1,
	parse: parse_1,
	parser: parser
}, '__esModule', {value: true});

/* eslint-disable new-cap */


var Compiler_1 = Compiler;
var precompile_1 = precompile;
var compile_1 = compile;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _exception2 = _interopRequireDefault(exception);





var _ast2 = _interopRequireDefault(ast);

var slice = [].slice;

function Compiler() {}

// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
// requires that context functions in blocks are evaluated by blockHelperMissing,
// and then proceed as if the resulting value was provided to blockHelperMissing.

Compiler.prototype = {
  compiler: Compiler,

  equals: function equals(other) {
    var len = this.opcodes.length;
    if (other.opcodes.length !== len) {
      return false;
    }

    for (var i = 0; i < len; i++) {
      var opcode = this.opcodes[i],
          otherOpcode = other.opcodes[i];
      if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
        return false;
      }
    }

    // We know that length is the same between the two arrays because they are directly tied
    // to the opcode behavior above.
    len = this.children.length;
    for (var i = 0; i < len; i++) {
      if (!this.children[i].equals(other.children[i])) {
        return false;
      }
    }

    return true;
  },

  guid: 0,

  compile: function compile(program, options) {
    this.sourceNode = [];
    this.opcodes = [];
    this.children = [];
    this.options = options;
    this.stringParams = options.stringParams;
    this.trackIds = options.trackIds;

    options.blockParams = options.blockParams || [];

    options.knownHelpers = utils.extend(Object.create(null), {
      helperMissing: true,
      blockHelperMissing: true,
      each: true,
      'if': true,
      unless: true,
      'with': true,
      log: true,
      lookup: true
    }, options.knownHelpers);

    return this.accept(program);
  },

  compileProgram: function compileProgram(program) {
    var childCompiler = new this.compiler(),
        // eslint-disable-line new-cap
    result = childCompiler.compile(program, this.options),
        guid = this.guid++;

    this.usePartial = this.usePartial || result.usePartial;

    this.children[guid] = result;
    this.useDepths = this.useDepths || result.useDepths;

    return guid;
  },

  accept: function accept(node) {
    /* istanbul ignore next: Sanity code */
    if (!this[node.type]) {
      throw new _exception2['default']('Unknown type: ' + node.type, node);
    }

    this.sourceNode.unshift(node);
    var ret = this[node.type](node);
    this.sourceNode.shift();
    return ret;
  },

  Program: function Program(program) {
    this.options.blockParams.unshift(program.blockParams);

    var body = program.body,
        bodyLength = body.length;
    for (var i = 0; i < bodyLength; i++) {
      this.accept(body[i]);
    }

    this.options.blockParams.shift();

    this.isSimple = bodyLength === 1;
    this.blockParams = program.blockParams ? program.blockParams.length : 0;

    return this;
  },

  BlockStatement: function BlockStatement(block) {
    transformLiteralToPath(block);

    var program = block.program,
        inverse = block.inverse;

    program = program && this.compileProgram(program);
    inverse = inverse && this.compileProgram(inverse);

    var type = this.classifySexpr(block);

    if (type === 'helper') {
      this.helperSexpr(block, program, inverse);
    } else if (type === 'simple') {
      this.simpleSexpr(block);

      // now that the simple mustache is resolved, we need to
      // evaluate it by executing `blockHelperMissing`
      this.opcode('pushProgram', program);
      this.opcode('pushProgram', inverse);
      this.opcode('emptyHash');
      this.opcode('blockValue', block.path.original);
    } else {
      this.ambiguousSexpr(block, program, inverse);

      // now that the simple mustache is resolved, we need to
      // evaluate it by executing `blockHelperMissing`
      this.opcode('pushProgram', program);
      this.opcode('pushProgram', inverse);
      this.opcode('emptyHash');
      this.opcode('ambiguousBlockValue');
    }

    this.opcode('append');
  },

  DecoratorBlock: function DecoratorBlock(decorator) {
    var program = decorator.program && this.compileProgram(decorator.program);
    var params = this.setupFullMustacheParams(decorator, program, undefined),
        path = decorator.path;

    this.useDecorators = true;
    this.opcode('registerDecorator', params.length, path.original);
  },

  PartialStatement: function PartialStatement(partial) {
    this.usePartial = true;

    var program = partial.program;
    if (program) {
      program = this.compileProgram(partial.program);
    }

    var params = partial.params;
    if (params.length > 1) {
      throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial);
    } else if (!params.length) {
      if (this.options.explicitPartialContext) {
        this.opcode('pushLiteral', 'undefined');
      } else {
        params.push({ type: 'PathExpression', parts: [], depth: 0 });
      }
    }

    var partialName = partial.name.original,
        isDynamic = partial.name.type === 'SubExpression';
    if (isDynamic) {
      this.accept(partial.name);
    }

    this.setupFullMustacheParams(partial, program, undefined, true);

    var indent = partial.indent || '';
    if (this.options.preventIndent && indent) {
      this.opcode('appendContent', indent);
      indent = '';
    }

    this.opcode('invokePartial', isDynamic, partialName, indent);
    this.opcode('append');
  },
  PartialBlockStatement: function PartialBlockStatement(partialBlock) {
    this.PartialStatement(partialBlock);
  },

  MustacheStatement: function MustacheStatement(mustache) {
    this.SubExpression(mustache);

    if (mustache.escaped && !this.options.noEscape) {
      this.opcode('appendEscaped');
    } else {
      this.opcode('append');
    }
  },
  Decorator: function Decorator(decorator) {
    this.DecoratorBlock(decorator);
  },

  ContentStatement: function ContentStatement(content) {
    if (content.value) {
      this.opcode('appendContent', content.value);
    }
  },

  CommentStatement: function CommentStatement() {},

  SubExpression: function SubExpression(sexpr) {
    transformLiteralToPath(sexpr);
    var type = this.classifySexpr(sexpr);

    if (type === 'simple') {
      this.simpleSexpr(sexpr);
    } else if (type === 'helper') {
      this.helperSexpr(sexpr);
    } else {
      this.ambiguousSexpr(sexpr);
    }
  },
  ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
    var path = sexpr.path,
        name = path.parts[0],
        isBlock = program != null || inverse != null;

    this.opcode('getContext', path.depth);

    this.opcode('pushProgram', program);
    this.opcode('pushProgram', inverse);

    path.strict = true;
    this.accept(path);

    this.opcode('invokeAmbiguous', name, isBlock);
  },

  simpleSexpr: function simpleSexpr(sexpr) {
    var path = sexpr.path;
    path.strict = true;
    this.accept(path);
    this.opcode('resolvePossibleLambda');
  },

  helperSexpr: function helperSexpr(sexpr, program, inverse) {
    var params = this.setupFullMustacheParams(sexpr, program, inverse),
        path = sexpr.path,
        name = path.parts[0];

    if (this.options.knownHelpers[name]) {
      this.opcode('invokeKnownHelper', params.length, name);
    } else if (this.options.knownHelpersOnly) {
      throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
    } else {
      path.strict = true;
      path.falsy = true;

      this.accept(path);
      this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path));
    }
  },

  PathExpression: function PathExpression(path) {
    this.addDepth(path.depth);
    this.opcode('getContext', path.depth);

    var name = path.parts[0],
        scoped = _ast2['default'].helpers.scopedId(path),
        blockParamId = !path.depth && !scoped && this.blockParamIndex(name);

    if (blockParamId) {
      this.opcode('lookupBlockParam', blockParamId, path.parts);
    } else if (!name) {
      // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
      this.opcode('pushContext');
    } else if (path.data) {
      this.options.data = true;
      this.opcode('lookupData', path.depth, path.parts, path.strict);
    } else {
      this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
    }
  },

  StringLiteral: function StringLiteral(string) {
    this.opcode('pushString', string.value);
  },

  NumberLiteral: function NumberLiteral(number) {
    this.opcode('pushLiteral', number.value);
  },

  BooleanLiteral: function BooleanLiteral(bool) {
    this.opcode('pushLiteral', bool.value);
  },

  UndefinedLiteral: function UndefinedLiteral() {
    this.opcode('pushLiteral', 'undefined');
  },

  NullLiteral: function NullLiteral() {
    this.opcode('pushLiteral', 'null');
  },

  Hash: function Hash(hash) {
    var pairs = hash.pairs,
        i = 0,
        l = pairs.length;

    this.opcode('pushHash');

    for (; i < l; i++) {
      this.pushParam(pairs[i].value);
    }
    while (i--) {
      this.opcode('assignToHash', pairs[i].key);
    }
    this.opcode('popHash');
  },

  // HELPERS
  opcode: function opcode(name) {
    this.opcodes.push({
      opcode: name,
      args: slice.call(arguments, 1),
      loc: this.sourceNode[0].loc
    });
  },

  addDepth: function addDepth(depth) {
    if (!depth) {
      return;
    }

    this.useDepths = true;
  },

  classifySexpr: function classifySexpr(sexpr) {
    var isSimple = _ast2['default'].helpers.simpleId(sexpr.path);

    var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);

    // a mustache is an eligible helper if:
    // * its id is simple (a single part, not `this` or `..`)
    var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr);

    // if a mustache is an eligible helper but not a definite
    // helper, it is ambiguous, and will be resolved in a later
    // pass or at runtime.
    var isEligible = !isBlockParam && (isHelper || isSimple);

    // if ambiguous, we can possibly resolve the ambiguity now
    // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
    if (isEligible && !isHelper) {
      var _name = sexpr.path.parts[0],
          options = this.options;
      if (options.knownHelpers[_name]) {
        isHelper = true;
      } else if (options.knownHelpersOnly) {
        isEligible = false;
      }
    }

    if (isHelper) {
      return 'helper';
    } else if (isEligible) {
      return 'ambiguous';
    } else {
      return 'simple';
    }
  },

  pushParams: function pushParams(params) {
    for (var i = 0, l = params.length; i < l; i++) {
      this.pushParam(params[i]);
    }
  },

  pushParam: function pushParam(val) {
    var value = val.value != null ? val.value : val.original || '';

    if (this.stringParams) {
      if (value.replace) {
        value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.');
      }

      if (val.depth) {
        this.addDepth(val.depth);
      }
      this.opcode('getContext', val.depth || 0);
      this.opcode('pushStringParam', value, val.type);

      if (val.type === 'SubExpression') {
        // SubExpressions get evaluated and passed in
        // in string params mode.
        this.accept(val);
      }
    } else {
      if (this.trackIds) {
        var blockParamIndex = undefined;
        if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) {
          blockParamIndex = this.blockParamIndex(val.parts[0]);
        }
        if (blockParamIndex) {
          var blockParamChild = val.parts.slice(1).join('.');
          this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
        } else {
          value = val.original || value;
          if (value.replace) {
            value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, '');
          }

          this.opcode('pushId', val.type, value);
        }
      }
      this.accept(val);
    }
  },

  setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) {
    var params = sexpr.params;
    this.pushParams(params);

    this.opcode('pushProgram', program);
    this.opcode('pushProgram', inverse);

    if (sexpr.hash) {
      this.accept(sexpr.hash);
    } else {
      this.opcode('emptyHash', omitEmpty);
    }

    return params;
  },

  blockParamIndex: function blockParamIndex(name) {
    for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
      var blockParams = this.options.blockParams[depth],
          param = blockParams && utils.indexOf(blockParams, name);
      if (blockParams && param >= 0) {
        return [depth, param];
      }
    }
  }
};

function precompile(input, options, env) {
  if (input == null || typeof input !== 'string' && input.type !== 'Program') {
    throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
  }

  options = options || {};
  if (!('data' in options)) {
    options.data = true;
  }
  if (options.compat) {
    options.useDepths = true;
  }

  var ast = env.parse(input, options),
      environment = new env.Compiler().compile(ast, options);
  return new env.JavaScriptCompiler().compile(environment, options);
}

function compile(input, options, env) {
  if (options === undefined) options = {};

  if (input == null || typeof input !== 'string' && input.type !== 'Program') {
    throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
  }

  options = utils.extend({}, options);
  if (!('data' in options)) {
    options.data = true;
  }
  if (options.compat) {
    options.useDepths = true;
  }

  var compiled = undefined;

  function compileInput() {
    var ast = env.parse(input, options),
        environment = new env.Compiler().compile(ast, options),
        templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
    return env.template(templateSpec);
  }

  // Template is only compiled on first use and cached after that point.
  function ret(context, execOptions) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled.call(this, context, execOptions);
  }
  ret._setup = function (setupOptions) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled._setup(setupOptions);
  };
  ret._child = function (i, data, blockParams, depths) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled._child(i, data, blockParams, depths);
  };
  return ret;
}

function argEquals(a, b) {
  if (a === b) {
    return true;
  }

  if (utils.isArray(a) && utils.isArray(b) && a.length === b.length) {
    for (var i = 0; i < a.length; i++) {
      if (!argEquals(a[i], b[i])) {
        return false;
      }
    }
    return true;
  }
}

function transformLiteralToPath(sexpr) {
  if (!sexpr.path.parts) {
    var literal = sexpr.path;
    // Casting to string here to make false and 0 literal values play nicely with the rest
    // of the system.
    sexpr.path = {
      type: 'PathExpression',
      data: false,
      depth: 0,
      parts: [literal.original + ''],
      original: literal.original + '',
      loc: literal.loc
    };
  }
}


var compiler = /*#__PURE__*/Object.defineProperty({
	Compiler: Compiler_1,
	precompile: precompile_1,
	compile: compile_1
}, '__esModule', {value: true});

/* -*- Mode: js; js-indent-level: 2; -*- */
/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');

/**
 * Encode an integer in the range of 0 to 63 to a single base 64 digit.
 */
var encode$1 = function (number) {
  if (0 <= number && number < intToCharMap.length) {
    return intToCharMap[number];
  }
  throw new TypeError("Must be between 0 and 63: " + number);
};

/**
 * Decode a single base 64 character code digit to an integer. Returns -1 on
 * failure.
 */
var decode$1 = function (charCode) {
  var bigA = 65;     // 'A'
  var bigZ = 90;     // 'Z'

  var littleA = 97;  // 'a'
  var littleZ = 122; // 'z'

  var zero = 48;     // '0'
  var nine = 57;     // '9'

  var plus = 43;     // '+'
  var slash = 47;    // '/'

  var littleOffset = 26;
  var numberOffset = 52;

  // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  if (bigA <= charCode && charCode <= bigZ) {
    return (charCode - bigA);
  }

  // 26 - 51: abcdefghijklmnopqrstuvwxyz
  if (littleA <= charCode && charCode <= littleZ) {
    return (charCode - littleA + littleOffset);
  }

  // 52 - 61: 0123456789
  if (zero <= charCode && charCode <= nine) {
    return (charCode - zero + numberOffset);
  }

  // 62: +
  if (charCode == plus) {
    return 62;
  }

  // 63: /
  if (charCode == slash) {
    return 63;
  }

  // Invalid base64 digit.
  return -1;
};

var base64 = {
	encode: encode$1,
	decode: decode$1
};

/* -*- Mode: js; js-indent-level: 2; -*- */

/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 *
 * Based on the Base 64 VLQ implementation in Closure Compiler:
 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
 *
 * Copyright 2011 The Closure Compiler Authors. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of Google Inc. nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */



// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
// the next four bits are the actual value, and the 6th bit is the
// continuation bit. The continuation bit tells us whether there are more
// digits in this value following this digit.
//
//   Continuation
//   |    Sign
//   |    |
//   V    V
//   101011

var VLQ_BASE_SHIFT = 5;

// binary: 100000
var VLQ_BASE = 1 << VLQ_BASE_SHIFT;

// binary: 011111
var VLQ_BASE_MASK = VLQ_BASE - 1;

// binary: 100000
var VLQ_CONTINUATION_BIT = VLQ_BASE;

/**
 * Converts from a two-complement value to a value where the sign bit is
 * placed in the least significant bit.  For example, as decimals:
 *   1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
 *   2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
 */
function toVLQSigned(aValue) {
  return aValue < 0
    ? ((-aValue) << 1) + 1
    : (aValue << 1) + 0;
}

/**
 * Converts to a two-complement value from a value where the sign bit is
 * placed in the least significant bit.  For example, as decimals:
 *   2 (10 binary) becomes 1, 3 (11 binary) becomes -1
 *   4 (100 binary) becomes 2, 5 (101 binary) becomes -2
 */
function fromVLQSigned(aValue) {
  var isNegative = (aValue & 1) === 1;
  var shifted = aValue >> 1;
  return isNegative
    ? -shifted
    : shifted;
}

/**
 * Returns the base 64 VLQ encoded value.
 */
var encode = function base64VLQ_encode(aValue) {
  var encoded = "";
  var digit;

  var vlq = toVLQSigned(aValue);

  do {
    digit = vlq & VLQ_BASE_MASK;
    vlq >>>= VLQ_BASE_SHIFT;
    if (vlq > 0) {
      // There are still more digits in this value, so we must make sure the
      // continuation bit is marked.
      digit |= VLQ_CONTINUATION_BIT;
    }
    encoded += base64.encode(digit);
  } while (vlq > 0);

  return encoded;
};

/**
 * Decodes the next base 64 VLQ value from the given string and returns the
 * value and the rest of the string via the out parameter.
 */
var decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
  var strLen = aStr.length;
  var result = 0;
  var shift = 0;
  var continuation, digit;

  do {
    if (aIndex >= strLen) {
      throw new Error("Expected more digits in base 64 VLQ value.");
    }

    digit = base64.decode(aStr.charCodeAt(aIndex++));
    if (digit === -1) {
      throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
    }

    continuation = !!(digit & VLQ_CONTINUATION_BIT);
    digit &= VLQ_BASE_MASK;
    result = result + (digit << shift);
    shift += VLQ_BASE_SHIFT;
  } while (continuation);

  aOutParam.value = fromVLQSigned(result);
  aOutParam.rest = aIndex;
};

var base64Vlq = {
	encode: encode,
	decode: decode
};

/* -*- Mode: js; js-indent-level: 2; -*- */

var util = createCommonjsModule(function (module, exports) {
/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

/**
 * This is a helper function for getting values from parameter/options
 * objects.
 *
 * @param args The object we are extracting values from
 * @param name The name of the property we are getting.
 * @param defaultValue An optional value to return if the property is missing
 * from the object. If this is not specified and the property is missing, an
 * error will be thrown.
 */
function getArg(aArgs, aName, aDefaultValue) {
  if (aName in aArgs) {
    return aArgs[aName];
  } else if (arguments.length === 3) {
    return aDefaultValue;
  } else {
    throw new Error('"' + aName + '" is a required argument.');
  }
}
exports.getArg = getArg;

var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;
var dataUrlRegexp = /^data:.+\,.+$/;

function urlParse(aUrl) {
  var match = aUrl.match(urlRegexp);
  if (!match) {
    return null;
  }
  return {
    scheme: match[1],
    auth: match[2],
    host: match[3],
    port: match[4],
    path: match[5]
  };
}
exports.urlParse = urlParse;

function urlGenerate(aParsedUrl) {
  var url = '';
  if (aParsedUrl.scheme) {
    url += aParsedUrl.scheme + ':';
  }
  url += '//';
  if (aParsedUrl.auth) {
    url += aParsedUrl.auth + '@';
  }
  if (aParsedUrl.host) {
    url += aParsedUrl.host;
  }
  if (aParsedUrl.port) {
    url += ":" + aParsedUrl.port;
  }
  if (aParsedUrl.path) {
    url += aParsedUrl.path;
  }
  return url;
}
exports.urlGenerate = urlGenerate;

/**
 * Normalizes a path, or the path portion of a URL:
 *
 * - Replaces consecutive slashes with one slash.
 * - Removes unnecessary '.' parts.
 * - Removes unnecessary '<dir>/..' parts.
 *
 * Based on code in the Node.js 'path' core module.
 *
 * @param aPath The path or url to normalize.
 */
function normalize(aPath) {
  var path = aPath;
  var url = urlParse(aPath);
  if (url) {
    if (!url.path) {
      return aPath;
    }
    path = url.path;
  }
  var isAbsolute = exports.isAbsolute(path);

  var parts = path.split(/\/+/);
  for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
    part = parts[i];
    if (part === '.') {
      parts.splice(i, 1);
    } else if (part === '..') {
      up++;
    } else if (up > 0) {
      if (part === '') {
        // The first part is blank if the path is absolute. Trying to go
        // above the root is a no-op. Therefore we can remove all '..' parts
        // directly after the root.
        parts.splice(i + 1, up);
        up = 0;
      } else {
        parts.splice(i, 2);
        up--;
      }
    }
  }
  path = parts.join('/');

  if (path === '') {
    path = isAbsolute ? '/' : '.';
  }

  if (url) {
    url.path = path;
    return urlGenerate(url);
  }
  return path;
}
exports.normalize = normalize;

/**
 * Joins two paths/URLs.
 *
 * @param aRoot The root path or URL.
 * @param aPath The path or URL to be joined with the root.
 *
 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
 *   scheme-relative URL: Then the scheme of aRoot, if any, is prepended
 *   first.
 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion
 *   is updated with the result and aRoot is returned. Otherwise the result
 *   is returned.
 *   - If aPath is absolute, the result is aPath.
 *   - Otherwise the two paths are joined with a slash.
 * - Joining for example 'http://' and 'www.example.com' is also supported.
 */
function join(aRoot, aPath) {
  if (aRoot === "") {
    aRoot = ".";
  }
  if (aPath === "") {
    aPath = ".";
  }
  var aPathUrl = urlParse(aPath);
  var aRootUrl = urlParse(aRoot);
  if (aRootUrl) {
    aRoot = aRootUrl.path || '/';
  }

  // `join(foo, '//www.example.org')`
  if (aPathUrl && !aPathUrl.scheme) {
    if (aRootUrl) {
      aPathUrl.scheme = aRootUrl.scheme;
    }
    return urlGenerate(aPathUrl);
  }

  if (aPathUrl || aPath.match(dataUrlRegexp)) {
    return aPath;
  }

  // `join('http://', 'www.example.com')`
  if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
    aRootUrl.host = aPath;
    return urlGenerate(aRootUrl);
  }

  var joined = aPath.charAt(0) === '/'
    ? aPath
    : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);

  if (aRootUrl) {
    aRootUrl.path = joined;
    return urlGenerate(aRootUrl);
  }
  return joined;
}
exports.join = join;

exports.isAbsolute = function (aPath) {
  return aPath.charAt(0) === '/' || urlRegexp.test(aPath);
};

/**
 * Make a path relative to a URL or another path.
 *
 * @param aRoot The root path or URL.
 * @param aPath The path or URL to be made relative to aRoot.
 */
function relative(aRoot, aPath) {
  if (aRoot === "") {
    aRoot = ".";
  }

  aRoot = aRoot.replace(/\/$/, '');

  // It is possible for the path to be above the root. In this case, simply
  // checking whether the root is a prefix of the path won't work. Instead, we
  // need to remove components from the root one by one, until either we find
  // a prefix that fits, or we run out of components to remove.
  var level = 0;
  while (aPath.indexOf(aRoot + '/') !== 0) {
    var index = aRoot.lastIndexOf("/");
    if (index < 0) {
      return aPath;
    }

    // If the only part of the root that is left is the scheme (i.e. http://,
    // file:///, etc.), one or more slashes (/), or simply nothing at all, we
    // have exhausted all components, so the path is not relative to the root.
    aRoot = aRoot.slice(0, index);
    if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
      return aPath;
    }

    ++level;
  }

  // Make sure we add a "../" for each component we removed from the root.
  return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
}
exports.relative = relative;

var supportsNullProto = (function () {
  var obj = Object.create(null);
  return !('__proto__' in obj);
}());

function identity (s) {
  return s;
}

/**
 * Because behavior goes wacky when you set `__proto__` on objects, we
 * have to prefix all the strings in our set with an arbitrary character.
 *
 * See https://github.com/mozilla/source-map/pull/31 and
 * https://github.com/mozilla/source-map/issues/30
 *
 * @param String aStr
 */
function toSetString(aStr) {
  if (isProtoString(aStr)) {
    return '$' + aStr;
  }

  return aStr;
}
exports.toSetString = supportsNullProto ? identity : toSetString;

function fromSetString(aStr) {
  if (isProtoString(aStr)) {
    return aStr.slice(1);
  }

  return aStr;
}
exports.fromSetString = supportsNullProto ? identity : fromSetString;

function isProtoString(s) {
  if (!s) {
    return false;
  }

  var length = s.length;

  if (length < 9 /* "__proto__".length */) {
    return false;
  }

  if (s.charCodeAt(length - 1) !== 95  /* '_' */ ||
      s.charCodeAt(length - 2) !== 95  /* '_' */ ||
      s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
      s.charCodeAt(length - 4) !== 116 /* 't' */ ||
      s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
      s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
      s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
      s.charCodeAt(length - 8) !== 95  /* '_' */ ||
      s.charCodeAt(length - 9) !== 95  /* '_' */) {
    return false;
  }

  for (var i = length - 10; i >= 0; i--) {
    if (s.charCodeAt(i) !== 36 /* '$' */) {
      return false;
    }
  }

  return true;
}

/**
 * Comparator between two mappings where the original positions are compared.
 *
 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
 * mappings with the same original source/line/column, but different generated
 * line and column the same. Useful when searching for a mapping with a
 * stubbed out mapping.
 */
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
  var cmp = strcmp(mappingA.source, mappingB.source);
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.originalLine - mappingB.originalLine;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.originalColumn - mappingB.originalColumn;
  if (cmp !== 0 || onlyCompareOriginal) {
    return cmp;
  }

  cmp = mappingA.generatedColumn - mappingB.generatedColumn;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.generatedLine - mappingB.generatedLine;
  if (cmp !== 0) {
    return cmp;
  }

  return strcmp(mappingA.name, mappingB.name);
}
exports.compareByOriginalPositions = compareByOriginalPositions;

/**
 * Comparator between two mappings with deflated source and name indices where
 * the generated positions are compared.
 *
 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
 * mappings with the same generated line and column, but different
 * source/name/original line and column the same. Useful when searching for a
 * mapping with a stubbed out mapping.
 */
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
  var cmp = mappingA.generatedLine - mappingB.generatedLine;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.generatedColumn - mappingB.generatedColumn;
  if (cmp !== 0 || onlyCompareGenerated) {
    return cmp;
  }

  cmp = strcmp(mappingA.source, mappingB.source);
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.originalLine - mappingB.originalLine;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.originalColumn - mappingB.originalColumn;
  if (cmp !== 0) {
    return cmp;
  }

  return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;

function strcmp(aStr1, aStr2) {
  if (aStr1 === aStr2) {
    return 0;
  }

  if (aStr1 === null) {
    return 1; // aStr2 !== null
  }

  if (aStr2 === null) {
    return -1; // aStr1 !== null
  }

  if (aStr1 > aStr2) {
    return 1;
  }

  return -1;
}

/**
 * Comparator between two mappings with inflated source and name strings where
 * the generated positions are compared.
 */
function compareByGeneratedPositionsInflated(mappingA, mappingB) {
  var cmp = mappingA.generatedLine - mappingB.generatedLine;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.generatedColumn - mappingB.generatedColumn;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = strcmp(mappingA.source, mappingB.source);
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.originalLine - mappingB.originalLine;
  if (cmp !== 0) {
    return cmp;
  }

  cmp = mappingA.originalColumn - mappingB.originalColumn;
  if (cmp !== 0) {
    return cmp;
  }

  return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;

/**
 * Strip any JSON XSSI avoidance prefix from the string (as documented
 * in the source maps specification), and then parse the string as
 * JSON.
 */
function parseSourceMapInput(str) {
  return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ''));
}
exports.parseSourceMapInput = parseSourceMapInput;

/**
 * Compute the URL of a source given the the source root, the source's
 * URL, and the source map's URL.
 */
function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
  sourceURL = sourceURL || '';

  if (sourceRoot) {
    // This follows what Chrome does.
    if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') {
      sourceRoot += '/';
    }
    // The spec says:
    //   Line 4: An optional source root, useful for relocating source
    //   files on a server or removing repeated values in the
    //   “sources” entry.  This value is prepended to the individual
    //   entries in the “source” field.
    sourceURL = sourceRoot + sourceURL;
  }

  // Historically, SourceMapConsumer did not take the sourceMapURL as
  // a parameter.  This mode is still somewhat supported, which is why
  // this code block is conditional.  However, it's preferable to pass
  // the source map URL to SourceMapConsumer, so that this function
  // can implement the source URL resolution algorithm as outlined in
  // the spec.  This block is basically the equivalent of:
  //    new URL(sourceURL, sourceMapURL).toString()
  // ... except it avoids using URL, which wasn't available in the
  // older releases of node still supported by this library.
  //
  // The spec says:
  //   If the sources are not absolute URLs after prepending of the
  //   “sourceRoot”, the sources are resolved relative to the
  //   SourceMap (like resolving script src in a html document).
  if (sourceMapURL) {
    var parsed = urlParse(sourceMapURL);
    if (!parsed) {
      throw new Error("sourceMapURL could not be parsed");
    }
    if (parsed.path) {
      // Strip the last path component, but keep the "/".
      var index = parsed.path.lastIndexOf('/');
      if (index >= 0) {
        parsed.path = parsed.path.substring(0, index + 1);
      }
    }
    sourceURL = join(urlGenerate(parsed), sourceURL);
  }

  return normalize(sourceURL);
}
exports.computeSourceURL = computeSourceURL;
});

/* -*- Mode: js; js-indent-level: 2; -*- */

/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */


var has = Object.prototype.hasOwnProperty;
var hasNativeMap = typeof Map !== "undefined";

/**
 * A data structure which is a combination of an array and a set. Adding a new
 * member is O(1), testing for membership is O(1), and finding the index of an
 * element is O(1). Removing elements from the set is not supported. Only
 * strings are supported for membership.
 */
function ArraySet$2() {
  this._array = [];
  this._set = hasNativeMap ? new Map() : Object.create(null);
}

/**
 * Static method for creating ArraySet instances from an existing array.
 */
ArraySet$2.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
  var set = new ArraySet$2();
  for (var i = 0, len = aArray.length; i < len; i++) {
    set.add(aArray[i], aAllowDuplicates);
  }
  return set;
};

/**
 * Return how many unique items are in this ArraySet. If duplicates have been
 * added, than those do not count towards the size.
 *
 * @returns Number
 */
ArraySet$2.prototype.size = function ArraySet_size() {
  return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;
};

/**
 * Add the given string to this set.
 *
 * @param String aStr
 */
ArraySet$2.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
  var sStr = hasNativeMap ? aStr : util.toSetString(aStr);
  var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);
  var idx = this._array.length;
  if (!isDuplicate || aAllowDuplicates) {
    this._array.push(aStr);
  }
  if (!isDuplicate) {
    if (hasNativeMap) {
      this._set.set(aStr, idx);
    } else {
      this._set[sStr] = idx;
    }
  }
};

/**
 * Is the given string a member of this set?
 *
 * @param String aStr
 */
ArraySet$2.prototype.has = function ArraySet_has(aStr) {
  if (hasNativeMap) {
    return this._set.has(aStr);
  } else {
    var sStr = util.toSetString(aStr);
    return has.call(this._set, sStr);
  }
};

/**
 * What is the index of the given string in the array?
 *
 * @param String aStr
 */
ArraySet$2.prototype.indexOf = function ArraySet_indexOf(aStr) {
  if (hasNativeMap) {
    var idx = this._set.get(aStr);
    if (idx >= 0) {
        return idx;
    }
  } else {
    var sStr = util.toSetString(aStr);
    if (has.call(this._set, sStr)) {
      return this._set[sStr];
    }
  }

  throw new Error('"' + aStr + '" is not in the set.');
};

/**
 * What is the element at the given index?
 *
 * @param Number aIdx
 */
ArraySet$2.prototype.at = function ArraySet_at(aIdx) {
  if (aIdx >= 0 && aIdx < this._array.length) {
    return this._array[aIdx];
  }
  throw new Error('No element indexed by ' + aIdx);
};

/**
 * Returns the array representation of this set (which has the proper indices
 * indicated by indexOf). Note that this is a copy of the internal array used
 * for storing the members so that no one can mess with internal state.
 */
ArraySet$2.prototype.toArray = function ArraySet_toArray() {
  return this._array.slice();
};

var ArraySet_1 = ArraySet$2;

var arraySet = {
	ArraySet: ArraySet_1
};

/* -*- Mode: js; js-indent-level: 2; -*- */

/*
 * Copyright 2014 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */



/**
 * Determine whether mappingB is after mappingA with respect to generated
 * position.
 */
function generatedPositionAfter(mappingA, mappingB) {
  // Optimized for most common case
  var lineA = mappingA.generatedLine;
  var lineB = mappingB.generatedLine;
  var columnA = mappingA.generatedColumn;
  var columnB = mappingB.generatedColumn;
  return lineB > lineA || lineB == lineA && columnB >= columnA ||
         util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
}

/**
 * A data structure to provide a sorted view of accumulated mappings in a
 * performance conscious manner. It trades a neglibable overhead in general
 * case for a large speedup in case of mappings being added in order.
 */
function MappingList$1() {
  this._array = [];
  this._sorted = true;
  // Serves as infimum
  this._last = {generatedLine: -1, generatedColumn: 0};
}

/**
 * Iterate through internal items. This method takes the same arguments that
 * `Array.prototype.forEach` takes.
 *
 * NOTE: The order of the mappings is NOT guaranteed.
 */
MappingList$1.prototype.unsortedForEach =
  function MappingList_forEach(aCallback, aThisArg) {
    this._array.forEach(aCallback, aThisArg);
  };

/**
 * Add the given source mapping.
 *
 * @param Object aMapping
 */
MappingList$1.prototype.add = function MappingList_add(aMapping) {
  if (generatedPositionAfter(this._last, aMapping)) {
    this._last = aMapping;
    this._array.push(aMapping);
  } else {
    this._sorted = false;
    this._array.push(aMapping);
  }
};

/**
 * Returns the flat, sorted array of mappings. The mappings are sorted by
 * generated position.
 *
 * WARNING: This method returns internal data without copying, for
 * performance. The return value must NOT be mutated, and should be treated as
 * an immutable borrow. If you want to take ownership, you must make your own
 * copy.
 */
MappingList$1.prototype.toArray = function MappingList_toArray() {
  if (!this._sorted) {
    this._array.sort(util.compareByGeneratedPositionsInflated);
    this._sorted = true;
  }
  return this._array;
};

var MappingList_1 = MappingList$1;

var mappingList = {
	MappingList: MappingList_1
};

/* -*- Mode: js; js-indent-level: 2; -*- */

/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */



var ArraySet$1 = arraySet.ArraySet;
var MappingList = mappingList.MappingList;

/**
 * An instance of the SourceMapGenerator represents a source map which is
 * being built incrementally. You may pass an object with the following
 * properties:
 *
 *   - file: The filename of the generated source.
 *   - sourceRoot: A root for all relative URLs in this source map.
 */
function SourceMapGenerator$2(aArgs) {
  if (!aArgs) {
    aArgs = {};
  }
  this._file = util.getArg(aArgs, 'file', null);
  this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
  this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
  this._sources = new ArraySet$1();
  this._names = new ArraySet$1();
  this._mappings = new MappingList();
  this._sourcesContents = null;
}

SourceMapGenerator$2.prototype._version = 3;

/**
 * Creates a new SourceMapGenerator based on a SourceMapConsumer
 *
 * @param aSourceMapConsumer The SourceMap.
 */
SourceMapGenerator$2.fromSourceMap =
  function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
    var sourceRoot = aSourceMapConsumer.sourceRoot;
    var generator = new SourceMapGenerator$2({
      file: aSourceMapConsumer.file,
      sourceRoot: sourceRoot
    });
    aSourceMapConsumer.eachMapping(function (mapping) {
      var newMapping = {
        generated: {
          line: mapping.generatedLine,
          column: mapping.generatedColumn
        }
      };

      if (mapping.source != null) {
        newMapping.source = mapping.source;
        if (sourceRoot != null) {
          newMapping.source = util.relative(sourceRoot, newMapping.source);
        }

        newMapping.original = {
          line: mapping.originalLine,
          column: mapping.originalColumn
        };

        if (mapping.name != null) {
          newMapping.name = mapping.name;
        }
      }

      generator.addMapping(newMapping);
    });
    aSourceMapConsumer.sources.forEach(function (sourceFile) {
      var sourceRelative = sourceFile;
      if (sourceRoot !== null) {
        sourceRelative = util.relative(sourceRoot, sourceFile);
      }

      if (!generator._sources.has(sourceRelative)) {
        generator._sources.add(sourceRelative);
      }

      var content = aSourceMapConsumer.sourceContentFor(sourceFile);
      if (content != null) {
        generator.setSourceContent(sourceFile, content);
      }
    });
    return generator;
  };

/**
 * Add a single mapping from original source line and column to the generated
 * source's line and column for this source map being created. The mapping
 * object should have the following properties:
 *
 *   - generated: An object with the generated line and column positions.
 *   - original: An object with the original line and column positions.
 *   - source: The original source file (relative to the sourceRoot).
 *   - name: An optional original token name for this mapping.
 */
SourceMapGenerator$2.prototype.addMapping =
  function SourceMapGenerator_addMapping(aArgs) {
    var generated = util.getArg(aArgs, 'generated');
    var original = util.getArg(aArgs, 'original', null);
    var source = util.getArg(aArgs, 'source', null);
    var name = util.getArg(aArgs, 'name', null);

    if (!this._skipValidation) {
      this._validateMapping(generated, original, source, name);
    }

    if (source != null) {
      source = String(source);
      if (!this._sources.has(source)) {
        this._sources.add(source);
      }
    }

    if (name != null) {
      name = String(name);
      if (!this._names.has(name)) {
        this._names.add(name);
      }
    }

    this._mappings.add({
      generatedLine: generated.line,
      generatedColumn: generated.column,
      originalLine: original != null && original.line,
      originalColumn: original != null && original.column,
      source: source,
      name: name
    });
  };

/**
 * Set the source content for a source file.
 */
SourceMapGenerator$2.prototype.setSourceContent =
  function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
    var source = aSourceFile;
    if (this._sourceRoot != null) {
      source = util.relative(this._sourceRoot, source);
    }

    if (aSourceContent != null) {
      // Add the source content to the _sourcesContents map.
      // Create a new _sourcesContents map if the property is null.
      if (!this._sourcesContents) {
        this._sourcesContents = Object.create(null);
      }
      this._sourcesContents[util.toSetString(source)] = aSourceContent;
    } else if (this._sourcesContents) {
      // Remove the source file from the _sourcesContents map.
      // If the _sourcesContents map is empty, set the property to null.
      delete this._sourcesContents[util.toSetString(source)];
      if (Object.keys(this._sourcesContents).length === 0) {
        this._sourcesContents = null;
      }
    }
  };

/**
 * Applies the mappings of a sub-source-map for a specific source file to the
 * source map being generated. Each mapping to the supplied source file is
 * rewritten using the supplied source map. Note: The resolution for the
 * resulting mappings is the minimium of this map and the supplied map.
 *
 * @param aSourceMapConsumer The source map to be applied.
 * @param aSourceFile Optional. The filename of the source file.
 *        If omitted, SourceMapConsumer's file property will be used.
 * @param aSourceMapPath Optional. The dirname of the path to the source map
 *        to be applied. If relative, it is relative to the SourceMapConsumer.
 *        This parameter is needed when the two source maps aren't in the same
 *        directory, and the source map to be applied contains relative source
 *        paths. If so, those relative source paths need to be rewritten
 *        relative to the SourceMapGenerator.
 */
SourceMapGenerator$2.prototype.applySourceMap =
  function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
    var sourceFile = aSourceFile;
    // If aSourceFile is omitted, we will use the file property of the SourceMap
    if (aSourceFile == null) {
      if (aSourceMapConsumer.file == null) {
        throw new Error(
          'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
          'or the source map\'s "file" property. Both were omitted.'
        );
      }
      sourceFile = aSourceMapConsumer.file;
    }
    var sourceRoot = this._sourceRoot;
    // Make "sourceFile" relative if an absolute Url is passed.
    if (sourceRoot != null) {
      sourceFile = util.relative(sourceRoot, sourceFile);
    }
    // Applying the SourceMap can add and remove items from the sources and
    // the names array.
    var newSources = new ArraySet$1();
    var newNames = new ArraySet$1();

    // Find mappings for the "sourceFile"
    this._mappings.unsortedForEach(function (mapping) {
      if (mapping.source === sourceFile && mapping.originalLine != null) {
        // Check if it can be mapped by the source map, then update the mapping.
        var original = aSourceMapConsumer.originalPositionFor({
          line: mapping.originalLine,
          column: mapping.originalColumn
        });
        if (original.source != null) {
          // Copy mapping
          mapping.source = original.source;
          if (aSourceMapPath != null) {
            mapping.source = util.join(aSourceMapPath, mapping.source);
          }
          if (sourceRoot != null) {
            mapping.source = util.relative(sourceRoot, mapping.source);
          }
          mapping.originalLine = original.line;
          mapping.originalColumn = original.column;
          if (original.name != null) {
            mapping.name = original.name;
          }
        }
      }

      var source = mapping.source;
      if (source != null && !newSources.has(source)) {
        newSources.add(source);
      }

      var name = mapping.name;
      if (name != null && !newNames.has(name)) {
        newNames.add(name);
      }

    }, this);
    this._sources = newSources;
    this._names = newNames;

    // Copy sourcesContents of applied map.
    aSourceMapConsumer.sources.forEach(function (sourceFile) {
      var content = aSourceMapConsumer.sourceContentFor(sourceFile);
      if (content != null) {
        if (aSourceMapPath != null) {
          sourceFile = util.join(aSourceMapPath, sourceFile);
        }
        if (sourceRoot != null) {
          sourceFile = util.relative(sourceRoot, sourceFile);
        }
        this.setSourceContent(sourceFile, content);
      }
    }, this);
  };

/**
 * A mapping can have one of the three levels of data:
 *
 *   1. Just the generated position.
 *   2. The Generated position, original position, and original source.
 *   3. Generated and original position, original source, as well as a name
 *      token.
 *
 * To maintain consistency, we validate that any new mapping being added falls
 * in to one of these categories.
 */
SourceMapGenerator$2.prototype._validateMapping =
  function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
                                              aName) {
    // When aOriginal is truthy but has empty values for .line and .column,
    // it is most likely a programmer error. In this case we throw a very
    // specific error message to try to guide them the right way.
    // For example: https://github.com/Polymer/polymer-bundler/pull/519
    if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
        throw new Error(
            'original.line and original.column are not numbers -- you probably meant to omit ' +
            'the original mapping entirely and only map the generated position. If so, pass ' +
            'null for the original mapping instead of an object with empty or null values.'
        );
    }

    if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
        && aGenerated.line > 0 && aGenerated.column >= 0
        && !aOriginal && !aSource && !aName) {
      // Case 1.
      return;
    }
    else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
             && aOriginal && 'line' in aOriginal && 'column' in aOriginal
             && aGenerated.line > 0 && aGenerated.column >= 0
             && aOriginal.line > 0 && aOriginal.column >= 0
             && aSource) {
      // Cases 2 and 3.
      return;
    }
    else {
      throw new Error('Invalid mapping: ' + JSON.stringify({
        generated: aGenerated,
        source: aSource,
        original: aOriginal,
        name: aName
      }));
    }
  };

/**
 * Serialize the accumulated mappings in to the stream of base 64 VLQs
 * specified by the source map format.
 */
SourceMapGenerator$2.prototype._serializeMappings =
  function SourceMapGenerator_serializeMappings() {
    var previousGeneratedColumn = 0;
    var previousGeneratedLine = 1;
    var previousOriginalColumn = 0;
    var previousOriginalLine = 0;
    var previousName = 0;
    var previousSource = 0;
    var result = '';
    var next;
    var mapping;
    var nameIdx;
    var sourceIdx;

    var mappings = this._mappings.toArray();
    for (var i = 0, len = mappings.length; i < len; i++) {
      mapping = mappings[i];
      next = '';

      if (mapping.generatedLine !== previousGeneratedLine) {
        previousGeneratedColumn = 0;
        while (mapping.generatedLine !== previousGeneratedLine) {
          next += ';';
          previousGeneratedLine++;
        }
      }
      else {
        if (i > 0) {
          if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
            continue;
          }
          next += ',';
        }
      }

      next += base64Vlq.encode(mapping.generatedColumn
                                 - previousGeneratedColumn);
      previousGeneratedColumn = mapping.generatedColumn;

      if (mapping.source != null) {
        sourceIdx = this._sources.indexOf(mapping.source);
        next += base64Vlq.encode(sourceIdx - previousSource);
        previousSource = sourceIdx;

        // lines are stored 0-based in SourceMap spec version 3
        next += base64Vlq.encode(mapping.originalLine - 1
                                   - previousOriginalLine);
        previousOriginalLine = mapping.originalLine - 1;

        next += base64Vlq.encode(mapping.originalColumn
                                   - previousOriginalColumn);
        previousOriginalColumn = mapping.originalColumn;

        if (mapping.name != null) {
          nameIdx = this._names.indexOf(mapping.name);
          next += base64Vlq.encode(nameIdx - previousName);
          previousName = nameIdx;
        }
      }

      result += next;
    }

    return result;
  };

SourceMapGenerator$2.prototype._generateSourcesContent =
  function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
    return aSources.map(function (source) {
      if (!this._sourcesContents) {
        return null;
      }
      if (aSourceRoot != null) {
        source = util.relative(aSourceRoot, source);
      }
      var key = util.toSetString(source);
      return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
        ? this._sourcesContents[key]
        : null;
    }, this);
  };

/**
 * Externalize the source map.
 */
SourceMapGenerator$2.prototype.toJSON =
  function SourceMapGenerator_toJSON() {
    var map = {
      version: this._version,
      sources: this._sources.toArray(),
      names: this._names.toArray(),
      mappings: this._serializeMappings()
    };
    if (this._file != null) {
      map.file = this._file;
    }
    if (this._sourceRoot != null) {
      map.sourceRoot = this._sourceRoot;
    }
    if (this._sourcesContents) {
      map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
    }

    return map;
  };

/**
 * Render the source map being generated to a string.
 */
SourceMapGenerator$2.prototype.toString =
  function SourceMapGenerator_toString() {
    return JSON.stringify(this.toJSON());
  };

var SourceMapGenerator_1 = SourceMapGenerator$2;

var sourceMapGenerator = {
	SourceMapGenerator: SourceMapGenerator_1
};

/* -*- Mode: js; js-indent-level: 2; -*- */

var binarySearch = createCommonjsModule(function (module, exports) {
/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

exports.GREATEST_LOWER_BOUND = 1;
exports.LEAST_UPPER_BOUND = 2;

/**
 * Recursive implementation of binary search.
 *
 * @param aLow Indices here and lower do not contain the needle.
 * @param aHigh Indices here and higher do not contain the needle.
 * @param aNeedle The element being searched for.
 * @param aHaystack The non-empty array being searched.
 * @param aCompare Function which takes two elements and returns -1, 0, or 1.
 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
 *     'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
 *     closest element that is smaller than or greater than the one we are
 *     searching for, respectively, if the exact element cannot be found.
 */
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {
  // This function terminates when one of the following is true:
  //
  //   1. We find the exact element we are looking for.
  //
  //   2. We did not find the exact element, but we can return the index of
  //      the next-closest element.
  //
  //   3. We did not find the exact element, and there is no next-closest
  //      element than the one we are searching for, so we return -1.
  var mid = Math.floor((aHigh - aLow) / 2) + aLow;
  var cmp = aCompare(aNeedle, aHaystack[mid], true);
  if (cmp === 0) {
    // Found the element we are looking for.
    return mid;
  }
  else if (cmp > 0) {
    // Our needle is greater than aHaystack[mid].
    if (aHigh - mid > 1) {
      // The element is in the upper half.
      return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
    }

    // The exact needle element was not found in this haystack. Determine if
    // we are in termination case (3) or (2) and return the appropriate thing.
    if (aBias == exports.LEAST_UPPER_BOUND) {
      return aHigh < aHaystack.length ? aHigh : -1;
    } else {
      return mid;
    }
  }
  else {
    // Our needle is less than aHaystack[mid].
    if (mid - aLow > 1) {
      // The element is in the lower half.
      return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
    }

    // we are in termination case (3) or (2) and return the appropriate thing.
    if (aBias == exports.LEAST_UPPER_BOUND) {
      return mid;
    } else {
      return aLow < 0 ? -1 : aLow;
    }
  }
}

/**
 * This is an implementation of binary search which will always try and return
 * the index of the closest element if there is no exact hit. This is because
 * mappings between original and generated line/col pairs are single points,
 * and there is an implicit region between each of them, so a miss just means
 * that you aren't on the very start of a region.
 *
 * @param aNeedle The element you are looking for.
 * @param aHaystack The array that is being searched.
 * @param aCompare A function which takes the needle and an element in the
 *     array and returns -1, 0, or 1 depending on whether the needle is less
 *     than, equal to, or greater than the element, respectively.
 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
 *     'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
 *     closest element that is smaller than or greater than the one we are
 *     searching for, respectively, if the exact element cannot be found.
 *     Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.
 */
exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
  if (aHaystack.length === 0) {
    return -1;
  }

  var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,
                              aCompare, aBias || exports.GREATEST_LOWER_BOUND);
  if (index < 0) {
    return -1;
  }

  // We have found either the exact element, or the next-closest element than
  // the one we are searching for. However, there may be more than one such
  // element. Make sure we always return the smallest of these.
  while (index - 1 >= 0) {
    if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {
      break;
    }
    --index;
  }

  return index;
};
});

/* -*- Mode: js; js-indent-level: 2; -*- */
/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

// It turns out that some (most?) JavaScript engines don't self-host
// `Array.prototype.sort`. This makes sense because C++ will likely remain
// faster than JS when doing raw CPU-intensive sorting. However, when using a
// custom comparator function, calling back and forth between the VM's C++ and
// JIT'd JS is rather slow *and* loses JIT type information, resulting in
// worse generated code for the comparator function than would be optimal. In
// fact, when sorting with a comparator, these costs outweigh the benefits of
// sorting in C++. By using our own JS-implemented Quick Sort (below), we get
// a ~3500ms mean speed-up in `bench/bench.html`.

/**
 * Swap the elements indexed by `x` and `y` in the array `ary`.
 *
 * @param {Array} ary
 *        The array.
 * @param {Number} x
 *        The index of the first item.
 * @param {Number} y
 *        The index of the second item.
 */
function swap(ary, x, y) {
  var temp = ary[x];
  ary[x] = ary[y];
  ary[y] = temp;
}

/**
 * Returns a random integer within the range `low .. high` inclusive.
 *
 * @param {Number} low
 *        The lower bound on the range.
 * @param {Number} high
 *        The upper bound on the range.
 */
function randomIntInRange(low, high) {
  return Math.round(low + (Math.random() * (high - low)));
}

/**
 * The Quick Sort algorithm.
 *
 * @param {Array} ary
 *        An array to sort.
 * @param {function} comparator
 *        Function to use to compare two items.
 * @param {Number} p
 *        Start index of the array
 * @param {Number} r
 *        End index of the array
 */
function doQuickSort(ary, comparator, p, r) {
  // If our lower bound is less than our upper bound, we (1) partition the
  // array into two pieces and (2) recurse on each half. If it is not, this is
  // the empty array and our base case.

  if (p < r) {
    // (1) Partitioning.
    //
    // The partitioning chooses a pivot between `p` and `r` and moves all
    // elements that are less than or equal to the pivot to the before it, and
    // all the elements that are greater than it after it. The effect is that
    // once partition is done, the pivot is in the exact place it will be when
    // the array is put in sorted order, and it will not need to be moved
    // again. This runs in O(n) time.

    // Always choose a random pivot so that an input array which is reverse
    // sorted does not cause O(n^2) running time.
    var pivotIndex = randomIntInRange(p, r);
    var i = p - 1;

    swap(ary, pivotIndex, r);
    var pivot = ary[r];

    // Immediately after `j` is incremented in this loop, the following hold
    // true:
    //
    //   * Every element in `ary[p .. i]` is less than or equal to the pivot.
    //
    //   * Every element in `ary[i+1 .. j-1]` is greater than the pivot.
    for (var j = p; j < r; j++) {
      if (comparator(ary[j], pivot) <= 0) {
        i += 1;
        swap(ary, i, j);
      }
    }

    swap(ary, i + 1, j);
    var q = i + 1;

    // (2) Recurse on each half.

    doQuickSort(ary, comparator, p, q - 1);
    doQuickSort(ary, comparator, q + 1, r);
  }
}

/**
 * Sort the given array in-place with the given comparator function.
 *
 * @param {Array} ary
 *        An array to sort.
 * @param {function} comparator
 *        Function to use to compare two items.
 */
var quickSort_1 = function (ary, comparator) {
  doQuickSort(ary, comparator, 0, ary.length - 1);
};

var quickSort$1 = {
	quickSort: quickSort_1
};

/* -*- Mode: js; js-indent-level: 2; -*- */

/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */



var ArraySet = arraySet.ArraySet;

var quickSort = quickSort$1.quickSort;

function SourceMapConsumer$1(aSourceMap, aSourceMapURL) {
  var sourceMap = aSourceMap;
  if (typeof aSourceMap === 'string') {
    sourceMap = util.parseSourceMapInput(aSourceMap);
  }

  return sourceMap.sections != null
    ? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL)
    : new BasicSourceMapConsumer(sourceMap, aSourceMapURL);
}

SourceMapConsumer$1.fromSourceMap = function(aSourceMap, aSourceMapURL) {
  return BasicSourceMapConsumer.fromSourceMap(aSourceMap, aSourceMapURL);
};

/**
 * The version of the source mapping spec that we are consuming.
 */
SourceMapConsumer$1.prototype._version = 3;

// `__generatedMappings` and `__originalMappings` are arrays that hold the
// parsed mapping coordinates from the source map's "mappings" attribute. They
// are lazily instantiated, accessed via the `_generatedMappings` and
// `_originalMappings` getters respectively, and we only parse the mappings
// and create these arrays once queried for a source location. We jump through
// these hoops because there can be many thousands of mappings, and parsing
// them is expensive, so we only want to do it if we must.
//
// Each object in the arrays is of the form:
//
//     {
//       generatedLine: The line number in the generated code,
//       generatedColumn: The column number in the generated code,
//       source: The path to the original source file that generated this
//               chunk of code,
//       originalLine: The line number in the original source that
//                     corresponds to this chunk of generated code,
//       originalColumn: The column number in the original source that
//                       corresponds to this chunk of generated code,
//       name: The name of the original symbol which generated this chunk of
//             code.
//     }
//
// All properties except for `generatedLine` and `generatedColumn` can be
// `null`.
//
// `_generatedMappings` is ordered by the generated positions.
//
// `_originalMappings` is ordered by the original positions.

SourceMapConsumer$1.prototype.__generatedMappings = null;
Object.defineProperty(SourceMapConsumer$1.prototype, '_generatedMappings', {
  configurable: true,
  enumerable: true,
  get: function () {
    if (!this.__generatedMappings) {
      this._parseMappings(this._mappings, this.sourceRoot);
    }

    return this.__generatedMappings;
  }
});

SourceMapConsumer$1.prototype.__originalMappings = null;
Object.defineProperty(SourceMapConsumer$1.prototype, '_originalMappings', {
  configurable: true,
  enumerable: true,
  get: function () {
    if (!this.__originalMappings) {
      this._parseMappings(this._mappings, this.sourceRoot);
    }

    return this.__originalMappings;
  }
});

SourceMapConsumer$1.prototype._charIsMappingSeparator =
  function SourceMapConsumer_charIsMappingSeparator(aStr, index) {
    var c = aStr.charAt(index);
    return c === ";" || c === ",";
  };

/**
 * Parse the mappings in a string in to a data structure which we can easily
 * query (the ordered arrays in the `this.__generatedMappings` and
 * `this.__originalMappings` properties).
 */
SourceMapConsumer$1.prototype._parseMappings =
  function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
    throw new Error("Subclasses must implement _parseMappings");
  };

SourceMapConsumer$1.GENERATED_ORDER = 1;
SourceMapConsumer$1.ORIGINAL_ORDER = 2;

SourceMapConsumer$1.GREATEST_LOWER_BOUND = 1;
SourceMapConsumer$1.LEAST_UPPER_BOUND = 2;

/**
 * Iterate over each mapping between an original source/line/column and a
 * generated line/column in this source map.
 *
 * @param Function aCallback
 *        The function that is called with each mapping.
 * @param Object aContext
 *        Optional. If specified, this object will be the value of `this` every
 *        time that `aCallback` is called.
 * @param aOrder
 *        Either `SourceMapConsumer.GENERATED_ORDER` or
 *        `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
 *        iterate over the mappings sorted by the generated file's line/column
 *        order or the original's source/line/column order, respectively. Defaults to
 *        `SourceMapConsumer.GENERATED_ORDER`.
 */
SourceMapConsumer$1.prototype.eachMapping =
  function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
    var context = aContext || null;
    var order = aOrder || SourceMapConsumer$1.GENERATED_ORDER;

    var mappings;
    switch (order) {
    case SourceMapConsumer$1.GENERATED_ORDER:
      mappings = this._generatedMappings;
      break;
    case SourceMapConsumer$1.ORIGINAL_ORDER:
      mappings = this._originalMappings;
      break;
    default:
      throw new Error("Unknown order of iteration.");
    }

    var sourceRoot = this.sourceRoot;
    mappings.map(function (mapping) {
      var source = mapping.source === null ? null : this._sources.at(mapping.source);
      source = util.computeSourceURL(sourceRoot, source, this._sourceMapURL);
      return {
        source: source,
        generatedLine: mapping.generatedLine,
        generatedColumn: mapping.generatedColumn,
        originalLine: mapping.originalLine,
        originalColumn: mapping.originalColumn,
        name: mapping.name === null ? null : this._names.at(mapping.name)
      };
    }, this).forEach(aCallback, context);
  };

/**
 * Returns all generated line and column information for the original source,
 * line, and column provided. If no column is provided, returns all mappings
 * corresponding to a either the line we are searching for or the next
 * closest line that has any mappings. Otherwise, returns all mappings
 * corresponding to the given line and either the column we are searching for
 * or the next closest column that has any offsets.
 *
 * The only argument is an object with the following properties:
 *
 *   - source: The filename of the original source.
 *   - line: The line number in the original source.  The line number is 1-based.
 *   - column: Optional. the column number in the original source.
 *    The column number is 0-based.
 *
 * and an array of objects is returned, each with the following properties:
 *
 *   - line: The line number in the generated source, or null.  The
 *    line number is 1-based.
 *   - column: The column number in the generated source, or null.
 *    The column number is 0-based.
 */
SourceMapConsumer$1.prototype.allGeneratedPositionsFor =
  function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
    var line = util.getArg(aArgs, 'line');

    // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping
    // returns the index of the closest mapping less than the needle. By
    // setting needle.originalColumn to 0, we thus find the last mapping for
    // the given line, provided such a mapping exists.
    var needle = {
      source: util.getArg(aArgs, 'source'),
      originalLine: line,
      originalColumn: util.getArg(aArgs, 'column', 0)
    };

    needle.source = this._findSourceIndex(needle.source);
    if (needle.source < 0) {
      return [];
    }

    var mappings = [];

    var index = this._findMapping(needle,
                                  this._originalMappings,
                                  "originalLine",
                                  "originalColumn",
                                  util.compareByOriginalPositions,
                                  binarySearch.LEAST_UPPER_BOUND);
    if (index >= 0) {
      var mapping = this._originalMappings[index];

      if (aArgs.column === undefined) {
        var originalLine = mapping.originalLine;

        // Iterate until either we run out of mappings, or we run into
        // a mapping for a different line than the one we found. Since
        // mappings are sorted, this is guaranteed to find all mappings for
        // the line we found.
        while (mapping && mapping.originalLine === originalLine) {
          mappings.push({
            line: util.getArg(mapping, 'generatedLine', null),
            column: util.getArg(mapping, 'generatedColumn', null),
            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
          });

          mapping = this._originalMappings[++index];
        }
      } else {
        var originalColumn = mapping.originalColumn;

        // Iterate until either we run out of mappings, or we run into
        // a mapping for a different line than the one we were searching for.
        // Since mappings are sorted, this is guaranteed to find all mappings for
        // the line we are searching for.
        while (mapping &&
               mapping.originalLine === line &&
               mapping.originalColumn == originalColumn) {
          mappings.push({
            line: util.getArg(mapping, 'generatedLine', null),
            column: util.getArg(mapping, 'generatedColumn', null),
            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
          });

          mapping = this._originalMappings[++index];
        }
      }
    }

    return mappings;
  };

var SourceMapConsumer_1 = SourceMapConsumer$1;

/**
 * A BasicSourceMapConsumer instance represents a parsed source map which we can
 * query for information about the original file positions by giving it a file
 * position in the generated source.
 *
 * The first parameter is the raw source map (either as a JSON string, or
 * already parsed to an object). According to the spec, source maps have the
 * following attributes:
 *
 *   - version: Which version of the source map spec this map is following.
 *   - sources: An array of URLs to the original source files.
 *   - names: An array of identifiers which can be referrenced by individual mappings.
 *   - sourceRoot: Optional. The URL root from which all sources are relative.
 *   - sourcesContent: Optional. An array of contents of the original source files.
 *   - mappings: A string of base64 VLQs which contain the actual mappings.
 *   - file: Optional. The generated file this source map is associated with.
 *
 * Here is an example source map, taken from the source map spec[0]:
 *
 *     {
 *       version : 3,
 *       file: "out.js",
 *       sourceRoot : "",
 *       sources: ["foo.js", "bar.js"],
 *       names: ["src", "maps", "are", "fun"],
 *       mappings: "AA,AB;;ABCDE;"
 *     }
 *
 * The second parameter, if given, is a string whose value is the URL
 * at which the source map was found.  This URL is used to compute the
 * sources array.
 *
 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
 */
function BasicSourceMapConsumer(aSourceMap, aSourceMapURL) {
  var sourceMap = aSourceMap;
  if (typeof aSourceMap === 'string') {
    sourceMap = util.parseSourceMapInput(aSourceMap);
  }

  var version = util.getArg(sourceMap, 'version');
  var sources = util.getArg(sourceMap, 'sources');
  // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
  // requires the array) to play nice here.
  var names = util.getArg(sourceMap, 'names', []);
  var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
  var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
  var mappings = util.getArg(sourceMap, 'mappings');
  var file = util.getArg(sourceMap, 'file', null);

  // Once again, Sass deviates from the spec and supplies the version as a
  // string rather than a number, so we use loose equality checking here.
  if (version != this._version) {
    throw new Error('Unsupported version: ' + version);
  }

  if (sourceRoot) {
    sourceRoot = util.normalize(sourceRoot);
  }

  sources = sources
    .map(String)
    // Some source maps produce relative source paths like "./foo.js" instead of
    // "foo.js".  Normalize these first so that future comparisons will succeed.
    // See bugzil.la/1090768.
    .map(util.normalize)
    // Always ensure that absolute sources are internally stored relative to
    // the source root, if the source root is absolute. Not doing this would
    // be particularly problematic when the source root is a prefix of the
    // source (valid, but why??). See github issue #199 and bugzil.la/1188982.
    .map(function (source) {
      return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
        ? util.relative(sourceRoot, source)
        : source;
    });

  // Pass `true` below to allow duplicate names and sources. While source maps
  // are intended to be compressed and deduplicated, the TypeScript compiler
  // sometimes generates source maps with duplicates in them. See Github issue
  // #72 and bugzil.la/889492.
  this._names = ArraySet.fromArray(names.map(String), true);
  this._sources = ArraySet.fromArray(sources, true);

  this._absoluteSources = this._sources.toArray().map(function (s) {
    return util.computeSourceURL(sourceRoot, s, aSourceMapURL);
  });

  this.sourceRoot = sourceRoot;
  this.sourcesContent = sourcesContent;
  this._mappings = mappings;
  this._sourceMapURL = aSourceMapURL;
  this.file = file;
}

BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer$1.prototype);
BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer$1;

/**
 * Utility function to find the index of a source.  Returns -1 if not
 * found.
 */
BasicSourceMapConsumer.prototype._findSourceIndex = function(aSource) {
  var relativeSource = aSource;
  if (this.sourceRoot != null) {
    relativeSource = util.relative(this.sourceRoot, relativeSource);
  }

  if (this._sources.has(relativeSource)) {
    return this._sources.indexOf(relativeSource);
  }

  // Maybe aSource is an absolute URL as returned by |sources|.  In
  // this case we can't simply undo the transform.
  var i;
  for (i = 0; i < this._absoluteSources.length; ++i) {
    if (this._absoluteSources[i] == aSource) {
      return i;
    }
  }

  return -1;
};

/**
 * Create a BasicSourceMapConsumer from a SourceMapGenerator.
 *
 * @param SourceMapGenerator aSourceMap
 *        The source map that will be consumed.
 * @param String aSourceMapURL
 *        The URL at which the source map can be found (optional)
 * @returns BasicSourceMapConsumer
 */
BasicSourceMapConsumer.fromSourceMap =
  function SourceMapConsumer_fromSourceMap(aSourceMap, aSourceMapURL) {
    var smc = Object.create(BasicSourceMapConsumer.prototype);

    var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
    var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
    smc.sourceRoot = aSourceMap._sourceRoot;
    smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),
                                                            smc.sourceRoot);
    smc.file = aSourceMap._file;
    smc._sourceMapURL = aSourceMapURL;
    smc._absoluteSources = smc._sources.toArray().map(function (s) {
      return util.computeSourceURL(smc.sourceRoot, s, aSourceMapURL);
    });

    // Because we are modifying the entries (by converting string sources and
    // names to indices into the sources and names ArraySets), we have to make
    // a copy of the entry or else bad things happen. Shared mutable state
    // strikes again! See github issue #191.

    var generatedMappings = aSourceMap._mappings.toArray().slice();
    var destGeneratedMappings = smc.__generatedMappings = [];
    var destOriginalMappings = smc.__originalMappings = [];

    for (var i = 0, length = generatedMappings.length; i < length; i++) {
      var srcMapping = generatedMappings[i];
      var destMapping = new Mapping;
      destMapping.generatedLine = srcMapping.generatedLine;
      destMapping.generatedColumn = srcMapping.generatedColumn;

      if (srcMapping.source) {
        destMapping.source = sources.indexOf(srcMapping.source);
        destMapping.originalLine = srcMapping.originalLine;
        destMapping.originalColumn = srcMapping.originalColumn;

        if (srcMapping.name) {
          destMapping.name = names.indexOf(srcMapping.name);
        }

        destOriginalMappings.push(destMapping);
      }

      destGeneratedMappings.push(destMapping);
    }

    quickSort(smc.__originalMappings, util.compareByOriginalPositions);

    return smc;
  };

/**
 * The version of the source mapping spec that we are consuming.
 */
BasicSourceMapConsumer.prototype._version = 3;

/**
 * The list of original sources.
 */
Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
  get: function () {
    return this._absoluteSources.slice();
  }
});

/**
 * Provide the JIT with a nice shape / hidden class.
 */
function Mapping() {
  this.generatedLine = 0;
  this.generatedColumn = 0;
  this.source = null;
  this.originalLine = null;
  this.originalColumn = null;
  this.name = null;
}

/**
 * Parse the mappings in a string in to a data structure which we can easily
 * query (the ordered arrays in the `this.__generatedMappings` and
 * `this.__originalMappings` properties).
 */
BasicSourceMapConsumer.prototype._parseMappings =
  function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
    var generatedLine = 1;
    var previousGeneratedColumn = 0;
    var previousOriginalLine = 0;
    var previousOriginalColumn = 0;
    var previousSource = 0;
    var previousName = 0;
    var length = aStr.length;
    var index = 0;
    var cachedSegments = {};
    var temp = {};
    var originalMappings = [];
    var generatedMappings = [];
    var mapping, str, segment, end, value;

    while (index < length) {
      if (aStr.charAt(index) === ';') {
        generatedLine++;
        index++;
        previousGeneratedColumn = 0;
      }
      else if (aStr.charAt(index) === ',') {
        index++;
      }
      else {
        mapping = new Mapping();
        mapping.generatedLine = generatedLine;

        // Because each offset is encoded relative to the previous one,
        // many segments often have the same encoding. We can exploit this
        // fact by caching the parsed variable length fields of each segment,
        // allowing us to avoid a second parse if we encounter the same
        // segment again.
        for (end = index; end < length; end++) {
          if (this._charIsMappingSeparator(aStr, end)) {
            break;
          }
        }
        str = aStr.slice(index, end);

        segment = cachedSegments[str];
        if (segment) {
          index += str.length;
        } else {
          segment = [];
          while (index < end) {
            base64Vlq.decode(aStr, index, temp);
            value = temp.value;
            index = temp.rest;
            segment.push(value);
          }

          if (segment.length === 2) {
            throw new Error('Found a source, but no line and column');
          }

          if (segment.length === 3) {
            throw new Error('Found a source and line, but no column');
          }

          cachedSegments[str] = segment;
        }

        // Generated column.
        mapping.generatedColumn = previousGeneratedColumn + segment[0];
        previousGeneratedColumn = mapping.generatedColumn;

        if (segment.length > 1) {
          // Original source.
          mapping.source = previousSource + segment[1];
          previousSource += segment[1];

          // Original line.
          mapping.originalLine = previousOriginalLine + segment[2];
          previousOriginalLine = mapping.originalLine;
          // Lines are stored 0-based
          mapping.originalLine += 1;

          // Original column.
          mapping.originalColumn = previousOriginalColumn + segment[3];
          previousOriginalColumn = mapping.originalColumn;

          if (segment.length > 4) {
            // Original name.
            mapping.name = previousName + segment[4];
            previousName += segment[4];
          }
        }

        generatedMappings.push(mapping);
        if (typeof mapping.originalLine === 'number') {
          originalMappings.push(mapping);
        }
      }
    }

    quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);
    this.__generatedMappings = generatedMappings;

    quickSort(originalMappings, util.compareByOriginalPositions);
    this.__originalMappings = originalMappings;
  };

/**
 * Find the mapping that best matches the hypothetical "needle" mapping that
 * we are searching for in the given "haystack" of mappings.
 */
BasicSourceMapConsumer.prototype._findMapping =
  function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
                                         aColumnName, aComparator, aBias) {
    // To return the position we are searching for, we must first find the
    // mapping for the given position and then return the opposite position it
    // points to. Because the mappings are sorted, we can use binary search to
    // find the best mapping.

    if (aNeedle[aLineName] <= 0) {
      throw new TypeError('Line must be greater than or equal to 1, got '
                          + aNeedle[aLineName]);
    }
    if (aNeedle[aColumnName] < 0) {
      throw new TypeError('Column must be greater than or equal to 0, got '
                          + aNeedle[aColumnName]);
    }

    return binarySearch.search(aNeedle, aMappings, aComparator, aBias);
  };

/**
 * Compute the last column for each generated mapping. The last column is
 * inclusive.
 */
BasicSourceMapConsumer.prototype.computeColumnSpans =
  function SourceMapConsumer_computeColumnSpans() {
    for (var index = 0; index < this._generatedMappings.length; ++index) {
      var mapping = this._generatedMappings[index];

      // Mappings do not contain a field for the last generated columnt. We
      // can come up with an optimistic estimate, however, by assuming that
      // mappings are contiguous (i.e. given two consecutive mappings, the
      // first mapping ends where the second one starts).
      if (index + 1 < this._generatedMappings.length) {
        var nextMapping = this._generatedMappings[index + 1];

        if (mapping.generatedLine === nextMapping.generatedLine) {
          mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
          continue;
        }
      }

      // The last mapping for each line spans the entire line.
      mapping.lastGeneratedColumn = Infinity;
    }
  };

/**
 * Returns the original source, line, and column information for the generated
 * source's line and column positions provided. The only argument is an object
 * with the following properties:
 *
 *   - line: The line number in the generated source.  The line number
 *     is 1-based.
 *   - column: The column number in the generated source.  The column
 *     number is 0-based.
 *   - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
 *     'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
 *     closest element that is smaller than or greater than the one we are
 *     searching for, respectively, if the exact element cannot be found.
 *     Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
 *
 * and an object is returned with the following properties:
 *
 *   - source: The original source file, or null.
 *   - line: The line number in the original source, or null.  The
 *     line number is 1-based.
 *   - column: The column number in the original source, or null.  The
 *     column number is 0-based.
 *   - name: The original identifier, or null.
 */
BasicSourceMapConsumer.prototype.originalPositionFor =
  function SourceMapConsumer_originalPositionFor(aArgs) {
    var needle = {
      generatedLine: util.getArg(aArgs, 'line'),
      generatedColumn: util.getArg(aArgs, 'column')
    };

    var index = this._findMapping(
      needle,
      this._generatedMappings,
      "generatedLine",
      "generatedColumn",
      util.compareByGeneratedPositionsDeflated,
      util.getArg(aArgs, 'bias', SourceMapConsumer$1.GREATEST_LOWER_BOUND)
    );

    if (index >= 0) {
      var mapping = this._generatedMappings[index];

      if (mapping.generatedLine === needle.generatedLine) {
        var source = util.getArg(mapping, 'source', null);
        if (source !== null) {
          source = this._sources.at(source);
          source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL);
        }
        var name = util.getArg(mapping, 'name', null);
        if (name !== null) {
          name = this._names.at(name);
        }
        return {
          source: source,
          line: util.getArg(mapping, 'originalLine', null),
          column: util.getArg(mapping, 'originalColumn', null),
          name: name
        };
      }
    }

    return {
      source: null,
      line: null,
      column: null,
      name: null
    };
  };

/**
 * Return true if we have the source content for every source in the source
 * map, false otherwise.
 */
BasicSourceMapConsumer.prototype.hasContentsOfAllSources =
  function BasicSourceMapConsumer_hasContentsOfAllSources() {
    if (!this.sourcesContent) {
      return false;
    }
    return this.sourcesContent.length >= this._sources.size() &&
      !this.sourcesContent.some(function (sc) { return sc == null; });
  };

/**
 * Returns the original source content. The only argument is the url of the
 * original source file. Returns null if no original source content is
 * available.
 */
BasicSourceMapConsumer.prototype.sourceContentFor =
  function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
    if (!this.sourcesContent) {
      return null;
    }

    var index = this._findSourceIndex(aSource);
    if (index >= 0) {
      return this.sourcesContent[index];
    }

    var relativeSource = aSource;
    if (this.sourceRoot != null) {
      relativeSource = util.relative(this.sourceRoot, relativeSource);
    }

    var url;
    if (this.sourceRoot != null
        && (url = util.urlParse(this.sourceRoot))) {
      // XXX: file:// URIs and absolute paths lead to unexpected behavior for
      // many users. We can help them out when they expect file:// URIs to
      // behave like it would if they were running a local HTTP server. See
      // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
      var fileUriAbsPath = relativeSource.replace(/^file:\/\//, "");
      if (url.scheme == "file"
          && this._sources.has(fileUriAbsPath)) {
        return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
      }

      if ((!url.path || url.path == "/")
          && this._sources.has("/" + relativeSource)) {
        return this.sourcesContent[this._sources.indexOf("/" + relativeSource)];
      }
    }

    // This function is used recursively from
    // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we
    // don't want to throw if we can't find the source - we just want to
    // return null, so we provide a flag to exit gracefully.
    if (nullOnMissing) {
      return null;
    }
    else {
      throw new Error('"' + relativeSource + '" is not in the SourceMap.');
    }
  };

/**
 * Returns the generated line and column information for the original source,
 * line, and column positions provided. The only argument is an object with
 * the following properties:
 *
 *   - source: The filename of the original source.
 *   - line: The line number in the original source.  The line number
 *     is 1-based.
 *   - column: The column number in the original source.  The column
 *     number is 0-based.
 *   - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
 *     'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
 *     closest element that is smaller than or greater than the one we are
 *     searching for, respectively, if the exact element cannot be found.
 *     Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
 *
 * and an object is returned with the following properties:
 *
 *   - line: The line number in the generated source, or null.  The
 *     line number is 1-based.
 *   - column: The column number in the generated source, or null.
 *     The column number is 0-based.
 */
BasicSourceMapConsumer.prototype.generatedPositionFor =
  function SourceMapConsumer_generatedPositionFor(aArgs) {
    var source = util.getArg(aArgs, 'source');
    source = this._findSourceIndex(source);
    if (source < 0) {
      return {
        line: null,
        column: null,
        lastColumn: null
      };
    }

    var needle = {
      source: source,
      originalLine: util.getArg(aArgs, 'line'),
      originalColumn: util.getArg(aArgs, 'column')
    };

    var index = this._findMapping(
      needle,
      this._originalMappings,
      "originalLine",
      "originalColumn",
      util.compareByOriginalPositions,
      util.getArg(aArgs, 'bias', SourceMapConsumer$1.GREATEST_LOWER_BOUND)
    );

    if (index >= 0) {
      var mapping = this._originalMappings[index];

      if (mapping.source === needle.source) {
        return {
          line: util.getArg(mapping, 'generatedLine', null),
          column: util.getArg(mapping, 'generatedColumn', null),
          lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
        };
      }
    }

    return {
      line: null,
      column: null,
      lastColumn: null
    };
  };

var BasicSourceMapConsumer_1 = BasicSourceMapConsumer;

/**
 * An IndexedSourceMapConsumer instance represents a parsed source map which
 * we can query for information. It differs from BasicSourceMapConsumer in
 * that it takes "indexed" source maps (i.e. ones with a "sections" field) as
 * input.
 *
 * The first parameter is a raw source map (either as a JSON string, or already
 * parsed to an object). According to the spec for indexed source maps, they
 * have the following attributes:
 *
 *   - version: Which version of the source map spec this map is following.
 *   - file: Optional. The generated file this source map is associated with.
 *   - sections: A list of section definitions.
 *
 * Each value under the "sections" field has two fields:
 *   - offset: The offset into the original specified at which this section
 *       begins to apply, defined as an object with a "line" and "column"
 *       field.
 *   - map: A source map definition. This source map could also be indexed,
 *       but doesn't have to be.
 *
 * Instead of the "map" field, it's also possible to have a "url" field
 * specifying a URL to retrieve a source map from, but that's currently
 * unsupported.
 *
 * Here's an example source map, taken from the source map spec[0], but
 * modified to omit a section which uses the "url" field.
 *
 *  {
 *    version : 3,
 *    file: "app.js",
 *    sections: [{
 *      offset: {line:100, column:10},
 *      map: {
 *        version : 3,
 *        file: "section.js",
 *        sources: ["foo.js", "bar.js"],
 *        names: ["src", "maps", "are", "fun"],
 *        mappings: "AAAA,E;;ABCDE;"
 *      }
 *    }],
 *  }
 *
 * The second parameter, if given, is a string whose value is the URL
 * at which the source map was found.  This URL is used to compute the
 * sources array.
 *
 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt
 */
function IndexedSourceMapConsumer(aSourceMap, aSourceMapURL) {
  var sourceMap = aSourceMap;
  if (typeof aSourceMap === 'string') {
    sourceMap = util.parseSourceMapInput(aSourceMap);
  }

  var version = util.getArg(sourceMap, 'version');
  var sections = util.getArg(sourceMap, 'sections');

  if (version != this._version) {
    throw new Error('Unsupported version: ' + version);
  }

  this._sources = new ArraySet();
  this._names = new ArraySet();

  var lastOffset = {
    line: -1,
    column: 0
  };
  this._sections = sections.map(function (s) {
    if (s.url) {
      // The url field will require support for asynchronicity.
      // See https://github.com/mozilla/source-map/issues/16
      throw new Error('Support for url field in sections not implemented.');
    }
    var offset = util.getArg(s, 'offset');
    var offsetLine = util.getArg(offset, 'line');
    var offsetColumn = util.getArg(offset, 'column');

    if (offsetLine < lastOffset.line ||
        (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {
      throw new Error('Section offsets must be ordered and non-overlapping.');
    }
    lastOffset = offset;

    return {
      generatedOffset: {
        // The offset fields are 0-based, but we use 1-based indices when
        // encoding/decoding from VLQ.
        generatedLine: offsetLine + 1,
        generatedColumn: offsetColumn + 1
      },
      consumer: new SourceMapConsumer$1(util.getArg(s, 'map'), aSourceMapURL)
    }
  });
}

IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer$1.prototype);
IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer$1;

/**
 * The version of the source mapping spec that we are consuming.
 */
IndexedSourceMapConsumer.prototype._version = 3;

/**
 * The list of original sources.
 */
Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {
  get: function () {
    var sources = [];
    for (var i = 0; i < this._sections.length; i++) {
      for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
        sources.push(this._sections[i].consumer.sources[j]);
      }
    }
    return sources;
  }
});

/**
 * Returns the original source, line, and column information for the generated
 * source's line and column positions provided. The only argument is an object
 * with the following properties:
 *
 *   - line: The line number in the generated source.  The line number
 *     is 1-based.
 *   - column: The column number in the generated source.  The column
 *     number is 0-based.
 *
 * and an object is returned with the following properties:
 *
 *   - source: The original source file, or null.
 *   - line: The line number in the original source, or null.  The
 *     line number is 1-based.
 *   - column: The column number in the original source, or null.  The
 *     column number is 0-based.
 *   - name: The original identifier, or null.
 */
IndexedSourceMapConsumer.prototype.originalPositionFor =
  function IndexedSourceMapConsumer_originalPositionFor(aArgs) {
    var needle = {
      generatedLine: util.getArg(aArgs, 'line'),
      generatedColumn: util.getArg(aArgs, 'column')
    };

    // Find the section containing the generated position we're trying to map
    // to an original position.
    var sectionIndex = binarySearch.search(needle, this._sections,
      function(needle, section) {
        var cmp = needle.generatedLine - section.generatedOffset.generatedLine;
        if (cmp) {
          return cmp;
        }

        return (needle.generatedColumn -
                section.generatedOffset.generatedColumn);
      });
    var section = this._sections[sectionIndex];

    if (!section) {
      return {
        source: null,
        line: null,
        column: null,
        name: null
      };
    }

    return section.consumer.originalPositionFor({
      line: needle.generatedLine -
        (section.generatedOffset.generatedLine - 1),
      column: needle.generatedColumn -
        (section.generatedOffset.generatedLine === needle.generatedLine
         ? section.generatedOffset.generatedColumn - 1
         : 0),
      bias: aArgs.bias
    });
  };

/**
 * Return true if we have the source content for every source in the source
 * map, false otherwise.
 */
IndexedSourceMapConsumer.prototype.hasContentsOfAllSources =
  function IndexedSourceMapConsumer_hasContentsOfAllSources() {
    return this._sections.every(function (s) {
      return s.consumer.hasContentsOfAllSources();
    });
  };

/**
 * Returns the original source content. The only argument is the url of the
 * original source file. Returns null if no original source content is
 * available.
 */
IndexedSourceMapConsumer.prototype.sourceContentFor =
  function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
    for (var i = 0; i < this._sections.length; i++) {
      var section = this._sections[i];

      var content = section.consumer.sourceContentFor(aSource, true);
      if (content) {
        return content;
      }
    }
    if (nullOnMissing) {
      return null;
    }
    else {
      throw new Error('"' + aSource + '" is not in the SourceMap.');
    }
  };

/**
 * Returns the generated line and column information for the original source,
 * line, and column positions provided. The only argument is an object with
 * the following properties:
 *
 *   - source: The filename of the original source.
 *   - line: The line number in the original source.  The line number
 *     is 1-based.
 *   - column: The column number in the original source.  The column
 *     number is 0-based.
 *
 * and an object is returned with the following properties:
 *
 *   - line: The line number in the generated source, or null.  The
 *     line number is 1-based. 
 *   - column: The column number in the generated source, or null.
 *     The column number is 0-based.
 */
IndexedSourceMapConsumer.prototype.generatedPositionFor =
  function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {
    for (var i = 0; i < this._sections.length; i++) {
      var section = this._sections[i];

      // Only consider this section if the requested source is in the list of
      // sources of the consumer.
      if (section.consumer._findSourceIndex(util.getArg(aArgs, 'source')) === -1) {
        continue;
      }
      var generatedPosition = section.consumer.generatedPositionFor(aArgs);
      if (generatedPosition) {
        var ret = {
          line: generatedPosition.line +
            (section.generatedOffset.generatedLine - 1),
          column: generatedPosition.column +
            (section.generatedOffset.generatedLine === generatedPosition.line
             ? section.generatedOffset.generatedColumn - 1
             : 0)
        };
        return ret;
      }
    }

    return {
      line: null,
      column: null
    };
  };

/**
 * Parse the mappings in a string in to a data structure which we can easily
 * query (the ordered arrays in the `this.__generatedMappings` and
 * `this.__originalMappings` properties).
 */
IndexedSourceMapConsumer.prototype._parseMappings =
  function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {
    this.__generatedMappings = [];
    this.__originalMappings = [];
    for (var i = 0; i < this._sections.length; i++) {
      var section = this._sections[i];
      var sectionMappings = section.consumer._generatedMappings;
      for (var j = 0; j < sectionMappings.length; j++) {
        var mapping = sectionMappings[j];

        var source = section.consumer._sources.at(mapping.source);
        source = util.computeSourceURL(section.consumer.sourceRoot, source, this._sourceMapURL);
        this._sources.add(source);
        source = this._sources.indexOf(source);

        var name = null;
        if (mapping.name) {
          name = section.consumer._names.at(mapping.name);
          this._names.add(name);
          name = this._names.indexOf(name);
        }

        // The mappings coming from the consumer for the section have
        // generated positions relative to the start of the section, so we
        // need to offset them to be relative to the start of the concatenated
        // generated file.
        var adjustedMapping = {
          source: source,
          generatedLine: mapping.generatedLine +
            (section.generatedOffset.generatedLine - 1),
          generatedColumn: mapping.generatedColumn +
            (section.generatedOffset.generatedLine === mapping.generatedLine
            ? section.generatedOffset.generatedColumn - 1
            : 0),
          originalLine: mapping.originalLine,
          originalColumn: mapping.originalColumn,
          name: name
        };

        this.__generatedMappings.push(adjustedMapping);
        if (typeof adjustedMapping.originalLine === 'number') {
          this.__originalMappings.push(adjustedMapping);
        }
      }
    }

    quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);
    quickSort(this.__originalMappings, util.compareByOriginalPositions);
  };

var IndexedSourceMapConsumer_1 = IndexedSourceMapConsumer;

var sourceMapConsumer = {
	SourceMapConsumer: SourceMapConsumer_1,
	BasicSourceMapConsumer: BasicSourceMapConsumer_1,
	IndexedSourceMapConsumer: IndexedSourceMapConsumer_1
};

/* -*- Mode: js; js-indent-level: 2; -*- */

/*
 * Copyright 2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

var SourceMapGenerator$1 = sourceMapGenerator.SourceMapGenerator;


// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
// operating systems these days (capturing the result).
var REGEX_NEWLINE = /(\r?\n)/;

// Newline character code for charCodeAt() comparisons
var NEWLINE_CODE = 10;

// Private symbol for identifying `SourceNode`s when multiple versions of
// the source-map library are loaded. This MUST NOT CHANGE across
// versions!
var isSourceNode = "$$$isSourceNode$$$";

/**
 * SourceNodes provide a way to abstract over interpolating/concatenating
 * snippets of generated JavaScript source code while maintaining the line and
 * column information associated with the original source code.
 *
 * @param aLine The original line number.
 * @param aColumn The original column number.
 * @param aSource The original source's filename.
 * @param aChunks Optional. An array of strings which are snippets of
 *        generated JS, or other SourceNodes.
 * @param aName The original identifier.
 */
function SourceNode$1(aLine, aColumn, aSource, aChunks, aName) {
  this.children = [];
  this.sourceContents = {};
  this.line = aLine == null ? null : aLine;
  this.column = aColumn == null ? null : aColumn;
  this.source = aSource == null ? null : aSource;
  this.name = aName == null ? null : aName;
  this[isSourceNode] = true;
  if (aChunks != null) this.add(aChunks);
}

/**
 * Creates a SourceNode from generated code and a SourceMapConsumer.
 *
 * @param aGeneratedCode The generated code
 * @param aSourceMapConsumer The SourceMap for the generated code
 * @param aRelativePath Optional. The path that relative sources in the
 *        SourceMapConsumer should be relative to.
 */
SourceNode$1.fromStringWithSourceMap =
  function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
    // The SourceNode we want to fill with the generated code
    // and the SourceMap
    var node = new SourceNode$1();

    // All even indices of this array are one line of the generated code,
    // while all odd indices are the newlines between two adjacent lines
    // (since `REGEX_NEWLINE` captures its match).
    // Processed fragments are accessed by calling `shiftNextLine`.
    var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
    var remainingLinesIndex = 0;
    var shiftNextLine = function() {
      var lineContents = getNextLine();
      // The last line of a file might not have a newline.
      var newLine = getNextLine() || "";
      return lineContents + newLine;

      function getNextLine() {
        return remainingLinesIndex < remainingLines.length ?
            remainingLines[remainingLinesIndex++] : undefined;
      }
    };

    // We need to remember the position of "remainingLines"
    var lastGeneratedLine = 1, lastGeneratedColumn = 0;

    // The generate SourceNodes we need a code range.
    // To extract it current and last mapping is used.
    // Here we store the last mapping.
    var lastMapping = null;

    aSourceMapConsumer.eachMapping(function (mapping) {
      if (lastMapping !== null) {
        // We add the code from "lastMapping" to "mapping":
        // First check if there is a new line in between.
        if (lastGeneratedLine < mapping.generatedLine) {
          // Associate first line with "lastMapping"
          addMappingWithCode(lastMapping, shiftNextLine());
          lastGeneratedLine++;
          lastGeneratedColumn = 0;
          // The remaining code is added without mapping
        } else {
          // There is no new line in between.
          // Associate the code between "lastGeneratedColumn" and
          // "mapping.generatedColumn" with "lastMapping"
          var nextLine = remainingLines[remainingLinesIndex] || '';
          var code = nextLine.substr(0, mapping.generatedColumn -
                                        lastGeneratedColumn);
          remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn -
                                              lastGeneratedColumn);
          lastGeneratedColumn = mapping.generatedColumn;
          addMappingWithCode(lastMapping, code);
          // No more remaining code, continue
          lastMapping = mapping;
          return;
        }
      }
      // We add the generated code until the first mapping
      // to the SourceNode without any mapping.
      // Each line is added as separate string.
      while (lastGeneratedLine < mapping.generatedLine) {
        node.add(shiftNextLine());
        lastGeneratedLine++;
      }
      if (lastGeneratedColumn < mapping.generatedColumn) {
        var nextLine = remainingLines[remainingLinesIndex] || '';
        node.add(nextLine.substr(0, mapping.generatedColumn));
        remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);
        lastGeneratedColumn = mapping.generatedColumn;
      }
      lastMapping = mapping;
    }, this);
    // We have processed all mappings.
    if (remainingLinesIndex < remainingLines.length) {
      if (lastMapping) {
        // Associate the remaining code in the current line with "lastMapping"
        addMappingWithCode(lastMapping, shiftNextLine());
      }
      // and add the remaining lines without any mapping
      node.add(remainingLines.splice(remainingLinesIndex).join(""));
    }

    // Copy sourcesContent into SourceNode
    aSourceMapConsumer.sources.forEach(function (sourceFile) {
      var content = aSourceMapConsumer.sourceContentFor(sourceFile);
      if (content != null) {
        if (aRelativePath != null) {
          sourceFile = util.join(aRelativePath, sourceFile);
        }
        node.setSourceContent(sourceFile, content);
      }
    });

    return node;

    function addMappingWithCode(mapping, code) {
      if (mapping === null || mapping.source === undefined) {
        node.add(code);
      } else {
        var source = aRelativePath
          ? util.join(aRelativePath, mapping.source)
          : mapping.source;
        node.add(new SourceNode$1(mapping.originalLine,
                                mapping.originalColumn,
                                source,
                                code,
                                mapping.name));
      }
    }
  };

/**
 * Add a chunk of generated JS to this source node.
 *
 * @param aChunk A string snippet of generated JS code, another instance of
 *        SourceNode, or an array where each member is one of those things.
 */
SourceNode$1.prototype.add = function SourceNode_add(aChunk) {
  if (Array.isArray(aChunk)) {
    aChunk.forEach(function (chunk) {
      this.add(chunk);
    }, this);
  }
  else if (aChunk[isSourceNode] || typeof aChunk === "string") {
    if (aChunk) {
      this.children.push(aChunk);
    }
  }
  else {
    throw new TypeError(
      "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
    );
  }
  return this;
};

/**
 * Add a chunk of generated JS to the beginning of this source node.
 *
 * @param aChunk A string snippet of generated JS code, another instance of
 *        SourceNode, or an array where each member is one of those things.
 */
SourceNode$1.prototype.prepend = function SourceNode_prepend(aChunk) {
  if (Array.isArray(aChunk)) {
    for (var i = aChunk.length-1; i >= 0; i--) {
      this.prepend(aChunk[i]);
    }
  }
  else if (aChunk[isSourceNode] || typeof aChunk === "string") {
    this.children.unshift(aChunk);
  }
  else {
    throw new TypeError(
      "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
    );
  }
  return this;
};

/**
 * Walk over the tree of JS snippets in this node and its children. The
 * walking function is called once for each snippet of JS and is passed that
 * snippet and the its original associated source's line/column location.
 *
 * @param aFn The traversal function.
 */
SourceNode$1.prototype.walk = function SourceNode_walk(aFn) {
  var chunk;
  for (var i = 0, len = this.children.length; i < len; i++) {
    chunk = this.children[i];
    if (chunk[isSourceNode]) {
      chunk.walk(aFn);
    }
    else {
      if (chunk !== '') {
        aFn(chunk, { source: this.source,
                     line: this.line,
                     column: this.column,
                     name: this.name });
      }
    }
  }
};

/**
 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
 * each of `this.children`.
 *
 * @param aSep The separator.
 */
SourceNode$1.prototype.join = function SourceNode_join(aSep) {
  var newChildren;
  var i;
  var len = this.children.length;
  if (len > 0) {
    newChildren = [];
    for (i = 0; i < len-1; i++) {
      newChildren.push(this.children[i]);
      newChildren.push(aSep);
    }
    newChildren.push(this.children[i]);
    this.children = newChildren;
  }
  return this;
};

/**
 * Call String.prototype.replace on the very right-most source snippet. Useful
 * for trimming whitespace from the end of a source node, etc.
 *
 * @param aPattern The pattern to replace.
 * @param aReplacement The thing to replace the pattern with.
 */
SourceNode$1.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
  var lastChild = this.children[this.children.length - 1];
  if (lastChild[isSourceNode]) {
    lastChild.replaceRight(aPattern, aReplacement);
  }
  else if (typeof lastChild === 'string') {
    this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
  }
  else {
    this.children.push(''.replace(aPattern, aReplacement));
  }
  return this;
};

/**
 * Set the source content for a source file. This will be added to the SourceMapGenerator
 * in the sourcesContent field.
 *
 * @param aSourceFile The filename of the source file
 * @param aSourceContent The content of the source file
 */
SourceNode$1.prototype.setSourceContent =
  function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
    this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
  };

/**
 * Walk over the tree of SourceNodes. The walking function is called for each
 * source file content and is passed the filename and source content.
 *
 * @param aFn The traversal function.
 */
SourceNode$1.prototype.walkSourceContents =
  function SourceNode_walkSourceContents(aFn) {
    for (var i = 0, len = this.children.length; i < len; i++) {
      if (this.children[i][isSourceNode]) {
        this.children[i].walkSourceContents(aFn);
      }
    }

    var sources = Object.keys(this.sourceContents);
    for (var i = 0, len = sources.length; i < len; i++) {
      aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
    }
  };

/**
 * Return the string representation of this source node. Walks over the tree
 * and concatenates all the various snippets together to one string.
 */
SourceNode$1.prototype.toString = function SourceNode_toString() {
  var str = "";
  this.walk(function (chunk) {
    str += chunk;
  });
  return str;
};

/**
 * Returns the string representation of this source node along with a source
 * map.
 */
SourceNode$1.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
  var generated = {
    code: "",
    line: 1,
    column: 0
  };
  var map = new SourceMapGenerator$1(aArgs);
  var sourceMappingActive = false;
  var lastOriginalSource = null;
  var lastOriginalLine = null;
  var lastOriginalColumn = null;
  var lastOriginalName = null;
  this.walk(function (chunk, original) {
    generated.code += chunk;
    if (original.source !== null
        && original.line !== null
        && original.column !== null) {
      if(lastOriginalSource !== original.source
         || lastOriginalLine !== original.line
         || lastOriginalColumn !== original.column
         || lastOriginalName !== original.name) {
        map.addMapping({
          source: original.source,
          original: {
            line: original.line,
            column: original.column
          },
          generated: {
            line: generated.line,
            column: generated.column
          },
          name: original.name
        });
      }
      lastOriginalSource = original.source;
      lastOriginalLine = original.line;
      lastOriginalColumn = original.column;
      lastOriginalName = original.name;
      sourceMappingActive = true;
    } else if (sourceMappingActive) {
      map.addMapping({
        generated: {
          line: generated.line,
          column: generated.column
        }
      });
      lastOriginalSource = null;
      sourceMappingActive = false;
    }
    for (var idx = 0, length = chunk.length; idx < length; idx++) {
      if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
        generated.line++;
        generated.column = 0;
        // Mappings end at eol
        if (idx + 1 === length) {
          lastOriginalSource = null;
          sourceMappingActive = false;
        } else if (sourceMappingActive) {
          map.addMapping({
            source: original.source,
            original: {
              line: original.line,
              column: original.column
            },
            generated: {
              line: generated.line,
              column: generated.column
            },
            name: original.name
          });
        }
      } else {
        generated.column++;
      }
    }
  });
  this.walkSourceContents(function (sourceFile, sourceContent) {
    map.setSourceContent(sourceFile, sourceContent);
  });

  return { code: generated.code, map: map };
};

var SourceNode_1 = SourceNode$1;

var sourceNode = {
	SourceNode: SourceNode_1
};

/*
 * Copyright 2009-2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE.txt or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

var SourceMapGenerator = sourceMapGenerator.SourceMapGenerator;
var SourceMapConsumer = sourceMapConsumer.SourceMapConsumer;
var SourceNode = sourceNode.SourceNode;

var sourceMap = {
	SourceMapGenerator: SourceMapGenerator,
	SourceMapConsumer: SourceMapConsumer,
	SourceNode: SourceNode
};

/* global define, require */

var codeGen = createCommonjsModule(function (module, exports) {

exports.__esModule = true;



var SourceNode = undefined;

try {
  /* istanbul ignore next */
  if (typeof undefined !== 'function' || !undefined.amd) {
    // We don't support this in AMD environments. For these environments, we assume that
    // they are running on the browser and thus have no need for the source-map library.
    var SourceMap = sourceMap;
    SourceNode = SourceMap.SourceNode;
  }
} catch (err) {}
/* NOP */

/* istanbul ignore if: tested but not covered in istanbul due to dist build  */
if (!SourceNode) {
  SourceNode = function (line, column, srcFile, chunks) {
    this.src = '';
    if (chunks) {
      this.add(chunks);
    }
  };
  /* istanbul ignore next */
  SourceNode.prototype = {
    add: function add(chunks) {
      if (utils.isArray(chunks)) {
        chunks = chunks.join('');
      }
      this.src += chunks;
    },
    prepend: function prepend(chunks) {
      if (utils.isArray(chunks)) {
        chunks = chunks.join('');
      }
      this.src = chunks + this.src;
    },
    toStringWithSourceMap: function toStringWithSourceMap() {
      return { code: this.toString() };
    },
    toString: function toString() {
      return this.src;
    }
  };
}

function castChunk(chunk, codeGen, loc) {
  if (utils.isArray(chunk)) {
    var ret = [];

    for (var i = 0, len = chunk.length; i < len; i++) {
      ret.push(codeGen.wrap(chunk[i], loc));
    }
    return ret;
  } else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
    // Handle primitives that the SourceNode will throw up on
    return chunk + '';
  }
  return chunk;
}

function CodeGen(srcFile) {
  this.srcFile = srcFile;
  this.source = [];
}

CodeGen.prototype = {
  isEmpty: function isEmpty() {
    return !this.source.length;
  },
  prepend: function prepend(source, loc) {
    this.source.unshift(this.wrap(source, loc));
  },
  push: function push(source, loc) {
    this.source.push(this.wrap(source, loc));
  },

  merge: function merge() {
    var source = this.empty();
    this.each(function (line) {
      source.add(['  ', line, '\n']);
    });
    return source;
  },

  each: function each(iter) {
    for (var i = 0, len = this.source.length; i < len; i++) {
      iter(this.source[i]);
    }
  },

  empty: function empty() {
    var loc = this.currentLocation || { start: {} };
    return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
  },
  wrap: function wrap(chunk) {
    var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1];

    if (chunk instanceof SourceNode) {
      return chunk;
    }

    chunk = castChunk(chunk, this, loc);

    return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
  },

  functionCall: function functionCall(fn, type, params) {
    params = this.generateList(params);
    return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
  },

  quotedString: function quotedString(str) {
    return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
    .replace(/\u2029/g, '\\u2029') + '"';
  },

  objectLiteral: function objectLiteral(obj) {
    // istanbul ignore next

    var _this = this;

    var pairs = [];

    Object.keys(obj).forEach(function (key) {
      var value = castChunk(obj[key], _this);
      if (value !== 'undefined') {
        pairs.push([_this.quotedString(key), ':', value]);
      }
    });

    var ret = this.generateList(pairs);
    ret.prepend('{');
    ret.add('}');
    return ret;
  },

  generateList: function generateList(entries) {
    var ret = this.empty();

    for (var i = 0, len = entries.length; i < len; i++) {
      if (i) {
        ret.add(',');
      }

      ret.add(castChunk(entries[i], this));
    }

    return ret;
  },

  generateArray: function generateArray(entries) {
    var ret = this.generateList(entries);
    ret.prepend('[');
    ret.add(']');

    return ret;
  }
};

exports['default'] = CodeGen;
module.exports = exports['default'];

});

var javascriptCompiler = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }





var _exception2 = _interopRequireDefault(exception);





var _codeGen2 = _interopRequireDefault(codeGen);

function Literal(value) {
  this.value = value;
}

function JavaScriptCompiler() {}

JavaScriptCompiler.prototype = {
  // PUBLIC API: You can override these methods in a subclass to provide
  // alternative compiled forms for name lookup and buffering semantics
  nameLookup: function nameLookup(parent, name /*,  type */) {
    return this.internalNameLookup(parent, name);
  },
  depthedLookup: function depthedLookup(name) {
    return [this.aliasable('container.lookup'), '(depths, ', JSON.stringify(name), ')'];
  },

  compilerInfo: function compilerInfo() {
    var revision = base$1.COMPILER_REVISION,
        versions = base$1.REVISION_CHANGES[revision];
    return [revision, versions];
  },

  appendToBuffer: function appendToBuffer(source, location, explicit) {
    // Force a source as this simplifies the merge logic.
    if (!utils.isArray(source)) {
      source = [source];
    }
    source = this.source.wrap(source, location);

    if (this.environment.isSimple) {
      return ['return ', source, ';'];
    } else if (explicit) {
      // This is a case where the buffer operation occurs as a child of another
      // construct, generally braces. We have to explicitly output these buffer
      // operations to ensure that the emitted code goes in the correct location.
      return ['buffer += ', source, ';'];
    } else {
      source.appendToBuffer = true;
      return source;
    }
  },

  initializeBuffer: function initializeBuffer() {
    return this.quotedString('');
  },
  // END PUBLIC API
  internalNameLookup: function internalNameLookup(parent, name) {
    this.lookupPropertyFunctionIsUsed = true;
    return ['lookupProperty(', parent, ',', JSON.stringify(name), ')'];
  },

  lookupPropertyFunctionIsUsed: false,

  compile: function compile(environment, options, context, asObject) {
    this.environment = environment;
    this.options = options;
    this.stringParams = this.options.stringParams;
    this.trackIds = this.options.trackIds;
    this.precompile = !asObject;

    this.name = this.environment.name;
    this.isChild = !!context;
    this.context = context || {
      decorators: [],
      programs: [],
      environments: []
    };

    this.preamble();

    this.stackSlot = 0;
    this.stackVars = [];
    this.aliases = {};
    this.registers = { list: [] };
    this.hashes = [];
    this.compileStack = [];
    this.inlineStack = [];
    this.blockParams = [];

    this.compileChildren(environment, options);

    this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat;
    this.useBlockParams = this.useBlockParams || environment.useBlockParams;

    var opcodes = environment.opcodes,
        opcode = undefined,
        firstLoc = undefined,
        i = undefined,
        l = undefined;

    for (i = 0, l = opcodes.length; i < l; i++) {
      opcode = opcodes[i];

      this.source.currentLocation = opcode.loc;
      firstLoc = firstLoc || opcode.loc;
      this[opcode.opcode].apply(this, opcode.args);
    }

    // Flush any trailing content that might be pending.
    this.source.currentLocation = firstLoc;
    this.pushSource('');

    /* istanbul ignore next */
    if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
      throw new _exception2['default']('Compile completed with content left on stack');
    }

    if (!this.decorators.isEmpty()) {
      this.useDecorators = true;

      this.decorators.prepend(['var decorators = container.decorators, ', this.lookupPropertyFunctionVarDeclaration(), ';\n']);
      this.decorators.push('return fn;');

      if (asObject) {
        this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]);
      } else {
        this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n');
        this.decorators.push('}\n');
        this.decorators = this.decorators.merge();
      }
    } else {
      this.decorators = undefined;
    }

    var fn = this.createFunctionContext(asObject);
    if (!this.isChild) {
      var ret = {
        compiler: this.compilerInfo(),
        main: fn
      };

      if (this.decorators) {
        ret.main_d = this.decorators; // eslint-disable-line camelcase
        ret.useDecorators = true;
      }

      var _context = this.context;
      var programs = _context.programs;
      var decorators = _context.decorators;

      for (i = 0, l = programs.length; i < l; i++) {
        if (programs[i]) {
          ret[i] = programs[i];
          if (decorators[i]) {
            ret[i + '_d'] = decorators[i];
            ret.useDecorators = true;
          }
        }
      }

      if (this.environment.usePartial) {
        ret.usePartial = true;
      }
      if (this.options.data) {
        ret.useData = true;
      }
      if (this.useDepths) {
        ret.useDepths = true;
      }
      if (this.useBlockParams) {
        ret.useBlockParams = true;
      }
      if (this.options.compat) {
        ret.compat = true;
      }

      if (!asObject) {
        ret.compiler = JSON.stringify(ret.compiler);

        this.source.currentLocation = { start: { line: 1, column: 0 } };
        ret = this.objectLiteral(ret);

        if (options.srcName) {
          ret = ret.toStringWithSourceMap({ file: options.destName });
          ret.map = ret.map && ret.map.toString();
        } else {
          ret = ret.toString();
        }
      } else {
        ret.compilerOptions = this.options;
      }

      return ret;
    } else {
      return fn;
    }
  },

  preamble: function preamble() {
    // track the last context pushed into place to allow skipping the
    // getContext opcode when it would be a noop
    this.lastContext = 0;
    this.source = new _codeGen2['default'](this.options.srcName);
    this.decorators = new _codeGen2['default'](this.options.srcName);
  },

  createFunctionContext: function createFunctionContext(asObject) {
    // istanbul ignore next

    var _this = this;

    var varDeclarations = '';

    var locals = this.stackVars.concat(this.registers.list);
    if (locals.length > 0) {
      varDeclarations += ', ' + locals.join(', ');
    }

    // Generate minimizer alias mappings
    //
    // When using true SourceNodes, this will update all references to the given alias
    // as the source nodes are reused in situ. For the non-source node compilation mode,
    // aliases will not be used, but this case is already being run on the client and
    // we aren't concern about minimizing the template size.
    var aliasCount = 0;
    Object.keys(this.aliases).forEach(function (alias) {
      var node = _this.aliases[alias];
      if (node.children && node.referenceCount > 1) {
        varDeclarations += ', alias' + ++aliasCount + '=' + alias;
        node.children[0] = 'alias' + aliasCount;
      }
    });

    if (this.lookupPropertyFunctionIsUsed) {
      varDeclarations += ', ' + this.lookupPropertyFunctionVarDeclaration();
    }

    var params = ['container', 'depth0', 'helpers', 'partials', 'data'];

    if (this.useBlockParams || this.useDepths) {
      params.push('blockParams');
    }
    if (this.useDepths) {
      params.push('depths');
    }

    // Perform a second pass over the output to merge content when possible
    var source = this.mergeSource(varDeclarations);

    if (asObject) {
      params.push(source);

      return Function.apply(this, params);
    } else {
      return this.source.wrap(['function(', params.join(','), ') {\n  ', source, '}']);
    }
  },
  mergeSource: function mergeSource(varDeclarations) {
    var isSimple = this.environment.isSimple,
        appendOnly = !this.forceBuffer,
        appendFirst = undefined,
        sourceSeen = undefined,
        bufferStart = undefined,
        bufferEnd = undefined;
    this.source.each(function (line) {
      if (line.appendToBuffer) {
        if (bufferStart) {
          line.prepend('  + ');
        } else {
          bufferStart = line;
        }
        bufferEnd = line;
      } else {
        if (bufferStart) {
          if (!sourceSeen) {
            appendFirst = true;
          } else {
            bufferStart.prepend('buffer += ');
          }
          bufferEnd.add(';');
          bufferStart = bufferEnd = undefined;
        }

        sourceSeen = true;
        if (!isSimple) {
          appendOnly = false;
        }
      }
    });

    if (appendOnly) {
      if (bufferStart) {
        bufferStart.prepend('return ');
        bufferEnd.add(';');
      } else if (!sourceSeen) {
        this.source.push('return "";');
      }
    } else {
      varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer());

      if (bufferStart) {
        bufferStart.prepend('return buffer + ');
        bufferEnd.add(';');
      } else {
        this.source.push('return buffer;');
      }
    }

    if (varDeclarations) {
      this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
    }

    return this.source.merge();
  },

  lookupPropertyFunctionVarDeclaration: function lookupPropertyFunctionVarDeclaration() {
    return '\n      lookupProperty = container.lookupProperty || function(parent, propertyName) {\n        if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {\n          return parent[propertyName];\n        }\n        return undefined\n    }\n    '.trim();
  },

  // [blockValue]
  //
  // On stack, before: hash, inverse, program, value
  // On stack, after: return value of blockHelperMissing
  //
  // The purpose of this opcode is to take a block of the form
  // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
  // replace it on the stack with the result of properly
  // invoking blockHelperMissing.
  blockValue: function blockValue(name) {
    var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
        params = [this.contextName(0)];
    this.setupHelperArgs(name, 0, params);

    var blockName = this.popStack();
    params.splice(1, 0, blockName);

    this.push(this.source.functionCall(blockHelperMissing, 'call', params));
  },

  // [ambiguousBlockValue]
  //
  // On stack, before: hash, inverse, program, value
  // Compiler value, before: lastHelper=value of last found helper, if any
  // On stack, after, if no lastHelper: same as [blockValue]
  // On stack, after, if lastHelper: value
  ambiguousBlockValue: function ambiguousBlockValue() {
    // We're being a bit cheeky and reusing the options value from the prior exec
    var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
        params = [this.contextName(0)];
    this.setupHelperArgs('', 0, params, true);

    this.flushInline();

    var current = this.topStack();
    params.splice(1, 0, current);

    this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']);
  },

  // [appendContent]
  //
  // On stack, before: ...
  // On stack, after: ...
  //
  // Appends the string value of `content` to the current buffer
  appendContent: function appendContent(content) {
    if (this.pendingContent) {
      content = this.pendingContent + content;
    } else {
      this.pendingLocation = this.source.currentLocation;
    }

    this.pendingContent = content;
  },

  // [append]
  //
  // On stack, before: value, ...
  // On stack, after: ...
  //
  // Coerces `value` to a String and appends it to the current buffer.
  //
  // If `value` is truthy, or 0, it is coerced into a string and appended
  // Otherwise, the empty string is appended
  append: function append() {
    if (this.isInline()) {
      this.replaceStack(function (current) {
        return [' != null ? ', current, ' : ""'];
      });

      this.pushSource(this.appendToBuffer(this.popStack()));
    } else {
      var local = this.popStack();
      this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
      if (this.environment.isSimple) {
        this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
      }
    }
  },

  // [appendEscaped]
  //
  // On stack, before: value, ...
  // On stack, after: ...
  //
  // Escape `value` and append it to the buffer
  appendEscaped: function appendEscaped() {
    this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')']));
  },

  // [getContext]
  //
  // On stack, before: ...
  // On stack, after: ...
  // Compiler value, after: lastContext=depth
  //
  // Set the value of the `lastContext` compiler value to the depth
  getContext: function getContext(depth) {
    this.lastContext = depth;
  },

  // [pushContext]
  //
  // On stack, before: ...
  // On stack, after: currentContext, ...
  //
  // Pushes the value of the current context onto the stack.
  pushContext: function pushContext() {
    this.pushStackLiteral(this.contextName(this.lastContext));
  },

  // [lookupOnContext]
  //
  // On stack, before: ...
  // On stack, after: currentContext[name], ...
  //
  // Looks up the value of `name` on the current context and pushes
  // it onto the stack.
  lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) {
    var i = 0;

    if (!scoped && this.options.compat && !this.lastContext) {
      // The depthed query is expected to handle the undefined logic for the root level that
      // is implemented below, so we evaluate that directly in compat mode
      this.push(this.depthedLookup(parts[i++]));
    } else {
      this.pushContext();
    }

    this.resolvePath('context', parts, i, falsy, strict);
  },

  // [lookupBlockParam]
  //
  // On stack, before: ...
  // On stack, after: blockParam[name], ...
  //
  // Looks up the value of `parts` on the given block param and pushes
  // it onto the stack.
  lookupBlockParam: function lookupBlockParam(blockParamId, parts) {
    this.useBlockParams = true;

    this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
    this.resolvePath('context', parts, 1);
  },

  // [lookupData]
  //
  // On stack, before: ...
  // On stack, after: data, ...
  //
  // Push the data lookup operator
  lookupData: function lookupData(depth, parts, strict) {
    if (!depth) {
      this.pushStackLiteral('data');
    } else {
      this.pushStackLiteral('container.data(data, ' + depth + ')');
    }

    this.resolvePath('data', parts, 0, true, strict);
  },

  resolvePath: function resolvePath(type, parts, i, falsy, strict) {
    // istanbul ignore next

    var _this2 = this;

    if (this.options.strict || this.options.assumeObjects) {
      this.push(strictLookup(this.options.strict && strict, this, parts, i, type));
      return;
    }

    var len = parts.length;
    for (; i < len; i++) {
      /* eslint-disable no-loop-func */
      this.replaceStack(function (current) {
        var lookup = _this2.nameLookup(current, parts[i], type);
        // We want to ensure that zero and false are handled properly if the context (falsy flag)
        // needs to have the special handling for these values.
        if (!falsy) {
          return [' != null ? ', lookup, ' : ', current];
        } else {
          // Otherwise we can use generic falsy handling
          return [' && ', lookup];
        }
      });
      /* eslint-enable no-loop-func */
    }
  },

  // [resolvePossibleLambda]
  //
  // On stack, before: value, ...
  // On stack, after: resolved value, ...
  //
  // If the `value` is a lambda, replace it on the stack by
  // the return value of the lambda
  resolvePossibleLambda: function resolvePossibleLambda() {
    this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
  },

  // [pushStringParam]
  //
  // On stack, before: ...
  // On stack, after: string, currentContext, ...
  //
  // This opcode is designed for use in string mode, which
  // provides the string value of a parameter along with its
  // depth rather than resolving it immediately.
  pushStringParam: function pushStringParam(string, type) {
    this.pushContext();
    this.pushString(type);

    // If it's a subexpression, the string result
    // will be pushed after this opcode.
    if (type !== 'SubExpression') {
      if (typeof string === 'string') {
        this.pushString(string);
      } else {
        this.pushStackLiteral(string);
      }
    }
  },

  emptyHash: function emptyHash(omitEmpty) {
    if (this.trackIds) {
      this.push('{}'); // hashIds
    }
    if (this.stringParams) {
      this.push('{}'); // hashContexts
      this.push('{}'); // hashTypes
    }
    this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
  },
  pushHash: function pushHash() {
    if (this.hash) {
      this.hashes.push(this.hash);
    }
    this.hash = { values: {}, types: [], contexts: [], ids: [] };
  },
  popHash: function popHash() {
    var hash = this.hash;
    this.hash = this.hashes.pop();

    if (this.trackIds) {
      this.push(this.objectLiteral(hash.ids));
    }
    if (this.stringParams) {
      this.push(this.objectLiteral(hash.contexts));
      this.push(this.objectLiteral(hash.types));
    }

    this.push(this.objectLiteral(hash.values));
  },

  // [pushString]
  //
  // On stack, before: ...
  // On stack, after: quotedString(string), ...
  //
  // Push a quoted version of `string` onto the stack
  pushString: function pushString(string) {
    this.pushStackLiteral(this.quotedString(string));
  },

  // [pushLiteral]
  //
  // On stack, before: ...
  // On stack, after: value, ...
  //
  // Pushes a value onto the stack. This operation prevents
  // the compiler from creating a temporary variable to hold
  // it.
  pushLiteral: function pushLiteral(value) {
    this.pushStackLiteral(value);
  },

  // [pushProgram]
  //
  // On stack, before: ...
  // On stack, after: program(guid), ...
  //
  // Push a program expression onto the stack. This takes
  // a compile-time guid and converts it into a runtime-accessible
  // expression.
  pushProgram: function pushProgram(guid) {
    if (guid != null) {
      this.pushStackLiteral(this.programExpression(guid));
    } else {
      this.pushStackLiteral(null);
    }
  },

  // [registerDecorator]
  //
  // On stack, before: hash, program, params..., ...
  // On stack, after: ...
  //
  // Pops off the decorator's parameters, invokes the decorator,
  // and inserts the decorator into the decorators list.
  registerDecorator: function registerDecorator(paramSize, name) {
    var foundDecorator = this.nameLookup('decorators', name, 'decorator'),
        options = this.setupHelperArgs(name, paramSize);

    this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']);
  },

  // [invokeHelper]
  //
  // On stack, before: hash, inverse, program, params..., ...
  // On stack, after: result of helper invocation
  //
  // Pops off the helper's parameters, invokes the helper,
  // and pushes the helper's return value onto the stack.
  //
  // If the helper is not found, `helperMissing` is called.
  invokeHelper: function invokeHelper(paramSize, name, isSimple) {
    var nonHelper = this.popStack(),
        helper = this.setupHelper(paramSize, name);

    var possibleFunctionCalls = [];

    if (isSimple) {
      // direct call to helper
      possibleFunctionCalls.push(helper.name);
    }
    // call a function from the input object
    possibleFunctionCalls.push(nonHelper);
    if (!this.options.strict) {
      possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing'));
    }

    var functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')'];
    var functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams);
    this.push(functionCall);
  },

  itemsSeparatedBy: function itemsSeparatedBy(items, separator) {
    var result = [];
    result.push(items[0]);
    for (var i = 1; i < items.length; i++) {
      result.push(separator, items[i]);
    }
    return result;
  },
  // [invokeKnownHelper]
  //
  // On stack, before: hash, inverse, program, params..., ...
  // On stack, after: result of helper invocation
  //
  // This operation is used when the helper is known to exist,
  // so a `helperMissing` fallback is not required.
  invokeKnownHelper: function invokeKnownHelper(paramSize, name) {
    var helper = this.setupHelper(paramSize, name);
    this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
  },

  // [invokeAmbiguous]
  //
  // On stack, before: hash, inverse, program, params..., ...
  // On stack, after: result of disambiguation
  //
  // This operation is used when an expression like `{{foo}}`
  // is provided, but we don't know at compile-time whether it
  // is a helper or a path.
  //
  // This operation emits more code than the other options,
  // and can be avoided by passing the `knownHelpers` and
  // `knownHelpersOnly` flags at compile-time.
  invokeAmbiguous: function invokeAmbiguous(name, helperCall) {
    this.useRegister('helper');

    var nonHelper = this.popStack();

    this.emptyHash();
    var helper = this.setupHelper(0, name, helperCall);

    var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');

    var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
    if (!this.options.strict) {
      lookup[0] = '(helper = ';
      lookup.push(' != null ? helper : ', this.aliasable('container.hooks.helperMissing'));
    }

    this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']);
  },

  // [invokePartial]
  //
  // On stack, before: context, ...
  // On stack after: result of partial invocation
  //
  // This operation pops off a context, invokes a partial with that context,
  // and pushes the result of the invocation back.
  invokePartial: function invokePartial(isDynamic, name, indent) {
    var params = [],
        options = this.setupParams(name, 1, params);

    if (isDynamic) {
      name = this.popStack();
      delete options.name;
    }

    if (indent) {
      options.indent = JSON.stringify(indent);
    }
    options.helpers = 'helpers';
    options.partials = 'partials';
    options.decorators = 'container.decorators';

    if (!isDynamic) {
      params.unshift(this.nameLookup('partials', name, 'partial'));
    } else {
      params.unshift(name);
    }

    if (this.options.compat) {
      options.depths = 'depths';
    }
    options = this.objectLiteral(options);
    params.push(options);

    this.push(this.source.functionCall('container.invokePartial', '', params));
  },

  // [assignToHash]
  //
  // On stack, before: value, ..., hash, ...
  // On stack, after: ..., hash, ...
  //
  // Pops a value off the stack and assigns it to the current hash
  assignToHash: function assignToHash(key) {
    var value = this.popStack(),
        context = undefined,
        type = undefined,
        id = undefined;

    if (this.trackIds) {
      id = this.popStack();
    }
    if (this.stringParams) {
      type = this.popStack();
      context = this.popStack();
    }

    var hash = this.hash;
    if (context) {
      hash.contexts[key] = context;
    }
    if (type) {
      hash.types[key] = type;
    }
    if (id) {
      hash.ids[key] = id;
    }
    hash.values[key] = value;
  },

  pushId: function pushId(type, name, child) {
    if (type === 'BlockParam') {
      this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : ''));
    } else if (type === 'PathExpression') {
      this.pushString(name);
    } else if (type === 'SubExpression') {
      this.pushStackLiteral('true');
    } else {
      this.pushStackLiteral('null');
    }
  },

  // HELPERS

  compiler: JavaScriptCompiler,

  compileChildren: function compileChildren(environment, options) {
    var children = environment.children,
        child = undefined,
        compiler = undefined;

    for (var i = 0, l = children.length; i < l; i++) {
      child = children[i];
      compiler = new this.compiler(); // eslint-disable-line new-cap

      var existing = this.matchExistingProgram(child);

      if (existing == null) {
        this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
        var index = this.context.programs.length;
        child.index = index;
        child.name = 'program' + index;
        this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
        this.context.decorators[index] = compiler.decorators;
        this.context.environments[index] = child;

        this.useDepths = this.useDepths || compiler.useDepths;
        this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
        child.useDepths = this.useDepths;
        child.useBlockParams = this.useBlockParams;
      } else {
        child.index = existing.index;
        child.name = 'program' + existing.index;

        this.useDepths = this.useDepths || existing.useDepths;
        this.useBlockParams = this.useBlockParams || existing.useBlockParams;
      }
    }
  },
  matchExistingProgram: function matchExistingProgram(child) {
    for (var i = 0, len = this.context.environments.length; i < len; i++) {
      var environment = this.context.environments[i];
      if (environment && environment.equals(child)) {
        return environment;
      }
    }
  },

  programExpression: function programExpression(guid) {
    var child = this.environment.children[guid],
        programParams = [child.index, 'data', child.blockParams];

    if (this.useBlockParams || this.useDepths) {
      programParams.push('blockParams');
    }
    if (this.useDepths) {
      programParams.push('depths');
    }

    return 'container.program(' + programParams.join(', ') + ')';
  },

  useRegister: function useRegister(name) {
    if (!this.registers[name]) {
      this.registers[name] = true;
      this.registers.list.push(name);
    }
  },

  push: function push(expr) {
    if (!(expr instanceof Literal)) {
      expr = this.source.wrap(expr);
    }

    this.inlineStack.push(expr);
    return expr;
  },

  pushStackLiteral: function pushStackLiteral(item) {
    this.push(new Literal(item));
  },

  pushSource: function pushSource(source) {
    if (this.pendingContent) {
      this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
      this.pendingContent = undefined;
    }

    if (source) {
      this.source.push(source);
    }
  },

  replaceStack: function replaceStack(callback) {
    var prefix = ['('],
        stack = undefined,
        createdStack = undefined,
        usedLiteral = undefined;

    /* istanbul ignore next */
    if (!this.isInline()) {
      throw new _exception2['default']('replaceStack on non-inline');
    }

    // We want to merge the inline statement into the replacement statement via ','
    var top = this.popStack(true);

    if (top instanceof Literal) {
      // Literals do not need to be inlined
      stack = [top.value];
      prefix = ['(', stack];
      usedLiteral = true;
    } else {
      // Get or create the current stack name for use by the inline
      createdStack = true;
      var _name = this.incrStack();

      prefix = ['((', this.push(_name), ' = ', top, ')'];
      stack = this.topStack();
    }

    var item = callback.call(this, stack);

    if (!usedLiteral) {
      this.popStack();
    }
    if (createdStack) {
      this.stackSlot--;
    }
    this.push(prefix.concat(item, ')'));
  },

  incrStack: function incrStack() {
    this.stackSlot++;
    if (this.stackSlot > this.stackVars.length) {
      this.stackVars.push('stack' + this.stackSlot);
    }
    return this.topStackName();
  },
  topStackName: function topStackName() {
    return 'stack' + this.stackSlot;
  },
  flushInline: function flushInline() {
    var inlineStack = this.inlineStack;
    this.inlineStack = [];
    for (var i = 0, len = inlineStack.length; i < len; i++) {
      var entry = inlineStack[i];
      /* istanbul ignore if */
      if (entry instanceof Literal) {
        this.compileStack.push(entry);
      } else {
        var stack = this.incrStack();
        this.pushSource([stack, ' = ', entry, ';']);
        this.compileStack.push(stack);
      }
    }
  },
  isInline: function isInline() {
    return this.inlineStack.length;
  },

  popStack: function popStack(wrapped) {
    var inline = this.isInline(),
        item = (inline ? this.inlineStack : this.compileStack).pop();

    if (!wrapped && item instanceof Literal) {
      return item.value;
    } else {
      if (!inline) {
        /* istanbul ignore next */
        if (!this.stackSlot) {
          throw new _exception2['default']('Invalid stack pop');
        }
        this.stackSlot--;
      }
      return item;
    }
  },

  topStack: function topStack() {
    var stack = this.isInline() ? this.inlineStack : this.compileStack,
        item = stack[stack.length - 1];

    /* istanbul ignore if */
    if (item instanceof Literal) {
      return item.value;
    } else {
      return item;
    }
  },

  contextName: function contextName(context) {
    if (this.useDepths && context) {
      return 'depths[' + context + ']';
    } else {
      return 'depth' + context;
    }
  },

  quotedString: function quotedString(str) {
    return this.source.quotedString(str);
  },

  objectLiteral: function objectLiteral(obj) {
    return this.source.objectLiteral(obj);
  },

  aliasable: function aliasable(name) {
    var ret = this.aliases[name];
    if (ret) {
      ret.referenceCount++;
      return ret;
    }

    ret = this.aliases[name] = this.source.wrap(name);
    ret.aliasable = true;
    ret.referenceCount = 1;

    return ret;
  },

  setupHelper: function setupHelper(paramSize, name, blockHelper) {
    var params = [],
        paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
    var foundHelper = this.nameLookup('helpers', name, 'helper'),
        callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})');

    return {
      params: params,
      paramsInit: paramsInit,
      name: foundHelper,
      callParams: [callContext].concat(params)
    };
  },

  setupParams: function setupParams(helper, paramSize, params) {
    var options = {},
        contexts = [],
        types = [],
        ids = [],
        objectArgs = !params,
        param = undefined;

    if (objectArgs) {
      params = [];
    }

    options.name = this.quotedString(helper);
    options.hash = this.popStack();

    if (this.trackIds) {
      options.hashIds = this.popStack();
    }
    if (this.stringParams) {
      options.hashTypes = this.popStack();
      options.hashContexts = this.popStack();
    }

    var inverse = this.popStack(),
        program = this.popStack();

    // Avoid setting fn and inverse if neither are set. This allows
    // helpers to do a check for `if (options.fn)`
    if (program || inverse) {
      options.fn = program || 'container.noop';
      options.inverse = inverse || 'container.noop';
    }

    // The parameters go on to the stack in order (making sure that they are evaluated in order)
    // so we need to pop them off the stack in reverse order
    var i = paramSize;
    while (i--) {
      param = this.popStack();
      params[i] = param;

      if (this.trackIds) {
        ids[i] = this.popStack();
      }
      if (this.stringParams) {
        types[i] = this.popStack();
        contexts[i] = this.popStack();
      }
    }

    if (objectArgs) {
      options.args = this.source.generateArray(params);
    }

    if (this.trackIds) {
      options.ids = this.source.generateArray(ids);
    }
    if (this.stringParams) {
      options.types = this.source.generateArray(types);
      options.contexts = this.source.generateArray(contexts);
    }

    if (this.options.data) {
      options.data = 'data';
    }
    if (this.useBlockParams) {
      options.blockParams = 'blockParams';
    }
    return options;
  },

  setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) {
    var options = this.setupParams(helper, paramSize, params);
    options.loc = JSON.stringify(this.source.currentLocation);
    options = this.objectLiteral(options);
    if (useRegister) {
      this.useRegister('options');
      params.push('options');
      return ['options=', options];
    } else if (params) {
      params.push(options);
      return '';
    } else {
      return options;
    }
  }
};

(function () {
  var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' ');

  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};

  for (var i = 0, l = reservedWords.length; i < l; i++) {
    compilerWords[reservedWords[i]] = true;
  }
})();

/**
 * @deprecated May be removed in the next major version
 */
JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
  return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
};

function strictLookup(requireTerminal, compiler, parts, i, type) {
  var stack = compiler.popStack(),
      len = parts.length;
  if (requireTerminal) {
    len--;
  }

  for (; i < len; i++) {
    stack = compiler.nameLookup(stack, parts[i], type);
  }

  if (requireTerminal) {
    return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ', ', JSON.stringify(compiler.source.currentLocation), ' )'];
  } else {
    return stack;
  }
}

exports['default'] = JavaScriptCompiler;
module.exports = exports['default'];

});

var handlebars = createCommonjsModule(function (module, exports) {

exports.__esModule = true;
// istanbul ignore next

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }



var _handlebarsRuntime2 = _interopRequireDefault(handlebars_runtime);

// Compiler imports



var _handlebarsCompilerAst2 = _interopRequireDefault(ast);







var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(javascriptCompiler);



var _handlebarsCompilerVisitor2 = _interopRequireDefault(visitor);



var _handlebarsNoConflict2 = _interopRequireDefault(noConflict);

var _create = _handlebarsRuntime2['default'].create;
function create() {
  var hb = _create();

  hb.compile = function (input, options) {
    return compiler.compile(input, options, hb);
  };
  hb.precompile = function (input, options) {
    return compiler.precompile(input, options, hb);
  };

  hb.AST = _handlebarsCompilerAst2['default'];
  hb.Compiler = compiler.Compiler;
  hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default'];
  hb.Parser = base.parser;
  hb.parse = base.parse;
  hb.parseWithoutProcessing = base.parseWithoutProcessing;

  return hb;
}

var inst = create();
inst.create = create;

_handlebarsNoConflict2['default'](inst);

inst.Visitor = _handlebarsCompilerVisitor2['default'];

inst['default'] = inst;

exports['default'] = inst;
module.exports = exports['default'];

});

const Ligatures = {
    "Ꜳ": "AA",
    "Æ": "AE",
    "Ꜵ": "AO",
    "Ꜷ": "AU",
    "Ꜹ": "AV",
    "Ꜻ": "AV",
    "Ꜽ": "AY",
    "ꜳ": "aa",
    "æ": "ae",
    "ꜵ": "ao",
    "ꜷ": "au",
    "ꜹ": "av",
    "ꜻ": "av",
    "ꜽ": "ay",
    "🙰": "et",
    "ﬀ": "ff",
    "ﬃ": "ffi",
    "ﬄ": "ffl",
    "ﬁ": "fi",
    "ﬂ": "fl",
    "℔": "lb",
    "Ƕ": "Hv",
    "Ỻ": "lL",
    "Œ": "OE",
    "Ꝏ": "OO",
    "ƕ": "hv",
    "ỻ": "ll",
    "œ": "oe",
    "ꝏ": "oo",
    "ꭢ": "ɔe",
    "ﬆ": "st",
    "ﬅ": "ſt",
    "ᵫ": "ue",
    "ꭣ": "uo",
    "ẞ": "ſs",
    "Ꜩ": "TZ",
    "W": "VV",
    "Ꝡ": "VY",
    "ß": "ſz",
    "ꜩ": "tz",
    // "w": "vv",
    "ꝡ": "vy",
    "ꬱ": "aə",
    "ꭁ": "əø",
    "ȸ": "db",
    "ʣ": "dz",
    "ꭦ": "dʐ",
    "ʥ": "dʑ",
    "ʤ": "dʒ",
    "ʩ": "fŋ",
    "ʪ": "ls",
    "ʫ": "lz",
    "ɮ": "lʒ",
    "ꭀ": "oə",
    "ȹ": "qp[c]",
    "ʨ": "tɕ",
    "ʦ": "ts",
    "ꭧ": "tʂ",
    "ʧ": "tʃ",
    "ꭐ": "ui",
    "ꭑ": "ui",
    "ɯ": "uu",
};
const GreekLetters = {
    'α': '\\alpha',
    'β': '\\beta',
    'γ': '\\gamma',
    'δ': '\\delta',
    'ε': '\\varepsilon',
    'ζ': '\\zeta',
    'η': '\\eta',
    'θ': '\\theta',
    'ι': '\\iota',
    'κ': '\\kappa',
    'λ': '\\lambda',
    'μ': '\\mu',
    'ν': '\\nu',
    'ξ': '\\xi',
    'ο': '\\omicron',
    'π': '\\pi',
    'ρ': '\\rho',
    'σ': '\\sigma',
    'τ': '\\tau',
    'υ': '\\upsilon',
    'φ': '\\varphi',
    'χ': '\\chi',
    'ψ': '\\psi',
    'ω': '\\omega',
    'Α': '\\Alpha',
    'Β': '\\Beta',
    'Γ': '\\Gamma',
    'Δ': '\\Delta',
    'Ε': '\\Epsilon',
    'Ζ': '\\Zeta',
    'Η': '\\Eta',
    'Θ': '\\Theta',
    'Ι': '\\Iota',
    'Κ': '\\Kappa',
    'Λ': '\\Lambda',
    'Μ': '\\Mu',
    'Ν': '\\Nu',
    'Ξ': '\\Xi',
    'Ο': '\\Omicron',
    'Π': '\\Pi',
    'Ρ': '\\Rho',
    'Σ': '\\Sigma',
    'Τ': '\\Tau',
    'Υ': '\\Upsilon',
    'Φ': '\\Phi',
    'Χ': '\\Chi',
    'Ψ': '\\Psi',
    'Ω': '\\Omega',
    ' ̃': '\\tilde ',
    '∞': '\\infty',
    '≠': '\\neq',
    '≤': '\\leq',
    '≥': '\\geq',
    ',...,': ',\\dots,',
    '∂': '\\partial',
};

function stringFormat(str, values) {
    return str.replace(/\{(\w+)\}/g, (match, key) => values[key] === undefined ? match : values[key]);
}
const LC = "[\\w\\u0400-\\u04FFåäöÅÄÖ]"; // Latin and Cyrillic and Swedish characters
function capitalizeWord(str) {
    var rx = new RegExp(LC + "\\S*", "g");
    return str.replace(rx, function (t) {
        return t.charAt(0).toUpperCase() + t.substr(1);
    });
}
function capitalizeSentence(s) {
    let lcp = "(" + LC + "+)"; // LC plus
    var rx = new RegExp(String.raw `(?:^|[\n"“]|[\.\!\?\~#]\s+|\s*- \s*)` + lcp, "g");
    return s.replace(rx, function (t0, t) {
        if (/^(ve|t|m|d|ll|s|re)$/.test(t)) {
            return t0;
        }
        else {
            return t0.replace(t, t.charAt(0).toUpperCase() + t.substr(1));
        }
    });
}
function headingLevel(s, upper = true, minLevel, isMultiLine) {
    let ignorePlain = minLevel > 0;
    let offset = 0;
    if (upper) {
        let prefix = `#`;
        if (!/^#+\s/.test(s)) { // plain text (not a heading)
            if (isMultiLine) {
                return { text: s, offset: offset };
            }
            prefix = `# `;
        }
        s = prefix + s;
        offset = prefix.length;
    }
    else { //: LOWER
        if (/^# /.test(s)) { //: heading level 1
            if (ignorePlain) {
                console.log("ignore plain text");
                return { text: s, offset: offset };
            }
            s = s.slice(2);
            offset = -2;
        }
        else if (/^#+ /.test(s)) {
            s = s.slice(1);
            offset = -1;
        }
    }
    return { text: s, offset: offset };
}
function ankiSelection(str) {
    let sections = str.split(/\r?\n/);
    var seclen = sections.length;
    let returned = "";
    if (sections[0] == "") {
        sections.shift();
        returned += "\n";
    }
    if (seclen > 1) {
        returned += "START\nCloze\n";
        let i = 1;
        let gap = 0;
        sections.forEach(function (entry) {
            if (entry != "" && gap > 0) {
                returned += "\nBack Extra:\nTags:\nEND\n";
                for (let n = 0; n < gap; n++) {
                    returned += "\n";
                }
                returned += "START\nCloze\n";
                gap = 0;
                i = 1;
            }
            if (entry != "") {
                returned += "{{c" + i + "::" + entry + "}} ";
                i++;
            }
            else {
                gap++;
            }
        });
        returned += "\nBack Extra:\nTags:\nEND";
        for (let n = 0; n < gap; n++) {
            returned += "\n";
        }
        return returned;
    }
    else {
        return str;
    }
}
function removeAllSpaces(s) {
    return s.replace(/(?:[^\)\]\:#\-]) +| +$/g, (t) => t.replace(/ +/g, ""));
}
function zoteroNote(text, regexp, template) {
    let template_regexp = new RegExp(regexp);
    let result = template_regexp.exec(text);
    if (result) {
        let z = result.groups;
        let text = result.groups.text.replace(/\\\[\d+\\\]/g, (t) => t.replace("\\[", "[").replace("\\]", "]"));
        // console.log(template);
        // @ts-ignore
        return template.format({
            text: text,
            item: z.item,
            pdf_url: z.pdf_url,
        });
    }
    else {
        return text;
    }
}
function table2bullet(content, withHeader = false) {
    let header_str = "";
    let output = "";
    // remove header from `content` but record the header string
    content = content.replace(/[\S\s]+\n[:\-\| ]+\|\n/g, (t) => {
        header_str = t
            .match(/^[\S ]+/)[0]
            .replace(/ *\| *$|^ *\| */g, "")
            .replace(/ *\| */g, "|");
        return "";
    });
    let headers = header_str.split("|");
    for (let i = 0; i < headers.length; i++) {
        headers[i] = withHeader ? `${headers[i]}: ` : "";
    }
    content.split("\n").forEach((line) => {
        let items = line.replace(/\| *$|^ *\|/g, "").split("|");
        output += `- ${items[0].trim()}\n`;
        for (let i = 1; i < items.length; i++) {
            output += `    - ${headers[i]}${items[i].trim()}\n`;
        }
    });
    return output;
}
function array2markdown(content) {
    let volume = content.match(/\{([clr\|]+)\}/)[1].match(/[clr]/g).length;
    // remove `\test{}`
    content = content
        .replace(/\$|\n/g, ``)
        .replace(/\\text *\{.*?\}/g, (t) => {
        return t.match(/\{((.*?))\}/g)[0].replace(/^ +| +$|[\{\}]/g, ``);
    });
    // return content
    // convert array to single line
    content = content.replace(/\\begin\{array\}\{[clr]\}.*?\\end\{array\}/g, (t) => {
        // console.log(t)
        return t
            .replace(/\\{1,2}begin\{array\}\{[clr]\}/g, "")
            .replace("\\end{array}", "")
            .replace(/\\\\ */g, "");
    });
    // add `\n`
    content = content.replace(/\\\\ ?\\hline|\\\\ */g, (t) => t + `\n`);
    // convert to table
    let markdown = ("|" +
        content
            .replace(/\\begin\{array\}\{[clr\|]+\}|\\end\{array\}|\\hline/g, "")
            .replace(/&/g, "|")
            .replace(/\n[ ]*$/, "")
            .replace(/\\\\[ ]*?\n/g, "|\n|")
            .replace("\\\\", "|")).replace("\n", "\n" + "|:-:".repeat(volume) + "|\n");
    let beautify_markdown = markdown
        .replace(/\[[\d,]+?\]/g, "")
        .replace(/\\[\w\{\}\d]+/g, (t) => `$${t}$`);
    return beautify_markdown;
}
function toTitleCase(text, settings = null) {
    // reference: https://github.com/gouch/to-title-case
    var properNouns = RegExp(`^(` + (settings === null || settings === void 0 ? void 0 : settings.ProperNoun.split(",").map((w) => w.trim()).join("|")) + `)$`);
    var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|v.?|vs.?|via)$/i;
    var alphanumericPattern = /([A-Za-z0-9\u00C0-\u00FF])/;
    var wordSeparators = /([\s\:\–\—\-\(\)])/;
    return text.split(wordSeparators)
        .map(function (current, index, array) {
        if (settings && current.search(properNouns) > -1) { /* Check for proper nouns */
            return current;
        }
        else {
            if (settings && settings.LowercaseFirst) {
                current = current.toLowerCase();
            }
        }
        if ( /* Check for small words */current.search(smallWords) > -1 &&
            /* Skip first and last word */
            index !== 0 &&
            index !== array.length - 1 &&
            /* Ignore title end and subtitle start */
            array[index - 3] !== ":" &&
            array[index + 1] !== ":" &&
            /* Ignore small words that start a hyphenated phrase */
            (array[index + 1] !== "-" ||
                (array[index - 1] === "-" && array[index + 1] === "-"))) {
            return current.toLowerCase();
        }
        /* Ignore intentional capitalization */
        if (current.substr(1).search(/[A-Z]|\../) > -1) {
            return current;
        }
        /* Ignore URLs */
        if (array[index + 1] === ":" && array[index + 2] !== "") {
            return current;
        }
        /* Capitalize the first letter */
        return current.replace(alphanumericPattern, function (match) {
            return match.toUpperCase();
        });
    })
        .join("");
}
String.prototype.format = function (args) {
    var result = this;
    if (arguments.length > 0) {
        if (arguments.length == 1 && typeof args == "object") {
            for (var key in args) {
                if (args[key] != undefined) {
                    var reg = new RegExp("({" + key + "})", "g");
                    result = result.replace(reg, args[key]);
                }
            }
        }
        else {
            for (var i = 0; i < arguments.length; i++) {
                if (arguments[i] != undefined) {
                    var reg = new RegExp("({)" + i + "(})", "g");
                    result = result.replace(reg, arguments[i]);
                }
            }
        }
    }
    return result;
};
function textWrapper(selectedText, context) {
    var _a;
    const editor = context.editor;
    const prefix_setting = context.prefix;
    const suffix_setting = context.suffix;
    const adjustRange = context.adjustRange;
    // let resetSelection;
    let resetSelectionOffset;
    let editorChange;
    let meta = {};
    const metaProperties = (_a = context.view.metadataEditor) === null || _a === void 0 ? void 0 : _a.properties;
    if (metaProperties) {
        for (const m of metaProperties) {
            meta[m.key] = m.value;
        }
    }
    let prefix_template = handlebars.compile(prefix_setting.replace(/\\n/g, "\n"), { noEscape: true });
    let suffix_template = handlebars.compile(suffix_setting.replace(/\\n/g, "\n"), { noEscape: true });
    const prefix = prefix_template(meta);
    const suffix = suffix_template(meta);
    const PL = prefix.length; // Prefix Length
    const SL = suffix.length; // Suffix Length
    function Cursor(offset) {
        const last_cursor = { line: editor.lastLine(), ch: editor.getLine(editor.lastLine()).length };
        const last_offset = editor.posToOffset(last_cursor);
        if (offset > last_offset) {
            return last_cursor;
        }
        offset = offset < 0 ? 0 : offset;
        return editor.offsetToPos(offset);
    }
    const fos = editor.posToOffset(adjustRange.from); // from offset
    const tos = editor.posToOffset(adjustRange.to); // to offset
    const len = selectedText.length;
    const outPrefix = editor.getRange(Cursor(fos - PL), Cursor(tos - len));
    const outSuffix = editor.getRange(Cursor(fos + len), Cursor(tos + SL));
    const inPrefix = editor.getRange(Cursor(fos), Cursor(fos + PL));
    const inSuffix = editor.getRange(Cursor(tos - SL), Cursor(tos));
    if (outPrefix === prefix && outSuffix === suffix) {
        //: selection outside match prefix and suffix => undo underline (inside selection)
        editorChange = { text: selectedText, from: Cursor(fos - PL), to: Cursor(tos + SL) };
        // resetSelection = { anchor: Cursor(fos - PL), head: Cursor(tos - PL) };
        resetSelectionOffset = { anchor: fos - PL, head: tos - PL };
        selectedText = prefix + selectedText + suffix;
    }
    else if (inPrefix === prefix && inSuffix === suffix) {
        //: selection inside match prefix and suffix => undo underline (outside selection)
        editorChange = Object.assign({ text: editor.getRange(Cursor(fos + PL), Cursor(tos - SL)) }, adjustRange);
        // resetSelection = { anchor: Cursor(fos), head: Cursor(tos - PL - SL) }
        resetSelectionOffset = { anchor: fos, head: tos - PL - SL };
    }
    else {
        //: Add prefix and suffix to selection
        editorChange = Object.assign({ text: prefix + selectedText + suffix }, adjustRange);
        // resetSelection = { anchor: editor.offsetToPos(fos + PL), head: editor.offsetToPos(tos + PL) }
        resetSelectionOffset = { anchor: fos + PL, head: tos + PL };
    }
    return {
        editorChange: editorChange,
        selectedText: selectedText,
        // resetSelection: resetSelection,
        resetSelectionOffset: resetSelectionOffset,
    };
}
function replaceLigature(s) {
    Object.entries(Ligatures).forEach(([key, value]) => {
        var rx = new RegExp(key, "g");
        s = s.replace(rx, value);
    });
    return s;
}
/**
 * @param [text] The text to sort
 * @param [context] The context of the sort, including the editor and the settings
 * @param [fromOffset=0] - the offset of the first line of the text to sort
*/
function sortTodo(text, context, fromLine = null) {
    const lines = text.split("\n");
    // console.log("lines", lines)
    let prefix_text_index = -1, suffix_text_index = -1;
    let todos = {};
    let todo_detected = false, sort_prefix = false;
    let indent = 0;
    let last_flag, // flag of last line that count in as a new todo of level `indent`
    flag;
    for (const [i, line] of lines.entries()) {
        let flags = /- \[([ \w])\] /g.exec(line);
        // console.log(i, flags, line);
        if (flags) { // it is a todo line
            let head = line.match(/^[ \t]*/g)[0];
            if (!todo_detected) {
                // first time to detect todo checkbox
                indent = head.length;
                todo_detected = true;
            }
            else {
                if (head.length < indent) {
                    // the level of this line is higher than before,
                    // reset the index and consider above lines as prefix text
                    prefix_text_index = i - 1;
                    indent = head.length;
                    todos = {}; // reset
                    sort_prefix = true;
                }
            }
            if (head.length > indent) {
                let last_idx = todos[last_flag].length - 1;
                todos[last_flag][last_idx] += "\n" + line;
            }
            else {
                flag = flags[1];
                if (!(flag in todos)) {
                    todos[flag] = [];
                }
                todos[flag].push(line);
                last_flag = flag;
            }
        }
        else {
            // console.log("else", flags, todo_detected, line)
            if (todo_detected) {
                suffix_text_index = i;
                break;
            }
            else {
                prefix_text_index = i;
            }
        }
    }
    // console.log("todos", todos)
    // console.log("prefix_text_line", prefix_text_index, "suffix_text_line", suffix_text_index)
    const todoBlockRangeLine = {
        from: prefix_text_index != -1 ? fromLine + prefix_text_index : fromLine,
        to: suffix_text_index != -1 ? fromLine + suffix_text_index : fromLine + lines.length
    };
    // console.log(context.originRange.from.line, context.originRange.to.line);//, fromLine, fromLine + prefix_text_index, fromLine + suffix_text_index)
    // console.log(todoBlockRangeLine)
    let body;
    if (fromLine === null
        || ((context.originRange.from.line >= todoBlockRangeLine.from && context.originRange.from.line <= todoBlockRangeLine.to)
            || (context.originRange.from.line <= todoBlockRangeLine.from && context.originRange.to.line >= todoBlockRangeLine.to)
            || (context.originRange.to.line >= todoBlockRangeLine.from && context.originRange.to.line <= todoBlockRangeLine.to))) {
        body = "";
        for (const [i, flag] of Object.keys(todos).sort().entries()) {
            todos[flag].forEach((line, j) => {
                // console.log("body line", line)
                if (line.match(/\n/g)) {
                    let sub_lines = line.split("\n");
                    line = sub_lines[0] + "\n" + sortTodo(sub_lines.slice(1, sub_lines.length).join("\n"), context, null);
                }
                body += line + "\n";
            });
        }
        body = body.slice(0, body.length - 1); // remove the last "\n"
    }
    else {
        // console.log("else: Do not sort")
        // body = lines.slice(todoBlockRangeLine.from, todoBlockRangeLine.to).join("\n");
        // body = lines.slice(prefix_text_line + 1, suffix_text_line + 1).join("\n");
        body = lines.slice(prefix_text_index === -1 ? 0 : prefix_text_index + 1, suffix_text_index === -1 ? lines.length : suffix_text_index).join("\n");
        // return text;
    }
    // return text;
    // console.log("input text")
    // console.log(text)
    // console.log("body", body)
    let prefix_text = prefix_text_index === -1 ? null : lines.slice(0, prefix_text_index + 1).join('\n');
    // prefix_text = lines.slice(0, prefix_text_line + 1).join('\n');
    // let suffix_text = suffix_text_index === -1 ? null : (
    //     suffix_text_index + 1 == lines.length ? null : lines.slice(suffix_text_index + 1, lines.length).join('\n'));
    // console.log("suffix_text", suffix_text_index + 1 == lines.length)
    if (sort_prefix) {
        prefix_text = sortTodo(prefix_text, context, fromLine);
    }
    let suffix_text = suffix_text_index === -1 ? null : lines.slice(suffix_text_index, lines.length + 1).join("\n");
    if (!(suffix_text_index == -1 || (suffix_text_index + 1 == lines.length))) {
        // suffix_text = lines.slice(suffix_text_index + 1, lines.length + 1).join("\n");
        suffix_text = sortTodo(suffix_text, context, suffix_text_index == -1 ? null : fromLine + suffix_text_index);
    }
    let whole = [prefix_text, body, suffix_text];
    // console.log(prefix_text_index, suffix_text_index)
    // console.log("text", text)
    // console.log("whole", whole);
    whole = whole.filter(item => item != null); // remove empty lines
    return whole.join('\n');
}
function requestAPI(s, file, url) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const data = {
                text: s,
                path: file.path,
            };
            const response = yield obsidian.requestUrl({
                url: url,
                method: "POST",
                contentType: "application/json",
                body: JSON.stringify(data),
            });
            const res = response.json;
            if (res.notification) {
                new obsidian.Notice(res.notification);
            }
            if (res.text) {
                return res.text;
            }
            else {
                return s;
            }
        }
        catch (e) {
            new obsidian.Notice(`Fail to request API.\n${e}`);
            return s;
        }
    });
}
function slugify(text, maxLength = 76) {
    // Convert to Lowercase
    text = text.toLowerCase();
    // Remove Special Characters, preserve Latin and Cyrillic and Swedish characters
    text = text.replace(/[^\w\s\u0400-\u04FFåäöÅÄÖ]|_/g, "").replace(/\s+/g, " ").trim();
    // Replace Spaces with Dashes
    text = text.replace(/\s+/g, "-");
    // Remove Accents and Diacritics
    text = text.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
    // Handle Multiple Dashes
    text = text.replace(/-{2,}/g, "-");
    // Handle Numerals
    if (/^\d+$/.test(text)) {
        // If the slug is numeric only, add a suffix to make it unique and descriptive
        text = `item-${text}`;
    }
    // Truncate Length if required
    if (text.length > maxLength) {
        text = text.substr(0, maxLength);
        // Handle case where the last character is a hyphen
        if (text.endsWith("-")) {
            text = text.substr(0, text.lastIndexOf("-"));
        }
    }
    // Handle Hyphens and Dashes
    text = text.replace(/^-+|-+$/g, "");
    return text;
}
function snakify(text) {
    text = text.toLowerCase();
    text = text.replace(/\s+/g, "_");
    return text;
}
function camelCase(text, lowerFirst = false) {
    text = toTitleCase(text.toLowerCase());
    text = text.replace(/\s+/g, "");
    if (lowerFirst) {
        text = text.charAt(0).toLowerCase() + text.slice(1);
    }
    return text;
}
function customReplace(text, s) {
    s.data.forEach(data => {
        const re = new RegExp(data.search, "g");
        text = text.replace(re, JSON.parse(`"${data.replace}"`));
    });
    return text;
}
function convertLatex(editor, selectedText) {
    //: If selectedText is surrounded by `$`, convert unicode Greek letters to latex commands
    if (editor) {
        const fos = editor.posToOffset(editor.getCursor("from")); // from offset
        const tos = editor.posToOffset(editor.getCursor("to")); // to offset
        const beforeText = editor.getRange(editor.offsetToPos(fos - 1), editor.offsetToPos(fos));
        const afterText = editor.getRange(editor.offsetToPos(tos), editor.offsetToPos(tos + 1));
        if (beforeText === "$" && afterText === "$") {
            let result = "";
            let lastGreek = false;
            for (let i = 0; i < selectedText.length; i++) {
                let char = GreekLetters[selectedText[i]];
                if (char) {
                    result += char;
                    lastGreek = true;
                }
                else {
                    if (lastGreek && !/\d/.test(selectedText[i])) {
                        result += " ";
                    }
                    result += selectedText[i];
                    lastGreek = false;
                }
            }
            return result.replace(/\s*$/g, "");
        }
    }
    function G(str) {
        return GreekLetters[str] || str;
    }
    // const reGreek = /[\u03B1-\u03C9\u0391-\u03A9]/g; 
    //: Or, find math text and surround it with `$`
    const pre = String.raw `([\s：（）。，、；—\(\)]|^)`;
    const suf = String.raw `(?=[\s\,\:\.\?\!，。、（）；—\(\)]|$)`;
    const patternChar2 = String.raw `([\u03B1-\u03C9\u0391-\u03A9a-zA-Z])([\u03B1-\u03C9\u0391-\u03A9a-zA-Z0-9])`;
    let replacedText = selectedText
        // single character
        .replace(RegExp(pre + String.raw `([a-zA-Z\u03B1-\u03C9\u0391-\u03A9])` + suf, "g"), (t, pre, t1) => {
        if (/[aA]/.test(t1)) {
            return t;
        }
        return pre + `$${G(t1)}$`;
    })
        // two characters
        .replace(RegExp(pre + patternChar2 + suf, "g"), (t, pre, t1, t2) => {
        // ignore cases
        if (/is|or|as|to|am|an|at|by|do|go|ha|he|hi|ho|if|in|it|my|no|of|on|so|up|us|we|be/g.test(t1 + t2)) {
            return t;
        }
        return pre + `$${G(t1)}_${G(t2)}$`;
    })
        .replace(RegExp(pre + String.raw `([a-z\u03B1-\u03C9\u0391-\u03A9])([\*])` + suf, "g"), (t, pre, t1, t2) => {
        return pre + `$${t1}^${t2}$`;
    })
        // calculator
        .replace(RegExp(pre + String.raw `([\w\u03B1-\u03C9\u0391-\u03A9]{1,3}[\+\-\*\/<>=][\w\u03B1-\u03C9\u0391-\u03A9]{1,3})` + suf, "g"), (t, pre, t1) => {
        // let content = t1.replace(/([a-z])([a-zA-Z0-9])/g, `$1_$2`)
        let content = t1.replace(RegExp(patternChar2, "g"), (t, t1, t2) => `${G(t1)}_${G(t2)}`);
        return pre + `$${content}$`;
    });
    return replacedText;
}

var Wikilink2mdPathMode;
(function (Wikilink2mdPathMode) {
    Wikilink2mdPathMode["relativeObsidian"] = "relative-obsidian";
    Wikilink2mdPathMode["relativeFile"] = "relative-file";
    Wikilink2mdPathMode["absolute"] = "absolute";
})(Wikilink2mdPathMode || (Wikilink2mdPathMode = {}));
var CalloutTypeDecider;
(function (CalloutTypeDecider) {
    CalloutTypeDecider["wholeFile"] = "whole-file";
    CalloutTypeDecider["preContent"] = "previous-content";
    // lastUsed = "last-used",
    CalloutTypeDecider["fix"] = "fix";
})(CalloutTypeDecider || (CalloutTypeDecider = {}));
const DEFAULT_SETTINGS = {
    manifest: {
        version: "0.0.0",
    },
    MergeParagraph_Newlines: true,
    MergeParagraph_Spaces: true,
    LowercaseFirst: true,
    RemoveBlanksWhenChinese: false,
    ZoteroNoteRegExp: String.raw `“(?<text>.*)” \((?<item>.*?)\) \(\[pdf\]\((?<pdf_url>.*?)\)\)`,
    ZoteroNoteTemplate: "{text} [🔖]({pdf_url})",
    BulletPoints: "•–§",
    WrapperList: [{ name: "underline", prefix: "<u>", suffix: "</u>", id: "underline" }],
    RequestList: [],
    customReplaceList: [],
    customReplaceBuiltInLog: {},
    ToggleSequence: "titleCase\nlowerCase\nupperCase",
    RemoveWikiURL2: false,
    WikiLinkFormat: { headingOnly: "{title} (> {heading})", aliasOnly: "{alias} ({title})", both: "{alias} ({title} > {heading})" },
    UrlLinkFormat: "{text}",
    ProperNoun: "",
    OrderedListOtherSeparator: String.raw ``,
    Wikilink2mdRelativePath: Wikilink2mdPathMode.relativeObsidian,
    calloutType: "NOTE",
    debugMode: false,
    headingLevelMin: 0,
    calloutTypeDecider: CalloutTypeDecider.preContent,
    formatOnSaveSettings: {
        enabled: false,
        commandsString: "",
    }
};

function removeWikiLink(s, formatGroup) {
    return s.replace(/\[\[.*?\]\]/g, function (t) {
        var _a, _b;
        let wiki_exec = /\[\[(?<title>[^\[#|]+)?(?<heading>#[^|\]]+)?(?<alias>\|[^|\]]+)?\]\]/g.exec(t);
        let G = wiki_exec.groups;
        console.log(G);
        let groupArgs = {
            title: G.title === undefined ? '' : G.title,
            heading: (_a = G.heading) === null || _a === void 0 ? void 0 : _a.slice(1),
            alias: (_b = G.alias) === null || _b === void 0 ? void 0 : _b.slice(1)
        };
        console.log(groupArgs);
        if (G.heading === undefined && G.alias === undefined) {
            return G.title;
        }
        else if (G.alias !== undefined && G.heading === undefined) {
            return stringFormat(formatGroup.aliasOnly, groupArgs);
        }
        else if (G.alias === undefined && G.heading !== undefined) {
            return stringFormat(formatGroup.headingOnly, groupArgs);
        }
        else {
            console.log(groupArgs);
            return stringFormat(formatGroup.both, groupArgs);
        }
    });
}
const RegexMarkdownLink = /\[(.+?)\]\((?:[^)]+\([^)]+\)[^)]*|[^)]+)\)/g;
function removeUrlLink(s, UrlLinkFormat) {
    console.log(s);
    const rx = RegexMarkdownLink;
    return s.replace(rx, function (t) {
        // TODO: add a setting to decide whether remove url link (starts with http) only or all kinds of links
        // const regex = /\[(?<text>.*?)\]\((?<url>https?:\/\/[\S\s]+)\)/;
        const regex = /\[(?<text>.*?)\]\((?<url>[\S\s]+?)\)/;
        const match = t.match(regex);
        console.log(match);
        if (match && match.length === 3) {
            return stringFormat(UrlLinkFormat, match.groups);
        }
        else {
            return t;
        }
    });
}
function url2WikiLink(s) {
    let rx = RegexMarkdownLink;
    return s.replace(rx, function (t) {
        return `[[${t.match(/\[(.*?)\]/)[1]}]]`;
    });
}
function convertWikiLinkToMarkdown(wikiLink, plugin) {
    const regex = /\[\[([^|\]]+)\|?([^\]]+)?\]\]/g;
    const markdown = wikiLink.replace(regex, (match, p1, p2) => {
        const linkText = p2 ? p2.trim() : p1.trim();
        let linkTarget = p1.trim().replace(/#.*$/g, "") + ".md";
        const note = plugin.app.vault.getAllLoadedFiles().find(file => file.name === linkTarget);
        let linkURL = linkTarget;
        if (note) {
            linkURL = note.path;
            switch (plugin.settings.Wikilink2mdRelativePath) {
                case Wikilink2mdPathMode.absolute:
                    // @ts-ignore
                    linkURL = plugin.app.vault.adapter.basePath + "/" + linkURL;
                    break;
                case Wikilink2mdPathMode.relativeFile:
                    const currentFilePath = plugin.app.workspace.getActiveFile().path;
                    linkURL = relativePath(linkURL, currentFilePath);
                    break;
            }
            linkURL = linkURL.replace(/\s/g, "%20");
        }
        const matchAlias = linkText.match(/#(.*)$/);
        let aliasLink = "";
        if (matchAlias) {
            aliasLink = "#" + matchAlias[1].replace(/\s/g, "%20");
        }
        return `[${linkText}](${linkURL}${aliasLink})`;
    });
    return markdown;
}
function relativePath(pathA, pathB) {
    const splitPathA = pathA.split('/');
    const splitPathB = pathB.split('/');
    // 找到共同根路径
    let commonRootIndex = 0;
    while (commonRootIndex < Math.min(splitPathA.length - 1, splitPathB.length - 1)
        && splitPathA[commonRootIndex] === splitPathB[commonRootIndex]) {
        commonRootIndex++;
    }
    // 构建相对路径
    let relativePath = '';
    for (let i = commonRootIndex; i < splitPathB.length - 1; i++) {
        relativePath += '../';
    }
    // 将路径 A 的剩余部分添加到相对路径中
    for (let i = commonRootIndex; i < splitPathA.length; i++) {
        relativePath += splitPathA[i] + '/';
    }
    return relativePath.slice(0, -1); // 去除末尾的斜杠
}

const EN = {
    command: {
        "uppercase": "Uppercase",
        "lowercase": "Lowercase",
        "capitalize-word": "Capitalize all words",
        "capitalize-sentence": "Capitalize only first word of sentence",
        "title-case": "Title-case",
        "cycle-case": "Cycle-case",
        "slugify": "Slugify",
        "snakify": "Snakify",
        "decodeURI": "Decode URL",
        "remove-trailing-spaces": "Remove trailing spaces",
        "remove-blank-line": "Remove blank line(s)",
        "add-line-break": "Add extra line break between paragraphs",
        "split-lines-by-blank": "Split line(s) by blanks",
        "heading-upper": "Upper heading level (more #)",
        "heading-lower": "Lower heading level (less #)",
        "open-settings": "Open preference settings tab",
    },
    setting: {
        "more-details": "More details in Github: ",
        "others": "Others",
        "remove-spaces-when-converting": "Remove spaces when converting Chinese punctuation marks",
        "remove-spaces-when-converting-desc": "for OCR case",
        "debug-logging": "Debug logging",
        "debug-logging-desc": "verbose logging in the console",
        "word-cases": "Word cases",
        "word-cases-desc": "lowercase / uppercase / title case / capitalize case / cycle case",
        "lowercase-before-capitalize": "Lowercase before capitalize/title case",
        "lowercase-before-capitalize-desc": "When running the capitalize or title case command, the plugin will lowercase the selection at first.",
        "cycle-case-sequence": "Cycle case sequence (one case in a line)",
        "cycle-case-sequence-desc": "Support cases: `lowerCase`, `upperCase`, `capitalizeWord`, `capitalizeSentence`, `titleCase`. \n" +
            "Note that the result of `capitalizeWord` and `titleCase` could be the same in some cases, " +
            "the two cases are not recommended to be used in the same time.",
        "proper-noun": "Proper noun",
        "proper-noun-desc": "The words will be ignore to format in title case. Separated by comma, e.g. `USA, UFO`.",
        paragraph: {
            header: "Merge broken paragraphs behavior",
            "remove-redundant-blank-lines": "Remove redundant blank lines",
            "remove-redundant-blank-lines-desc": 'change blank lines into single blank lines, e.g. "\\n\\n\\n" will be changed to "\\n\\n"',
        },
        "remove-redundant-blank-spaces": "Remove redundant blank spaces",
        "remove-redundant-blank-spaces-desc": "ensure only one space between words",
        "link-format": "Link format",
        "link-format-desc": "Markdown links (`[]()`), Wiki links (`[[ ]]`)",
        "Wikilink2mdPathMode-relative-obsidian": "Relative to Obsidian Vault",
        "Wikilink2mdPathModerelative-file": "Relative to current file",
        "Wikilink2mdPathMode-absolute": "Absolute",
        "path-mode": "Path mode when covering wikilinks to plain markdown links.",
        "result-format": "The format of result when calling `Remove URL links format in selection`",
        "result-format-desc": "Matching with `[{text}]({url})`, use `{text}` if you want to maintain the text, or use `{url}` if you want to maintain the url.",
        "remove-wikilink-url": "Remove WikiLink as well when calling `Remove URL links format in selection`",
        "wiki-link-format-heading": "WikiLink with heading",
        "wiki-link-format-heading-desc": "e.g. [[title#heading]]",
        "wiki-link-format-alias": "WikiLink with alias",
        "wiki-link-format-alias-desc": "e.g. [[title|alias]]",
        "wiki-link-format-both": "WikiLink with both heading and alias",
        "wiki-link-format-both-desc": "e.g. [[title#heading|alias]]",
        "list-format": "List format",
        "list-format-desc": "Detect and convert bullet list / ordered list",
        "bullet-point-characters": "Possible bullet point characters",
        "bullet-point-characters-desc": "The characters that will be regarded as bullet points.",
        "ordered-list-custom-separator": "Format ordered list custom separator RegExp",
        "ordered-list-custom-separator-desc": "Separated by `|`. e.g.: `\sand\s|\s?AND\s?`. Default as empty.",
        wrapper: {
            "header": "Wrapper",
            "desc": "Wrap the selection with prefix and suffix",
            "rule-desc1": "<Wrapper Name> <Prefix Template> <Suffix Template>",
            "rule-desc2": "Template for metadata (file properties) is supported with Handlebars syntax. For example, `{{link}}` will be replaced with the value of current file's property `link`.",
            "add-new-wrapper": "Add new wrapper",
            "new-wrapper-rule-tooltip": "Add new rule",
            "name-placeholder": "Wrapper Name (command name)",
            "prefix-placeholder": "Prefix",
            "suffix-placeholder": "Suffix",
        },
        "delete-tooltip": "Delete",
        "api-request": "API Request",
        "api-request-desc": "Send a request to an API and replace the selection with the return",
        "api-request-url": "API Request URL",
        "api-request-url-desc": "The URL that plugin will send a POST and replace with return.\n" +
            "The return json should have two attribution: `text` and `notification`.\n" +
            "If `text` exist then `text` will replace the selection, or do nothing.\n" +
            "If `notification` exist then Send a notice if this string, or do nothing.",
        "new-request-tooltip": "Add new request",
        "request-name-placeholder": "Request Name (command name)",
        "request-url-placeholder": "Request URL",
        "custom-replacement": "Custom replacement",
        "custom-replacement-desc": "Replace specific pattern with custom string",
        "add-custom-replacement": "Add custom replacement",
        "add-custom-replacement-desc": "The plugin will replace the `search` string with the `replace` string in the selection. RegExp is supported.",
        "add-new-replacement-tooltip": "Add new replacement",
        "replacement-command-name-placeholder": "Command name",
        "replacement-search-placeholder": "Search",
        "replacement-replace-placeholder": "Replace (empty is fine)",
        "zotero-pdf-note-format": "Zotero pdf note format",
        "zotero-input-regexp": "Zotero pdf note (input) RegExp",
        "zotero-output-format": "Zotero note pasted in Obsidian (output) format",
        "zotero-output-format-desc": "Variables: \n" +
            "{text}: <text>,\n" +
            "{pdf_url}: <pdf_url>,\n" +
            "{item}: <item>.",
        "markdown-quicker": "Markdown quicker",
        "markdown-quicker-desc": "Quickly format the selection with common markdown syntax",
        "heading-lower-to-plain": "Heading lower to plain text",
        "heading-lower-to-plain-desc": "If disabled, heading level 1 cannot be lowered to plain text.",
        "method-decide-callout-type": "Method to decide callout type",
        "method-decide-callout-type-desc": "How to decide the type of new callout block for command `Callout format`? `Fix callout type` use the default callout type always, other methods only use the default type when it fails to find previous callout block.",
        "default-callout-type": "Default callout type",
        "default-callout-type-desc": "Set the default callout type for command `Callout format`. "
    }
};
const ZH = {
    command: {
        "uppercase": "全部大写",
        "lowercase": "全部小写",
        "capitalize-word": "首字母大写（所有单词）",
        "capitalize-sentence": "首字母大写（句首单词）",
        "title-case": "标题格式大小写",
        "cycle-case": "循环切换大小写格式",
        "slugify": "使用 Slugify 格式化（`-`连字符）",
        "snakify": "使用 Snakify 格式化（`_`连字符）",
        "remove-trailing-spaces": "移除所有行末空格",
        "remove-blank-line": "移除空行",
        "add-line-break": "在段落间添加额外换行",
        "split-lines-by-blank": "按空格分行",
        "heading-upper": "降级标题（加 #）",
        "heading-lower": "升级标题（减 #）",
        "open-settings": "打开插件设置选项卡",
        "decodeURI": "解码 URL",
    },
    setting: {
        "more-details": "在 Github 查看更多详情：",
        "others": "其他设置",
        "remove-spaces-when-converting": "转换中文标点时去除空格",
        "remove-spaces-when-converting-desc": "适用于 OCR 场景",
        "debug-logging": "Debug 日志",
        "debug-logging-desc": "在控制台中显示 Debug 详细日志",
        "word-cases": "文字大小写转换",
        "word-cases-desc": "转换为小写 / 转换为大写 / 标题式大小写 / 单词首字母大写 / 大小写循环切换",
        "lowercase-before-capitalize": "在首字母大写之前转换为小写",
        "lowercase-before-capitalize-desc": "执行首字母大写或标题式大小写命令前，先将选中文本转换为小写。",
        "cycle-case-sequence": "大小写循环变换（单行）",
        "cycle-case-sequence-desc": "支持以下大小写格式：`lowerCase`、`upperCase`、`capitalizeWord`、`capitalizeSentence`、`titleCase`。\n" +
            "注意，在某些情况下，`capitalizeWord`与`titleCase`的效果可能相同，" +
            "不推荐同时使用。",
        "proper-noun": "专有名词例外",
        "proper-noun-desc": "在执行标题式大小写时，会忽略以下指定的专有名词。例如：`USA, UFO`。",
        paragraph: {
            header: "合并段落",
            "remove-redundant-blank-lines": "删除多余的空白行",
            "remove-redundant-blank-lines-desc": "将多余的空白行转换为单一空白行，例如：`\\n\\n\\n`会被转换为单一的`\\n\\n`。",
        },
        "remove-redundant-blank-spaces": "删除多余的空格",
        "remove-redundant-blank-spaces-desc": "确保单词之间只有一个空格。",
        "link-format": "链接格式化",
        "link-format-desc": "Markdown 链接 (`[]()`)，Wiki 链接 (`[[ ]]`)",
        "Wikilink2mdPathMode-relative-obsidian": "相对于Obsidian库",
        "Wikilink2mdPathMode-relative-file": "相对于当前文件",
        "Wikilink2mdPathMode-absolute": "绝对路径",
        "path-mode": "转换 Wikilink 为 Markdown 链接时的路径模式",
        "result-format": "移除选中链接格式的结果",
        "result-format-desc": "与 `[{text}]({url})` 匹配，使用 `{text}` 维持文本或 `{url}` 维持链接。",
        "remove-wikilink-url": "移除 WikiLink 时也移除 URL",
        "wiki-link-format-heading": "带标题的 WikiLink 格式化",
        "wiki-link-format-heading-desc": "如：[[title#heading]]",
        "wiki-link-format-alias": "带别名的 WikiLink 格式化",
        "wiki-link-format-alias-desc": "如：[[title|alias]]",
        "wiki-link-format-both": "同时带标题和别名的 WikiLink 格式化",
        "wiki-link-format-both-desc": "如：[[title#heading|alias]]",
        "list-format": "列表格式化",
        "list-format-desc": "检测并转换无序列表和有序列表。",
        "bullet-point-characters": "项目符号字符",
        "bullet-point-characters-desc": "被视为项目符号的字符。",
        "ordered-list-custom-separator": "有序列表自定义分隔符正则表达式",
        "ordered-list-custom-separator-desc": "使用`|`分隔，例如：`\sand\s|\s?AND\s?`。默认为空。",
        wrapper: {
            "header": "包装器",
            "desc": "在选中的文本前后添加前缀和后缀。",
            "rule-desc1": "包装器名称、前缀模板、后缀模板",
            "rule-desc2": "支持使用 Handlebars 语法的文件元数据属性模板。例如，`{{link}}` 将替换为当前文件的 `link` 属性值。",
            "add-new-wrapper": "添加新的包装器",
            "new-wrapper-rule-tooltip": "添加新规则",
            "name-placeholder": "包装器名称（命令名）",
            "prefix-placeholder": "前缀",
            "suffix-placeholder": "后缀",
        },
        "delete-tooltip": "删除",
        "api-request": "API 请求",
        "api-request-desc": "向 API 发送请求，并用返回值替换选择文本",
        "api-request-url": "API 请求 URL",
        "api-request-url-desc": "插件将发送POST请求并用返回值替换选择文本。\n" +
            "返回的JSON应包含两个属性：`text` 和 `notification`。\n" +
            "如果存在 `text`，则用 `text` 替换选择文本，否则不做任何操作。\n" +
            "如果存在 `notification`，则发送此字符串作为通知，否则不做任何操作。",
        "new-request-tooltip": "添加新请求",
        "request-name-placeholder": "请求名称（命令名称）",
        "request-url-placeholder": "请求 URL",
        "custom-replacement": "自定义替换",
        "custom-replacement-desc": "使用自定义字符串替换特定模式",
        "add-custom-replacement": "添加自定义替换",
        "add-custom-replacement-desc": "插件将使用 `replace` 字符串替换 `search` 字符串。支持正则表达式。",
        "add-new-replacement-tooltip": "添加新替换",
        "replacement-command-name-placeholder": "命令名称",
        "replacement-search-placeholder": "搜索",
        "replacement-replace-placeholder": "替换（可为空）",
        "zotero-pdf-note-format": "Zotero PDF 注释格式",
        "zotero-input-regexp": "Zotero PDF 注释（输入）正则表达式",
        "zotero-output-format": "Zotero 注释粘贴到 Obsidian 中的（输出）格式",
        "zotero-output-format-desc": "变量: \n" +
            "{text}: <文本>,\n" +
            "{pdf_url}: <PDF链接>,\n" +
            "{item}: <条目>。",
        "markdown-quicker": "Markdown 快速格式化",
        "markdown-quicker-desc": "使用常见 Markdown 语法快速格式化选中文本",
        "heading-lower-to-plain": "标题降级为普通文本",
        "heading-lower-to-plain-desc": "如果禁用，一级标题不能降为普通文本。",
        "method-decide-callout-type": "决定标注类型的方法",
        "method-decide-callout-type-desc": "选择用于命令 `Callout format` 的新标注块的类型的方法。如果选择固定标注类型，则总是使用默认的标注类型。在无法找到前一个标注块时，其它方法也将使用默认类型。",
        "default-callout-type": "默认callout类型",
        "default-callout-type-desc": "设置命令 `Callout format` 的默认标注类型。"
    }
};
const languages = {
    en: EN,
    zh: ZH
};
function setLanguage(lang) {
    let currentLanguage = 'en';
    if (lang === "zh-TW") {
        return "zh";
    }
    if (lang in languages) {
        currentLanguage = lang;
    }
    return currentLanguage;
}
// 获取多级内容的字符串
function getString(keys, useDefault = false) {
    let currentLanguage = "en";
    if (!useDefault) {
        currentLanguage = setLanguage(window.localStorage.getItem("language"));
    }
    let obj = languages[currentLanguage];
    let fail = false;
    for (let key of keys) {
        if (!(key in obj)) {
            fail = true;
            break;
        }
        obj = obj[key];
    }
    if (fail) {
        return getString(keys, true);
    }
    else {
        return obj;
    }
}

function addDonationElement(containerEl) {
    const lang = window.localStorage.getItem("language");
    let text = [];
    switch (lang) {
        case "zh":
        case "zh-tw":
            text = [
                `如果插件对您有帮助，欢迎打赏！🤩 可以通过`,
                `<a>微信、支付宝</a>、`,
                `<a href="https://afdian.net/a/Benature-K">⚡️ 爱发电</a>、<a href="https://www.buymeacoffee.com/benature">☕️ Buy Me a Coffee</a>请木一喝杯咖啡。不胜感激！🙇`,
            ];
            break;
        default:
            text = [`If you find this plugin useful and would like to support its development, you can sponsor me via
				<a href="https://www.buymeacoffee.com/benature">☕️ Buy Me a Coffee</a>,
				<a href="https://afdian.net/a/Benature-K">⚡️ AiFaDian</a>, `,
                `<a>WeChat or Alipay</a>. `,
                `Any amount is welcome, thank you!`];
            break;
    }
    addDonationElementContent(containerEl, text);
}
function addDonationElementContent(containerEl, text) {
    const donateELdiv = containerEl.createEl("div");
    donateELdiv.setAttribute("style", "text-align: center; margin-top: 5rem; border-top: 0.2px solid grey");
    const textContainerEl = document.createElement('div');
    textContainerEl.setCssProps({ "font-size": "10px", color: "gray", "margin-bottom": "10px", "margin-top": "10px" });
    let textEl1 = textContainerEl.createEl("span");
    let textEl2 = textContainerEl.createEl("span");
    let textEl3 = textContainerEl.createEl("span");
    textEl1.innerHTML = text[0];
    textEl2.innerHTML = text[1];
    textEl3.innerHTML = text[2];
    // donateELa1.appendText("If you find this plugin useful and would like to support its development, you can sponsor me by the button below.");
    donateELdiv.appendChild(textContainerEl);
    let centerEl = donateELdiv.createEl("div");
    centerEl.setCssProps({ "display": "flex", "justify-content": "center" });
    // centerEl.createEl("div", { text: "dfsfdsd" });
    let qrcodeEl = centerEl.createEl("img");
    qrcodeEl.setAttribute("src", "https://s2.loli.net/2024/04/01/VtX3vYLobdF6MBc.png");
    qrcodeEl.setCssProps({ display: "none", width: "300px", "margin-bottom": "1rem" });
    textEl2.addEventListener("click", () => {
        qrcodeEl.setCssStyles({ "display": "block", });
    });
    const parser = new DOMParser();
    const donateELa2 = document.createElement('a');
    donateELa2.setAttribute('href', "https://www.buymeacoffee.com/benature");
    // donateELa2.addClass('advanced-tables-donate-button');
    donateELa2.appendChild(parser.parseFromString(buyMeACoffee, 'text/xml').documentElement);
    donateELdiv.appendChild(donateELa2);
}
const buyMeACoffee = `
<svg width="150" height="42" viewBox="0 0 260 73" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 11.68C0 5.22932 5.22931 0 11.68 0H248.2C254.651 0 259.88 5.22931 259.88 11.68V61.32C259.88 67.7707 254.651 73 248.2 73H11.68C5.22931 73 0 67.7707 0 61.32V11.68Z" fill="#FFDD00"/>
<path d="M52.2566 24.0078L52.2246 23.9889L52.1504 23.9663C52.1802 23.9915 52.2176 24.0061 52.2566 24.0078Z" fill="#0D0C22"/>
<path d="M52.7248 27.3457L52.6895 27.3556L52.7248 27.3457Z" fill="#0D0C22"/>
<path d="M52.2701 24.0024C52.266 24.0019 52.2619 24.0009 52.258 23.9995C52.2578 24.0022 52.2578 24.0049 52.258 24.0076C52.2624 24.007 52.2666 24.0052 52.2701 24.0024Z" fill="#0D0C22"/>
<path d="M52.2578 24.0094H52.2643V24.0054L52.2578 24.0094Z" fill="#0D0C22"/>
<path d="M52.6973 27.3394L52.7513 27.3086L52.7714 27.2973L52.7897 27.2778C52.7554 27.2926 52.7241 27.3135 52.6973 27.3394Z" fill="#0D0C22"/>
<path d="M52.3484 24.0812L52.2956 24.031L52.2598 24.0115C52.279 24.0454 52.3108 24.0705 52.3484 24.0812Z" fill="#0D0C22"/>
<path d="M39.0684 56.469C39.0262 56.4872 38.9893 56.5158 38.9609 56.552L38.9943 56.5306C39.0169 56.5098 39.0489 56.4853 39.0684 56.469Z" fill="#0D0C22"/>
<path d="M46.7802 54.9518C46.7802 54.9041 46.7569 54.9129 46.7626 55.0826C46.7626 55.0687 46.7683 55.0549 46.7708 55.0417C46.7739 55.0115 46.7764 54.982 46.7802 54.9518Z" fill="#0D0C22"/>
<path d="M45.9844 56.469C45.9422 56.4872 45.9053 56.5158 45.877 56.552L45.9103 56.5306C45.9329 56.5098 45.9649 56.4853 45.9844 56.469Z" fill="#0D0C22"/>
<path d="M33.6307 56.8301C33.5987 56.8023 33.5595 56.784 33.5176 56.7773C33.5515 56.7937 33.5855 56.81 33.6081 56.8226L33.6307 56.8301Z" fill="#0D0C22"/>
<path d="M32.4118 55.6598C32.4068 55.6103 32.3916 55.5624 32.3672 55.519C32.3845 55.5642 32.399 55.6104 32.4106 55.6573L32.4118 55.6598Z" fill="#0D0C22"/>
<path d="M40.623 34.7221C38.9449 35.4405 37.0404 36.2551 34.5722 36.2551C33.5397 36.2531 32.5122 36.1114 31.5176 35.834L33.2247 53.3605C33.2851 54.093 33.6188 54.7761 34.1595 55.2739C34.7003 55.7718 35.4085 56.0482 36.1435 56.048C36.1435 56.048 38.564 56.1737 39.3716 56.1737C40.2409 56.1737 42.8474 56.048 42.8474 56.048C43.5823 56.048 44.2904 55.7716 44.831 55.2737C45.3716 54.7759 45.7052 54.0929 45.7656 53.3605L47.594 33.993C46.7769 33.714 45.9523 33.5286 45.0227 33.5286C43.415 33.5279 42.1196 34.0817 40.623 34.7221Z" fill="white"/>
<path d="M26.2344 27.2449L26.2633 27.2719L26.2821 27.2832C26.2676 27.2688 26.2516 27.2559 26.2344 27.2449Z" fill="#0D0C22"/>
<path d="M55.4906 25.6274L55.2336 24.3307C55.0029 23.1673 54.4793 22.068 53.2851 21.6475C52.9024 21.513 52.468 21.4552 52.1745 21.1768C51.881 20.8983 51.7943 20.4659 51.7264 20.0649C51.6007 19.3289 51.4825 18.5923 51.3537 17.8575C51.2424 17.2259 51.1544 16.5163 50.8647 15.9368C50.4876 15.1586 49.705 14.7036 48.9269 14.4025C48.5282 14.2537 48.1213 14.1278 47.7082 14.0254C45.7642 13.5125 43.7202 13.324 41.7202 13.2165C39.3197 13.084 36.9128 13.1239 34.518 13.3359C32.7355 13.4981 30.8581 13.6942 29.1642 14.3108C28.5451 14.5364 27.9071 14.8073 27.4364 15.2856C26.8587 15.8733 26.6702 16.7821 27.0919 17.515C27.3917 18.0354 27.8996 18.4031 28.4382 18.6463C29.1398 18.9597 29.8726 19.1982 30.6242 19.3578C32.7172 19.8204 34.885 20.0021 37.0233 20.0794C39.3932 20.175 41.767 20.0975 44.1256 19.8474C44.7089 19.7833 45.2911 19.7064 45.8723 19.6168C46.5568 19.5118 46.9961 18.6168 46.7943 17.9933C46.553 17.2479 45.9044 16.9587 45.1709 17.0712C45.0628 17.0882 44.9553 17.1039 44.8472 17.1196L44.7692 17.131C44.5208 17.1624 44.2723 17.1917 44.0238 17.219C43.5105 17.2743 42.9959 17.3195 42.4801 17.3547C41.3249 17.4352 40.1665 17.4722 39.0088 17.4741C37.8712 17.4741 36.7329 17.4421 35.5978 17.3673C35.0799 17.3333 34.5632 17.2902 34.0478 17.2378C33.8134 17.2133 33.5796 17.1875 33.3458 17.1586L33.1233 17.1303L33.0749 17.1234L32.8442 17.0901C32.3728 17.0191 31.9014 16.9374 31.435 16.8387C31.388 16.8283 31.3459 16.8021 31.3157 16.7645C31.2856 16.7269 31.2691 16.6801 31.2691 16.6319C31.2691 16.5837 31.2856 16.5369 31.3157 16.4993C31.3459 16.4617 31.388 16.4356 31.435 16.4251H31.4438C31.848 16.339 32.2553 16.2655 32.6638 16.2014C32.8 16.18 32.9366 16.159 33.0736 16.1385H33.0774C33.3332 16.1215 33.5903 16.0757 33.8448 16.0455C36.0595 15.8151 38.2874 15.7366 40.5128 15.8104C41.5933 15.8419 42.6731 15.9053 43.7485 16.0147C43.9798 16.0386 44.2098 16.0637 44.4399 16.092C44.5279 16.1027 44.6165 16.1153 44.7051 16.1259L44.8836 16.1517C45.404 16.2292 45.9217 16.3233 46.4367 16.4339C47.1997 16.5999 48.1796 16.6539 48.519 17.4898C48.6271 17.7551 48.6761 18.0499 48.7359 18.3283L48.8119 18.6834C48.8139 18.6898 48.8154 18.6963 48.8163 18.7029C48.9961 19.5409 49.176 20.379 49.3562 21.217C49.3694 21.2789 49.3697 21.3429 49.3571 21.4049C49.3445 21.4669 49.3193 21.5257 49.2829 21.5776C49.2466 21.6294 49.2 21.6732 49.146 21.7062C49.092 21.7392 49.0317 21.7608 48.969 21.7695H48.964L48.854 21.7846L48.7453 21.799C48.4009 21.8439 48.056 21.8858 47.7107 21.9247C47.0307 22.0022 46.3496 22.0693 45.6674 22.1259C44.3119 22.2386 42.9536 22.3125 41.5927 22.3477C40.8992 22.3662 40.2059 22.3748 39.5129 22.3735C36.7543 22.3713 33.9981 22.211 31.2578 21.8933C30.9611 21.8581 30.6645 21.8204 30.3678 21.7821C30.5978 21.8116 30.2006 21.7594 30.1202 21.7481C29.9316 21.7217 29.7431 21.6943 29.5545 21.6658C28.9216 21.5709 28.2924 21.454 27.6607 21.3515C26.8971 21.2258 26.1667 21.2887 25.476 21.6658C24.909 21.976 24.4501 22.4518 24.1605 23.0297C23.8626 23.6456 23.7739 24.3163 23.6407 24.9781C23.5074 25.6399 23.3 26.3521 23.3786 27.0315C23.5477 28.4979 24.5728 29.6895 26.0473 29.956C27.4345 30.2074 28.8292 30.4111 30.2276 30.5846C35.7212 31.2574 41.2711 31.3379 46.7818 30.8247C47.2305 30.7828 47.6787 30.7371 48.1262 30.6876C48.266 30.6723 48.4074 30.6884 48.5401 30.7348C48.6729 30.7812 48.7936 30.8566 48.8934 30.9557C48.9932 31.0548 49.0695 31.1749 49.1169 31.3073C49.1642 31.4397 49.1814 31.5811 49.167 31.7209L49.0275 33.0773C48.7463 35.8181 48.4652 38.5587 48.184 41.299C47.8907 44.1769 47.5955 47.0545 47.2984 49.9319C47.2146 50.7422 47.1308 51.5524 47.047 52.3624C46.9666 53.16 46.9552 53.9827 46.8038 54.7709C46.5649 56.0103 45.7258 56.7715 44.5015 57.0499C43.3798 57.3052 42.2339 57.4392 41.0836 57.4497C39.8083 57.4566 38.5336 57.4 37.2583 57.4069C35.897 57.4145 34.2295 57.2887 33.1786 56.2756C32.2553 55.3856 32.1277 53.9921 32.002 52.7872C31.8344 51.192 31.6682 49.5971 31.5036 48.0023L30.5796 39.1344L29.9819 33.3966C29.9718 33.3017 29.9618 33.208 29.9524 33.1125C29.8807 32.428 29.3961 31.758 28.6324 31.7926C27.9788 31.8215 27.2359 32.3771 27.3125 33.1125L27.7557 37.3664L28.672 46.1657C28.9331 48.6652 29.1935 51.165 29.4533 53.6653C29.5036 54.1442 29.5507 54.6244 29.6035 55.1034C29.8908 57.7205 31.8895 59.131 34.3646 59.5282C35.8102 59.7607 37.291 59.8085 38.758 59.8324C40.6386 59.8626 42.538 59.9348 44.3877 59.5942C47.1287 59.0914 49.1853 57.2611 49.4788 54.422C49.5626 53.6024 49.6464 52.7826 49.7302 51.9626C50.0088 49.2507 50.2871 46.5386 50.5649 43.8263L51.4737 34.9641L51.8904 30.9026C51.9112 30.7012 51.9962 30.5118 52.133 30.3625C52.2697 30.2132 52.4509 30.1119 52.6497 30.0736C53.4335 29.9208 54.1827 29.66 54.7402 29.0635C55.6277 28.1138 55.8043 26.8756 55.4906 25.6274ZM26.0071 26.5035C26.019 26.4979 25.997 26.6003 25.9876 26.6481C25.9857 26.5758 25.9895 26.5117 26.0071 26.5035ZM26.0831 27.0918C26.0894 27.0874 26.1083 27.1126 26.1278 27.1428C26.0982 27.1151 26.0794 27.0944 26.0825 27.0918H26.0831ZM26.1579 27.1905C26.185 27.2364 26.1994 27.2653 26.1579 27.1905V27.1905ZM26.3082 27.3125H26.3119C26.3119 27.3169 26.3188 27.3213 26.3214 27.3257C26.3172 27.3208 26.3126 27.3164 26.3075 27.3125H26.3082ZM52.6132 27.1302C52.3317 27.3979 51.9074 27.5224 51.4882 27.5846C46.7868 28.2823 42.0169 28.6355 37.264 28.4796C33.8624 28.3633 30.4967 27.9856 27.129 27.5098C26.799 27.4633 26.4414 27.403 26.2145 27.1597C25.7871 26.7009 25.997 25.777 26.1083 25.2226C26.2101 24.7148 26.405 24.0378 27.009 23.9656C27.9518 23.8549 29.0466 24.2528 29.9794 24.3942C31.1023 24.5656 32.2295 24.7028 33.3609 24.8059C38.1892 25.2459 43.0986 25.1774 47.9056 24.5337C48.7817 24.416 49.6548 24.2792 50.5246 24.1233C51.2996 23.9844 52.1588 23.7236 52.6271 24.5262C52.9482 25.073 52.991 25.8046 52.9413 26.4225C52.926 26.6917 52.8084 26.9448 52.6126 27.1302H52.6132Z" fill="#0D0C22"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M81.1302 40.1929C80.8556 40.7169 80.4781 41.1732 79.9978 41.5604C79.5175 41.9479 78.9571 42.2633 78.3166 42.5062C77.6761 42.7497 77.0315 42.9131 76.3835 42.9964C75.7352 43.0799 75.106 43.0727 74.4963 42.9735C73.8863 42.8749 73.3674 42.6737 72.9408 42.3695L73.4214 37.3779C73.8633 37.2261 74.4197 37.0703 75.0909 36.9107C75.7619 36.7513 76.452 36.6371 77.1613 36.5689C77.8705 36.5003 78.5412 36.5084 79.1744 36.5917C79.8068 36.6753 80.3065 36.8765 80.6725 37.1958C80.8707 37.378 81.0387 37.5754 81.176 37.7883C81.313 38.0011 81.3969 38.2214 81.4276 38.4493C81.5037 39.0875 81.4047 39.6687 81.1302 40.1929ZM74.153 29.5602C74.4734 29.3627 74.8585 29.1877 75.3083 29.0356C75.7581 28.8841 76.2195 28.7774 76.6923 28.7167C77.1648 28.6562 77.6262 28.6481 78.0763 28.6938C78.5258 28.7395 78.9228 28.8647 79.2659 29.0697C79.6089 29.2751 79.8643 29.5714 80.032 29.9586C80.1997 30.3464 80.2456 30.8365 80.1693 31.429C80.1083 31.9001 79.9211 32.2991 79.6089 32.6256C79.2963 32.9526 78.9147 33.2259 78.4652 33.4462C78.0154 33.6668 77.5388 33.8415 77.0356 33.9702C76.5321 34.0997 76.0477 34.1949 75.5828 34.2553C75.1176 34.3163 74.7137 34.3545 74.3706 34.3692C74.0273 34.3845 73.8021 34.3921 73.6956 34.3921L74.153 29.5602ZM83.6007 36.9676C83.3566 36.4361 83.0287 35.9689 82.6172 35.5658C82.2054 35.1633 81.717 34.8709 81.1531 34.6885C81.3969 34.491 81.6371 34.1795 81.8737 33.7539C82.1099 33.3288 82.3119 32.865 82.4796 32.3636C82.6474 31.8619 82.762 31.357 82.8229 30.8478C82.8836 30.3389 82.8607 29.902 82.7544 29.537C82.4947 28.6256 82.087 27.9114 81.5303 27.3946C80.9734 26.8782 80.3257 26.5211 79.586 26.3233C78.8462 26.1264 78.0304 26.0842 77.1383 26.1981C76.2462 26.312 75.3347 26.5361 74.4049 26.8704C74.4049 26.7946 74.4124 26.7148 74.4278 26.6312C74.4426 26.548 74.4504 26.4604 74.4504 26.369C74.4504 26.1411 74.3361 25.9439 74.1074 25.7765C73.8787 25.6093 73.6155 25.5107 73.3183 25.4801C73.0209 25.45 72.731 25.5142 72.4489 25.6738C72.1665 25.8334 71.9721 26.1264 71.8656 26.5511C71.7434 27.9189 71.6215 29.3398 71.4996 30.8134C71.3774 32.2875 71.248 33.7767 71.1107 35.2812C70.9735 36.7855 70.8362 38.2784 70.6989 39.7598C70.5616 41.2414 70.4244 42.6659 70.2871 44.0333C70.333 44.4436 70.4473 44.7629 70.6304 44.9907C70.8133 45.2189 71.0268 45.3556 71.2709 45.401C71.5147 45.4467 71.7704 45.4045 72.0371 45.2755C72.3038 45.1469 72.5365 44.9222 72.735 44.6032C73.3447 44.9375 74.0311 45.1541 74.7938 45.253C75.5561 45.3516 76.3298 45.3516 77.1157 45.253C77.9007 45.1541 78.6747 44.9682 79.4374 44.6943C80.1997 44.4211 80.8936 44.079 81.519 43.669C82.1441 43.2586 82.6703 42.7911 83.0975 42.2671C83.5244 41.7426 83.8065 41.1767 83.9437 40.5691C84.081 39.946 84.119 39.3231 84.0581 38.7C83.9971 38.0771 83.8445 37.5 83.6007 36.9676Z" fill="#0D0C23"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.915 49.0017C105.832 49.5031 105.713 50.0311 105.561 50.586C105.408 51.1403 105.229 51.6458 105.023 52.1018C104.818 52.5575 104.589 52.9256 104.337 53.207C104.085 53.488 103.815 53.606 103.525 53.5606C103.296 53.5297 103.151 53.3854 103.091 53.1274C103.029 52.8686 103.029 52.5497 103.091 52.17C103.151 51.7901 103.269 51.3607 103.445 50.8821C103.62 50.4035 103.834 49.9284 104.085 49.4577C104.337 48.9864 104.623 48.5347 104.943 48.1015C105.264 47.6686 105.599 47.3075 105.95 47.0189C106.026 47.11 106.06 47.3378 106.053 47.7028C106.045 48.0674 105.999 48.5006 105.915 49.0017ZM113.67 39.1097C113.464 38.8819 113.213 38.7529 112.915 38.7223C112.618 38.6919 112.317 38.859 112.012 39.2237C111.813 39.5883 111.562 39.9379 111.257 40.2722C110.952 40.6067 110.635 40.9103 110.307 41.1839C109.98 41.4572 109.667 41.6931 109.37 41.8903C109.072 42.0881 108.84 42.2324 108.672 42.3235C108.611 41.8374 108.576 41.3132 108.569 40.7507C108.561 40.1886 108.573 39.619 108.603 39.0415C108.649 38.2209 108.744 37.393 108.889 36.557C109.034 35.7213 109.244 34.9007 109.518 34.0951C109.518 33.67 109.419 33.3242 109.221 33.0582C109.022 32.7924 108.782 32.625 108.5 32.5567C108.218 32.4885 107.929 32.5264 107.631 32.6707C107.334 32.8153 107.078 33.0775 106.865 33.4569C106.682 33.9586 106.472 34.5207 106.236 35.1436C105.999 35.7667 105.732 36.4012 105.435 37.0469C105.138 37.6931 104.806 38.3197 104.44 38.9273C104.074 39.5354 103.674 40.075 103.239 40.5457C102.804 41.0168 102.331 41.3854 101.821 41.6512C101.31 41.9172 100.757 42.0349 100.162 42.0045C99.8876 41.9285 99.6893 41.7235 99.5675 41.3889C99.4453 41.0549 99.373 40.6368 99.3504 40.1354C99.3275 39.634 99.3504 39.0831 99.4189 38.4828C99.4877 37.8828 99.5791 37.2863 99.6934 36.6938C99.8078 36.101 99.9337 35.5389 100.071 35.0071C100.208 34.4753 100.337 34.0268 100.46 33.6622C100.643 33.2218 100.643 32.8529 100.46 32.5567C100.277 32.2604 100.025 32.0631 99.705 31.964C99.3846 31.8654 99.0489 31.8694 98.6983 31.9755C98.3474 32.0819 98.0958 32.3173 97.9435 32.682C97.684 33.3054 97.4475 34.004 97.2342 34.779C97.0206 35.5539 96.8491 36.3558 96.7197 37.1836C96.5896 38.0121 96.5171 38.8327 96.502 39.6456C96.5011 39.6985 96.5037 39.7488 96.5034 39.8014C96.1709 40.6848 95.854 41.3525 95.553 41.7992C95.1641 42.377 94.7253 42.6277 94.2375 42.5513C94.0236 42.4603 93.8832 42.2477 93.8147 41.9132C93.7453 41.5792 93.7227 41.1689 93.7453 40.6822C93.7688 40.1964 93.826 39.6456 93.9171 39.0299C94.0091 38.4146 94.1229 37.7764 94.2601 37.1154C94.3977 36.4541 94.5425 35.7899 94.6949 35.121C94.8472 34.4525 94.9845 33.8218 95.107 33.2291C95.0916 32.6973 94.9352 32.291 94.6377 32.0097C94.3405 31.7289 93.9247 31.6187 93.3913 31.6791C93.0253 31.8312 92.7542 32.029 92.579 32.2719C92.4034 32.5148 92.2623 32.8265 92.1558 33.2062C92.0946 33.404 92.0032 33.799 91.8813 34.3918C91.7591 34.984 91.603 35.6644 91.4123 36.4315C91.2217 37.1992 90.9967 38.0005 90.7376 38.8362C90.4781 39.6719 90.1885 40.4283 89.8684 41.1041C89.548 41.7801 89.1972 42.3235 88.8161 42.7338C88.4348 43.1438 88.023 43.3113 87.5807 43.2352C87.3366 43.1895 87.1805 42.9388 87.112 42.4831C87.0432 42.0271 87.0319 41.4653 87.0775 40.7964C87.1233 40.1279 87.2148 39.3946 87.352 38.5971C87.4893 37.7993 87.63 37.0434 87.7752 36.3289C87.92 35.6149 88.0535 34.984 88.1756 34.4372C88.2975 33.8901 88.3814 33.5254 88.4272 33.3433C88.4272 32.9026 88.3277 32.5495 88.1298 32.2832C87.9313 32.0178 87.6913 31.8503 87.4092 31.7818C87.1268 31.7136 86.8372 31.7514 86.54 31.8957C86.2426 32.0403 85.9872 32.3026 85.7736 32.682C85.6973 33.0923 85.598 33.5674 85.4761 34.1067C85.3539 34.6459 85.2361 35.2006 85.1218 35.7705C85.0074 36.3404 84.9003 36.8988 84.8014 37.4459C84.7021 37.993 84.6299 38.4716 84.584 38.8819C84.5536 39.2008 84.519 39.5923 84.4813 40.0556C84.443 40.5194 84.4238 41.0092 84.4238 41.5257C84.4238 42.0427 84.4618 42.5554 84.5385 43.0643C84.6145 43.5735 84.7518 44.0408 84.95 44.4659C85.1482 44.8915 85.4265 45.2408 85.7852 45.5144C86.1433 45.7879 86.5972 45.9397 87.1463 45.9704C87.7101 46.0005 88.202 45.9591 88.6217 45.8449C89.041 45.731 89.4221 45.5523 89.7654 45.3091C90.1084 45.0665 90.421 44.7776 90.7033 44.443C90.9851 44.1091 91.2637 43.7444 91.5383 43.3491C91.7974 43.9269 92.1329 44.3748 92.5447 44.694C92.9565 45.013 93.3913 45.2032 93.8486 45.2637C94.306 45.3241 94.7715 45.2602 95.2442 45.0699C95.7167 44.8803 96.1436 44.5573 96.5252 44.1012C96.7762 43.8216 97.0131 43.5038 97.2354 43.1525C97.3297 43.317 97.4301 43.4758 97.543 43.6224C97.9168 44.1091 98.424 44.443 99.0645 44.6255C99.7506 44.808 100.421 44.8386 101.077 44.7169C101.733 44.5954 102.358 44.3748 102.953 44.0559C103.548 43.7366 104.101 43.3532 104.612 42.9047C105.122 42.4565 105.568 41.9895 105.95 41.5028C105.934 41.8524 105.927 42.1832 105.927 42.4944C105.927 42.8061 105.919 43.1438 105.904 43.5088C105.141 44.0408 104.421 44.679 103.742 45.4233C103.064 46.1676 102.469 46.9616 101.958 47.8051C101.447 48.6483 101.047 49.5031 100.757 50.3691C100.467 51.2357 100.326 52.0445 100.334 52.7969C100.341 53.549 100.521 54.206 100.871 54.7681C101.222 55.3306 101.794 55.7331 102.587 55.9763C103.411 56.2348 104.135 56.242 104.76 55.9991C105.386 55.7559 105.931 55.3531 106.396 54.791C106.861 54.2289 107.242 53.549 107.54 52.7512C107.837 51.9534 108.073 51.1215 108.249 50.2555C108.424 49.3894 108.535 48.5379 108.58 47.7028C108.626 46.8668 108.626 46.1219 108.58 45.4687C109.892 44.9219 110.967 44.2305 111.806 43.3945C112.645 42.5594 113.338 41.6778 113.887 40.7507C114.055 40.5229 114.112 40.2493 114.059 39.9304C114.006 39.6111 113.876 39.3376 113.67 39.1097Z" fill="#0D0C23"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M142.53 37.6515C142.575 37.3022 142.644 36.9335 142.735 36.546C142.827 36.1585 142.941 35.7823 143.079 35.4177C143.216 35.0531 143.376 34.7379 143.559 34.4718C143.742 34.2061 143.937 34.0161 144.142 33.9019C144.348 33.7883 144.558 33.7995 144.771 33.936C145 34.0731 145.141 34.3617 145.195 34.8021C145.248 35.2433 145.195 35.7141 145.034 36.2155C144.874 36.7172 144.588 37.1879 144.177 37.6286C143.765 38.0696 143.208 38.3579 142.507 38.4947C142.476 38.2824 142.484 38.0011 142.53 37.6515ZM150.456 38.5857C150.204 38.5103 149.964 38.5025 149.735 38.5632C149.506 38.6239 149.361 38.7835 149.301 39.042C149.178 39.5281 148.984 40.0258 148.717 40.5347C148.45 41.0439 148.122 41.5262 147.734 41.9822C147.345 42.438 146.906 42.8408 146.418 43.1901C145.93 43.5397 145.419 43.7904 144.886 43.9422C144.351 44.1096 143.91 44.1284 143.559 43.9991C143.208 43.8705 142.93 43.6498 142.724 43.3384C142.518 43.027 142.369 42.6508 142.278 42.2101C142.186 41.7694 142.133 41.3137 142.118 40.8424C142.987 40.9034 143.761 40.7478 144.44 40.3751C145.118 40.0032 145.694 39.509 146.167 38.8937C146.639 38.2784 146.998 37.587 147.242 36.8195C147.485 36.0524 147.623 35.2887 147.653 34.5288C147.669 33.8146 147.562 33.2108 147.333 32.7169C147.105 32.2233 146.796 31.839 146.407 31.5658C146.018 31.2922 145.572 31.1326 145.069 31.0872C144.566 31.0415 144.054 31.11 143.536 31.2922C142.91 31.505 142.381 31.8506 141.946 32.3294C141.512 32.808 141.149 33.3629 140.86 33.9933C140.57 34.6239 140.341 35.3038 140.173 36.033C140.005 36.7626 139.883 37.4806 139.807 38.1873C139.739 38.8214 139.702 39.4278 139.689 40.013C139.657 40.0874 139.625 40.1588 139.59 40.2383C139.354 40.7782 139.079 41.3062 138.766 41.8226C138.454 42.3394 138.107 42.7725 137.726 43.1218C137.344 43.4714 136.948 43.5929 136.536 43.4865C136.292 43.426 136.159 43.1444 136.136 42.6433C136.113 42.1416 136.139 41.5187 136.216 40.7741C136.292 40.0298 136.38 39.2239 136.479 38.3579C136.578 37.4918 136.628 36.664 136.628 35.8737C136.628 35.1898 136.498 34.5329 136.239 33.9019C135.979 33.2718 135.625 32.7473 135.175 32.3294C134.725 31.9113 134.203 31.634 133.608 31.4975C133.013 31.3605 132.373 31.4518 131.687 31.7708C131 32.09 130.455 32.5382 130.051 33.1157C129.647 33.6934 129.277 34.3009 128.942 34.9391C128.819 34.4528 128.641 34.0011 128.404 33.583C128.167 33.1651 127.878 32.8005 127.535 32.4888C127.191 32.1776 126.806 31.9344 126.38 31.7595C125.953 31.5851 125.502 31.4975 125.03 31.4975C124.572 31.4975 124.149 31.5851 123.76 31.7595C123.371 31.9344 123.017 32.1583 122.696 32.4318C122.376 32.7056 122.087 33.013 121.827 33.3551C121.568 33.6969 121.339 34.0352 121.141 34.3692C121.11 33.9742 121.076 33.6286 121.038 33.332C121 33.0359 120.931 32.7852 120.832 32.5801C120.733 32.3748 120.592 32.2193 120.409 32.1129C120.226 32.0067 119.967 31.9532 119.632 31.9532C119.464 31.9532 119.296 31.9874 119.128 32.0556C118.96 32.1241 118.811 32.2193 118.682 32.3407C118.552 32.4627 118.453 32.6105 118.385 32.7852C118.316 32.9598 118.297 33.1614 118.327 33.3892C118.342 33.5566 118.385 33.7576 118.453 33.9933C118.522 34.2289 118.587 34.5369 118.648 34.9163C118.708 35.2962 118.758 35.756 118.796 36.2953C118.834 36.8349 118.846 37.4959 118.831 38.2784C118.815 39.0611 118.758 39.9763 118.659 41.0248C118.56 42.0733 118.403 43.289 118.19 44.6714C118.16 44.9907 118.282 45.2492 118.556 45.4467C118.831 45.6439 119.143 45.7578 119.494 45.7885C119.845 45.8188 120.177 45.7578 120.489 45.6063C120.802 45.4539 120.981 45.1882 121.027 44.8085C121.072 44.0943 121.16 43.3347 121.29 42.529C121.419 41.724 121.579 40.9262 121.77 40.1359C121.961 39.346 122.178 38.5938 122.422 37.8793C122.666 37.1651 122.937 36.5347 123.234 35.9876C123.532 35.4405 123.84 35.0039 124.161 34.6771C124.481 34.3504 124.816 34.187 125.167 34.187C125.594 34.187 125.926 34.3805 126.162 34.7679C126.398 35.1557 126.566 35.6536 126.666 36.2609C126.765 36.869 126.81 37.5341 126.803 38.2555C126.795 38.9773 126.765 39.6724 126.711 40.341C126.658 41.0098 126.597 41.606 126.528 42.1303C126.46 42.6545 126.41 43.0157 126.38 43.2129C126.38 43.5625 126.513 43.8395 126.78 44.0448C127.046 44.2498 127.344 44.3716 127.672 44.4095C128 44.4476 128.309 44.3866 128.598 44.227C128.888 44.0674 129.056 43.7982 129.102 43.4179C129.254 42.324 129.464 41.2264 129.731 40.1247C129.997 39.023 130.303 38.0355 130.646 37.1616C130.989 36.2878 131.37 35.5735 131.79 35.0189C132.209 34.4646 132.655 34.187 133.128 34.187C133.371 34.187 133.559 34.3544 133.688 34.6884C133.818 35.0227 133.883 35.4784 133.883 36.0559C133.883 36.4815 133.848 36.9184 133.78 37.3666C133.711 37.8148 133.631 38.2784 133.54 38.7569C133.448 39.2358 133.368 39.7256 133.299 40.227C133.231 40.7287 133.196 41.2527 133.196 41.7998C133.196 42.1797 133.235 42.6204 133.311 43.1218C133.387 43.6229 133.532 44.0983 133.745 44.5462C133.959 44.9947 134.252 45.3744 134.626 45.6858C135 45.9973 135.476 46.1531 136.056 46.1531C136.925 46.1531 137.695 45.9669 138.366 45.5947C139.037 45.2226 139.613 44.7365 140.093 44.1362C140.118 44.1047 140.141 44.0711 140.165 44.0399C140.202 44.1287 140.235 44.2227 140.276 44.3071C140.604 44.9756 141.05 45.4921 141.615 45.857C142.178 46.2216 142.842 46.4229 143.605 46.4611C144.367 46.4987 145.198 46.3581 146.098 46.0392C146.769 45.796 147.352 45.4921 147.848 45.1275C148.343 44.7628 148.789 44.3184 149.186 43.7941C149.583 43.2699 149.945 42.6658 150.273 41.9822C150.601 41.2981 150.932 40.5159 151.268 39.6342C151.329 39.3916 151.272 39.1751 151.097 38.9848C150.921 38.7951 150.708 38.6621 150.456 38.5857Z" fill="#0D0C23"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M162.887 36.0434C162.81 36.4918 162.707 36.986 162.578 37.525C162.448 38.0646 162.284 38.623 162.086 39.2004C161.888 39.7779 161.644 40.2984 161.354 40.7616C161.064 41.2254 160.733 41.5935 160.359 41.8671C159.985 42.1406 159.555 42.2546 159.066 42.2089C158.822 42.1788 158.635 42.0117 158.506 41.7075C158.376 41.4038 158.308 41.0161 158.3 40.545C158.292 40.0743 158.334 39.5575 158.426 38.9951C158.517 38.4333 158.658 37.8821 158.849 37.3426C159.04 36.8036 159.272 36.3056 159.547 35.8496C159.821 35.3939 160.138 35.0405 160.496 34.7898C160.854 34.5391 161.247 34.4217 161.674 34.4365C162.101 34.4518 162.559 34.6643 163.047 35.0747C163.016 35.2725 162.963 35.5954 162.887 36.0434ZM171.019 37.787C170.782 37.6656 170.538 37.6392 170.287 37.7075C170.035 37.7757 169.856 38.0076 169.749 38.4026C169.688 38.8283 169.551 39.3294 169.338 39.9069C169.124 40.4843 168.861 41.0317 168.548 41.5478C168.236 42.0646 167.877 42.494 167.473 42.8358C167.069 43.1778 166.638 43.3337 166.181 43.3028C165.799 43.2727 165.532 43.079 165.38 42.7218C165.227 42.3647 165.147 41.9168 165.14 41.3769C165.132 40.838 165.186 40.2301 165.3 39.5538C165.414 38.8777 165.552 38.2054 165.712 37.5363C165.872 36.868 166.036 36.2258 166.204 35.6105C166.371 34.9951 166.508 34.4747 166.616 34.0493C166.738 33.6693 166.699 33.3466 166.501 33.0803C166.303 32.8149 166.055 32.6246 165.758 32.5107C165.46 32.3967 165.159 32.3664 164.854 32.4196C164.549 32.4728 164.351 32.6362 164.259 32.9094C163.359 32.1345 162.494 31.7166 161.663 31.6559C160.831 31.5952 160.065 31.7776 159.364 32.203C158.662 32.6284 158.041 33.2437 157.5 34.0493C156.958 34.8549 156.52 35.7322 156.184 36.6818C155.849 37.6314 155.639 38.6004 155.555 39.5879C155.471 40.5757 155.536 41.4761 155.75 42.289C155.963 43.1018 156.34 43.7669 156.882 44.283C157.423 44.7998 158.159 45.0583 159.089 45.0583C159.501 45.0583 159.898 44.9747 160.279 44.8076C160.66 44.6401 161.011 44.4426 161.331 44.2148C161.651 43.9869 161.933 43.7475 162.178 43.4968C162.421 43.2461 162.612 43.0373 162.749 42.8699C162.856 43.417 163.032 43.8808 163.276 44.2605C163.519 44.6401 163.798 44.9521 164.111 45.1948C164.423 45.4376 164.751 45.6164 165.094 45.7306C165.437 45.8445 165.769 45.9015 166.089 45.9015C166.806 45.9015 167.477 45.6583 168.102 45.1719C168.727 44.6861 169.288 44.0893 169.784 43.3829C170.279 42.6762 170.687 41.9319 171.007 41.1491C171.328 40.3666 171.541 39.6715 171.648 39.0634C171.755 38.8355 171.735 38.5964 171.591 38.3457C171.446 38.095 171.255 37.909 171.019 37.787Z" fill="#0D0C23"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M212.194 50.3701C212.064 50.8866 211.862 51.3238 211.587 51.6806C211.313 52.0377 210.97 52.2239 210.558 52.2393C210.299 52.2543 210.101 52.1175 209.963 51.8289C209.826 51.5401 209.731 51.1679 209.678 50.7122C209.624 50.2562 209.601 49.747 209.609 49.1849C209.616 48.6227 209.639 48.0681 209.678 47.521C209.715 46.9742 209.761 46.4647 209.815 45.9939C209.868 45.5226 209.91 45.1586 209.94 44.9C210.459 44.9608 210.89 45.1846 211.233 45.5723C211.576 45.9598 211.839 46.4193 212.022 46.9514C212.205 47.4831 212.312 48.0568 212.343 48.6722C212.373 49.2875 212.323 49.8534 212.194 50.3701ZM203.913 50.3701C203.783 50.8866 203.581 51.3238 203.307 51.6806C203.032 52.0377 202.689 52.2239 202.277 52.2393C202.018 52.2543 201.82 52.1175 201.683 51.8289C201.545 51.5401 201.45 51.1679 201.397 50.7122C201.343 50.2562 201.32 49.747 201.328 49.1849C201.336 48.6227 201.358 48.0681 201.397 47.521C201.434 46.9742 201.48 46.4647 201.534 45.9939C201.587 45.5226 201.629 45.1586 201.66 44.9C202.178 44.9608 202.609 45.1846 202.952 45.5723C203.295 45.9598 203.558 46.4193 203.741 46.9514C203.924 47.4831 204.031 48.0568 204.062 48.6722C204.092 49.2875 204.042 49.8534 203.913 50.3701ZM195.415 37.4241C195.399 37.7884 195.365 38.1114 195.312 38.3925C195.258 38.6741 195.186 38.8522 195.095 38.9283C194.927 38.8369 194.721 38.6018 194.477 38.2216C194.233 37.8419 194.042 37.4122 193.905 36.9336C193.768 36.4551 193.725 35.9843 193.779 35.5205C193.832 35.0573 194.073 34.6967 194.5 34.4379C194.667 34.3468 194.812 34.3809 194.934 34.5405C195.056 34.7001 195.155 34.9318 195.232 35.2357C195.308 35.5399 195.361 35.8892 195.392 36.2842C195.422 36.6795 195.43 37.0591 195.415 37.4241ZM193.39 41.9711C193.154 42.2215 192.89 42.4381 192.601 42.6206C192.311 42.803 192.014 42.9398 191.709 43.0309C191.404 43.1223 191.129 43.1448 190.885 43.0991C190.199 42.9627 189.673 42.666 189.307 42.2103C188.941 41.7545 188.708 41.219 188.609 40.6037C188.51 39.9881 188.521 39.3308 188.644 38.6319C188.765 37.933 188.971 37.2835 189.261 36.6832C189.551 36.0829 189.902 35.5662 190.313 35.1333C190.725 34.7001 191.175 34.4306 191.663 34.3239C191.48 35.0989 191.419 35.9007 191.48 36.7286C191.541 37.5568 191.739 38.3355 192.075 39.0648C192.288 39.506 192.544 39.9082 192.841 40.2729C193.139 40.6378 193.501 40.9492 193.928 41.2075C193.806 41.466 193.626 41.7204 193.39 41.9711ZM218.702 37.6519C218.747 37.3026 218.816 36.9336 218.908 36.5462C218.999 36.159 219.114 35.7828 219.251 35.4181C219.388 35.0532 219.548 34.738 219.731 34.4723C219.914 34.2065 220.108 34.0163 220.314 33.9024C220.52 33.7884 220.73 33.7997 220.943 33.9365C221.172 34.0735 221.313 34.3621 221.367 34.8025C221.42 35.2435 221.367 35.7142 221.207 36.2159C221.046 36.7173 220.761 37.1884 220.349 37.6288C219.937 38.07 219.38 38.3583 218.679 38.4951C218.648 38.2826 218.656 38.0015 218.702 37.6519ZM227.921 37.6519C227.966 37.3026 228.035 36.9336 228.126 36.5462C228.218 36.159 228.332 35.7828 228.47 35.4181C228.607 35.0532 228.767 34.738 228.95 34.4723C229.133 34.2065 229.328 34.0163 229.533 33.9024C229.739 33.7884 229.949 33.7997 230.162 33.9365C230.391 34.0735 230.532 34.3621 230.586 34.8025C230.639 35.2435 230.586 35.7142 230.425 36.2159C230.265 36.7173 229.979 37.1884 229.568 37.6288C229.156 38.07 228.599 38.3583 227.898 38.4951C227.867 38.2826 227.875 38.0015 227.921 37.6519ZM236.488 38.9852C236.312 38.7955 236.099 38.6625 235.847 38.5862C235.595 38.5104 235.355 38.5029 235.126 38.5636C234.897 38.6244 234.752 38.784 234.692 39.0422C234.57 39.5286 234.375 40.0262 234.108 40.5349C233.841 41.0444 233.514 41.5267 233.125 41.9824C232.736 42.4381 232.297 42.8412 231.81 43.1905C231.321 43.5401 230.81 43.7908 230.277 43.9423C229.743 44.1101 229.301 44.1289 228.95 43.9996C228.599 43.8706 228.321 43.6503 228.115 43.3389C227.909 43.0271 227.761 42.6512 227.669 42.2103C227.578 41.7699 227.524 41.3142 227.509 40.8428C228.378 40.9038 229.152 40.7483 229.831 40.3755C230.509 40.0034 231.085 39.5092 231.558 38.8939C232.031 38.2788 232.389 37.5874 232.633 36.82C232.877 36.0526 233.014 35.2892 233.045 34.5293C233.06 33.815 232.953 33.211 232.724 32.7171C232.496 32.2235 232.187 31.8395 231.798 31.5662C231.409 31.2924 230.963 31.133 230.46 31.0874C229.957 31.0417 229.445 31.1105 228.927 31.2924C228.302 31.5055 227.772 31.851 227.338 32.3296C226.903 32.8085 226.54 33.3634 226.251 33.9934C225.961 34.6244 225.732 35.3039 225.564 36.0335C225.396 36.7627 225.274 37.481 225.199 38.1874C225.124 38.873 225.084 39.5292 225.075 40.1572C225.017 40.2824 224.956 40.4082 224.889 40.5349C224.622 41.0444 224.295 41.5267 223.906 41.9824C223.517 42.4381 223.078 42.8412 222.591 43.1905C222.102 43.5401 221.592 43.7908 221.058 43.9423C220.524 44.1101 220.082 44.1289 219.731 43.9996C219.38 43.8706 219.102 43.6503 218.896 43.3389C218.691 43.0271 218.542 42.6512 218.45 42.2103C218.359 41.7699 218.305 41.3142 218.29 40.8428C219.159 40.9038 219.933 40.7483 220.612 40.3755C221.29 40.0034 221.866 39.5092 222.339 38.8939C222.811 38.2788 223.17 37.5874 223.414 36.82C223.658 36.0526 223.795 35.2892 223.826 34.5293C223.841 33.815 223.734 33.211 223.506 32.7171C223.277 32.2235 222.968 31.8395 222.579 31.5662C222.19 31.2924 221.744 31.133 221.241 31.0874C220.738 31.0417 220.227 31.1105 219.708 31.2924C219.083 31.5055 218.553 31.851 218.119 32.3296C217.684 32.8085 217.321 33.3634 217.032 33.9934C216.742 34.6244 216.513 35.3039 216.346 36.0335C216.178 36.7627 216.056 37.481 215.98 38.1874C215.936 38.5859 215.907 38.9722 215.886 39.3516C215.739 39.4765 215.595 39.6023 215.442 39.7258C214.916 40.1514 214.363 40.5349 213.784 40.8769C213.204 41.219 212.601 41.5001 211.977 41.7204C211.351 41.9408 210.71 42.0738 210.055 42.1192L211.473 26.9847C211.565 26.6655 211.519 26.3847 211.336 26.1415C211.153 25.8983 210.916 25.7312 210.627 25.6401C210.337 25.5488 210.028 25.5566 209.7 25.6627C209.372 25.7694 209.102 26.0126 208.888 26.3919C208.781 26.9697 208.671 27.7597 208.557 28.7625C208.442 29.7653 208.328 30.8595 208.213 32.0448C208.099 33.23 207.985 34.4532 207.87 35.7142C207.756 36.9759 207.657 38.1533 207.573 39.2472C207.569 39.2958 207.566 39.3398 207.562 39.3878C207.429 39.5005 207.299 39.6142 207.161 39.7258C206.635 40.1514 206.082 40.5349 205.503 40.8769C204.923 41.219 204.321 41.5001 203.696 41.7204C203.07 41.9408 202.429 42.0738 201.774 42.1192L203.192 26.9847C203.284 26.6655 203.238 26.3847 203.055 26.1415C202.872 25.8983 202.635 25.7312 202.346 25.6401C202.056 25.5488 201.747 25.5566 201.419 25.6627C201.091 25.7694 200.821 26.0126 200.607 26.3919C200.501 26.9697 200.39 27.7597 200.276 28.7625C200.161 29.7653 200.047 30.8595 199.933 32.0448C199.818 33.23 199.704 34.4532 199.589 35.7142C199.475 36.9759 199.376 38.1533 199.292 39.2472C199.29 39.2692 199.289 39.2891 199.287 39.3111C199.048 39.4219 198.786 39.519 198.503 39.6006C198.213 39.6844 197.885 39.7339 197.519 39.7489C197.58 39.4751 197.63 39.1712 197.668 38.8369C197.706 38.5029 197.737 38.1533 197.76 37.7884C197.782 37.4241 197.79 37.0591 197.782 36.6945C197.774 36.3296 197.755 35.9956 197.725 35.6914C197.649 35.0385 197.508 34.4191 197.302 33.8338C197.096 33.2491 196.818 32.7593 196.467 32.3637C196.116 31.9687 195.678 31.7027 195.151 31.5662C194.626 31.4294 194.012 31.4748 193.31 31.7027C192.273 31.5662 191.339 31.6613 190.508 31.9878C189.677 32.3149 188.956 32.7894 188.346 33.4122C187.736 34.0357 187.237 34.7684 186.848 35.6119C186.459 36.4551 186.2 37.3214 186.07 38.21C186.015 38.5868 185.988 38.9618 185.98 39.336C185.744 39.8177 185.486 40.2388 185.201 40.5921C184.797 41.0935 184.377 41.5038 183.943 41.8228C183.508 42.142 183.077 42.3852 182.65 42.5523C182.223 42.7198 181.842 42.8337 181.507 42.8941C181.11 42.9702 180.729 42.978 180.363 42.917C179.997 42.8565 179.661 42.6816 179.357 42.3927C179.112 42.1802 178.925 41.8381 178.796 41.3671C178.666 40.896 178.59 40.3608 178.567 39.7602C178.544 39.1599 178.567 38.533 178.636 37.8798C178.705 37.2266 178.822 36.6072 178.99 36.0222C179.158 35.4372 179.371 34.913 179.631 34.4492C179.89 33.9862 180.195 33.6554 180.546 33.4579C180.744 33.4886 180.866 33.606 180.912 33.811C180.958 34.0163 180.969 34.2595 180.946 34.5405C180.923 34.8219 180.889 35.1105 180.843 35.4066C180.797 35.703 180.775 35.9502 180.775 36.1474C180.851 36.5577 180.999 36.877 181.221 37.1048C181.441 37.3327 181.69 37.466 181.964 37.5036C182.239 37.5417 182.509 37.4773 182.776 37.3098C183.043 37.143 183.26 36.877 183.428 36.512C183.443 36.5274 183.466 36.5349 183.497 36.5349L183.817 33.6404C183.909 33.2451 183.847 32.8958 183.634 32.5919C183.42 32.288 183.138 32.113 182.788 32.0676C182.345 31.4294 181.747 31.0914 180.992 31.0532C180.237 31.0154 179.463 31.2623 178.67 31.7941C178.182 32.144 177.751 32.626 177.378 33.2413C177.004 33.857 176.699 34.5405 176.463 35.2926C176.226 36.0448 176.058 36.8391 175.959 37.6748C175.86 38.5104 175.841 39.3236 175.902 40.1133C175.963 40.9038 176.104 41.6484 176.325 42.347C176.546 43.0462 176.855 43.6312 177.252 44.102C177.587 44.5123 177.968 44.8127 178.395 45.0027C178.822 45.1927 179.268 45.3101 179.734 45.3558C180.199 45.4012 180.66 45.3821 181.118 45.2988C181.575 45.2155 182.01 45.0978 182.421 44.9454C182.955 44.7482 183.505 44.4972 184.069 44.1933C184.633 43.8897 185.174 43.5248 185.693 43.0991C185.966 42.8753 186.228 42.6313 186.482 42.3696C186.598 42.6553 186.727 42.9317 186.882 43.1905C187.294 43.8741 187.85 44.429 188.552 44.8544C189.253 45.2797 190.115 45.4844 191.137 45.4697C192.235 45.4544 193.249 45.1774 194.18 44.6378C195.11 44.0988 195.872 43.3042 196.467 42.256C197.358 42.256 198.234 42.1096 199.096 41.819C199.089 41.911 199.081 42.0079 199.075 42.0966C199.014 42.9019 198.983 43.4487 198.983 43.7376C198.968 44.239 198.934 44.8581 198.88 45.5949C198.827 46.332 198.793 47.1069 198.778 47.9198C198.763 48.7326 198.793 49.5532 198.869 50.3817C198.945 51.2096 199.105 51.962 199.349 52.6383C199.593 53.3141 199.94 53.8878 200.39 54.3591C200.84 54.8299 201.431 55.1112 202.163 55.2023C202.941 55.3084 203.612 55.1717 204.176 54.792C204.74 54.412 205.198 53.8918 205.549 53.2308C205.899 52.5695 206.147 51.8061 206.292 50.9401C206.437 50.074 206.479 49.2039 206.418 48.3301C206.357 47.4562 206.196 46.6321 205.937 45.8575C205.678 45.0822 205.319 44.444 204.862 43.9423C205.137 43.8669 205.465 43.7226 205.846 43.5095C206.227 43.2969 206.62 43.0575 207.024 42.7915C207.123 42.7261 207.221 42.6573 207.32 42.5902C207.283 43.1286 207.264 43.5126 207.264 43.7376C207.249 44.239 207.215 44.8581 207.161 45.5949C207.108 46.332 207.073 47.1069 207.058 47.9198C207.043 48.7326 207.073 49.5532 207.15 50.3817C207.226 51.2096 207.386 51.962 207.63 52.6383C207.874 53.3141 208.221 53.8878 208.671 54.3591C209.121 54.8299 209.712 55.1112 210.444 55.2023C211.221 55.3084 211.892 55.1717 212.457 54.792C213.021 54.412 213.478 53.8918 213.83 53.2308C214.18 52.5695 214.428 51.8061 214.573 50.9401C214.718 50.074 214.759 49.2039 214.699 48.3301C214.637 47.4562 214.477 46.6321 214.218 45.8575C213.959 45.0822 213.601 44.444 213.143 43.9423C213.418 43.8669 213.745 43.7226 214.127 43.5095C214.508 43.2969 214.9 43.0575 215.305 42.7915C215.515 42.6533 215.724 42.5107 215.932 42.3641C216.01 43.1072 216.179 43.759 216.448 44.3073C216.776 44.9761 217.222 45.4925 217.787 45.8575C218.351 46.2218 219.014 46.4234 219.777 46.4612C220.539 46.4988 221.37 46.3586 222.271 46.0393C222.941 45.7965 223.525 45.4925 224.02 45.1279C224.516 44.763 224.962 44.3185 225.358 43.7946C225.381 43.7642 225.403 43.7313 225.425 43.7006C225.496 43.9134 225.574 44.1179 225.667 44.3073C225.995 44.9761 226.441 45.4925 227.006 45.8575C227.569 46.2218 228.233 46.4234 228.996 46.4612C229.758 46.4988 230.589 46.3586 231.489 46.0393C232.16 45.7965 232.744 45.4925 233.239 45.1279C233.735 44.763 234.181 44.3185 234.577 43.7946C234.974 43.27 235.336 42.666 235.664 41.9824C235.992 41.2985 236.323 40.5164 236.659 39.6347C236.72 39.3918 236.663 39.1752 236.488 38.9852Z" fill="#0D0C23"/>
</svg>`;

// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
let getRandomValues;
const rnds8 = new Uint8Array(16);
function rng() {
  // lazy load so that environments that need to polyfill have a chance to do so
  if (!getRandomValues) {
    // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
    getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);

    if (!getRandomValues) {
      throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
    }
  }

  return getRandomValues(rnds8);
}

/**
 * Convert array of 16 byte values to UUID string format of the form:
 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 */

const byteToHex = [];

for (let i = 0; i < 256; ++i) {
  byteToHex.push((i + 0x100).toString(16).slice(1));
}

function unsafeStringify(arr, offset = 0) {
  // Note: Be careful editing this code!  It's been tuned for performance
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
  return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
}

const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
var native = {
  randomUUID
};

function v4(options, buf, offset) {
  if (native.randomUUID && !buf && !options) {
    return native.randomUUID();
  }

  options = options || {};
  const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`

  rnds[6] = rnds[6] & 0x0f | 0x40;
  rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided

  if (buf) {
    offset = offset || 0;

    for (let i = 0; i < 16; ++i) {
      buf[offset + i] = rnds[i];
    }

    return buf;
  }

  return unsafeStringify(rnds);
}

class TextFormatSettingTab extends obsidian.PluginSettingTab {
    constructor(app, plugin) {
        super(app, plugin);
        this.plugin = plugin;
        this.collapseMemory = {};
        // this.builtInCustomReplacement();
    }
    // async builtInCustomReplacement() {
    //   for (let command of CustomReplacementBuiltInCommands) {
    //     if (this.plugin.settings.customReplaceBuiltInLog[command.id] == null) {
    //       this.plugin.settings.customReplaceList.push({ name: getString(["command", command.id]), data: command.data });
    //       this.plugin.settings.customReplaceBuiltInLog[command.id] = { id: command.id, modified: false };
    //     }
    //   }
    //   await this.plugin.saveSettings();
    // }
    display() {
        let { containerEl } = this;
        let headerEl;
        containerEl.empty();
        containerEl.addClass("plugin-text-format");
        containerEl
            .createEl("p", { text: getString(["setting", "more-details"]) })
            .createEl("a", {
            text: "text-format",
            href: "https://github.com/Benature/obsidian-text-format",
        });
        this.addSettingsAboutWordCase(containerEl);
        this.addSettingsAboutLink(containerEl);
        this.addSettingsAboutList(containerEl);
        this.addSettingsAboutMarkdownQuicker(containerEl);
        this.addSettingsAboutWrapper(containerEl);
        this.addSettingsAboutApiRequest(containerEl);
        this.addSettingsAboutReplacement(containerEl);
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        headerEl = headerDiv.createEl("h3", { text: getString(["setting", "others"]) });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl, true);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "remove-spaces-when-converting"]))
            .setDesc(getString(["setting", "remove-spaces-when-converting-desc"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.RemoveBlanksWhenChinese)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.RemoveBlanksWhenChinese = value;
                yield this.plugin.saveSettings();
            }));
        });
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "debug-logging"]))
            .setDesc(getString(["setting", "debug-logging-desc"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.debugMode)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.debugMode = value;
                yield this.plugin.saveSettings();
            }));
        });
        this.addSettingsAboutParagraph(this.contentEl);
        this.addSettingsAboutZotero(this.contentEl);
        addDonationElement(containerEl);
    }
    // refer from https://github.com/Mocca101/obsidian-plugin-groups/tree/main
    makeCollapsible(foldClickElement, content, startOpened) {
        if (!content.hasClass('tf-collapsible-content')) {
            content.addClass('tf-collapsible-content');
        }
        if (!foldClickElement.hasClass('tf-collapsible-header')) {
            foldClickElement.addClass('tf-collapsible-header');
        }
        toggleCollapsibleIcon(foldClickElement);
        let text = "<unknown>";
        // settings headers are H3
        if (["H3", "H4"].includes(foldClickElement.tagName)) {
            text = foldClickElement.textContent;
            if (!(text in this.collapseMemory)) {
                this.collapseMemory[text] = false;
            }
            startOpened = startOpened ? true : this.collapseMemory[text];
        }
        if (startOpened) {
            content.addClass('is-active');
            toggleCollapsibleIcon(foldClickElement);
        }
        foldClickElement.onclick = () => {
            if (content.hasClass('is-active')) {
                content.removeClass('is-active');
                this.collapseMemory[text] = false;
            }
            else {
                content.addClass('is-active');
                this.collapseMemory[text] = true;
            }
            toggleCollapsibleIcon(foldClickElement);
        };
    }
    addSettingsAboutWordCase(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "word-cases"]) });
        headerDiv.createEl("div", { text: getString(["setting", "word-cases-desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "lowercase-before-capitalize"]))
            .setDesc(getString(["setting", "lowercase-before-capitalize-desc"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.LowercaseFirst)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.LowercaseFirst = value;
                yield this.plugin.saveSettings();
            }));
        });
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "cycle-case-sequence"]))
            .setDesc(getString(["setting", "cycle-case-sequence-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("lowerCase\nupperCase")
            .setValue(this.plugin.settings.ToggleSequence)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.ToggleSequence = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "proper-noun"]))
            .setDesc(getString(["setting", "proper-noun-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("USA, UFO")
            .setValue(this.plugin.settings.ProperNoun)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.ProperNoun = value;
            yield this.plugin.saveSettings();
        })));
    }
    addSettingsAboutParagraph(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h4", { text: getString(["setting", "paragraph", "header"]) });
        let contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, contentEl);
        new obsidian.Setting(contentEl)
            .setName(getString(["setting", "paragraph", "remove-redundant-blank-lines"]))
            .setDesc(getString(["setting", "paragraph", "remove-redundant-blank-lines-desc"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.MergeParagraph_Newlines)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.MergeParagraph_Newlines = value;
                yield this.plugin.saveSettings();
            }));
        });
        new obsidian.Setting(contentEl)
            .setName(getString(["setting", "remove-redundant-blank-spaces"]))
            .setDesc(getString(["setting", "remove-redundant-blank-spaces-desc"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.MergeParagraph_Spaces)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.MergeParagraph_Spaces = value;
                yield this.plugin.saveSettings();
            }));
        });
    }
    addSettingsAboutLink(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "link-format"]) });
        headerDiv.createEl("div", { text: getString(["setting", "link-format-desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "path-mode"]))
            // .setDesc("Or will use absolute path instead.")
            .addDropdown(dropDown => dropDown
            .addOption(Wikilink2mdPathMode.relativeObsidian, getString(["setting", "Wikilink2mdPathMode-relative-obsidian"]))
            .addOption(Wikilink2mdPathMode.relativeFile, getString(["setting", "Wikilink2mdPathModerelative-file"]))
            .addOption(Wikilink2mdPathMode.absolute, getString(["setting", "Wikilink2mdPathMode-absolute"]))
            .setValue(this.plugin.settings.Wikilink2mdRelativePath || Wikilink2mdPathMode.relativeObsidian)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.Wikilink2mdRelativePath = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "result-format"]))
            .setDesc(getString(["setting", "result-format-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("{url}")
            .setValue(this.plugin.settings.UrlLinkFormat)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.UrlLinkFormat = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "remove-wikilink-url"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.RemoveWikiURL2)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.RemoveWikiURL2 = value;
                yield this.plugin.saveSettings();
            }));
        });
        this.contentEl.createEl("h4", { text: "Format when removing wikiLink" });
        // containerEl.createEl("p", { text: "Define the result of calling `Remove WikiLink format in selection`" });
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "wiki-link-format-heading"]))
            .setDesc(getString(["setting", "wiki-link-format-heading-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("{title} (> {heading})")
            .setValue(this.plugin.settings.WikiLinkFormat.headingOnly)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.WikiLinkFormat.headingOnly = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "wiki-link-format-alias"]))
            .setDesc(getString(["setting", "wiki-link-format-alias-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("{alias} ({title})")
            .setValue(this.plugin.settings.WikiLinkFormat.aliasOnly)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.WikiLinkFormat.aliasOnly = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "wiki-link-format-both"]))
            .setDesc(getString(["setting", "wiki-link-format-both-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("{alias} ({title})")
            .setValue(this.plugin.settings.WikiLinkFormat.both)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.WikiLinkFormat.both = value;
            yield this.plugin.saveSettings();
        })));
    }
    addSettingsAboutList(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "list-format"]) });
        headerDiv.createEl("div", { text: getString(["setting", "list-format-desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "bullet-point-characters"]))
            .setDesc(getString(["setting", "bullet-point-characters-desc"]))
            .addTextArea((text) => text
            .setPlaceholder("•–")
            .setValue(this.plugin.settings.BulletPoints)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.BulletPoints = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "ordered-list-custom-separator"]))
            .setDesc(getString(["setting", "ordered-list-custom-separator-desc"]))
            .addTextArea((text) => text
            .setPlaceholder(String.raw ``)
            .setValue(this.plugin.settings.OrderedListOtherSeparator)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.OrderedListOtherSeparator = value;
            yield this.plugin.saveSettings();
        })));
    }
    addSettingsAboutWrapper(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "wrapper", "header"]) });
        headerDiv.createEl("div", { text: getString(["setting", "wrapper", "desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        const wrapperRuleDesc = document.createDocumentFragment();
        wrapperRuleDesc.append(getString(["setting", "wrapper", "rule-desc1"]), document.createDocumentFragment().createEl("br"), getString(["setting", "wrapper", "rule-desc2"]));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "wrapper", "add-new-wrapper"]))
            .setDesc(wrapperRuleDesc)
            .addButton((button) => {
            button
                .setTooltip(getString(["setting", "wrapper", "new-wrapper-rule-tooltip"]))
                .setButtonText("+")
                .setCta()
                .onClick(() => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.WrapperList.push({
                    id: v4(),
                    name: "",
                    prefix: "",
                    suffix: "",
                });
                yield this.plugin.saveSettings();
                this.display();
            }));
        });
        this.plugin.settings.WrapperList.forEach((wrapperSetting, index) => {
            const s = new obsidian.Setting(this.contentEl)
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "wrapper", "name-placeholder"]))
                    .setValue(wrapperSetting.name)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.WrapperList[index].name = newValue;
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandWrapper();
                }));
            })
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "wrapper", "prefix-placeholder"]))
                    .setValue(wrapperSetting.prefix)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.WrapperList[index].prefix = newValue;
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandWrapper();
                }));
            })
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "wrapper", "suffix-placeholder"]))
                    .setValue(wrapperSetting.suffix)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.WrapperList[index].suffix = newValue;
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandWrapper();
                }));
            })
                .addExtraButton((cb) => {
                cb.setIcon("cross")
                    .setTooltip(getString(["setting", "delete-tooltip"]))
                    .onClick(() => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.WrapperList.splice(index, 1);
                    yield this.plugin.saveSettings();
                    this.display();
                }));
            });
            s.infoEl.remove();
            s.settingEl.addClass("wrapper");
        });
    }
    addSettingsAboutApiRequest(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "api-request"]) });
        headerDiv.createEl("div", { text: getString(["setting", "api-request-desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "api-request-url"]))
            .setDesc(getString(["setting", "api-request-url-desc"]))
            .addButton((button) => {
            button.setTooltip(getString(["setting", "new-request-tooltip"]))
                .setButtonText("+")
                .setCta().onClick(() => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.RequestList.push({
                    id: v4(),
                    name: "",
                    url: "",
                });
                yield this.plugin.saveSettings();
                this.display();
            }));
        });
        this.plugin.settings.RequestList.forEach((requestSetting, index) => {
            const s = new obsidian.Setting(this.contentEl)
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "request-name-placeholder"]))
                    .setValue(requestSetting.name)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.RequestList[index].name = newValue;
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandRequest();
                }));
            })
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "request-url-placeholder"]))
                    .setValue(requestSetting.url)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.RequestList[index].url = newValue;
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandRequest();
                }));
            })
                .addExtraButton((cb) => {
                cb.setIcon("cross")
                    .setTooltip(getString(["setting", "delete-tooltip"]))
                    .onClick(() => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.RequestList.splice(index, 1);
                    yield this.plugin.saveSettings();
                    this.display();
                }));
            });
            s.infoEl.remove();
            s.settingEl.addClass("api-request");
        });
    }
    addSettingsAboutReplacement(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "custom-replacement"]) });
        headerDiv.createEl("div", { text: getString(["setting", "custom-replacement-desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "add-custom-replacement"]))
            .setDesc(getString(["setting", "add-custom-replacement-desc"]))
            .addButton((button) => {
            button.setTooltip(getString(["setting", "add-new-replacement-tooltip"]))
                .setButtonText("+")
                .setCta().onClick(() => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.customReplaceList.push({
                    id: v4(),
                    name: "",
                    data: [{
                            search: "",
                            replace: "",
                        }]
                });
                yield this.plugin.saveSettings();
                this.display();
            }));
        });
        this.plugin.settings.customReplaceList.forEach((replaceSetting, index) => {
            const checkIsBuiltIn = () => {
                if (this.plugin.settings.customReplaceBuiltInLog[replaceSetting.id]) {
                    let logData = this.plugin.settings.customReplaceBuiltInLog[replaceSetting.id].data;
                    let nowData = replaceSetting.data;
                    if (logData.length != nowData.length) {
                        this.plugin.settings.customReplaceBuiltInLog[replaceSetting.id].modified = true;
                        return;
                    }
                    for (let i = 0; i < logData.length; i++) {
                        console.log(logData[i], nowData[i]);
                        if (logData[i].search !== nowData[i].search || logData[i].replace !== nowData[i].replace) {
                            this.plugin.settings.customReplaceBuiltInLog[replaceSetting.id].modified = true;
                            return;
                        }
                    }
                    this.plugin.settings.customReplaceBuiltInLog[replaceSetting.id].modified = false;
                }
            };
            const s = new obsidian.Setting(this.contentEl)
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "replacement-command-name-placeholder"]))
                    .setValue(replaceSetting.name)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.customReplaceList[index].name = newValue;
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandCustomReplace();
                }));
            })
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "replacement-search-placeholder"]))
                    .setValue(replaceSetting.data[0].search)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.customReplaceList[index].data[0].search = newValue;
                    checkIsBuiltIn();
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandCustomReplace();
                }));
            })
                .addText((cb) => {
                cb.setPlaceholder(getString(["setting", "replacement-replace-placeholder"]))
                    .setValue(replaceSetting.data[0].replace)
                    .onChange((newValue) => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.customReplaceList[index].data[0].replace = newValue;
                    checkIsBuiltIn();
                    yield this.plugin.saveSettings();
                    this.plugin.debounceUpdateCommandCustomReplace();
                }));
            })
                .addExtraButton((cb) => {
                cb.setIcon("cross")
                    .setTooltip(getString(["setting", "delete-tooltip"]))
                    .onClick(() => __awaiter(this, void 0, void 0, function* () {
                    this.plugin.settings.customReplaceList.splice(index, 1);
                    yield this.plugin.saveSettings();
                    this.display();
                }));
            });
            s.settingEl.addClass("custom-replace");
            s.infoEl.remove();
        });
    }
    addSettingsAboutZotero(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h4", { text: getString(["setting", "zotero-pdf-note-format"]) });
        let contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, contentEl);
        const zoteroEl = new obsidian.Setting(contentEl)
            .setName(getString(["setting", "zotero-input-regexp"]))
            .addTextArea((text) => {
            text
                .setPlaceholder(String.raw `“(?<text>.*)” \((?<item>.*?)\) \(\[pdf\]\((?<pdf_url>.*?)\)\)`)
                .setValue(this.plugin.settings.ZoteroNoteRegExp)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.ZoteroNoteRegExp = value;
                yield this.plugin.saveSettings();
            }));
            text.inputEl.setCssProps({ "height": "5rem" });
        });
        zoteroEl.descEl.innerHTML = `<div>The format of note template can configured refer to <a href="https://github.com/Benature/obsidian-text-format?tab=readme-ov-file#zotero-format">document</a>.</div>
    <ul>
    <li><code>text</code>: highlight</li>
    <li><code>pdf_url</code>: comment</li>
    <li><code>item</code>: citation</li>
    </ul>`;
        new obsidian.Setting(contentEl)
            .setName(getString(["setting", "zotero-output-format"]))
            .setDesc(getString(["setting", "zotero-output-format-desc"]))
            .addTextArea((text) => {
            text
                .setPlaceholder("{text} [🔖]({pdf_url})")
                .setValue(this.plugin.settings.ZoteroNoteTemplate)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.ZoteroNoteTemplate = value;
                yield this.plugin.saveSettings();
            }));
        });
    }
    addSettingsAboutMarkdownQuicker(containerEl) {
        let headerDiv = containerEl.createDiv({ cls: "header-div" });
        let headerEl = headerDiv.createEl("h3", { text: getString(["setting", "markdown-quicker"]) });
        headerDiv.createEl("div", { text: getString(["setting", "markdown-quicker-desc"]), cls: "setting-item-description heading-description" });
        this.contentEl = containerEl.createDiv();
        this.makeCollapsible(headerEl, this.contentEl);
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "heading-lower-to-plain"]))
            .setDesc(getString(["setting", "heading-lower-to-plain-desc"]))
            .addToggle((toggle) => {
            toggle
                .setValue(this.plugin.settings.headingLevelMin === 0)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.headingLevelMin = value ? 0 : 1;
                yield this.plugin.saveSettings();
            }));
        });
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "method-decide-callout-type"]))
            .setDesc(getString(["setting", "method-decide-callout-type-desc"]))
            .addDropdown(dropDown => dropDown
            .addOption(CalloutTypeDecider.preContent, 'Last callout type before the cursor')
            .addOption(CalloutTypeDecider.wholeFile, 'Last callout type in the whole file')
            .addOption(CalloutTypeDecider.fix, 'Fixed callout type')
            .setValue(this.plugin.settings.calloutTypeDecider || CalloutTypeDecider.preContent)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.calloutTypeDecider = value;
            yield this.plugin.saveSettings();
        })));
        new obsidian.Setting(this.contentEl)
            .setName(getString(["setting", "default-callout-type"]))
            .setDesc(getString(["setting", "default-callout-type-desc"]))
            .addText((text) => text
            .setPlaceholder("Callout type")
            .setValue(this.plugin.settings.calloutType)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.calloutType = value;
            yield this.plugin.saveSettings();
        })));
    }
}
function toggleCollapsibleIcon(parentEl) {
    let foldable = parentEl.querySelector(':scope > .tf-collapsible-icon');
    if (!foldable) {
        foldable = parentEl.createSpan({ cls: 'tf-collapsible-icon' });
    }
    if (foldable.dataset.togglestate === 'up') {
        obsidian.setIcon(foldable, 'chevron-down');
        foldable.dataset.togglestate = 'down';
    }
    else {
        obsidian.setIcon(foldable, 'chevron-up');
        foldable.dataset.togglestate = 'up';
    }
}

const GlobalCommands = [
    {
        id: "lowercase",
        icon: "case-sensitive",
    }, {
        id: "uppercase",
        icon: "case-sensitive",
    }, {
        id: "capitalize-word",
        icon: "case-sensitive",
    }, {
        id: "capitalize-sentence",
        icon: "case-sensitive",
    }, {
        id: "title-case",
        icon: "case-sensitive",
    }, {
        id: "cycle-case",
        icon: "case-sensitive",
    }, {
        id: "decodeURI",
        icon: "link",
    }
];
const CustomReplacementBuiltInCommands = [
    {
        id: "remove-trailing-spaces",
        data: [{
                search: String.raw `(\s*)(?=\n)|(\s*)$`,
                replace: "",
            }]
    },
    {
        id: "remove-blank-line",
        data: [{
                search: String.raw `\n\s*\n`,
                replace: String.raw `\n`,
            }]
    },
    {
        id: "add-line-break",
        data: [{
                search: String.raw `\n`,
                replace: String.raw `\n\n`,
            }]
    },
    {
        id: "split-lines-by-blank",
        data: [{
                search: String.raw ` `,
                replace: String.raw `\n`,
            }]
    },
];

var selectionBehavior;
(function (selectionBehavior) {
    selectionBehavior["default"] = "do-nothing";
    selectionBehavior["wholeLine"] = "select-whole-line";
})(selectionBehavior || (selectionBehavior = {}));
// export interface TextFormatMemory {
//     lastCallout: string;
// }

function renew(data) {
    return JSON.parse(JSON.stringify(data));
}

function getLang() {
    let lang = window.localStorage.getItem('language');
    if (["en", "zh", "zh-TW"].indexOf(lang) == -1) {
        lang = "en";
    }
    return lang;
}
class TextFormat extends obsidian.Plugin {
    constructor() {
        super(...arguments);
        this.debounceUpdateCommandWrapper = obsidian.debounce(this.updateCommandWrapper, 1000, true);
        this.debounceUpdateCommandRequest = obsidian.debounce(this.updateCommandRequest, 1000, true);
    }
    // memory: TextFormatMemory;
    executeCommandById(cmd) {
        // @ts-ignore
        this.app.commands.executeCommandById(cmd);
    }
    quickFormat(text, cmd) {
        return __awaiter(this, void 0, void 0, function* () {
            let formatRes = yield this.formatSelection(text, cmd);
            let res = formatRes.editorChange.text;
            if (res)
                return res;
            return text;
        });
    }
    formatGlobal(cmd) {
        return __awaiter(this, void 0, void 0, function* () {
            let activeElement = document.activeElement;
            const activeClasses = activeElement.classList;
            let where = "editor";
            if (activeClasses.contains("inline-title") || activeClasses.contains("view-header-title")) {
                where = "title";
            }
            else if (activeClasses.contains("metadata-input-longtext")) {
                where = "metadata-long-text";
            }
            else if (activeClasses.contains("metadata-property")) {
                let longtext = activeElement.querySelector(".metadata-input-longtext");
                if (longtext) {
                    activeElement = longtext;
                    where = "metadata-long-text";
                }
            }
            const file = this.app.workspace.getActiveFile();
            switch (where) {
                case "editor":
                    this.executeCommandById(`obsidian-text-format::private:${cmd}`);
                    break;
                case "title":
                    const formatResult = yield this.formatSelection(file.basename, cmd);
                    const newName = formatResult.editorChange.text;
                    const newPath = obsidian.normalizePath(file.parent.path + "/" + newName + "." + file.extension);
                    this.app.vault.adapter.rename(file.path, newPath);
                    break;
                case "metadata-long-text":
                    const activePPElement = activeElement.parentElement.parentElement;
                    let metadataKey = activePPElement.getAttribute("data-property-key");
                    // focus on parent element, so that the new frontmatter can be updated
                    activePPElement.focus();
                    if (!file)
                        break;
                    const text = activeElement.textContent;
                    const replacedText = yield this.quickFormat(text, cmd);
                    yield this.app.fileManager.processFrontMatter(file, (fm) => {
                        fm[metadataKey] = replacedText;
                    });
                    // let keyboardEvent = new KeyboardEvent('keydown', {
                    //   keyCode: 13, code: 'KeyEnter', key: 'Enter'
                    // })
                    //  document.activeElement.dispatchEvent(keyboardEvent);
                    break;
            }
        });
    }
    onload() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.loadSettings();
            yield this.initCustomSettings();
            this.addSettingTab(new TextFormatSettingTab(this.app, this));
            const lang = getLang();
            this.registerEvent(this.app.workspace.on('editor-paste', (evt, editor, info) => __awaiter(this, void 0, void 0, function* () {
                var _a, _b;
                this.log(evt, editor, info);
                // refer: https://github.com/kxxt/obsidian-advanced-paste/blob/cfb04918298f14ffa7f04aefa49beaef9a2e8a76/src/main.ts#L220
                const isManuallyTriggered = evt == null; // Not triggered by Ctrl+V
                if (!isManuallyTriggered && (((_a = evt.clipboardData) === null || _a === void 0 ? void 0 : _a.getData("application/x-textformat-tag")) == "tag")) {
                    //: Event was triggered by this plugin, don't handle it again
                    return;
                }
                // @ts-ignore
                const formatOnPasteCmdList = (_b = info.metadataEditor.properties.find(m => m.key === "tfFormatOnPaste")) === null || _b === void 0 ? void 0 : _b.value;
                // console.log(formatOnPasteCmdList)
                if (formatOnPasteCmdList === undefined || (formatOnPasteCmdList === null || formatOnPasteCmdList === void 0 ? void 0 : formatOnPasteCmdList.length) == 0) {
                    return;
                }
                let clipboard = evt.clipboardData.getData('text/html') || evt.clipboardData.getData('text/plain');
                if (!clipboard) {
                    return;
                }
                evt === null || evt === void 0 ? void 0 : evt.preventDefault();
                // evt?.stopPropagation();
                for (let cmd of formatOnPasteCmdList) {
                    const formatText = (yield this.formatSelection(clipboard, cmd)).editorChange.text;
                    if (formatText) {
                        clipboard = formatText;
                    }
                }
                // await navigator.clipboard.writeText('Some text to paste');
                const dat = new DataTransfer();
                dat.setData('text/html', `<pre>${clipboard}</pre>`);
                // dat.setData('text/html', clipboard);
                dat.setData("application/x-textformat-tag", "tag");
                const e = new ClipboardEvent("paste", {
                    clipboardData: dat,
                });
                // @ts-ignore
                yield info.currentMode.clipboardManager.handlePaste(e, editor, info);
                if (formatOnPasteCmdList.includes("easy-typing-format")) {
                    // @ts-ignore
                    const activePlugins = this.app.plugins.plugins;
                    if (activePlugins["easy-typing-obsidian"]) {
                        try {
                            const pluginEasyTyping = activePlugins["easy-typing-obsidian"];
                            // console.log(.formatSelectionOrCurLine);
                            const cursorTo = editor.getCursor("to");
                            editor.setSelection(editor.offsetToPos(editor.posToOffset(cursorTo) - clipboard.length), cursorTo);
                            pluginEasyTyping.formatSelectionOrCurLine(editor, info);
                            editor.setCursor(editor.getCursor("to"));
                        }
                        catch (e) {
                            console.error(e);
                        }
                    }
                }
            })));
            this.addCommand({
                id: "open-settings",
                name: getString(["command", "open-settings"]),
                icon: "bolt",
                callback: () => {
                    // @ts-ignore
                    const settings = this.app.setting;
                    settings.open();
                    settings.openTabById(`obsidian-text-format`);
                },
            });
            GlobalCommands.forEach(command => {
                this.addCommand({
                    id: command.id,
                    name: getString(["command", command.id]),
                    icon: "case-sensitive",
                    callback: () => __awaiter(this, void 0, void 0, function* () {
                        yield this.formatGlobal(command.id);
                    }),
                });
                this.addCommand({
                    id: `:private:${command.id}`,
                    name: getString(["command", command.id]) + " in editor",
                    editorCheckCallback: (checking, editor, view) => {
                        if (!checking) {
                            this.editorTextFormat(editor, view, command.id);
                        }
                        return !checking;
                    },
                });
            });
            this.addCommand({
                id: "slugify",
                name: { en: "Slugify selected text (`-` for space)", zh: "使用 Slugify 格式化选中文本（`-`连字符）", "zh-TW": "使用 Slugify 格式化選取文字（`-`連字符）" }[lang],
                icon: "case-sensitive",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "slugify");
                },
            });
            this.addCommand({
                id: "snakify",
                name: { en: "Snakify selected text (`_` for space)", zh: "使用 Snakify 格式化选中文本（`_`连字符）", "zh-TW": "使用 Snakify 格式化選取文字（`_`連字符）" }[lang],
                icon: "case-sensitive",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "snakify");
                },
            });
            this.addCommand({
                id: "camel-case-lower",
                name: { en: "camelCase selected text", zh: "使用小驼峰格式化选中文本", "zh-TW": "使用小駝峰格式化選取文字" }[lang],
                icon: "case-sensitive",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "camel-case", { lowerFirst: true });
                },
            });
            this.addCommand({
                id: "camel-case-upper",
                name: { en: "CamelCase selected text", zh: "使用大驼峰格式化选中文本", "zh-TW": "使用大駝峰格式化選取文字" }[lang],
                icon: "case-sensitive",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "camel-case", { lowerFirst: false });
                },
            });
            this.addCommand({
                id: "heading-upper",
                name: getString(["command", "heading-upper"]),
                icon: "indent-increase",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "heading", { upper: true });
                },
                repeatable: false,
                hotkeys: [
                    {
                        modifiers: ["Ctrl", "Shift"],
                        key: "]",
                    }
                ],
            });
            this.addCommand({
                id: "heading-lower",
                name: getString(["command", "heading-lower"]),
                icon: "indent-decrease",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "heading", { upper: false });
                },
                repeatable: false,
                hotkeys: [
                    {
                        modifiers: ["Ctrl", "Shift"],
                        key: "[",
                    }
                ],
            });
            this.addCommand({
                id: "convert-bullet-list",
                name: { en: "Detect and format bullet list", zh: "识别并格式化无序列表", "zh-TW": "識別並格式化無序清單" }[lang],
                icon: "list",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "convert-bullet-list");
                },
            });
            this.addCommand({
                id: "convert-ordered-list",
                name: { en: "Detect and format ordered list", zh: "识别并格式化有序列表", "zh-TW": "識別並格式化有序清單" }[lang],
                icon: "list-ordered",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "convert-ordered-list");
                },
            });
            this.addCommand({
                id: "table2bullet",
                name: { en: "Convert table to bullet list without header", zh: "将表格转换为无序列表（不含标题）", "zh-TW": "將表格轉換為無序清單（不含標題）" }[lang],
                icon: "list",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "table2bullet");
                },
            });
            this.addCommand({
                id: "table2bullet-head",
                name: { en: "Convert table to bullet list with header", zh: "将表格转换为无序列表（含标题）", "zh-TW": "將表格轉換為無序清單（含標題）" }[lang],
                icon: "list",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "table2bullet-header");
                },
            });
            this.addCommand({
                id: "sort-todo",
                name: { en: "Sort to-do list", zh: "将待办事项列表排序", "zh-TW": "將待辦事項列表排序" }[lang],
                icon: "arrow-down-narrow-wide",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "sort-todo");
                },
            });
            this.addCommand({
                id: "remove-wiki-link",
                name: { "en": "Remove WikiLinks format in selection", "zh": "移除选中文本中的 WikiLinks 格式", "zh-TW": "移除選取文字中的 WikiLinks 格式" }[lang],
                icon: "link-2-off",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "remove-wiki-link");
                },
            });
            this.addCommand({
                id: "remove-url-link",
                name: { "en": "Remove URL links format in selection", "zh": "移除选中文本中的 URL 链接格式", "zh-TW": "移除選取文字中的 URL 鏈接格式" }[lang],
                icon: "link-2-off",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "remove-url-link");
                },
            });
            this.addCommand({
                id: "link-url2wiki",
                name: { en: "Convert URL links to WikiLinks in selection", zh: "将选中文本中的 URL 链接转换为 WikiLinks 格式", "zh-TW": "將選取文字中的 URL 鏈接轉換為 WikiLinks 格式" }[lang],
                icon: "link-2",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "link-url2wiki");
                },
            });
            this.addCommand({
                id: "link-wiki2md",
                name: { en: "Convert wikiLinks to plain markdown links in selection", zh: "将选中文本中的 WikiLinks 转换为普通 Markdown 链接格式", "zh-TW": "將選取文字中的 WikiLinks 轉換為普通 Markdown 鏈接格式" }[lang],
                icon: "link-2",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "link-wiki2md");
                },
            });
            this.addCommand({
                id: "remove-redundant-spaces",
                name: { en: "Remove redundant spaces in selection", zh: "将选中文本中的多余空格移除", "zh-TW": "將選取文字中的多餘空格移除" }[lang],
                icon: "space",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "remove-redundant-spaces");
                },
            });
            this.addCommand({
                id: "remove-spaces-all",
                name: { en: "Remove all spaces in selection", zh: "将选中文本中的所有空格移除", "zh-TW": "將選取文字中的所有空格移除" }[lang],
                icon: "space",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "spaces-all");
                },
            });
            // this.addCommand({
            //   id: "remove-trailing-all",
            //   name: { en: "Remove trailing spaces in selection", zh: "将选中文本中的所有行末空格移除", "zh-TW": "將選取文字中的所有行尾空格移除" }[lang],
            //   editorCallback: (editor: Editor, view: MarkdownView) => {
            //     this.editorTextFormat(editor, view, "trailing-spaces");
            //   },
            // });
            // this.addCommand({
            //   id: "remove-blank-line",
            //   name: { en: "Remove blank line(s)", zh: "将选中文本中的空行移除", "zh-TW": "將選取文字中的空行移除" }[lang],
            //   editorCallback: (editor: Editor, view: MarkdownView) => {
            //     this.editorTextFormat(editor, view, "remove-blank-line");
            //   },
            // });
            this.addCommand({
                id: "merge-line",
                name: { en: "Merge broken paragraph(s) in selection", zh: "将选中文本中的断行合并", "zh-TW": "將選取文字中的斷行合併" }[lang],
                icon: "wrap-text",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "merge-line");
                },
            });
            // this.addCommand({
            //   id: "split-blank",
            //   name: { en: "Split line(s) by blanks", zh: "将选中文本按空格分行", "zh-TW": "將選取文字按空格分行" }[lang],
            //   editorCallback: (editor: Editor, view: MarkdownView) => {
            //     this.editorTextFormat(editor, view, "split-blank");
            //   },
            // });
            this.addCommand({
                id: "chinese-punctuation",
                name: { en: "Convert to Chinese punctuation marks (,;:!?)", zh: "转换为中文标点符号（,;:!?）", "zh-TW": "轉換為中文標點符號（,;:!?）" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "Chinese-punctuation");
                },
            });
            this.addCommand({
                id: "english-punctuation",
                name: { en: "Convert to English punctuation marks", zh: "转换为英文标点符号", "zh-TW": "轉換為英文標點符號" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "English-punctuation");
                },
            });
            this.addCommand({
                id: "hyphen",
                name: { en: "Remove hyphens", zh: "移除连字符", "zh-TW": "移除連字符" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "hyphen");
                },
            });
            this.addCommand({
                id: "ligature",
                name: { "en": "Replace ligature", "zh": "替换连字", "zh-TW": "取代連字" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "ligature");
                },
            });
            this.addCommand({
                id: "anki-card",
                name: { "en": "Convert selection into Anki card format", "zh": "将选中内容转换为 Anki 卡片格式", "zh-TW": "將選取內容轉換為 Anki 卡片格式" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "anki");
                },
            });
            this.addCommand({
                id: "remove-citation-index",
                name: { en: "Remove citation index", zh: "移除引用索引编号", "zh-TW": "移除引用索引編號" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "remove-citation");
                },
            });
            this.addCommand({
                id: "zotero-note",
                name: { en: "Get Zotero note from clipboard and paste", zh: "从剪贴板获取 Zotero 笔记并粘贴", "zh-TW": "從剪貼板獲取 Zotero 筆記並粘貼" }[lang],
                icon: "clipboard-type",
                editorCallback: (editor, view) => __awaiter(this, void 0, void 0, function* () {
                    const clipboardText = yield navigator.clipboard.readText();
                    let text = zoteroNote(clipboardText, this.settings.ZoteroNoteRegExp, this.settings.ZoteroNoteTemplate);
                    editor.replaceSelection(text);
                }),
            });
            this.addCommand({
                id: "latex-letter",
                name: { en: "Detect and convert characters to math mode (LaTeX)", zh: "识别并转换字符为数学模式（LaTeX）", "zh-TW": "識別並轉換字符為數學模式（LaTeX）" }[lang],
                icon: "square-sigma",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "latex-letter");
                },
            });
            this.addCommand({
                id: "mathpix-array2table",
                name: {
                    en: "Convert Mathpix's LaTeX array to markdown table", zh: "将 Mathpix 的 LaTeX 数组转换为 Markdown 表格", "zh-TW": "將 Mathpix 的 LaTeX 陣列轉換為 Markdown 表格"
                }[lang],
                icon: "square-sigma",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "array2table");
                },
            });
            this.addCommand({
                id: "callout",
                name: { en: "Callout format", zh: "Callout 格式", "zh-TW": "Callout 格式" }[lang],
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "callout");
                },
            });
            this.debounceUpdateCommandWrapper();
            this.debounceUpdateCommandRequest();
            this.debounceUpdateCommandCustomReplace();
            // this.addCommand({
            //   id: "decodeURI",
            //   name: { en: "Decode URL", zh: "解码 URL", "zh-TW": "解碼 URL" }[lang],
            //   icon: "link",
            //   callback: async () => {
            //     const activeElement = document.activeElement;
            //     if (activeElement.classList.contains("metadata-input-longtext")) {
            //       let metadataKey = activeElement.parentElement.parentElement.getAttribute("data-property-key");
            //       // focus on parent element, so that the new frontmatter can be updated
            //       activeElement.parentElement.parentElement.focus();
            //       const file = this.app.workspace.getActiveFile();
            //       const frontmatter = this.app.metadataCache.getCache(file?.path as string)?.frontmatter;
            //       let formatRes = await this.formatSelection(frontmatter[metadataKey], "decodeURI");
            //       if (file) {
            //         await this.app.fileManager.processFrontMatter(file, (fm) => {
            //           fm[metadataKey] = formatRes.editorChange.text;
            //         });
            //         // activeElement.parentElement.focus();
            //       }
            //     } else {
            //       this.executeCommandById(`obsidian-text-format::editor:decodeURI`);
            //     }
            //   },
            // });
            // this.addCommand({
            //   id: ":editor:decodeURI",
            //   name: { en: "Decode URL", zh: "解码 URL", "zh-TW": "解碼 URL" }[lang] + " (Editor)",
            //   icon: "link",
            //   editorCallback: (editor: Editor, view: MarkdownView) => {
            //     this.editorTextFormat(editor, view, "decodeURI");
            //   },
            // });
            this.addCommand({
                id: "space-word-symbol",
                name: { en: "Format space between words and symbols", zh: "格式化单词与符号之间的空格", "zh-TW": "格式化單詞與符號之間的空格" }[lang],
                icon: "space",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "space-word-symbol");
                },
            });
        });
    }
    updateCommandWrapper() {
        const lang = getLang();
        this.settings.WrapperList.forEach((wrapper, index) => {
            this.addCommand({
                id: `wrapper:${wrapper.id}`,
                name: { "en": "Wrapper", "zh": "包装器", "zh-TW": "包裝器" }[lang] + " - " + wrapper.name,
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "wrapper", wrapper);
                },
            });
        });
    }
    updateCommandRequest() {
        const lang = getLang();
        this.settings.RequestList.forEach((request, index) => {
            this.addCommand({
                id: `request:${request.id}`,
                name: { "en": "API Request", "zh": "API 请求", "zh-TW": "API 請求" }[lang] + " - " + request.name,
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "api-request", { url: request.url });
                },
            });
        });
    }
    debounceUpdateCommandCustomReplace() {
        const lang = getLang();
        this.settings.customReplaceList.forEach((customReplace, index) => {
            this.addCommand({
                id: `custom-replace:${customReplace.id}`,
                name: { "en": "Custom Replace", "zh": "自定义替换", "zh-TW": "自定義取代" }[lang] + " - " + customReplace.name,
                icon: "a-large-small",
                editorCallback: (editor, view) => {
                    this.editorTextFormat(editor, view, "custom-replace", { settings: customReplace });
                },
            });
        });
    }
    formatSelection(selectedText, cmd, context = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            this.log("formatSelection", selectedText, cmd, context);
            let replacedText = selectedText;
            let ret = { editorChange: {} };
            try {
                switch (cmd) {
                    case "anki":
                        replacedText = ankiSelection(selectedText);
                        break;
                    case "lowercase":
                        replacedText = selectedText.toLowerCase();
                        break;
                    case "uppercase":
                        replacedText = selectedText.toUpperCase();
                        break;
                    case "capitalize-word":
                        replacedText = capitalizeWord(this.settings.LowercaseFirst ? selectedText.toLowerCase() : selectedText);
                        break;
                    case "capitalize-sentence":
                        replacedText = capitalizeSentence(this.settings.LowercaseFirst ? selectedText.toLowerCase() : selectedText);
                        break;
                    case "title-case":
                        replacedText = toTitleCase(selectedText, this.settings);
                        break;
                    case "cycle-case":
                        let lowerString = selectedText.toLowerCase();
                        const settings = this.settings;
                        function getNewString(caseCommand) {
                            switch (caseCommand) {
                                case "titleCase": return toTitleCase(selectedText, settings);
                                case "lowerCase": return lowerString;
                                case "upperCase": return selectedText.toUpperCase();
                                case "capitalizeWord": return capitalizeWord(lowerString);
                                case "capitalizeSentence": return capitalizeSentence(lowerString);
                                default:
                                    new obsidian.Notice(`Unknown case ${caseCommand}. \nOnly lowerCase, upperCase, capitalizeWord, capitalizeSentence, titleCase supported.`);
                                    return null;
                            }
                        }
                        let toggleSeq = this.settings.ToggleSequence.replace(/ /g, "").replace(/\n+/g, "\n").split('\n');
                        let textHistory = new Array();
                        let i;
                        const L = toggleSeq.length;
                        for (i = 0; i < L; i++) {
                            let resText = getNewString(toggleSeq[i]), duplicated = false;
                            // console.log(resText, toggleSeq[i])
                            for (let j = 0; j < textHistory.length; j++) {
                                if (textHistory[j] == resText) {
                                    duplicated = true;
                                    break;
                                }
                            }
                            if (!duplicated) { //: if the converted text is the same as before cycle case, ignore it
                                if (selectedText == resText) {
                                    break;
                                }
                            }
                            textHistory.push(resText);
                        }
                        //: find the cycle case that is different from the original text
                        for (i++; i < i + L; i++) {
                            let resText = getNewString(toggleSeq[i % L]);
                            if (selectedText != resText) {
                                // console.log("!", toggleSeq[i % L])
                                replacedText = resText;
                                break;
                            }
                        }
                        if (!(replacedText)) {
                            return;
                        }
                        break;
                    case "remove-redundant-spaces":
                        replacedText = selectedText
                            .replace(/(\S) {2,}/g, "$1 ")
                            .replace(/ $| (?=\n)/g, "");
                        // replacedText = replacedText.replace(/\n /g, "\n"); // when a single space left at the head of the line
                        break;
                    case "spaces-all":
                        replacedText = removeAllSpaces(selectedText);
                        break;
                    case "merge-line":
                        replacedText = selectedText.replace(/(?:[^\n])(\n)(?!\n)/g, (t, t1) => t.replace(t1, " "));
                        if (this.settings.MergeParagraph_Newlines) {
                            replacedText = replacedText.replace(/\n\n+/g, "\n\n");
                        }
                        if (this.settings.MergeParagraph_Spaces) {
                            replacedText = replacedText.replace(/ +/g, " ");
                        }
                        break;
                    case "space-word-symbol":
                        replacedText = selectedText
                            .replace(/([\u4e00-\u9fa5]+)([\(\[\{])/g, "$1 $2")
                            .replace(/([\)\]\}])([a-zA-Z0-9\u4e00-\u9fa5]+)/g, "$1 $2")
                            .replace(/([\u4e00-\u9fa5])([a-zA-Z])/g, "$1 $2")
                            .replace(/([a-zA-Z])([\u4e00-\u9fa5])/g, "$1 $2");
                        break;
                    case "remove-citation":
                        replacedText = selectedText.replace(/\[\d+\]|【\d+】/g, "").replace(/ +/g, " ");
                        break;
                    case "convert-ordered-list":
                        let orderedCount = 0;
                        // var rx = new RegExp(
                        //   String.raw`(?:^|[\s，。])((?:[:;]?i{1,4}[）\)]|\d\.) *)` +
                        //   "|" +
                        //   String.raw`(?:^|\s| and )[^\s\(\[\]]\)`,
                        //   "g"
                        // );
                        let sepCustom = "";
                        if (this.settings.OrderedListOtherSeparator.length > 0) {
                            sepCustom = "|" + this.settings.OrderedListOtherSeparator;
                        }
                        const rx = new RegExp(String.raw `([\(（]?(\b\d+|\b[a-zA-Z]|[ivx]{1,4})[.\)）](\s|(?=[\u4e00-\u9fa5]))` + sepCustom + `)`, "g");
                        // const rx = /([\(（]?(\b\d+|\b[a-zA-Z]|[ivx]{1,4})[.\)）](\s|(?=[\u4e00-\u9fa5]))|\sand\s|\s?(以及和)\s?)/g;
                        replacedText = selectedText.replace(rx, function (t, t1) {
                            orderedCount++;
                            let head = "\n"; // if single line, then add newline character.
                            return t.replace(t1, `${head}${orderedCount}. `);
                        });
                        replacedText = replacedText.replace(/\n+/g, "\n").replace(/^\n/, "");
                        break;
                    case "convert-bullet-list":
                        let r = this.settings.BulletPoints; //.replace("-", "");
                        let bulletSymbolFound = false;
                        replacedText = selectedText
                            .replace(RegExp(`\s*([${r}] *)|(\n[~\/Vv-] +)`, "g"), (t, t1, t2) => {
                            // console.log(t, t1, t2)
                            bulletSymbolFound = true;
                            return t.replace(t1 || t2, "\n- ");
                        })
                            .replace(/\n+/g, "\n")
                            .replace(/^\n/, "");
                        // if "-" in this.settings.BulletPoints
                        // if (this.settings.BulletPoints.indexOf("-") > -1) {
                        //   replacedText = replacedText.replace(/^- /g, "\n- ");
                        // }
                        // if select multi-paragraphs, add `- ` to the beginning
                        if (bulletSymbolFound && selectedText.indexOf("\n") > -1 && replacedText.slice(0, 2) != "- ") {
                            replacedText = "- " + replacedText;
                        }
                        replacedText = replacedText.replace(/^\n*/, "");
                        break;
                    // case "split-blank":
                    //   replacedText = selectedText.replace(/ /g, "\n");
                    //   break;
                    case "Chinese-punctuation":
                        replacedText = selectedText;
                        replacedText = replacedText
                            .replace(/(?:[\u4e00-\u9fa5])( ?, ?)(?:[\u4e00-\u9fa5])/g, (t, t1) => t.replace(t1, "，"))
                            .replace(/(?:[^\d])( ?\. ?)/g, (t, t1) => t.replace(t1, "。"))
                            .replace(/ ?、 ?/g, "、")
                            .replace(/;/g, "；")
                            .replace(/--/g, "——")
                            .replace(/[^a-zA-Z0-9](: ?)/g, (t, t1) => t.replace(t1, "："))
                            .replace(/\!(?=[^\[])/g, "！")
                            .replace(/\?/g, "？")
                            .replace(/[\(（][^\)]*?[\u4e00-\u9fa5]+?[^\)]*?[\)）]/g, (t) => `（${t.slice(1, t.length - 1)}）`);
                        // TODO: ignore `!` that is `[!note]`
                        if (this.settings.RemoveBlanksWhenChinese) {
                            replacedText = replacedText.replace(/([\u4e00-\u9fa5【】（）「」《》：“？‘、；])( +)([\u4e00-\u9fa5【】（）「」《》：“？‘、；])/g, "$1$3");
                        }
                        break;
                    case "English-punctuation":
                        replacedText = selectedText
                            .replace(/[（\(]([\w !\"#$%&'()*+,-./:;<=>?@\[\\\]^_`{\|}~]+)[）\)]/g, "($1)")
                            .replace(/(?:[a-zA-Z])(， ?)(?:[a-zA-Z])/g, (t, t1) => t.replace(t1, ", "));
                        break;
                    case "decodeURI":
                        replacedText = selectedText.replace(/(\w+):\/\/[-\w+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g, function (t) {
                            return decodeURI(t)
                                .replace(/\s/g, "%20")
                                .replace(/%2F/g, "/");
                        });
                        console.log(replacedText);
                        break;
                    case "hyphen":
                        replacedText = selectedText.replace(/(\w)-[ ]/g, "$1");
                        break;
                    case "array2table":
                        replacedText = array2markdown(selectedText);
                        break;
                    case "table2bullet":
                        replacedText = table2bullet(selectedText, false);
                        break;
                    case "table2bullet-header":
                        replacedText = table2bullet(selectedText, true);
                        break;
                    case "remove-wiki-link":
                        replacedText = removeWikiLink(selectedText, this.settings.WikiLinkFormat);
                        break;
                    case "remove-url-link":
                        replacedText = removeUrlLink(selectedText, this.settings.UrlLinkFormat);
                        if (this.settings.RemoveWikiURL2) {
                            replacedText = removeWikiLink(replacedText, this.settings.WikiLinkFormat);
                        }
                        break;
                    case "link-url2wiki":
                        replacedText = url2WikiLink(selectedText);
                        break;
                    case "link-wiki2md":
                        replacedText = convertWikiLinkToMarkdown(selectedText, this);
                        break;
                    case "ligature":
                        replacedText = replaceLigature(selectedText);
                        break;
                    case "sort-todo":
                        // const blocks = selectedText.split(/\n\s*\n/g);
                        // const results: string[] = [];
                        // for (const block of blocks) {
                        //   results.push(sortTodo(block));
                        // }
                        // replacedText = results.join("\n\n");
                        let fromLine = context.adjustRange.from.line;
                        if ((context.originRange.from.line === context.originRange.to.line) && (!context.editor.getLine(context.originRange.from.line).match(/\s*- \[[ \w\?\!\-]\] /))) {
                            fromLine = null;
                        }
                        replacedText = sortTodo(selectedText, context, fromLine);
                        break;
                    case "slugify":
                        replacedText = slugify(selectedText);
                        break;
                    case "snakify":
                        replacedText = snakify(selectedText);
                        break;
                    case "camel-case":
                        replacedText = camelCase(selectedText, context.lowerFirst);
                        break;
                    case "custom-replace":
                        replacedText = customReplace(selectedText, context.settings);
                        break;
                    case "heading":
                        const adjustRange = context.adjustRange;
                        if (adjustRange.from.line === adjustRange.to.line) {
                            const headingRes = headingLevel(selectedText, context.upper, this.settings.headingLevelMin);
                            replacedText = headingRes.text;
                        }
                        else {
                            replacedText = "";
                            selectedText.split("\n").forEach((line, index) => {
                                const headingRes = headingLevel(line, context.upper, this.settings.headingLevelMin, true);
                                replacedText += headingRes.text + "\n";
                            });
                            replacedText = replacedText.slice(0, -1); // remove the last `\n`
                        }
                        break;
                    case "api-request":
                        replacedText = yield requestAPI(selectedText, context.view.file, context.url);
                        break;
                    case "wrapper":
                        const wrapperResult = textWrapper(selectedText, context);
                        selectedText = wrapperResult.selectedText;
                        replacedText = wrapperResult.editorChange.text;
                        context.adjustRange = { from: wrapperResult.editorChange.from, to: wrapperResult.editorChange.to };
                        // ret.resetSelection = wrapperResult.resetSelection;
                        ret.resetSelectionOffset = wrapperResult.resetSelectionOffset;
                        break;
                    case "callout":
                        const reCalloutType = /(?:(^|\n)\>\s*\[\!)(\w+)(?:\])/gm;
                        const lines = selectedText.replace(/^\n|\n$/g, "").split("\n");
                        if (lines[0].match(reCalloutType)) { //: detect callout grammar, delete callout prefix
                            replacedText = lines[0].replace(reCalloutType, "").replace(/^\s*/g, "");
                            let i = 1;
                            for (; i < lines.length; i++) {
                                if (lines[i].match(/^>/g)) {
                                    replacedText += "\n" + lines[i].replace(/^>\s*/, "");
                                }
                                else {
                                    break;
                                }
                            }
                            //: add rest part of lines in original format
                            replacedText = (replacedText + "\n" + lines.slice(i, lines.length).join("\n")).replace(/\n$/g, "");
                        }
                        else { //: To add callout prefix
                            //: Get the previous callout types at first
                            let wholeContent, type;
                            switch (this.settings.calloutTypeDecider) {
                                // case CalloutTypeDecider.lastUsed:
                                //   type = this.memory.lastCallout;
                                //   break;
                                case CalloutTypeDecider.fix:
                                    type = this.settings.calloutType;
                                    break;
                                case CalloutTypeDecider.wholeFile:
                                    wholeContent = context.editor.getValue();
                                    break;
                                case CalloutTypeDecider.preContent:
                                    wholeContent = context.editor.getRange({ line: 0, ch: 0 }, context.adjustRange.from);
                                    break;
                            }
                            const preCalloutList = wholeContent.match(reCalloutType);
                            if (preCalloutList) {
                                type = reCalloutType.exec(preCalloutList[preCalloutList.length - 1])[2];
                            }
                            else {
                                type = this.settings.calloutType;
                            }
                            if (type.startsWith("!")) {
                                type = type.substring(1, type.length);
                            }
                            replacedText = `> [!${type}] ${lines[0]}`;
                            if (lines.length > 1) {
                                for (let idx = 1; idx < lines.length; idx++) {
                                    replacedText += `\n> ` + lines[idx];
                                }
                            }
                            // this.memory.lastCallout = type;
                        }
                        break;
                    case "latex-letter":
                        replacedText = convertLatex(context.editor, selectedText);
                        break;
                    default:
                        Error("Unknown command");
                }
            }
            catch (e) {
                new obsidian.Notice(e);
                console.error(e);
            }
            if (replacedText != selectedText) {
                ret.editorChange = Object.assign({ text: replacedText }, context === null || context === void 0 ? void 0 : context.adjustRange);
            }
            return ret;
        });
    }
    log(...args) {
        // TODO: add verbose log setting
        if (this.settings.debugMode) {
            console.log(...args);
        }
    }
    editorTextFormat(editor, view, cmd, context = {}) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const originSelectionList = editor.listSelections();
            const resetSelectionList = [];
            for (let originSelection of originSelectionList) {
                const originRange = selection2range(editor, originSelection);
                const somethingSelected = !(originRange.from.ch == originRange.to.ch && originRange.from.line == originRange.to.line);
                let adjustRange = originRange;
                this.log(originSelection);
                this.log(originRange);
                //： Adjust Selection
                let adjustSelectionCmd;
                switch (cmd) {
                    case "wrapper":
                        //: Keep the selection as it is
                        break;
                    case "heading":
                        adjustSelectionCmd = selectionBehavior.wholeLine;
                        break;
                    case "split-blank":
                    case "convert-bullet-list":
                    case "convert-ordered-list":
                    case "callout":
                        //: Force to select whole paragraph(s)
                        adjustSelectionCmd = selectionBehavior.wholeLine;
                        break;
                    case "sort-todo":
                        //: Select whole file if nothing selected
                        if (originRange.from.line == originRange.to.line) {
                            adjustRange = {
                                from: { line: 0, ch: 0 },
                                // to: { line: editor.lastLine(), ch: editor.getLine(editor.lastLine()).length }
                                to: { line: editor.lastLine() + 1, ch: 0 }
                            };
                        }
                        else {
                            adjustSelectionCmd = selectionBehavior.wholeLine;
                        }
                        context.originRange = originRange;
                        break;
                    default:
                        if (!somethingSelected) {
                            // if nothing is selected, select the whole line.
                            adjustSelectionCmd = selectionBehavior.wholeLine;
                        }
                        //: Except special process of adjusting selection, get all selected text (for now)
                        break;
                }
                switch (adjustSelectionCmd) {
                    case selectionBehavior.wholeLine: //: Force to select whole paragraph(s)
                        adjustRange = {
                            from: { line: originRange.from.line, ch: 0 },
                            to: { line: originRange.to.line, ch: editor.getLine(originRange.to.line).length }
                        };
                        break;
                }
                const selectedText = editor.getRange(adjustRange.from, adjustRange.to);
                this.log("adjustRange", adjustRange);
                this.log("selectedText", selectedText);
                //: MODIFY SELECTION
                context.editor = editor;
                context.view = view;
                context.adjustRange = adjustRange;
                const formatResult = yield this.formatSelection(selectedText, cmd, context);
                this.log("formatResult", formatResult);
                //: Make change immediately
                if (formatResult.editorChange.text == undefined) {
                    this.log("nothing changed.");
                    editor.setSelections(originSelectionList);
                    return;
                }
                editor.transaction({ changes: [formatResult.editorChange] });
                //: Set cursor selection
                let resetSelection = { anchor: adjustRange.from, head: adjustRange.to };
                const fos = editor.posToOffset(adjustRange.from);
                const replacedText = ((_a = formatResult.editorChange) === null || _a === void 0 ? void 0 : _a.text) || selectedText;
                const textOffset = replacedText.length - selectedText.length;
                const cursorLast = editor.offsetToPos(fos + replacedText.length);
                const selections = {
                    keepOriginSelection: {
                        anchor: editor.offsetToPos(editor.posToOffset(originRange.from) + textOffset),
                        head: editor.offsetToPos(editor.posToOffset(originRange.to) + textOffset)
                    },
                    wholeReplacedText: {
                        anchor: adjustRange.from,
                        head: cursorLast
                    }
                };
                switch (cmd) {
                    case "sort-todo":
                        resetSelection = originSelection;
                        break;
                    case "wrapper":
                        // resetSelection = formatResult.resetSelection;
                        resetSelection = {
                            anchor: editor.offsetToPos(formatResult.resetSelectionOffset.anchor),
                            head: editor.offsetToPos(formatResult.resetSelectionOffset.head)
                        };
                        // console.log(resetSelection)
                        break;
                    case "callout":
                    case "heading":
                        if (originRange.from.line === originRange.to.line) {
                            resetSelection = selections.keepOriginSelection;
                        }
                        else {
                            resetSelection = selections.wholeReplacedText;
                        }
                        break;
                    default:
                        resetSelection = selections.wholeReplacedText;
                }
                this.log("resetSelection", resetSelection);
                resetSelectionList.push(resetSelection);
            }
            this.log("resetSelectionList", resetSelectionList);
            editor.setSelections(resetSelectionList);
        });
    }
    loadSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
            this.compatibleSettingsUpgrade();
        });
    }
    saveSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.saveData(this.settings);
        });
    }
    initCustomSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.manifest.version === this.settings.manifest.version) {
                return;
            } // no need to upgrade
            this.compatibleSettingsUpgrade();
            for (let command of CustomReplacementBuiltInCommands) {
                if (!this.settings.customReplaceBuiltInLog[command.id]) {
                    this.settings.customReplaceList.push({
                        id: command.id,
                        name: getString(["command", command.id]),
                        data: renew(command.data)
                    });
                    this.settings.customReplaceBuiltInLog[command.id] = {
                        id: command.id,
                        modified: false,
                        data: renew(command.data)
                    };
                }
                else { // build in command is loaded in older version, then check if modified
                    if (!this.settings.customReplaceBuiltInLog[command.id].modified) {
                        // upgrade replacement data
                        const index = this.settings.customReplaceList.findIndex(item => item.id === command.id);
                        // console.log(index);
                        if (index > -1) {
                            this.settings.customReplaceList[index].data = renew(command.data);
                        }
                        // this.settings.customReplaceBuiltInLog[command.id].data = command.data;
                    }
                }
            }
            yield this.backupDataJson();
            // update version AFTER backup data.json
            this.settings.manifest.version = this.manifest.version; // update version
            yield this.saveSettings();
        });
    }
    backupDataJson() {
        return __awaiter(this, void 0, void 0, function* () {
            // save a backup data.json before overwriting data.json
            const vault = this.app.vault;
            // @ts-ignore
            const originDataPath = obsidian.normalizePath(this.manifest.dir + "/data.json");
            const newDataPath = obsidian.normalizePath(this.manifest.dir + `/data-backup-v${this.settings.manifest.version}-to-v${this.manifest.version}.json`);
            if (yield vault.adapter.exists(originDataPath)) {
                // exist data.json of old version
                new obsidian.Notice(`[INFO] Updated ${this.manifest.name} from ${this.settings.manifest.version} to v${this.manifest.version}, backup ongoing...`);
                yield vault.adapter.copy(originDataPath, newDataPath);
            }
        });
    }
    compatibleSettingsUpgrade() {
        // uuid init
        for (let i in this.settings.customReplaceList)
            if (!this.settings.customReplaceList[i].id)
                this.settings.customReplaceList[i].id = v4();
        for (let i in this.settings.WrapperList)
            if (!this.settings.WrapperList[i].id)
                this.settings.WrapperList[i].id = v4();
        for (let i in this.settings.RequestList)
            if (!this.settings.RequestList[i].id)
                this.settings.RequestList[i].id = v4();
        // @ts-ignore
        const oldCustomReplaceBuiltIn = this.settings.customReplaceBuiltIn;
        if (oldCustomReplaceBuiltIn &&
            (!this.settings.customReplaceBuiltInLog || Object.keys(this.settings.customReplaceBuiltInLog).length == 0)) {
            console.log("upgrade customReplaceBuiltInLog");
            let newBuiltIn = {};
            for (const i in oldCustomReplaceBuiltIn) {
                const id = oldCustomReplaceBuiltIn[i]; // string
                newBuiltIn[id] = { id: id, modified: false, data: CustomReplacementBuiltInCommands.find(x => x.id === id).data };
            }
            this.settings.customReplaceBuiltInLog = newBuiltIn;
        }
    }
}
function selection2range(editor, selection) {
    let anchorOffset = editor.posToOffset(selection.anchor), headOffset = editor.posToOffset(selection.head);
    const from = editor.offsetToPos(Math.min(anchorOffset, headOffset));
    const to = editor.offsetToPos(Math.max(anchorOffset, headOffset));
    return { from: from, to: to };
}

module.exports = TextFormat;


/* nosourcemap */