diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json
index d3f66fab..d59d42be 100644
--- a/.obsidian/community-plugins.json
+++ b/.obsidian/community-plugins.json
@@ -1,3 +1,6 @@
[
- "obsidian-git"
+ "obsidian-git",
+ "table-editor-obsidian",
+ "calendar",
+ "obsidian-outliner"
]
\ No newline at end of file
diff --git a/.obsidian/daily-notes.json b/.obsidian/daily-notes.json
new file mode 100644
index 00000000..bbdf5bb4
--- /dev/null
+++ b/.obsidian/daily-notes.json
@@ -0,0 +1,4 @@
+{
+ "folder": "Journal",
+ "autorun": true
+}
\ No newline at end of file
diff --git a/.obsidian/graph.json b/.obsidian/graph.json
new file mode 100644
index 00000000..e21a18dc
--- /dev/null
+++ b/.obsidian/graph.json
@@ -0,0 +1,22 @@
+{
+ "collapse-filter": true,
+ "search": "",
+ "showTags": false,
+ "showAttachments": false,
+ "hideUnresolved": false,
+ "showOrphans": true,
+ "collapse-color-groups": true,
+ "colorGroups": [],
+ "collapse-display": true,
+ "showArrow": false,
+ "textFadeMultiplier": 0,
+ "nodeSizeMultiplier": 1,
+ "lineSizeMultiplier": 1,
+ "collapse-forces": true,
+ "centerStrength": 0.518713248970312,
+ "repelStrength": 10,
+ "linkStrength": 1,
+ "linkDistance": 250,
+ "scale": 1,
+ "close": false
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/calendar/data.json b/.obsidian/plugins/calendar/data.json
new file mode 100644
index 00000000..b88b5ed2
--- /dev/null
+++ b/.obsidian/plugins/calendar/data.json
@@ -0,0 +1,10 @@
+{
+ "shouldConfirmBeforeCreate": true,
+ "weekStart": "locale",
+ "wordsPerDot": 250,
+ "showWeeklyNote": true,
+ "weeklyNoteFormat": "",
+ "weeklyNoteTemplate": "",
+ "weeklyNoteFolder": "",
+ "localeOverride": "system-default"
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/calendar/main.js b/.obsidian/plugins/calendar/main.js
new file mode 100644
index 00000000..eb2951b7
--- /dev/null
+++ b/.obsidian/plugins/calendar/main.js
@@ -0,0 +1,4457 @@
+'use strict';
+
+var obsidian = require('obsidian');
+
+function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+
+var obsidian__default = /*#__PURE__*/_interopDefaultLegacy(obsidian);
+
+const DEFAULT_WEEK_FORMAT = "gggg-[W]ww";
+const DEFAULT_WORDS_PER_DOT = 250;
+const VIEW_TYPE_CALENDAR = "calendar";
+const TRIGGER_ON_OPEN = "calendar:open";
+
+const DEFAULT_DAILY_NOTE_FORMAT = "YYYY-MM-DD";
+const DEFAULT_WEEKLY_NOTE_FORMAT = "gggg-[W]ww";
+const DEFAULT_MONTHLY_NOTE_FORMAT = "YYYY-MM";
+
+function shouldUsePeriodicNotesSettings(periodicity) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const periodicNotes = window.app.plugins.getPlugin("periodic-notes");
+ return periodicNotes && periodicNotes.settings?.[periodicity]?.enabled;
+}
+/**
+ * Read the user settings for the `daily-notes` plugin
+ * to keep behavior of creating a new note in-sync.
+ */
+function getDailyNoteSettings() {
+ try {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const { internalPlugins, plugins } = window.app;
+ if (shouldUsePeriodicNotesSettings("daily")) {
+ const { format, folder, template } = plugins.getPlugin("periodic-notes")?.settings?.daily || {};
+ return {
+ format: format || DEFAULT_DAILY_NOTE_FORMAT,
+ folder: folder?.trim() || "",
+ template: template?.trim() || "",
+ };
+ }
+ const { folder, format, template } = internalPlugins.getPluginById("daily-notes")?.instance?.options || {};
+ return {
+ format: format || DEFAULT_DAILY_NOTE_FORMAT,
+ folder: folder?.trim() || "",
+ template: template?.trim() || "",
+ };
+ }
+ catch (err) {
+ console.info("No custom daily note settings found!", err);
+ }
+}
+/**
+ * Read the user settings for the `weekly-notes` plugin
+ * to keep behavior of creating a new note in-sync.
+ */
+function getWeeklyNoteSettings() {
+ try {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const pluginManager = window.app.plugins;
+ const calendarSettings = pluginManager.getPlugin("calendar")?.options;
+ const periodicNotesSettings = pluginManager.getPlugin("periodic-notes")
+ ?.settings?.weekly;
+ if (shouldUsePeriodicNotesSettings("weekly")) {
+ return {
+ format: periodicNotesSettings.format || DEFAULT_WEEKLY_NOTE_FORMAT,
+ folder: periodicNotesSettings.folder?.trim() || "",
+ template: periodicNotesSettings.template?.trim() || "",
+ };
+ }
+ const settings = calendarSettings || {};
+ return {
+ format: settings.weeklyNoteFormat || DEFAULT_WEEKLY_NOTE_FORMAT,
+ folder: settings.weeklyNoteFolder?.trim() || "",
+ template: settings.weeklyNoteTemplate?.trim() || "",
+ };
+ }
+ catch (err) {
+ console.info("No custom weekly note settings found!", err);
+ }
+}
+/**
+ * Read the user settings for the `periodic-notes` plugin
+ * to keep behavior of creating a new note in-sync.
+ */
+function getMonthlyNoteSettings() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const pluginManager = window.app.plugins;
+ try {
+ const settings = (shouldUsePeriodicNotesSettings("monthly") &&
+ pluginManager.getPlugin("periodic-notes")?.settings?.monthly) ||
+ {};
+ return {
+ format: settings.format || DEFAULT_MONTHLY_NOTE_FORMAT,
+ folder: settings.folder?.trim() || "",
+ template: settings.template?.trim() || "",
+ };
+ }
+ catch (err) {
+ console.info("No custom monthly note settings found!", err);
+ }
+}
+
+/**
+ * dateUID is a way of weekly identifying daily/weekly/monthly notes.
+ * They are prefixed with the granularity to avoid ambiguity.
+ */
+function getDateUID$1(date, granularity = "day") {
+ const ts = date.clone().startOf(granularity).format();
+ return `${granularity}-${ts}`;
+}
+function removeEscapedCharacters(format) {
+ return format.replace(/\[[^\]]*\]/g, ""); // remove everything within brackets
+}
+/**
+ * XXX: When parsing dates that contain both week numbers and months,
+ * Moment choses to ignore the week numbers. For the week dateUID, we
+ * want the opposite behavior. Strip the MMM from the format to patch.
+ */
+function isFormatAmbiguous(format, granularity) {
+ if (granularity === "week") {
+ const cleanFormat = removeEscapedCharacters(format);
+ return (/w{1,2}/i.test(cleanFormat) &&
+ (/M{1,4}/.test(cleanFormat) || /D{1,4}/.test(cleanFormat)));
+ }
+ return false;
+}
+function getDateFromFile(file, granularity) {
+ const getSettings = {
+ day: getDailyNoteSettings,
+ week: getWeeklyNoteSettings,
+ month: getMonthlyNoteSettings,
+ };
+ const format = getSettings[granularity]().format.split("/").pop();
+ const noteDate = window.moment(file.basename, format, true);
+ if (!noteDate.isValid()) {
+ return null;
+ }
+ if (isFormatAmbiguous(format, granularity)) {
+ if (granularity === "week") {
+ const cleanFormat = removeEscapedCharacters(format);
+ if (/w{1,2}/i.test(cleanFormat)) {
+ return window.moment(file.basename,
+ // If format contains week, remove day & month formatting
+ format.replace(/M{1,4}/g, "").replace(/D{1,4}/g, ""), false);
+ }
+ }
+ }
+ return noteDate;
+}
+
+// Credit: @creationix/path.js
+function join(...partSegments) {
+ // Split the inputs into a list of path commands.
+ let parts = [];
+ for (let i = 0, l = partSegments.length; i < l; i++) {
+ parts = parts.concat(partSegments[i].split("/"));
+ }
+ // Interpret the path commands to get the new resolved path.
+ const newParts = [];
+ for (let i = 0, l = parts.length; i < l; i++) {
+ const part = parts[i];
+ // Remove leading and trailing slashes
+ // Also remove "." segments
+ if (!part || part === ".")
+ continue;
+ // Push new path segments.
+ else
+ newParts.push(part);
+ }
+ // Preserve the initial slash if there was one.
+ if (parts[0] === "")
+ newParts.unshift("");
+ // Turn back into a single string path.
+ return newParts.join("/");
+}
+async function ensureFolderExists(path) {
+ const dirs = path.replace(/\\/g, "/").split("/");
+ dirs.pop(); // remove basename
+ if (dirs.length) {
+ const dir = join(...dirs);
+ if (!window.app.vault.getAbstractFileByPath(dir)) {
+ await window.app.vault.createFolder(dir);
+ }
+ }
+}
+async function getNotePath(directory, filename) {
+ if (!filename.endsWith(".md")) {
+ filename += ".md";
+ }
+ const path = obsidian__default['default'].normalizePath(join(directory, filename));
+ await ensureFolderExists(path);
+ return path;
+}
+async function getTemplateInfo(template) {
+ const { metadataCache, vault } = window.app;
+ const templatePath = obsidian__default['default'].normalizePath(template);
+ if (templatePath === "/") {
+ return Promise.resolve(["", null]);
+ }
+ try {
+ const templateFile = metadataCache.getFirstLinkpathDest(templatePath, "");
+ const contents = await vault.cachedRead(templateFile);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const IFoldInfo = window.app.foldManager.load(templateFile);
+ return [contents, IFoldInfo];
+ }
+ catch (err) {
+ console.error(`Failed to read the daily note template '${templatePath}'`, err);
+ new obsidian__default['default'].Notice("Failed to read the daily note template");
+ return ["", null];
+ }
+}
+
+class DailyNotesFolderMissingError extends Error {
+}
+/**
+ * This function mimics the behavior of the daily-notes plugin
+ * so it will replace {{date}}, {{title}}, and {{time}} with the
+ * formatted timestamp.
+ *
+ * Note: it has an added bonus that it's not 'today' specific.
+ */
+async function createDailyNote(date) {
+ const app = window.app;
+ const { vault } = app;
+ const moment = window.moment;
+ const { template, format, folder } = getDailyNoteSettings();
+ const [templateContents, IFoldInfo] = await getTemplateInfo(template);
+ const filename = date.format(format);
+ const normalizedPath = await getNotePath(folder, filename);
+ try {
+ const createdFile = await vault.create(normalizedPath, templateContents
+ .replace(/{{\s*date\s*}}/gi, filename)
+ .replace(/{{\s*time\s*}}/gi, moment().format("HH:mm"))
+ .replace(/{{\s*title\s*}}/gi, filename)
+ .replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
+ const now = moment();
+ const currentDate = date.clone().set({
+ hour: now.get("hour"),
+ minute: now.get("minute"),
+ second: now.get("second"),
+ });
+ if (calc) {
+ currentDate.add(parseInt(timeDelta, 10), unit);
+ }
+ if (momentFormat) {
+ return currentDate.format(momentFormat.substring(1).trim());
+ }
+ return currentDate.format(format);
+ })
+ .replace(/{{\s*yesterday\s*}}/gi, date.clone().subtract(1, "day").format(format))
+ .replace(/{{\s*tomorrow\s*}}/gi, date.clone().add(1, "d").format(format)));
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ app.foldManager.save(createdFile, IFoldInfo);
+ return createdFile;
+ }
+ catch (err) {
+ console.error(`Failed to create file: '${normalizedPath}'`, err);
+ new obsidian__default['default'].Notice("Unable to create new file.");
+ }
+}
+function getDailyNote(date, dailyNotes) {
+ return dailyNotes[getDateUID$1(date, "day")] ?? null;
+}
+function getAllDailyNotes() {
+ /**
+ * Find all daily notes in the daily note folder
+ */
+ const { vault } = window.app;
+ const { folder } = getDailyNoteSettings();
+ const dailyNotesFolder = vault.getAbstractFileByPath(obsidian__default['default'].normalizePath(folder));
+ if (!dailyNotesFolder) {
+ throw new DailyNotesFolderMissingError("Failed to find daily notes folder");
+ }
+ const dailyNotes = {};
+ obsidian__default['default'].Vault.recurseChildren(dailyNotesFolder, (note) => {
+ if (note instanceof obsidian__default['default'].TFile) {
+ const date = getDateFromFile(note, "day");
+ if (date) {
+ const dateString = getDateUID$1(date, "day");
+ dailyNotes[dateString] = note;
+ }
+ }
+ });
+ return dailyNotes;
+}
+
+class WeeklyNotesFolderMissingError extends Error {
+}
+function getDaysOfWeek$1() {
+ const { moment } = window;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let weekStart = moment.localeData()._week.dow;
+ const daysOfWeek = [
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday",
+ ];
+ while (weekStart) {
+ daysOfWeek.push(daysOfWeek.shift());
+ weekStart--;
+ }
+ return daysOfWeek;
+}
+function getDayOfWeekNumericalValue(dayOfWeekName) {
+ return getDaysOfWeek$1().indexOf(dayOfWeekName.toLowerCase());
+}
+async function createWeeklyNote(date) {
+ const { vault } = window.app;
+ const { template, format, folder } = getWeeklyNoteSettings();
+ const [templateContents, IFoldInfo] = await getTemplateInfo(template);
+ const filename = date.format(format);
+ const normalizedPath = await getNotePath(folder, filename);
+ try {
+ const createdFile = await vault.create(normalizedPath, templateContents
+ .replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
+ const now = window.moment();
+ const currentDate = date.clone().set({
+ hour: now.get("hour"),
+ minute: now.get("minute"),
+ second: now.get("second"),
+ });
+ if (calc) {
+ currentDate.add(parseInt(timeDelta, 10), unit);
+ }
+ if (momentFormat) {
+ return currentDate.format(momentFormat.substring(1).trim());
+ }
+ return currentDate.format(format);
+ })
+ .replace(/{{\s*title\s*}}/gi, filename)
+ .replace(/{{\s*time\s*}}/gi, window.moment().format("HH:mm"))
+ .replace(/{{\s*(sunday|monday|tuesday|wednesday|thursday|friday|saturday)\s*:(.*?)}}/gi, (_, dayOfWeek, momentFormat) => {
+ const day = getDayOfWeekNumericalValue(dayOfWeek);
+ return date.weekday(day).format(momentFormat.trim());
+ }));
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ window.app.foldManager.save(createdFile, IFoldInfo);
+ return createdFile;
+ }
+ catch (err) {
+ console.error(`Failed to create file: '${normalizedPath}'`, err);
+ new obsidian__default['default'].Notice("Unable to create new file.");
+ }
+}
+function getWeeklyNote(date, weeklyNotes) {
+ return weeklyNotes[getDateUID$1(date, "week")] ?? null;
+}
+function getAllWeeklyNotes() {
+ const { vault } = window.app;
+ const { folder } = getWeeklyNoteSettings();
+ const weeklyNotesFolder = vault.getAbstractFileByPath(obsidian__default['default'].normalizePath(folder));
+ if (!weeklyNotesFolder) {
+ throw new WeeklyNotesFolderMissingError("Failed to find weekly notes folder");
+ }
+ const weeklyNotes = {};
+ obsidian__default['default'].Vault.recurseChildren(weeklyNotesFolder, (note) => {
+ if (note instanceof obsidian__default['default'].TFile) {
+ const date = getDateFromFile(note, "week");
+ if (date) {
+ const dateString = getDateUID$1(date, "week");
+ weeklyNotes[dateString] = note;
+ }
+ }
+ });
+ return weeklyNotes;
+}
+
+function appHasDailyNotesPluginLoaded() {
+ const { app } = window;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const dailyNotesPlugin = app.internalPlugins.plugins["daily-notes"];
+ if (dailyNotesPlugin && dailyNotesPlugin.enabled) {
+ return true;
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const periodicNotes = app.plugins.getPlugin("periodic-notes");
+ return periodicNotes && periodicNotes.settings?.daily?.enabled;
+}
+var appHasDailyNotesPluginLoaded_1 = appHasDailyNotesPluginLoaded;
+var createDailyNote_1 = createDailyNote;
+var createWeeklyNote_1 = createWeeklyNote;
+var getAllDailyNotes_1 = getAllDailyNotes;
+var getAllWeeklyNotes_1 = getAllWeeklyNotes;
+var getDailyNote_1 = getDailyNote;
+var getDailyNoteSettings_1 = getDailyNoteSettings;
+var getDateFromFile_1 = getDateFromFile;
+var getDateUID_1$1 = getDateUID$1;
+var getWeeklyNote_1 = getWeeklyNote;
+var getWeeklyNoteSettings_1 = getWeeklyNoteSettings;
+
+function noop$1() { }
+function run$1(fn) {
+ return fn();
+}
+function blank_object$1() {
+ return Object.create(null);
+}
+function run_all$1(fns) {
+ fns.forEach(run$1);
+}
+function is_function$1(thing) {
+ return typeof thing === 'function';
+}
+function safe_not_equal$1(a, b) {
+ return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
+}
+function not_equal$1(a, b) {
+ return a != a ? b == b : a !== b;
+}
+function is_empty$1(obj) {
+ return Object.keys(obj).length === 0;
+}
+function subscribe(store, ...callbacks) {
+ if (store == null) {
+ return noop$1;
+ }
+ const unsub = store.subscribe(...callbacks);
+ return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
+}
+function get_store_value(store) {
+ let value;
+ subscribe(store, _ => value = _)();
+ return value;
+}
+function component_subscribe(component, store, callback) {
+ component.$$.on_destroy.push(subscribe(store, callback));
+}
+function detach$1(node) {
+ node.parentNode.removeChild(node);
+}
+function children$1(element) {
+ return Array.from(element.childNodes);
+}
+
+let current_component$1;
+function set_current_component$1(component) {
+ current_component$1 = component;
+}
+function get_current_component$1() {
+ if (!current_component$1)
+ throw new Error('Function called outside component initialization');
+ return current_component$1;
+}
+function onDestroy(fn) {
+ get_current_component$1().$$.on_destroy.push(fn);
+}
+
+const dirty_components$1 = [];
+const binding_callbacks$1 = [];
+const render_callbacks$1 = [];
+const flush_callbacks$1 = [];
+const resolved_promise$1 = Promise.resolve();
+let update_scheduled$1 = false;
+function schedule_update$1() {
+ if (!update_scheduled$1) {
+ update_scheduled$1 = true;
+ resolved_promise$1.then(flush$1);
+ }
+}
+function add_render_callback$1(fn) {
+ render_callbacks$1.push(fn);
+}
+function add_flush_callback(fn) {
+ flush_callbacks$1.push(fn);
+}
+let flushing$1 = false;
+const seen_callbacks$1 = new Set();
+function flush$1() {
+ if (flushing$1)
+ return;
+ flushing$1 = true;
+ do {
+ // first, call beforeUpdate functions
+ // and update components
+ for (let i = 0; i < dirty_components$1.length; i += 1) {
+ const component = dirty_components$1[i];
+ set_current_component$1(component);
+ update$1(component.$$);
+ }
+ set_current_component$1(null);
+ dirty_components$1.length = 0;
+ while (binding_callbacks$1.length)
+ binding_callbacks$1.pop()();
+ // then, once components are updated, call
+ // afterUpdate functions. This may cause
+ // subsequent updates...
+ for (let i = 0; i < render_callbacks$1.length; i += 1) {
+ const callback = render_callbacks$1[i];
+ if (!seen_callbacks$1.has(callback)) {
+ // ...so guard against infinite loops
+ seen_callbacks$1.add(callback);
+ callback();
+ }
+ }
+ render_callbacks$1.length = 0;
+ } while (dirty_components$1.length);
+ while (flush_callbacks$1.length) {
+ flush_callbacks$1.pop()();
+ }
+ update_scheduled$1 = false;
+ flushing$1 = false;
+ seen_callbacks$1.clear();
+}
+function update$1($$) {
+ if ($$.fragment !== null) {
+ $$.update();
+ run_all$1($$.before_update);
+ const dirty = $$.dirty;
+ $$.dirty = [-1];
+ $$.fragment && $$.fragment.p($$.ctx, dirty);
+ $$.after_update.forEach(add_render_callback$1);
+ }
+}
+const outroing$1 = new Set();
+let outros$1;
+function transition_in$1(block, local) {
+ if (block && block.i) {
+ outroing$1.delete(block);
+ block.i(local);
+ }
+}
+function transition_out$1(block, local, detach, callback) {
+ if (block && block.o) {
+ if (outroing$1.has(block))
+ return;
+ outroing$1.add(block);
+ outros$1.c.push(() => {
+ outroing$1.delete(block);
+ if (callback) {
+ if (detach)
+ block.d(1);
+ callback();
+ }
+ });
+ block.o(local);
+ }
+}
+
+function bind(component, name, callback) {
+ const index = component.$$.props[name];
+ if (index !== undefined) {
+ component.$$.bound[index] = callback;
+ callback(component.$$.ctx[index]);
+ }
+}
+function create_component$1(block) {
+ block && block.c();
+}
+function mount_component$1(component, target, anchor, customElement) {
+ const { fragment, on_mount, on_destroy, after_update } = component.$$;
+ fragment && fragment.m(target, anchor);
+ if (!customElement) {
+ // onMount happens before the initial afterUpdate
+ add_render_callback$1(() => {
+ const new_on_destroy = on_mount.map(run$1).filter(is_function$1);
+ if (on_destroy) {
+ on_destroy.push(...new_on_destroy);
+ }
+ else {
+ // Edge case - component was destroyed immediately,
+ // most likely as a result of a binding initialising
+ run_all$1(new_on_destroy);
+ }
+ component.$$.on_mount = [];
+ });
+ }
+ after_update.forEach(add_render_callback$1);
+}
+function destroy_component$1(component, detaching) {
+ const $$ = component.$$;
+ if ($$.fragment !== null) {
+ run_all$1($$.on_destroy);
+ $$.fragment && $$.fragment.d(detaching);
+ // TODO null out other refs, including component.$$ (but need to
+ // preserve final state?)
+ $$.on_destroy = $$.fragment = null;
+ $$.ctx = [];
+ }
+}
+function make_dirty$1(component, i) {
+ if (component.$$.dirty[0] === -1) {
+ dirty_components$1.push(component);
+ schedule_update$1();
+ component.$$.dirty.fill(0);
+ }
+ component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
+}
+function init$1(component, options, instance, create_fragment, not_equal, props, dirty = [-1]) {
+ const parent_component = current_component$1;
+ set_current_component$1(component);
+ const $$ = component.$$ = {
+ fragment: null,
+ ctx: null,
+ // state
+ props,
+ update: noop$1,
+ not_equal,
+ bound: blank_object$1(),
+ // lifecycle
+ on_mount: [],
+ on_destroy: [],
+ on_disconnect: [],
+ before_update: [],
+ after_update: [],
+ context: new Map(parent_component ? parent_component.$$.context : []),
+ // everything else
+ callbacks: blank_object$1(),
+ dirty,
+ skip_bound: false
+ };
+ let ready = false;
+ $$.ctx = instance
+ ? instance(component, options.props || {}, (i, ret, ...rest) => {
+ const value = rest.length ? rest[0] : ret;
+ if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
+ if (!$$.skip_bound && $$.bound[i])
+ $$.bound[i](value);
+ if (ready)
+ make_dirty$1(component, i);
+ }
+ return ret;
+ })
+ : [];
+ $$.update();
+ ready = true;
+ run_all$1($$.before_update);
+ // `false` as a special case of no DOM component
+ $$.fragment = create_fragment ? create_fragment($$.ctx) : false;
+ if (options.target) {
+ if (options.hydrate) {
+ const nodes = children$1(options.target);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ $$.fragment && $$.fragment.l(nodes);
+ nodes.forEach(detach$1);
+ }
+ else {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ $$.fragment && $$.fragment.c();
+ }
+ if (options.intro)
+ transition_in$1(component.$$.fragment);
+ mount_component$1(component, options.target, options.anchor, options.customElement);
+ flush$1();
+ }
+ set_current_component$1(parent_component);
+}
+/**
+ * Base class for Svelte components. Used when dev=false.
+ */
+class SvelteComponent$1 {
+ $destroy() {
+ destroy_component$1(this, 1);
+ this.$destroy = noop$1;
+ }
+ $on(type, callback) {
+ const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
+ callbacks.push(callback);
+ return () => {
+ const index = callbacks.indexOf(callback);
+ if (index !== -1)
+ callbacks.splice(index, 1);
+ };
+ }
+ $set($$props) {
+ if (this.$$set && !is_empty$1($$props)) {
+ this.$$.skip_bound = true;
+ this.$$set($$props);
+ this.$$.skip_bound = false;
+ }
+ }
+}
+
+const subscriber_queue = [];
+/**
+ * Create a `Writable` store that allows both updating and reading by subscription.
+ * @param {*=}value initial value
+ * @param {StartStopNotifier=}start start and stop notifications for subscriptions
+ */
+function writable(value, start = noop$1) {
+ let stop;
+ const subscribers = [];
+ function set(new_value) {
+ if (safe_not_equal$1(value, new_value)) {
+ value = new_value;
+ if (stop) { // store is ready
+ const run_queue = !subscriber_queue.length;
+ for (let i = 0; i < subscribers.length; i += 1) {
+ const s = subscribers[i];
+ s[1]();
+ subscriber_queue.push(s, value);
+ }
+ if (run_queue) {
+ for (let i = 0; i < subscriber_queue.length; i += 2) {
+ subscriber_queue[i][0](subscriber_queue[i + 1]);
+ }
+ subscriber_queue.length = 0;
+ }
+ }
+ }
+ }
+ function update(fn) {
+ set(fn(value));
+ }
+ function subscribe(run, invalidate = noop$1) {
+ const subscriber = [run, invalidate];
+ subscribers.push(subscriber);
+ if (subscribers.length === 1) {
+ stop = start(set) || noop$1;
+ }
+ run(value);
+ return () => {
+ const index = subscribers.indexOf(subscriber);
+ if (index !== -1) {
+ subscribers.splice(index, 1);
+ }
+ if (subscribers.length === 0) {
+ stop();
+ stop = null;
+ }
+ };
+ }
+ return { set, update, subscribe };
+}
+
+const weekdays$1 = [
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday",
+];
+const defaultSettings = Object.freeze({
+ shouldConfirmBeforeCreate: true,
+ weekStart: "locale",
+ wordsPerDot: DEFAULT_WORDS_PER_DOT,
+ showWeeklyNote: false,
+ weeklyNoteFormat: "",
+ weeklyNoteTemplate: "",
+ weeklyNoteFolder: "",
+ localeOverride: "system-default",
+});
+function appHasPeriodicNotesPluginLoaded() {
+ var _a, _b;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const periodicNotes = window.app.plugins.getPlugin("periodic-notes");
+ return periodicNotes && ((_b = (_a = periodicNotes.settings) === null || _a === void 0 ? void 0 : _a.weekly) === null || _b === void 0 ? void 0 : _b.enabled);
+}
+class CalendarSettingsTab extends obsidian.PluginSettingTab {
+ constructor(app, plugin) {
+ super(app, plugin);
+ this.plugin = plugin;
+ }
+ display() {
+ this.containerEl.empty();
+ if (!appHasDailyNotesPluginLoaded_1()) {
+ this.containerEl.createDiv("settings-banner", (banner) => {
+ banner.createEl("h3", {
+ text: "⚠️ Daily Notes plugin not enabled",
+ });
+ banner.createEl("p", {
+ cls: "setting-item-description",
+ text: "The calendar is best used in conjunction with either the Daily Notes plugin or the Periodic Notes plugin (available in the Community Plugins catalog).",
+ });
+ });
+ }
+ this.containerEl.createEl("h3", {
+ text: "General Settings",
+ });
+ this.addDotThresholdSetting();
+ this.addWeekStartSetting();
+ this.addConfirmCreateSetting();
+ this.addShowWeeklyNoteSetting();
+ if (this.plugin.options.showWeeklyNote &&
+ !appHasPeriodicNotesPluginLoaded()) {
+ this.containerEl.createEl("h3", {
+ text: "Weekly Note Settings",
+ });
+ this.containerEl.createEl("p", {
+ cls: "setting-item-description",
+ text: "Note: Weekly Note settings are moving. You are encouraged to install the 'Periodic Notes' plugin to keep the functionality in the future.",
+ });
+ this.addWeeklyNoteFormatSetting();
+ this.addWeeklyNoteTemplateSetting();
+ this.addWeeklyNoteFolderSetting();
+ }
+ this.containerEl.createEl("h3", {
+ text: "Advanced Settings",
+ });
+ this.addLocaleOverrideSetting();
+ }
+ addDotThresholdSetting() {
+ new obsidian.Setting(this.containerEl)
+ .setName("Words per dot")
+ .setDesc("How many words should be represented by a single dot?")
+ .addText((textfield) => {
+ textfield.setPlaceholder(String(DEFAULT_WORDS_PER_DOT));
+ textfield.inputEl.type = "number";
+ textfield.setValue(String(this.plugin.options.wordsPerDot));
+ textfield.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({
+ wordsPerDot: value !== "" ? Number(value) : undefined,
+ }));
+ });
+ });
+ }
+ addWeekStartSetting() {
+ const { moment } = window;
+ const localizedWeekdays = moment.weekdays();
+ const localeWeekStartNum = window._bundledLocaleWeekSpec.dow;
+ const localeWeekStart = moment.weekdays()[localeWeekStartNum];
+ new obsidian.Setting(this.containerEl)
+ .setName("Start week on:")
+ .setDesc("Choose what day of the week to start. Select 'Locale default' to use the default specified by moment.js")
+ .addDropdown((dropdown) => {
+ dropdown.addOption("locale", `Locale default (${localeWeekStart})`);
+ localizedWeekdays.forEach((day, i) => {
+ dropdown.addOption(weekdays$1[i], day);
+ });
+ dropdown.setValue(this.plugin.options.weekStart);
+ dropdown.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({
+ weekStart: value,
+ }));
+ });
+ });
+ }
+ addConfirmCreateSetting() {
+ new obsidian.Setting(this.containerEl)
+ .setName("Confirm before creating new note")
+ .setDesc("Show a confirmation modal before creating a new note")
+ .addToggle((toggle) => {
+ toggle.setValue(this.plugin.options.shouldConfirmBeforeCreate);
+ toggle.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({
+ shouldConfirmBeforeCreate: value,
+ }));
+ });
+ });
+ }
+ addShowWeeklyNoteSetting() {
+ new obsidian.Setting(this.containerEl)
+ .setName("Show week number")
+ .setDesc("Enable this to add a column with the week number")
+ .addToggle((toggle) => {
+ toggle.setValue(this.plugin.options.showWeeklyNote);
+ toggle.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({ showWeeklyNote: value }));
+ this.display(); // show/hide weekly settings
+ });
+ });
+ }
+ addWeeklyNoteFormatSetting() {
+ new obsidian.Setting(this.containerEl)
+ .setName("Weekly note format")
+ .setDesc("For more syntax help, refer to format reference")
+ .addText((textfield) => {
+ textfield.setValue(this.plugin.options.weeklyNoteFormat);
+ textfield.setPlaceholder(DEFAULT_WEEK_FORMAT);
+ textfield.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({ weeklyNoteFormat: value }));
+ });
+ });
+ }
+ addWeeklyNoteTemplateSetting() {
+ new obsidian.Setting(this.containerEl)
+ .setName("Weekly note template")
+ .setDesc("Choose the file you want to use as the template for your weekly notes")
+ .addText((textfield) => {
+ textfield.setValue(this.plugin.options.weeklyNoteTemplate);
+ textfield.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({ weeklyNoteTemplate: value }));
+ });
+ });
+ }
+ addWeeklyNoteFolderSetting() {
+ new obsidian.Setting(this.containerEl)
+ .setName("Weekly note folder")
+ .setDesc("New weekly notes will be placed here")
+ .addText((textfield) => {
+ textfield.setValue(this.plugin.options.weeklyNoteFolder);
+ textfield.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({ weeklyNoteFolder: value }));
+ });
+ });
+ }
+ addLocaleOverrideSetting() {
+ var _a;
+ const { moment } = window;
+ const sysLocale = (_a = navigator.language) === null || _a === void 0 ? void 0 : _a.toLowerCase();
+ new obsidian.Setting(this.containerEl)
+ .setName("Override locale:")
+ .setDesc("Set this if you want to use a locale different from the default")
+ .addDropdown((dropdown) => {
+ dropdown.addOption("system-default", `Same as system (${sysLocale})`);
+ moment.locales().forEach((locale) => {
+ dropdown.addOption(locale, locale);
+ });
+ dropdown.setValue(this.plugin.options.localeOverride);
+ dropdown.onChange(async (value) => {
+ this.plugin.writeOptions(() => ({
+ localeOverride: value,
+ }));
+ });
+ });
+ }
+}
+
+const classList = (obj) => {
+ return Object.entries(obj)
+ .filter(([_k, v]) => !!v)
+ .map(([k, _k]) => k);
+};
+function clamp(num, lowerBound, upperBound) {
+ return Math.min(Math.max(lowerBound, num), upperBound);
+}
+function partition(arr, predicate) {
+ const pass = [];
+ const fail = [];
+ arr.forEach((elem) => {
+ if (predicate(elem)) {
+ pass.push(elem);
+ }
+ else {
+ fail.push(elem);
+ }
+ });
+ return [pass, fail];
+}
+/**
+ * Lookup the dateUID for a given file. It compares the filename
+ * to the daily and weekly note formats to find a match.
+ *
+ * @param file
+ */
+function getDateUIDFromFile(file) {
+ if (!file) {
+ return null;
+ }
+ // TODO: I'm not checking the path!
+ let date = getDateFromFile_1(file, "day");
+ if (date) {
+ return getDateUID_1$1(date, "day");
+ }
+ date = getDateFromFile_1(file, "week");
+ if (date) {
+ return getDateUID_1$1(date, "week");
+ }
+ return null;
+}
+function getWordCount(text) {
+ const spaceDelimitedChars = /A-Za-z\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC/
+ .source;
+ const nonSpaceDelimitedWords = /\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u4E00-\u9FD5/
+ .source;
+ const pattern = new RegExp([
+ `(?:[0-9]+(?:(?:,|\\.)[0-9]+)*|[\\-${spaceDelimitedChars}])+`,
+ nonSpaceDelimitedWords,
+ ].join("|"), "g");
+ return (text.match(pattern) || []).length;
+}
+
+function createDailyNotesStore() {
+ let hasError = false;
+ const store = writable(null);
+ return Object.assign({ reindex: () => {
+ try {
+ const dailyNotes = getAllDailyNotes_1();
+ store.set(dailyNotes);
+ hasError = false;
+ }
+ catch (err) {
+ if (!hasError) {
+ // Avoid error being shown multiple times
+ console.log("[Calendar] Failed to find daily notes folder", err);
+ }
+ store.set({});
+ hasError = true;
+ }
+ } }, store);
+}
+function createWeeklyNotesStore() {
+ let hasError = false;
+ const store = writable(null);
+ return Object.assign({ reindex: () => {
+ try {
+ const weeklyNotes = getAllWeeklyNotes_1();
+ store.set(weeklyNotes);
+ hasError = false;
+ }
+ catch (err) {
+ if (!hasError) {
+ // Avoid error being shown multiple times
+ console.log("[Calendar] Failed to find weekly notes folder", err);
+ }
+ store.set({});
+ hasError = true;
+ }
+ } }, store);
+}
+const settings = writable(defaultSettings);
+const dailyNotes = createDailyNotesStore();
+const weeklyNotes = createWeeklyNotesStore();
+function createSelectedFileStore() {
+ const store = writable(null);
+ return Object.assign({ setFile: (file) => {
+ const id = getDateUIDFromFile(file);
+ store.set(id);
+ } }, store);
+}
+const activeFile = createSelectedFileStore();
+
+class ConfirmationModal extends obsidian.Modal {
+ constructor(app, config) {
+ super(app);
+ const { cta, onAccept, text, title } = config;
+ this.contentEl.createEl("h2", { text: title });
+ this.contentEl.createEl("p", { text });
+ this.contentEl.createDiv("modal-button-container", (buttonsEl) => {
+ buttonsEl
+ .createEl("button", { text: "Never mind" })
+ .addEventListener("click", () => this.close());
+ buttonsEl
+ .createEl("button", {
+ cls: "mod-cta",
+ text: cta,
+ })
+ .addEventListener("click", async (e) => {
+ await onAccept(e);
+ this.close();
+ });
+ });
+ }
+}
+function createConfirmationDialog({ cta, onAccept, text, title, }) {
+ new ConfirmationModal(window.app, { cta, onAccept, text, title }).open();
+}
+
+/**
+ * Create a Daily Note for a given date.
+ */
+async function tryToCreateDailyNote(date, inNewSplit, settings, cb) {
+ const { workspace } = window.app;
+ const { format } = getDailyNoteSettings_1();
+ const filename = date.format(format);
+ const createFile = async () => {
+ const dailyNote = await createDailyNote_1(date);
+ const leaf = inNewSplit
+ ? workspace.splitActiveLeaf()
+ : workspace.getUnpinnedLeaf();
+ await leaf.openFile(dailyNote);
+ cb === null || cb === void 0 ? void 0 : cb(dailyNote);
+ };
+ if (settings.shouldConfirmBeforeCreate) {
+ createConfirmationDialog({
+ cta: "Create",
+ onAccept: createFile,
+ text: `File ${filename} does not exist. Would you like to create it?`,
+ title: "New Daily Note",
+ });
+ }
+ else {
+ await createFile();
+ }
+}
+
+/**
+ * Create a Weekly Note for a given date.
+ */
+async function tryToCreateWeeklyNote(date, inNewSplit, settings, cb) {
+ const { workspace } = window.app;
+ const { format } = getWeeklyNoteSettings_1();
+ const filename = date.format(format);
+ const createFile = async () => {
+ const dailyNote = await createWeeklyNote_1(date);
+ const leaf = inNewSplit
+ ? workspace.splitActiveLeaf()
+ : workspace.getUnpinnedLeaf();
+ await leaf.openFile(dailyNote);
+ cb === null || cb === void 0 ? void 0 : cb(dailyNote);
+ };
+ if (settings.shouldConfirmBeforeCreate) {
+ createConfirmationDialog({
+ cta: "Create",
+ onAccept: createFile,
+ text: `File ${filename} does not exist. Would you like to create it?`,
+ title: "New Weekly Note",
+ });
+ }
+ else {
+ await createFile();
+ }
+}
+
+function noop() { }
+function assign(tar, src) {
+ // @ts-ignore
+ for (const k in src)
+ tar[k] = src[k];
+ return tar;
+}
+function is_promise(value) {
+ return value && typeof value === 'object' && typeof value.then === 'function';
+}
+function run(fn) {
+ return fn();
+}
+function blank_object() {
+ return Object.create(null);
+}
+function run_all(fns) {
+ fns.forEach(run);
+}
+function is_function(thing) {
+ return typeof thing === 'function';
+}
+function safe_not_equal(a, b) {
+ return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
+}
+function not_equal(a, b) {
+ return a != a ? b == b : a !== b;
+}
+function is_empty(obj) {
+ return Object.keys(obj).length === 0;
+}
+function create_slot(definition, ctx, $$scope, fn) {
+ if (definition) {
+ const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);
+ return definition[0](slot_ctx);
+ }
+}
+function get_slot_context(definition, ctx, $$scope, fn) {
+ return definition[1] && fn
+ ? assign($$scope.ctx.slice(), definition[1](fn(ctx)))
+ : $$scope.ctx;
+}
+function get_slot_changes(definition, $$scope, dirty, fn) {
+ if (definition[2] && fn) {
+ const lets = definition[2](fn(dirty));
+ if ($$scope.dirty === undefined) {
+ return lets;
+ }
+ if (typeof lets === 'object') {
+ const merged = [];
+ const len = Math.max($$scope.dirty.length, lets.length);
+ for (let i = 0; i < len; i += 1) {
+ merged[i] = $$scope.dirty[i] | lets[i];
+ }
+ return merged;
+ }
+ return $$scope.dirty | lets;
+ }
+ return $$scope.dirty;
+}
+function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
+ const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
+ if (slot_changes) {
+ const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
+ slot.p(slot_context, slot_changes);
+ }
+}
+function null_to_empty(value) {
+ return value == null ? '' : value;
+}
+
+function append(target, node) {
+ target.appendChild(node);
+}
+function insert(target, node, anchor) {
+ target.insertBefore(node, anchor || null);
+}
+function detach(node) {
+ node.parentNode.removeChild(node);
+}
+function destroy_each(iterations, detaching) {
+ for (let i = 0; i < iterations.length; i += 1) {
+ if (iterations[i])
+ iterations[i].d(detaching);
+ }
+}
+function element(name) {
+ return document.createElement(name);
+}
+function svg_element(name) {
+ return document.createElementNS('http://www.w3.org/2000/svg', name);
+}
+function text(data) {
+ return document.createTextNode(data);
+}
+function space() {
+ return text(' ');
+}
+function empty() {
+ return text('');
+}
+function listen(node, event, handler, options) {
+ node.addEventListener(event, handler, options);
+ return () => node.removeEventListener(event, handler, options);
+}
+function attr(node, attribute, value) {
+ if (value == null)
+ node.removeAttribute(attribute);
+ else if (node.getAttribute(attribute) !== value)
+ node.setAttribute(attribute, value);
+}
+function set_attributes(node, attributes) {
+ // @ts-ignore
+ const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
+ for (const key in attributes) {
+ if (attributes[key] == null) {
+ node.removeAttribute(key);
+ }
+ else if (key === 'style') {
+ node.style.cssText = attributes[key];
+ }
+ else if (key === '__value') {
+ node.value = node[key] = attributes[key];
+ }
+ else if (descriptors[key] && descriptors[key].set) {
+ node[key] = attributes[key];
+ }
+ else {
+ attr(node, key, attributes[key]);
+ }
+ }
+}
+function children(element) {
+ return Array.from(element.childNodes);
+}
+function set_data(text, data) {
+ data = '' + data;
+ if (text.wholeText !== data)
+ text.data = data;
+}
+function toggle_class(element, name, toggle) {
+ element.classList[toggle ? 'add' : 'remove'](name);
+}
+
+let current_component;
+function set_current_component(component) {
+ current_component = component;
+}
+function get_current_component() {
+ if (!current_component)
+ throw new Error('Function called outside component initialization');
+ return current_component;
+}
+
+const dirty_components = [];
+const binding_callbacks = [];
+const render_callbacks = [];
+const flush_callbacks = [];
+const resolved_promise = Promise.resolve();
+let update_scheduled = false;
+function schedule_update() {
+ if (!update_scheduled) {
+ update_scheduled = true;
+ resolved_promise.then(flush);
+ }
+}
+function add_render_callback(fn) {
+ render_callbacks.push(fn);
+}
+let flushing = false;
+const seen_callbacks = new Set();
+function flush() {
+ if (flushing)
+ return;
+ flushing = true;
+ do {
+ // first, call beforeUpdate functions
+ // and update components
+ for (let i = 0; i < dirty_components.length; i += 1) {
+ const component = dirty_components[i];
+ set_current_component(component);
+ update(component.$$);
+ }
+ set_current_component(null);
+ dirty_components.length = 0;
+ while (binding_callbacks.length)
+ binding_callbacks.pop()();
+ // then, once components are updated, call
+ // afterUpdate functions. This may cause
+ // subsequent updates...
+ for (let i = 0; i < render_callbacks.length; i += 1) {
+ const callback = render_callbacks[i];
+ if (!seen_callbacks.has(callback)) {
+ // ...so guard against infinite loops
+ seen_callbacks.add(callback);
+ callback();
+ }
+ }
+ render_callbacks.length = 0;
+ } while (dirty_components.length);
+ while (flush_callbacks.length) {
+ flush_callbacks.pop()();
+ }
+ update_scheduled = false;
+ flushing = false;
+ seen_callbacks.clear();
+}
+function update($$) {
+ if ($$.fragment !== null) {
+ $$.update();
+ run_all($$.before_update);
+ const dirty = $$.dirty;
+ $$.dirty = [-1];
+ $$.fragment && $$.fragment.p($$.ctx, dirty);
+ $$.after_update.forEach(add_render_callback);
+ }
+}
+const outroing = new Set();
+let outros;
+function group_outros() {
+ outros = {
+ r: 0,
+ c: [],
+ p: outros // parent group
+ };
+}
+function check_outros() {
+ if (!outros.r) {
+ run_all(outros.c);
+ }
+ outros = outros.p;
+}
+function transition_in(block, local) {
+ if (block && block.i) {
+ outroing.delete(block);
+ block.i(local);
+ }
+}
+function transition_out(block, local, detach, callback) {
+ if (block && block.o) {
+ if (outroing.has(block))
+ return;
+ outroing.add(block);
+ outros.c.push(() => {
+ outroing.delete(block);
+ if (callback) {
+ if (detach)
+ block.d(1);
+ callback();
+ }
+ });
+ block.o(local);
+ }
+}
+
+function handle_promise(promise, info) {
+ const token = info.token = {};
+ function update(type, index, key, value) {
+ if (info.token !== token)
+ return;
+ info.resolved = value;
+ let child_ctx = info.ctx;
+ if (key !== undefined) {
+ child_ctx = child_ctx.slice();
+ child_ctx[key] = value;
+ }
+ const block = type && (info.current = type)(child_ctx);
+ let needs_flush = false;
+ if (info.block) {
+ if (info.blocks) {
+ info.blocks.forEach((block, i) => {
+ if (i !== index && block) {
+ group_outros();
+ transition_out(block, 1, 1, () => {
+ if (info.blocks[i] === block) {
+ info.blocks[i] = null;
+ }
+ });
+ check_outros();
+ }
+ });
+ }
+ else {
+ info.block.d(1);
+ }
+ block.c();
+ transition_in(block, 1);
+ block.m(info.mount(), info.anchor);
+ needs_flush = true;
+ }
+ info.block = block;
+ if (info.blocks)
+ info.blocks[index] = block;
+ if (needs_flush) {
+ flush();
+ }
+ }
+ if (is_promise(promise)) {
+ const current_component = get_current_component();
+ promise.then(value => {
+ set_current_component(current_component);
+ update(info.then, 1, info.value, value);
+ set_current_component(null);
+ }, error => {
+ set_current_component(current_component);
+ update(info.catch, 2, info.error, error);
+ set_current_component(null);
+ if (!info.hasCatch) {
+ throw error;
+ }
+ });
+ // if we previously had a then/catch block, destroy it
+ if (info.current !== info.pending) {
+ update(info.pending, 0);
+ return true;
+ }
+ }
+ else {
+ if (info.current !== info.then) {
+ update(info.then, 1, info.value, promise);
+ return true;
+ }
+ info.resolved = promise;
+ }
+}
+function outro_and_destroy_block(block, lookup) {
+ transition_out(block, 1, 1, () => {
+ lookup.delete(block.key);
+ });
+}
+function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {
+ let o = old_blocks.length;
+ let n = list.length;
+ let i = o;
+ const old_indexes = {};
+ while (i--)
+ old_indexes[old_blocks[i].key] = i;
+ const new_blocks = [];
+ const new_lookup = new Map();
+ const deltas = new Map();
+ i = n;
+ while (i--) {
+ const child_ctx = get_context(ctx, list, i);
+ const key = get_key(child_ctx);
+ let block = lookup.get(key);
+ if (!block) {
+ block = create_each_block(key, child_ctx);
+ block.c();
+ }
+ else if (dynamic) {
+ block.p(child_ctx, dirty);
+ }
+ new_lookup.set(key, new_blocks[i] = block);
+ if (key in old_indexes)
+ deltas.set(key, Math.abs(i - old_indexes[key]));
+ }
+ const will_move = new Set();
+ const did_move = new Set();
+ function insert(block) {
+ transition_in(block, 1);
+ block.m(node, next);
+ lookup.set(block.key, block);
+ next = block.first;
+ n--;
+ }
+ while (o && n) {
+ const new_block = new_blocks[n - 1];
+ const old_block = old_blocks[o - 1];
+ const new_key = new_block.key;
+ const old_key = old_block.key;
+ if (new_block === old_block) {
+ // do nothing
+ next = new_block.first;
+ o--;
+ n--;
+ }
+ else if (!new_lookup.has(old_key)) {
+ // remove old block
+ destroy(old_block, lookup);
+ o--;
+ }
+ else if (!lookup.has(new_key) || will_move.has(new_key)) {
+ insert(new_block);
+ }
+ else if (did_move.has(old_key)) {
+ o--;
+ }
+ else if (deltas.get(new_key) > deltas.get(old_key)) {
+ did_move.add(new_key);
+ insert(new_block);
+ }
+ else {
+ will_move.add(old_key);
+ o--;
+ }
+ }
+ while (o--) {
+ const old_block = old_blocks[o];
+ if (!new_lookup.has(old_block.key))
+ destroy(old_block, lookup);
+ }
+ while (n)
+ insert(new_blocks[n - 1]);
+ return new_blocks;
+}
+
+function get_spread_update(levels, updates) {
+ const update = {};
+ const to_null_out = {};
+ const accounted_for = { $$scope: 1 };
+ let i = levels.length;
+ while (i--) {
+ const o = levels[i];
+ const n = updates[i];
+ if (n) {
+ for (const key in o) {
+ if (!(key in n))
+ to_null_out[key] = 1;
+ }
+ for (const key in n) {
+ if (!accounted_for[key]) {
+ update[key] = n[key];
+ accounted_for[key] = 1;
+ }
+ }
+ levels[i] = n;
+ }
+ else {
+ for (const key in o) {
+ accounted_for[key] = 1;
+ }
+ }
+ }
+ for (const key in to_null_out) {
+ if (!(key in update))
+ update[key] = undefined;
+ }
+ return update;
+}
+function get_spread_object(spread_props) {
+ return typeof spread_props === 'object' && spread_props !== null ? spread_props : {};
+}
+function create_component(block) {
+ block && block.c();
+}
+function mount_component(component, target, anchor, customElement) {
+ const { fragment, on_mount, on_destroy, after_update } = component.$$;
+ fragment && fragment.m(target, anchor);
+ if (!customElement) {
+ // onMount happens before the initial afterUpdate
+ add_render_callback(() => {
+ const new_on_destroy = on_mount.map(run).filter(is_function);
+ if (on_destroy) {
+ on_destroy.push(...new_on_destroy);
+ }
+ else {
+ // Edge case - component was destroyed immediately,
+ // most likely as a result of a binding initialising
+ run_all(new_on_destroy);
+ }
+ component.$$.on_mount = [];
+ });
+ }
+ after_update.forEach(add_render_callback);
+}
+function destroy_component(component, detaching) {
+ const $$ = component.$$;
+ if ($$.fragment !== null) {
+ run_all($$.on_destroy);
+ $$.fragment && $$.fragment.d(detaching);
+ // TODO null out other refs, including component.$$ (but need to
+ // preserve final state?)
+ $$.on_destroy = $$.fragment = null;
+ $$.ctx = [];
+ }
+}
+function make_dirty(component, i) {
+ if (component.$$.dirty[0] === -1) {
+ dirty_components.push(component);
+ schedule_update();
+ component.$$.dirty.fill(0);
+ }
+ component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
+}
+function init(component, options, instance, create_fragment, not_equal, props, dirty = [-1]) {
+ const parent_component = current_component;
+ set_current_component(component);
+ const $$ = component.$$ = {
+ fragment: null,
+ ctx: null,
+ // state
+ props,
+ update: noop,
+ not_equal,
+ bound: blank_object(),
+ // lifecycle
+ on_mount: [],
+ on_destroy: [],
+ on_disconnect: [],
+ before_update: [],
+ after_update: [],
+ context: new Map(parent_component ? parent_component.$$.context : []),
+ // everything else
+ callbacks: blank_object(),
+ dirty,
+ skip_bound: false
+ };
+ let ready = false;
+ $$.ctx = instance
+ ? instance(component, options.props || {}, (i, ret, ...rest) => {
+ const value = rest.length ? rest[0] : ret;
+ if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
+ if (!$$.skip_bound && $$.bound[i])
+ $$.bound[i](value);
+ if (ready)
+ make_dirty(component, i);
+ }
+ return ret;
+ })
+ : [];
+ $$.update();
+ ready = true;
+ run_all($$.before_update);
+ // `false` as a special case of no DOM component
+ $$.fragment = create_fragment ? create_fragment($$.ctx) : false;
+ if (options.target) {
+ if (options.hydrate) {
+ const nodes = children(options.target);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ $$.fragment && $$.fragment.l(nodes);
+ nodes.forEach(detach);
+ }
+ else {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ $$.fragment && $$.fragment.c();
+ }
+ if (options.intro)
+ transition_in(component.$$.fragment);
+ mount_component(component, options.target, options.anchor, options.customElement);
+ flush();
+ }
+ set_current_component(parent_component);
+}
+/**
+ * Base class for Svelte components. Used when dev=false.
+ */
+class SvelteComponent {
+ $destroy() {
+ destroy_component(this, 1);
+ this.$destroy = noop;
+ }
+ $on(type, callback) {
+ const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
+ callbacks.push(callback);
+ return () => {
+ const index = callbacks.indexOf(callback);
+ if (index !== -1)
+ callbacks.splice(index, 1);
+ };
+ }
+ $set($$props) {
+ if (this.$$set && !is_empty($$props)) {
+ this.$$.skip_bound = true;
+ this.$$set($$props);
+ this.$$.skip_bound = false;
+ }
+ }
+}
+
+/**
+ * dateUID is a way of weekly identifying daily/weekly/monthly notes.
+ * They are prefixed with the granularity to avoid ambiguity.
+ */
+function getDateUID(date, granularity = "day") {
+ const ts = date.clone().startOf(granularity).format();
+ return `${granularity}-${ts}`;
+}
+var getDateUID_1 = getDateUID;
+
+/* src/components/Dot.svelte generated by Svelte v3.35.0 */
+
+function add_css$5() {
+ var style = element("style");
+ style.id = "svelte-1widvzq-style";
+ style.textContent = ".dot.svelte-1widvzq,.hollow.svelte-1widvzq{display:inline-block;height:6px;width:6px;margin:0 1px}.filled.svelte-1widvzq{fill:var(--color-dot)}.active.filled.svelte-1widvzq{fill:var(--text-on-accent)}.hollow.svelte-1widvzq{fill:none;stroke:var(--color-dot)}.active.hollow.svelte-1widvzq{fill:none;stroke:var(--text-on-accent)}";
+ append(document.head, style);
+}
+
+// (14:0) {:else}
+function create_else_block$1(ctx) {
+ let svg;
+ let circle;
+ let svg_class_value;
+
+ return {
+ c() {
+ svg = svg_element("svg");
+ circle = svg_element("circle");
+ attr(circle, "cx", "3");
+ attr(circle, "cy", "3");
+ attr(circle, "r", "2");
+ attr(svg, "class", svg_class_value = "" + (null_to_empty(`hollow ${/*className*/ ctx[0]}`) + " svelte-1widvzq"));
+ attr(svg, "viewBox", "0 0 6 6");
+ attr(svg, "xmlns", "http://www.w3.org/2000/svg");
+ toggle_class(svg, "active", /*isActive*/ ctx[2]);
+ },
+ m(target, anchor) {
+ insert(target, svg, anchor);
+ append(svg, circle);
+ },
+ p(ctx, dirty) {
+ if (dirty & /*className*/ 1 && svg_class_value !== (svg_class_value = "" + (null_to_empty(`hollow ${/*className*/ ctx[0]}`) + " svelte-1widvzq"))) {
+ attr(svg, "class", svg_class_value);
+ }
+
+ if (dirty & /*className, isActive*/ 5) {
+ toggle_class(svg, "active", /*isActive*/ ctx[2]);
+ }
+ },
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+// (6:0) {#if isFilled}
+function create_if_block$2(ctx) {
+ let svg;
+ let circle;
+ let svg_class_value;
+
+ return {
+ c() {
+ svg = svg_element("svg");
+ circle = svg_element("circle");
+ attr(circle, "cx", "3");
+ attr(circle, "cy", "3");
+ attr(circle, "r", "2");
+ attr(svg, "class", svg_class_value = "" + (null_to_empty(`dot filled ${/*className*/ ctx[0]}`) + " svelte-1widvzq"));
+ attr(svg, "viewBox", "0 0 6 6");
+ attr(svg, "xmlns", "http://www.w3.org/2000/svg");
+ toggle_class(svg, "active", /*isActive*/ ctx[2]);
+ },
+ m(target, anchor) {
+ insert(target, svg, anchor);
+ append(svg, circle);
+ },
+ p(ctx, dirty) {
+ if (dirty & /*className*/ 1 && svg_class_value !== (svg_class_value = "" + (null_to_empty(`dot filled ${/*className*/ ctx[0]}`) + " svelte-1widvzq"))) {
+ attr(svg, "class", svg_class_value);
+ }
+
+ if (dirty & /*className, isActive*/ 5) {
+ toggle_class(svg, "active", /*isActive*/ ctx[2]);
+ }
+ },
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+function create_fragment$6(ctx) {
+ let if_block_anchor;
+
+ function select_block_type(ctx, dirty) {
+ if (/*isFilled*/ ctx[1]) return create_if_block$2;
+ return create_else_block$1;
+ }
+
+ let current_block_type = select_block_type(ctx);
+ let if_block = current_block_type(ctx);
+
+ return {
+ c() {
+ if_block.c();
+ if_block_anchor = empty();
+ },
+ m(target, anchor) {
+ if_block.m(target, anchor);
+ insert(target, if_block_anchor, anchor);
+ },
+ p(ctx, [dirty]) {
+ if (current_block_type === (current_block_type = select_block_type(ctx)) && if_block) {
+ if_block.p(ctx, dirty);
+ } else {
+ if_block.d(1);
+ if_block = current_block_type(ctx);
+
+ if (if_block) {
+ if_block.c();
+ if_block.m(if_block_anchor.parentNode, if_block_anchor);
+ }
+ }
+ },
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if_block.d(detaching);
+ if (detaching) detach(if_block_anchor);
+ }
+ };
+}
+
+function instance$6($$self, $$props, $$invalidate) {
+ let { className = "" } = $$props;
+ let { isFilled } = $$props;
+ let { isActive } = $$props;
+
+ $$self.$$set = $$props => {
+ if ("className" in $$props) $$invalidate(0, className = $$props.className);
+ if ("isFilled" in $$props) $$invalidate(1, isFilled = $$props.isFilled);
+ if ("isActive" in $$props) $$invalidate(2, isActive = $$props.isActive);
+ };
+
+ return [className, isFilled, isActive];
+}
+
+class Dot extends SvelteComponent {
+ constructor(options) {
+ super();
+ if (!document.getElementById("svelte-1widvzq-style")) add_css$5();
+ init(this, options, instance$6, create_fragment$6, safe_not_equal, { className: 0, isFilled: 1, isActive: 2 });
+ }
+}
+
+/* src/components/MetadataResolver.svelte generated by Svelte v3.35.0 */
+
+const get_default_slot_changes_1 = dirty => ({});
+const get_default_slot_context_1 = ctx => ({ metadata: null });
+const get_default_slot_changes = dirty => ({ metadata: dirty & /*metadata*/ 1 });
+const get_default_slot_context = ctx => ({ metadata: /*resolvedMeta*/ ctx[3] });
+
+// (11:0) {:else}
+function create_else_block(ctx) {
+ let current;
+ const default_slot_template = /*#slots*/ ctx[2].default;
+ const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[1], get_default_slot_context_1);
+
+ return {
+ c() {
+ if (default_slot) default_slot.c();
+ },
+ m(target, anchor) {
+ if (default_slot) {
+ default_slot.m(target, anchor);
+ }
+
+ current = true;
+ },
+ p(ctx, dirty) {
+ if (default_slot) {
+ if (default_slot.p && dirty & /*$$scope*/ 2) {
+ update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[1], dirty, get_default_slot_changes_1, get_default_slot_context_1);
+ }
+ }
+ },
+ i(local) {
+ if (current) return;
+ transition_in(default_slot, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(default_slot, local);
+ current = false;
+ },
+ d(detaching) {
+ if (default_slot) default_slot.d(detaching);
+ }
+ };
+}
+
+// (7:0) {#if metadata}
+function create_if_block$1(ctx) {
+ let await_block_anchor;
+ let promise;
+ let current;
+
+ let info = {
+ ctx,
+ current: null,
+ token: null,
+ hasCatch: false,
+ pending: create_pending_block,
+ then: create_then_block,
+ catch: create_catch_block,
+ value: 3,
+ blocks: [,,,]
+ };
+
+ handle_promise(promise = /*metadata*/ ctx[0], info);
+
+ return {
+ c() {
+ await_block_anchor = empty();
+ info.block.c();
+ },
+ m(target, anchor) {
+ insert(target, await_block_anchor, anchor);
+ info.block.m(target, info.anchor = anchor);
+ info.mount = () => await_block_anchor.parentNode;
+ info.anchor = await_block_anchor;
+ current = true;
+ },
+ p(new_ctx, dirty) {
+ ctx = new_ctx;
+ info.ctx = ctx;
+
+ if (dirty & /*metadata*/ 1 && promise !== (promise = /*metadata*/ ctx[0]) && handle_promise(promise, info)) ; else {
+ const child_ctx = ctx.slice();
+ child_ctx[3] = info.resolved;
+ info.block.p(child_ctx, dirty);
+ }
+ },
+ i(local) {
+ if (current) return;
+ transition_in(info.block);
+ current = true;
+ },
+ o(local) {
+ for (let i = 0; i < 3; i += 1) {
+ const block = info.blocks[i];
+ transition_out(block);
+ }
+
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(await_block_anchor);
+ info.block.d(detaching);
+ info.token = null;
+ info = null;
+ }
+ };
+}
+
+// (1:0) {#if metadata}
+function create_catch_block(ctx) {
+ return {
+ c: noop,
+ m: noop,
+ p: noop,
+ i: noop,
+ o: noop,
+ d: noop
+ };
+}
+
+// (8:37) ; export let metadata; {#if metadata}
+function create_pending_block(ctx) {
+ return {
+ c: noop,
+ m: noop,
+ p: noop,
+ i: noop,
+ o: noop,
+ d: noop
+ };
+}
+
+function create_fragment$5(ctx) {
+ let current_block_type_index;
+ let if_block;
+ let if_block_anchor;
+ let current;
+ const if_block_creators = [create_if_block$1, create_else_block];
+ const if_blocks = [];
+
+ function select_block_type(ctx, dirty) {
+ if (/*metadata*/ ctx[0]) return 0;
+ return 1;
+ }
+
+ current_block_type_index = select_block_type(ctx);
+ if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
+
+ return {
+ c() {
+ if_block.c();
+ if_block_anchor = empty();
+ },
+ m(target, anchor) {
+ if_blocks[current_block_type_index].m(target, anchor);
+ insert(target, if_block_anchor, anchor);
+ current = true;
+ },
+ p(ctx, [dirty]) {
+ let previous_block_index = current_block_type_index;
+ current_block_type_index = select_block_type(ctx);
+
+ if (current_block_type_index === previous_block_index) {
+ if_blocks[current_block_type_index].p(ctx, dirty);
+ } else {
+ group_outros();
+
+ transition_out(if_blocks[previous_block_index], 1, 1, () => {
+ if_blocks[previous_block_index] = null;
+ });
+
+ check_outros();
+ if_block = if_blocks[current_block_type_index];
+
+ if (!if_block) {
+ if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
+ if_block.c();
+ } else {
+ if_block.p(ctx, dirty);
+ }
+
+ transition_in(if_block, 1);
+ if_block.m(if_block_anchor.parentNode, if_block_anchor);
+ }
+ },
+ i(local) {
+ if (current) return;
+ transition_in(if_block);
+ current = true;
+ },
+ o(local) {
+ transition_out(if_block);
+ current = false;
+ },
+ d(detaching) {
+ if_blocks[current_block_type_index].d(detaching);
+ if (detaching) detach(if_block_anchor);
+ }
+ };
+}
+
+function instance$5($$self, $$props, $$invalidate) {
+ let { $$slots: slots = {}, $$scope } = $$props;
+
+ let { metadata } = $$props;
+
+ $$self.$$set = $$props => {
+ if ("metadata" in $$props) $$invalidate(0, metadata = $$props.metadata);
+ if ("$$scope" in $$props) $$invalidate(1, $$scope = $$props.$$scope);
+ };
+
+ return [metadata, $$scope, slots];
+}
+
+class MetadataResolver extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, instance$5, create_fragment$5, not_equal, { metadata: 0 });
+ }
+}
+
+function isMacOS() {
+ return navigator.appVersion.indexOf("Mac") !== -1;
+}
+function isMetaPressed(e) {
+ return isMacOS() ? e.metaKey : e.ctrlKey;
+}
+function getDaysOfWeek(..._args) {
+ return window.moment.weekdaysShort(true);
+}
+function isWeekend(date) {
+ return date.isoWeekday() === 6 || date.isoWeekday() === 7;
+}
+function getStartOfWeek(days) {
+ return days[0].weekday(0);
+}
+/**
+ * Generate a 2D array of daily information to power
+ * the calendar view.
+ */
+function getMonth(displayedMonth, ..._args) {
+ const locale = window.moment().locale();
+ const month = [];
+ let week;
+ const startOfMonth = displayedMonth.clone().locale(locale).date(1);
+ const startOffset = startOfMonth.weekday();
+ let date = startOfMonth.clone().subtract(startOffset, "days");
+ for (let _day = 0; _day < 42; _day++) {
+ if (_day % 7 === 0) {
+ week = {
+ days: [],
+ weekNum: date.week(),
+ };
+ month.push(week);
+ }
+ week.days.push(date);
+ date = date.clone().add(1, "days");
+ }
+ return month;
+}
+
+/* src/components/Day.svelte generated by Svelte v3.35.0 */
+
+function add_css$4() {
+ var style = element("style");
+ style.id = "svelte-q3wqg9-style";
+ style.textContent = ".day.svelte-q3wqg9{background-color:var(--color-background-day);border-radius:4px;color:var(--color-text-day);cursor:pointer;font-size:0.8em;height:100%;padding:4px;position:relative;text-align:center;transition:background-color 0.1s ease-in, color 0.1s ease-in;vertical-align:baseline}.day.svelte-q3wqg9:hover{background-color:var(--interactive-hover)}.day.active.svelte-q3wqg9:hover{background-color:var(--interactive-accent-hover)}.adjacent-month.svelte-q3wqg9{opacity:0.25}.today.svelte-q3wqg9{color:var(--color-text-today)}.day.svelte-q3wqg9:active,.active.svelte-q3wqg9,.active.today.svelte-q3wqg9{color:var(--text-on-accent);background-color:var(--interactive-accent)}.dot-container.svelte-q3wqg9{display:flex;flex-wrap:wrap;justify-content:center;line-height:6px;min-height:6px}";
+ append(document.head, style);
+}
+
+function get_each_context$2(ctx, list, i) {
+ const child_ctx = ctx.slice();
+ child_ctx[11] = list[i];
+ return child_ctx;
+}
+
+// (36:8) {#each metadata.dots as dot}
+function create_each_block$2(ctx) {
+ let dot;
+ let current;
+ const dot_spread_levels = [/*dot*/ ctx[11]];
+ let dot_props = {};
+
+ for (let i = 0; i < dot_spread_levels.length; i += 1) {
+ dot_props = assign(dot_props, dot_spread_levels[i]);
+ }
+
+ dot = new Dot({ props: dot_props });
+
+ return {
+ c() {
+ create_component(dot.$$.fragment);
+ },
+ m(target, anchor) {
+ mount_component(dot, target, anchor);
+ current = true;
+ },
+ p(ctx, dirty) {
+ const dot_changes = (dirty & /*metadata*/ 128)
+ ? get_spread_update(dot_spread_levels, [get_spread_object(/*dot*/ ctx[11])])
+ : {};
+
+ dot.$set(dot_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(dot.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(dot.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ destroy_component(dot, detaching);
+ }
+ };
+}
+
+// (22:2)
+function create_default_slot$1(ctx) {
+ let div1;
+ let t0_value = /*date*/ ctx[0].format("D") + "";
+ let t0;
+ let t1;
+ let div0;
+ let div1_class_value;
+ let current;
+ let mounted;
+ let dispose;
+ let each_value = /*metadata*/ ctx[7].dots;
+ let each_blocks = [];
+
+ for (let i = 0; i < each_value.length; i += 1) {
+ each_blocks[i] = create_each_block$2(get_each_context$2(ctx, each_value, i));
+ }
+
+ const out = i => transition_out(each_blocks[i], 1, 1, () => {
+ each_blocks[i] = null;
+ });
+
+ let div1_levels = [
+ {
+ class: div1_class_value = `day ${/*metadata*/ ctx[7].classes.join(" ")}`
+ },
+ /*metadata*/ ctx[7].dataAttributes || {}
+ ];
+
+ let div1_data = {};
+
+ for (let i = 0; i < div1_levels.length; i += 1) {
+ div1_data = assign(div1_data, div1_levels[i]);
+ }
+
+ return {
+ c() {
+ div1 = element("div");
+ t0 = text(t0_value);
+ t1 = space();
+ div0 = element("div");
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].c();
+ }
+
+ attr(div0, "class", "dot-container svelte-q3wqg9");
+ set_attributes(div1, div1_data);
+ toggle_class(div1, "active", /*selectedId*/ ctx[6] === getDateUID_1(/*date*/ ctx[0], "day"));
+ toggle_class(div1, "adjacent-month", !/*date*/ ctx[0].isSame(/*displayedMonth*/ ctx[5], "month"));
+ toggle_class(div1, "today", /*date*/ ctx[0].isSame(/*today*/ ctx[4], "day"));
+ toggle_class(div1, "svelte-q3wqg9", true);
+ },
+ m(target, anchor) {
+ insert(target, div1, anchor);
+ append(div1, t0);
+ append(div1, t1);
+ append(div1, div0);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].m(div0, null);
+ }
+
+ current = true;
+
+ if (!mounted) {
+ dispose = [
+ listen(div1, "click", function () {
+ if (is_function(/*onClick*/ ctx[2] && /*click_handler*/ ctx[8])) (/*onClick*/ ctx[2] && /*click_handler*/ ctx[8]).apply(this, arguments);
+ }),
+ listen(div1, "contextmenu", function () {
+ if (is_function(/*onContextMenu*/ ctx[3] && /*contextmenu_handler*/ ctx[9])) (/*onContextMenu*/ ctx[3] && /*contextmenu_handler*/ ctx[9]).apply(this, arguments);
+ }),
+ listen(div1, "pointerover", function () {
+ if (is_function(/*onHover*/ ctx[1] && /*pointerover_handler*/ ctx[10])) (/*onHover*/ ctx[1] && /*pointerover_handler*/ ctx[10]).apply(this, arguments);
+ })
+ ];
+
+ mounted = true;
+ }
+ },
+ p(new_ctx, dirty) {
+ ctx = new_ctx;
+ if ((!current || dirty & /*date*/ 1) && t0_value !== (t0_value = /*date*/ ctx[0].format("D") + "")) set_data(t0, t0_value);
+
+ if (dirty & /*metadata*/ 128) {
+ each_value = /*metadata*/ ctx[7].dots;
+ let i;
+
+ for (i = 0; i < each_value.length; i += 1) {
+ const child_ctx = get_each_context$2(ctx, each_value, i);
+
+ if (each_blocks[i]) {
+ each_blocks[i].p(child_ctx, dirty);
+ transition_in(each_blocks[i], 1);
+ } else {
+ each_blocks[i] = create_each_block$2(child_ctx);
+ each_blocks[i].c();
+ transition_in(each_blocks[i], 1);
+ each_blocks[i].m(div0, null);
+ }
+ }
+
+ group_outros();
+
+ for (i = each_value.length; i < each_blocks.length; i += 1) {
+ out(i);
+ }
+
+ check_outros();
+ }
+
+ set_attributes(div1, div1_data = get_spread_update(div1_levels, [
+ (!current || dirty & /*metadata*/ 128 && div1_class_value !== (div1_class_value = `day ${/*metadata*/ ctx[7].classes.join(" ")}`)) && { class: div1_class_value },
+ dirty & /*metadata*/ 128 && (/*metadata*/ ctx[7].dataAttributes || {})
+ ]));
+
+ toggle_class(div1, "active", /*selectedId*/ ctx[6] === getDateUID_1(/*date*/ ctx[0], "day"));
+ toggle_class(div1, "adjacent-month", !/*date*/ ctx[0].isSame(/*displayedMonth*/ ctx[5], "month"));
+ toggle_class(div1, "today", /*date*/ ctx[0].isSame(/*today*/ ctx[4], "day"));
+ toggle_class(div1, "svelte-q3wqg9", true);
+ },
+ i(local) {
+ if (current) return;
+
+ for (let i = 0; i < each_value.length; i += 1) {
+ transition_in(each_blocks[i]);
+ }
+
+ current = true;
+ },
+ o(local) {
+ each_blocks = each_blocks.filter(Boolean);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ transition_out(each_blocks[i]);
+ }
+
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(div1);
+ destroy_each(each_blocks, detaching);
+ mounted = false;
+ run_all(dispose);
+ }
+ };
+}
+
+function create_fragment$4(ctx) {
+ let td;
+ let metadataresolver;
+ let current;
+
+ metadataresolver = new MetadataResolver({
+ props: {
+ metadata: /*metadata*/ ctx[7],
+ $$slots: {
+ default: [
+ create_default_slot$1,
+ ({ metadata }) => ({ 7: metadata }),
+ ({ metadata }) => metadata ? 128 : 0
+ ]
+ },
+ $$scope: { ctx }
+ }
+ });
+
+ return {
+ c() {
+ td = element("td");
+ create_component(metadataresolver.$$.fragment);
+ },
+ m(target, anchor) {
+ insert(target, td, anchor);
+ mount_component(metadataresolver, td, null);
+ current = true;
+ },
+ p(ctx, [dirty]) {
+ const metadataresolver_changes = {};
+ if (dirty & /*metadata*/ 128) metadataresolver_changes.metadata = /*metadata*/ ctx[7];
+
+ if (dirty & /*$$scope, metadata, selectedId, date, displayedMonth, today, onClick, onContextMenu, onHover*/ 16639) {
+ metadataresolver_changes.$$scope = { dirty, ctx };
+ }
+
+ metadataresolver.$set(metadataresolver_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(metadataresolver.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(metadataresolver.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(td);
+ destroy_component(metadataresolver);
+ }
+ };
+}
+
+function instance$4($$self, $$props, $$invalidate) {
+
+
+ let { date } = $$props;
+ let { metadata } = $$props;
+ let { onHover } = $$props;
+ let { onClick } = $$props;
+ let { onContextMenu } = $$props;
+ let { today } = $$props;
+ let { displayedMonth = null } = $$props;
+ let { selectedId = null } = $$props;
+ const click_handler = e => onClick(date, isMetaPressed(e));
+ const contextmenu_handler = e => onContextMenu(date, e);
+ const pointerover_handler = e => onHover(date, e.target, isMetaPressed(e));
+
+ $$self.$$set = $$props => {
+ if ("date" in $$props) $$invalidate(0, date = $$props.date);
+ if ("metadata" in $$props) $$invalidate(7, metadata = $$props.metadata);
+ if ("onHover" in $$props) $$invalidate(1, onHover = $$props.onHover);
+ if ("onClick" in $$props) $$invalidate(2, onClick = $$props.onClick);
+ if ("onContextMenu" in $$props) $$invalidate(3, onContextMenu = $$props.onContextMenu);
+ if ("today" in $$props) $$invalidate(4, today = $$props.today);
+ if ("displayedMonth" in $$props) $$invalidate(5, displayedMonth = $$props.displayedMonth);
+ if ("selectedId" in $$props) $$invalidate(6, selectedId = $$props.selectedId);
+ };
+
+ return [
+ date,
+ onHover,
+ onClick,
+ onContextMenu,
+ today,
+ displayedMonth,
+ selectedId,
+ metadata,
+ click_handler,
+ contextmenu_handler,
+ pointerover_handler
+ ];
+}
+
+class Day extends SvelteComponent {
+ constructor(options) {
+ super();
+ if (!document.getElementById("svelte-q3wqg9-style")) add_css$4();
+
+ init(this, options, instance$4, create_fragment$4, not_equal, {
+ date: 0,
+ metadata: 7,
+ onHover: 1,
+ onClick: 2,
+ onContextMenu: 3,
+ today: 4,
+ displayedMonth: 5,
+ selectedId: 6
+ });
+ }
+}
+
+/* src/components/Arrow.svelte generated by Svelte v3.35.0 */
+
+function add_css$3() {
+ var style = element("style");
+ style.id = "svelte-156w7na-style";
+ style.textContent = ".arrow.svelte-156w7na.svelte-156w7na{align-items:center;cursor:pointer;display:flex;justify-content:center;width:24px}.arrow.is-mobile.svelte-156w7na.svelte-156w7na{width:32px}.right.svelte-156w7na.svelte-156w7na{transform:rotate(180deg)}.arrow.svelte-156w7na svg.svelte-156w7na{color:var(--color-arrow);height:16px;width:16px}";
+ append(document.head, style);
+}
+
+function create_fragment$3(ctx) {
+ let div;
+ let svg;
+ let path;
+ let mounted;
+ let dispose;
+
+ return {
+ c() {
+ div = element("div");
+ svg = svg_element("svg");
+ path = svg_element("path");
+ attr(path, "fill", "currentColor");
+ attr(path, "d", "M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z");
+ attr(svg, "focusable", "false");
+ attr(svg, "role", "img");
+ attr(svg, "xmlns", "http://www.w3.org/2000/svg");
+ attr(svg, "viewBox", "0 0 320 512");
+ attr(svg, "class", "svelte-156w7na");
+ attr(div, "class", "arrow svelte-156w7na");
+ attr(div, "aria-label", /*tooltip*/ ctx[1]);
+ toggle_class(div, "is-mobile", /*isMobile*/ ctx[3]);
+ toggle_class(div, "right", /*direction*/ ctx[2] === "right");
+ },
+ m(target, anchor) {
+ insert(target, div, anchor);
+ append(div, svg);
+ append(svg, path);
+
+ if (!mounted) {
+ dispose = listen(div, "click", function () {
+ if (is_function(/*onClick*/ ctx[0])) /*onClick*/ ctx[0].apply(this, arguments);
+ });
+
+ mounted = true;
+ }
+ },
+ p(new_ctx, [dirty]) {
+ ctx = new_ctx;
+
+ if (dirty & /*tooltip*/ 2) {
+ attr(div, "aria-label", /*tooltip*/ ctx[1]);
+ }
+
+ if (dirty & /*direction*/ 4) {
+ toggle_class(div, "right", /*direction*/ ctx[2] === "right");
+ }
+ },
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if (detaching) detach(div);
+ mounted = false;
+ dispose();
+ }
+ };
+}
+
+function instance$3($$self, $$props, $$invalidate) {
+ let { onClick } = $$props;
+ let { tooltip } = $$props;
+ let { direction } = $$props;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let isMobile = window.app.isMobile;
+
+ $$self.$$set = $$props => {
+ if ("onClick" in $$props) $$invalidate(0, onClick = $$props.onClick);
+ if ("tooltip" in $$props) $$invalidate(1, tooltip = $$props.tooltip);
+ if ("direction" in $$props) $$invalidate(2, direction = $$props.direction);
+ };
+
+ return [onClick, tooltip, direction, isMobile];
+}
+
+class Arrow extends SvelteComponent {
+ constructor(options) {
+ super();
+ if (!document.getElementById("svelte-156w7na-style")) add_css$3();
+ init(this, options, instance$3, create_fragment$3, safe_not_equal, { onClick: 0, tooltip: 1, direction: 2 });
+ }
+}
+
+/* src/components/Nav.svelte generated by Svelte v3.35.0 */
+
+function add_css$2() {
+ var style = element("style");
+ style.id = "svelte-1vwr9dd-style";
+ style.textContent = ".nav.svelte-1vwr9dd.svelte-1vwr9dd{align-items:center;display:flex;margin:0.6em 0 1em;padding:0 8px;width:100%}.nav.is-mobile.svelte-1vwr9dd.svelte-1vwr9dd{padding:0}.title.svelte-1vwr9dd.svelte-1vwr9dd{color:var(--color-text-title);font-size:1.5em;margin:0}.is-mobile.svelte-1vwr9dd .title.svelte-1vwr9dd{font-size:1.3em}.month.svelte-1vwr9dd.svelte-1vwr9dd{font-weight:500;text-transform:capitalize}.year.svelte-1vwr9dd.svelte-1vwr9dd{color:var(--interactive-accent)}.right-nav.svelte-1vwr9dd.svelte-1vwr9dd{display:flex;justify-content:center;margin-left:auto}.reset-button.svelte-1vwr9dd.svelte-1vwr9dd{cursor:pointer;border-radius:4px;color:var(--text-muted);font-size:0.7em;font-weight:600;letter-spacing:1px;margin:0 4px;padding:0px 4px;text-transform:uppercase}.is-mobile.svelte-1vwr9dd .reset-button.svelte-1vwr9dd{display:none}";
+ append(document.head, style);
+}
+
+function create_fragment$2(ctx) {
+ let div2;
+ let h3;
+ let span0;
+ let t0_value = /*displayedMonth*/ ctx[0].format("MMM") + "";
+ let t0;
+ let t1;
+ let span1;
+ let t2_value = /*displayedMonth*/ ctx[0].format("YYYY") + "";
+ let t2;
+ let t3;
+ let div1;
+ let arrow0;
+ let t4;
+ let div0;
+ let t6;
+ let arrow1;
+ let current;
+ let mounted;
+ let dispose;
+
+ arrow0 = new Arrow({
+ props: {
+ direction: "left",
+ onClick: /*decrementDisplayedMonth*/ ctx[3],
+ tooltip: "Previous Month"
+ }
+ });
+
+ arrow1 = new Arrow({
+ props: {
+ direction: "right",
+ onClick: /*incrementDisplayedMonth*/ ctx[2],
+ tooltip: "Next Month"
+ }
+ });
+
+ return {
+ c() {
+ div2 = element("div");
+ h3 = element("h3");
+ span0 = element("span");
+ t0 = text(t0_value);
+ t1 = space();
+ span1 = element("span");
+ t2 = text(t2_value);
+ t3 = space();
+ div1 = element("div");
+ create_component(arrow0.$$.fragment);
+ t4 = space();
+ div0 = element("div");
+ div0.textContent = `${/*todayDisplayStr*/ ctx[4]}`;
+ t6 = space();
+ create_component(arrow1.$$.fragment);
+ attr(span0, "class", "month svelte-1vwr9dd");
+ attr(span1, "class", "year svelte-1vwr9dd");
+ attr(h3, "class", "title svelte-1vwr9dd");
+ attr(div0, "class", "reset-button svelte-1vwr9dd");
+ attr(div1, "class", "right-nav svelte-1vwr9dd");
+ attr(div2, "class", "nav svelte-1vwr9dd");
+ toggle_class(div2, "is-mobile", /*isMobile*/ ctx[5]);
+ },
+ m(target, anchor) {
+ insert(target, div2, anchor);
+ append(div2, h3);
+ append(h3, span0);
+ append(span0, t0);
+ append(h3, t1);
+ append(h3, span1);
+ append(span1, t2);
+ append(div2, t3);
+ append(div2, div1);
+ mount_component(arrow0, div1, null);
+ append(div1, t4);
+ append(div1, div0);
+ append(div1, t6);
+ mount_component(arrow1, div1, null);
+ current = true;
+
+ if (!mounted) {
+ dispose = [
+ listen(h3, "click", function () {
+ if (is_function(/*resetDisplayedMonth*/ ctx[1])) /*resetDisplayedMonth*/ ctx[1].apply(this, arguments);
+ }),
+ listen(div0, "click", function () {
+ if (is_function(/*resetDisplayedMonth*/ ctx[1])) /*resetDisplayedMonth*/ ctx[1].apply(this, arguments);
+ })
+ ];
+
+ mounted = true;
+ }
+ },
+ p(new_ctx, [dirty]) {
+ ctx = new_ctx;
+ if ((!current || dirty & /*displayedMonth*/ 1) && t0_value !== (t0_value = /*displayedMonth*/ ctx[0].format("MMM") + "")) set_data(t0, t0_value);
+ if ((!current || dirty & /*displayedMonth*/ 1) && t2_value !== (t2_value = /*displayedMonth*/ ctx[0].format("YYYY") + "")) set_data(t2, t2_value);
+ const arrow0_changes = {};
+ if (dirty & /*decrementDisplayedMonth*/ 8) arrow0_changes.onClick = /*decrementDisplayedMonth*/ ctx[3];
+ arrow0.$set(arrow0_changes);
+ const arrow1_changes = {};
+ if (dirty & /*incrementDisplayedMonth*/ 4) arrow1_changes.onClick = /*incrementDisplayedMonth*/ ctx[2];
+ arrow1.$set(arrow1_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(arrow0.$$.fragment, local);
+ transition_in(arrow1.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(arrow0.$$.fragment, local);
+ transition_out(arrow1.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(div2);
+ destroy_component(arrow0);
+ destroy_component(arrow1);
+ mounted = false;
+ run_all(dispose);
+ }
+ };
+}
+
+function instance$2($$self, $$props, $$invalidate) {
+
+ let { displayedMonth } = $$props;
+ let { today } = $$props;
+ let { resetDisplayedMonth } = $$props;
+ let { incrementDisplayedMonth } = $$props;
+ let { decrementDisplayedMonth } = $$props;
+
+ // Get the word 'Today' but localized to the current language
+ const todayDisplayStr = today.calendar().split(/\d|\s/)[0];
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let isMobile = window.app.isMobile;
+
+ $$self.$$set = $$props => {
+ if ("displayedMonth" in $$props) $$invalidate(0, displayedMonth = $$props.displayedMonth);
+ if ("today" in $$props) $$invalidate(6, today = $$props.today);
+ if ("resetDisplayedMonth" in $$props) $$invalidate(1, resetDisplayedMonth = $$props.resetDisplayedMonth);
+ if ("incrementDisplayedMonth" in $$props) $$invalidate(2, incrementDisplayedMonth = $$props.incrementDisplayedMonth);
+ if ("decrementDisplayedMonth" in $$props) $$invalidate(3, decrementDisplayedMonth = $$props.decrementDisplayedMonth);
+ };
+
+ return [
+ displayedMonth,
+ resetDisplayedMonth,
+ incrementDisplayedMonth,
+ decrementDisplayedMonth,
+ todayDisplayStr,
+ isMobile,
+ today
+ ];
+}
+
+class Nav extends SvelteComponent {
+ constructor(options) {
+ super();
+ if (!document.getElementById("svelte-1vwr9dd-style")) add_css$2();
+
+ init(this, options, instance$2, create_fragment$2, safe_not_equal, {
+ displayedMonth: 0,
+ today: 6,
+ resetDisplayedMonth: 1,
+ incrementDisplayedMonth: 2,
+ decrementDisplayedMonth: 3
+ });
+ }
+}
+
+/* src/components/WeekNum.svelte generated by Svelte v3.35.0 */
+
+function add_css$1() {
+ var style = element("style");
+ style.id = "svelte-egt0yd-style";
+ style.textContent = "td.svelte-egt0yd{border-right:1px solid var(--background-modifier-border)}.week-num.svelte-egt0yd{background-color:var(--color-background-weeknum);border-radius:4px;color:var(--color-text-weeknum);cursor:pointer;font-size:0.65em;height:100%;padding:4px;text-align:center;transition:background-color 0.1s ease-in, color 0.1s ease-in;vertical-align:baseline}.week-num.svelte-egt0yd:hover{background-color:var(--interactive-hover)}.week-num.active.svelte-egt0yd:hover{background-color:var(--interactive-accent-hover)}.active.svelte-egt0yd{color:var(--text-on-accent);background-color:var(--interactive-accent)}.dot-container.svelte-egt0yd{display:flex;flex-wrap:wrap;justify-content:center;line-height:6px;min-height:6px}";
+ append(document.head, style);
+}
+
+function get_each_context$1(ctx, list, i) {
+ const child_ctx = ctx.slice();
+ child_ctx[11] = list[i];
+ return child_ctx;
+}
+
+// (35:8) {#each metadata.dots as dot}
+function create_each_block$1(ctx) {
+ let dot;
+ let current;
+ const dot_spread_levels = [/*dot*/ ctx[11]];
+ let dot_props = {};
+
+ for (let i = 0; i < dot_spread_levels.length; i += 1) {
+ dot_props = assign(dot_props, dot_spread_levels[i]);
+ }
+
+ dot = new Dot({ props: dot_props });
+
+ return {
+ c() {
+ create_component(dot.$$.fragment);
+ },
+ m(target, anchor) {
+ mount_component(dot, target, anchor);
+ current = true;
+ },
+ p(ctx, dirty) {
+ const dot_changes = (dirty & /*metadata*/ 64)
+ ? get_spread_update(dot_spread_levels, [get_spread_object(/*dot*/ ctx[11])])
+ : {};
+
+ dot.$set(dot_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(dot.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(dot.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ destroy_component(dot, detaching);
+ }
+ };
+}
+
+// (24:2)
+function create_default_slot(ctx) {
+ let div1;
+ let t0;
+ let t1;
+ let div0;
+ let div1_class_value;
+ let current;
+ let mounted;
+ let dispose;
+ let each_value = /*metadata*/ ctx[6].dots;
+ let each_blocks = [];
+
+ for (let i = 0; i < each_value.length; i += 1) {
+ each_blocks[i] = create_each_block$1(get_each_context$1(ctx, each_value, i));
+ }
+
+ const out = i => transition_out(each_blocks[i], 1, 1, () => {
+ each_blocks[i] = null;
+ });
+
+ return {
+ c() {
+ div1 = element("div");
+ t0 = text(/*weekNum*/ ctx[0]);
+ t1 = space();
+ div0 = element("div");
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].c();
+ }
+
+ attr(div0, "class", "dot-container svelte-egt0yd");
+ attr(div1, "class", div1_class_value = "" + (null_to_empty(`week-num ${/*metadata*/ ctx[6].classes.join(" ")}`) + " svelte-egt0yd"));
+ toggle_class(div1, "active", /*selectedId*/ ctx[5] === getDateUID_1(/*days*/ ctx[1][0], "week"));
+ },
+ m(target, anchor) {
+ insert(target, div1, anchor);
+ append(div1, t0);
+ append(div1, t1);
+ append(div1, div0);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].m(div0, null);
+ }
+
+ current = true;
+
+ if (!mounted) {
+ dispose = [
+ listen(div1, "click", function () {
+ if (is_function(/*onClick*/ ctx[3] && /*click_handler*/ ctx[8])) (/*onClick*/ ctx[3] && /*click_handler*/ ctx[8]).apply(this, arguments);
+ }),
+ listen(div1, "contextmenu", function () {
+ if (is_function(/*onContextMenu*/ ctx[4] && /*contextmenu_handler*/ ctx[9])) (/*onContextMenu*/ ctx[4] && /*contextmenu_handler*/ ctx[9]).apply(this, arguments);
+ }),
+ listen(div1, "pointerover", function () {
+ if (is_function(/*onHover*/ ctx[2] && /*pointerover_handler*/ ctx[10])) (/*onHover*/ ctx[2] && /*pointerover_handler*/ ctx[10]).apply(this, arguments);
+ })
+ ];
+
+ mounted = true;
+ }
+ },
+ p(new_ctx, dirty) {
+ ctx = new_ctx;
+ if (!current || dirty & /*weekNum*/ 1) set_data(t0, /*weekNum*/ ctx[0]);
+
+ if (dirty & /*metadata*/ 64) {
+ each_value = /*metadata*/ ctx[6].dots;
+ let i;
+
+ for (i = 0; i < each_value.length; i += 1) {
+ const child_ctx = get_each_context$1(ctx, each_value, i);
+
+ if (each_blocks[i]) {
+ each_blocks[i].p(child_ctx, dirty);
+ transition_in(each_blocks[i], 1);
+ } else {
+ each_blocks[i] = create_each_block$1(child_ctx);
+ each_blocks[i].c();
+ transition_in(each_blocks[i], 1);
+ each_blocks[i].m(div0, null);
+ }
+ }
+
+ group_outros();
+
+ for (i = each_value.length; i < each_blocks.length; i += 1) {
+ out(i);
+ }
+
+ check_outros();
+ }
+
+ if (!current || dirty & /*metadata*/ 64 && div1_class_value !== (div1_class_value = "" + (null_to_empty(`week-num ${/*metadata*/ ctx[6].classes.join(" ")}`) + " svelte-egt0yd"))) {
+ attr(div1, "class", div1_class_value);
+ }
+
+ if (dirty & /*metadata, selectedId, getDateUID, days*/ 98) {
+ toggle_class(div1, "active", /*selectedId*/ ctx[5] === getDateUID_1(/*days*/ ctx[1][0], "week"));
+ }
+ },
+ i(local) {
+ if (current) return;
+
+ for (let i = 0; i < each_value.length; i += 1) {
+ transition_in(each_blocks[i]);
+ }
+
+ current = true;
+ },
+ o(local) {
+ each_blocks = each_blocks.filter(Boolean);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ transition_out(each_blocks[i]);
+ }
+
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(div1);
+ destroy_each(each_blocks, detaching);
+ mounted = false;
+ run_all(dispose);
+ }
+ };
+}
+
+function create_fragment$1(ctx) {
+ let td;
+ let metadataresolver;
+ let current;
+
+ metadataresolver = new MetadataResolver({
+ props: {
+ metadata: /*metadata*/ ctx[6],
+ $$slots: {
+ default: [
+ create_default_slot,
+ ({ metadata }) => ({ 6: metadata }),
+ ({ metadata }) => metadata ? 64 : 0
+ ]
+ },
+ $$scope: { ctx }
+ }
+ });
+
+ return {
+ c() {
+ td = element("td");
+ create_component(metadataresolver.$$.fragment);
+ attr(td, "class", "svelte-egt0yd");
+ },
+ m(target, anchor) {
+ insert(target, td, anchor);
+ mount_component(metadataresolver, td, null);
+ current = true;
+ },
+ p(ctx, [dirty]) {
+ const metadataresolver_changes = {};
+ if (dirty & /*metadata*/ 64) metadataresolver_changes.metadata = /*metadata*/ ctx[6];
+
+ if (dirty & /*$$scope, metadata, selectedId, days, onClick, startOfWeek, onContextMenu, onHover, weekNum*/ 16639) {
+ metadataresolver_changes.$$scope = { dirty, ctx };
+ }
+
+ metadataresolver.$set(metadataresolver_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(metadataresolver.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(metadataresolver.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(td);
+ destroy_component(metadataresolver);
+ }
+ };
+}
+
+function instance$1($$self, $$props, $$invalidate) {
+
+
+ let { weekNum } = $$props;
+ let { days } = $$props;
+ let { metadata } = $$props;
+ let { onHover } = $$props;
+ let { onClick } = $$props;
+ let { onContextMenu } = $$props;
+ let { selectedId = null } = $$props;
+ let startOfWeek;
+ const click_handler = e => onClick(startOfWeek, isMetaPressed(e));
+ const contextmenu_handler = e => onContextMenu(days[0], e);
+ const pointerover_handler = e => onHover(startOfWeek, e.target, isMetaPressed(e));
+
+ $$self.$$set = $$props => {
+ if ("weekNum" in $$props) $$invalidate(0, weekNum = $$props.weekNum);
+ if ("days" in $$props) $$invalidate(1, days = $$props.days);
+ if ("metadata" in $$props) $$invalidate(6, metadata = $$props.metadata);
+ if ("onHover" in $$props) $$invalidate(2, onHover = $$props.onHover);
+ if ("onClick" in $$props) $$invalidate(3, onClick = $$props.onClick);
+ if ("onContextMenu" in $$props) $$invalidate(4, onContextMenu = $$props.onContextMenu);
+ if ("selectedId" in $$props) $$invalidate(5, selectedId = $$props.selectedId);
+ };
+
+ $$self.$$.update = () => {
+ if ($$self.$$.dirty & /*days*/ 2) {
+ $$invalidate(7, startOfWeek = getStartOfWeek(days));
+ }
+ };
+
+ return [
+ weekNum,
+ days,
+ onHover,
+ onClick,
+ onContextMenu,
+ selectedId,
+ metadata,
+ startOfWeek,
+ click_handler,
+ contextmenu_handler,
+ pointerover_handler
+ ];
+}
+
+class WeekNum extends SvelteComponent {
+ constructor(options) {
+ super();
+ if (!document.getElementById("svelte-egt0yd-style")) add_css$1();
+
+ init(this, options, instance$1, create_fragment$1, not_equal, {
+ weekNum: 0,
+ days: 1,
+ metadata: 6,
+ onHover: 2,
+ onClick: 3,
+ onContextMenu: 4,
+ selectedId: 5
+ });
+ }
+}
+
+async function metadataReducer(promisedMetadata) {
+ const meta = {
+ dots: [],
+ classes: [],
+ dataAttributes: {},
+ };
+ const metas = await Promise.all(promisedMetadata);
+ return metas.reduce((acc, meta) => ({
+ classes: [...acc.classes, ...(meta.classes || [])],
+ dataAttributes: Object.assign(acc.dataAttributes, meta.dataAttributes),
+ dots: [...acc.dots, ...(meta.dots || [])],
+ }), meta);
+}
+function getDailyMetadata(sources, date, ..._args) {
+ return metadataReducer(sources.map((source) => source.getDailyMetadata(date)));
+}
+function getWeeklyMetadata(sources, date, ..._args) {
+ return metadataReducer(sources.map((source) => source.getWeeklyMetadata(date)));
+}
+
+/* src/components/Calendar.svelte generated by Svelte v3.35.0 */
+
+function add_css() {
+ var style = element("style");
+ style.id = "svelte-pcimu8-style";
+ style.textContent = ".container.svelte-pcimu8{--color-background-heading:transparent;--color-background-day:transparent;--color-background-weeknum:transparent;--color-background-weekend:transparent;--color-dot:var(--text-muted);--color-arrow:var(--text-muted);--color-button:var(--text-muted);--color-text-title:var(--text-normal);--color-text-heading:var(--text-muted);--color-text-day:var(--text-normal);--color-text-today:var(--interactive-accent);--color-text-weeknum:var(--text-muted)}.container.svelte-pcimu8{padding:0 8px}.container.is-mobile.svelte-pcimu8{padding:0}th.svelte-pcimu8{text-align:center}.weekend.svelte-pcimu8{background-color:var(--color-background-weekend)}.calendar.svelte-pcimu8{border-collapse:collapse;width:100%}th.svelte-pcimu8{background-color:var(--color-background-heading);color:var(--color-text-heading);font-size:0.6em;letter-spacing:1px;padding:4px;text-transform:uppercase}";
+ append(document.head, style);
+}
+
+function get_each_context(ctx, list, i) {
+ const child_ctx = ctx.slice();
+ child_ctx[18] = list[i];
+ return child_ctx;
+}
+
+function get_each_context_1(ctx, list, i) {
+ const child_ctx = ctx.slice();
+ child_ctx[21] = list[i];
+ return child_ctx;
+}
+
+function get_each_context_2(ctx, list, i) {
+ const child_ctx = ctx.slice();
+ child_ctx[24] = list[i];
+ return child_ctx;
+}
+
+function get_each_context_3(ctx, list, i) {
+ const child_ctx = ctx.slice();
+ child_ctx[27] = list[i];
+ return child_ctx;
+}
+
+// (55:6) {#if showWeekNums}
+function create_if_block_2(ctx) {
+ let col;
+
+ return {
+ c() {
+ col = element("col");
+ },
+ m(target, anchor) {
+ insert(target, col, anchor);
+ },
+ d(detaching) {
+ if (detaching) detach(col);
+ }
+ };
+}
+
+// (58:6) {#each month[1].days as date}
+function create_each_block_3(ctx) {
+ let col;
+
+ return {
+ c() {
+ col = element("col");
+ attr(col, "class", "svelte-pcimu8");
+ toggle_class(col, "weekend", isWeekend(/*date*/ ctx[27]));
+ },
+ m(target, anchor) {
+ insert(target, col, anchor);
+ },
+ p(ctx, dirty) {
+ if (dirty & /*isWeekend, month*/ 16384) {
+ toggle_class(col, "weekend", isWeekend(/*date*/ ctx[27]));
+ }
+ },
+ d(detaching) {
+ if (detaching) detach(col);
+ }
+ };
+}
+
+// (64:8) {#if showWeekNums}
+function create_if_block_1(ctx) {
+ let th;
+
+ return {
+ c() {
+ th = element("th");
+ th.textContent = "W";
+ attr(th, "class", "svelte-pcimu8");
+ },
+ m(target, anchor) {
+ insert(target, th, anchor);
+ },
+ d(detaching) {
+ if (detaching) detach(th);
+ }
+ };
+}
+
+// (67:8) {#each daysOfWeek as dayOfWeek}
+function create_each_block_2(ctx) {
+ let th;
+ let t_value = /*dayOfWeek*/ ctx[24] + "";
+ let t;
+
+ return {
+ c() {
+ th = element("th");
+ t = text(t_value);
+ attr(th, "class", "svelte-pcimu8");
+ },
+ m(target, anchor) {
+ insert(target, th, anchor);
+ append(th, t);
+ },
+ p(ctx, dirty) {
+ if (dirty & /*daysOfWeek*/ 32768 && t_value !== (t_value = /*dayOfWeek*/ ctx[24] + "")) set_data(t, t_value);
+ },
+ d(detaching) {
+ if (detaching) detach(th);
+ }
+ };
+}
+
+// (75:10) {#if showWeekNums}
+function create_if_block(ctx) {
+ let weeknum;
+ let current;
+
+ const weeknum_spread_levels = [
+ /*week*/ ctx[18],
+ {
+ metadata: getWeeklyMetadata(/*sources*/ ctx[8], /*week*/ ctx[18].days[0], /*today*/ ctx[10])
+ },
+ { onClick: /*onClickWeek*/ ctx[7] },
+ {
+ onContextMenu: /*onContextMenuWeek*/ ctx[5]
+ },
+ { onHover: /*onHoverWeek*/ ctx[3] },
+ { selectedId: /*selectedId*/ ctx[9] }
+ ];
+
+ let weeknum_props = {};
+
+ for (let i = 0; i < weeknum_spread_levels.length; i += 1) {
+ weeknum_props = assign(weeknum_props, weeknum_spread_levels[i]);
+ }
+
+ weeknum = new WeekNum({ props: weeknum_props });
+
+ return {
+ c() {
+ create_component(weeknum.$$.fragment);
+ },
+ m(target, anchor) {
+ mount_component(weeknum, target, anchor);
+ current = true;
+ },
+ p(ctx, dirty) {
+ const weeknum_changes = (dirty & /*month, getWeeklyMetadata, sources, today, onClickWeek, onContextMenuWeek, onHoverWeek, selectedId*/ 18344)
+ ? get_spread_update(weeknum_spread_levels, [
+ dirty & /*month*/ 16384 && get_spread_object(/*week*/ ctx[18]),
+ dirty & /*getWeeklyMetadata, sources, month, today*/ 17664 && {
+ metadata: getWeeklyMetadata(/*sources*/ ctx[8], /*week*/ ctx[18].days[0], /*today*/ ctx[10])
+ },
+ dirty & /*onClickWeek*/ 128 && { onClick: /*onClickWeek*/ ctx[7] },
+ dirty & /*onContextMenuWeek*/ 32 && {
+ onContextMenu: /*onContextMenuWeek*/ ctx[5]
+ },
+ dirty & /*onHoverWeek*/ 8 && { onHover: /*onHoverWeek*/ ctx[3] },
+ dirty & /*selectedId*/ 512 && { selectedId: /*selectedId*/ ctx[9] }
+ ])
+ : {};
+
+ weeknum.$set(weeknum_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(weeknum.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(weeknum.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ destroy_component(weeknum, detaching);
+ }
+ };
+}
+
+// (85:10) {#each week.days as day (day.format())}
+function create_each_block_1(key_1, ctx) {
+ let first;
+ let day;
+ let current;
+
+ day = new Day({
+ props: {
+ date: /*day*/ ctx[21],
+ today: /*today*/ ctx[10],
+ displayedMonth: /*displayedMonth*/ ctx[0],
+ onClick: /*onClickDay*/ ctx[6],
+ onContextMenu: /*onContextMenuDay*/ ctx[4],
+ onHover: /*onHoverDay*/ ctx[2],
+ metadata: getDailyMetadata(/*sources*/ ctx[8], /*day*/ ctx[21], /*today*/ ctx[10]),
+ selectedId: /*selectedId*/ ctx[9]
+ }
+ });
+
+ return {
+ key: key_1,
+ first: null,
+ c() {
+ first = empty();
+ create_component(day.$$.fragment);
+ this.first = first;
+ },
+ m(target, anchor) {
+ insert(target, first, anchor);
+ mount_component(day, target, anchor);
+ current = true;
+ },
+ p(new_ctx, dirty) {
+ ctx = new_ctx;
+ const day_changes = {};
+ if (dirty & /*month*/ 16384) day_changes.date = /*day*/ ctx[21];
+ if (dirty & /*today*/ 1024) day_changes.today = /*today*/ ctx[10];
+ if (dirty & /*displayedMonth*/ 1) day_changes.displayedMonth = /*displayedMonth*/ ctx[0];
+ if (dirty & /*onClickDay*/ 64) day_changes.onClick = /*onClickDay*/ ctx[6];
+ if (dirty & /*onContextMenuDay*/ 16) day_changes.onContextMenu = /*onContextMenuDay*/ ctx[4];
+ if (dirty & /*onHoverDay*/ 4) day_changes.onHover = /*onHoverDay*/ ctx[2];
+ if (dirty & /*sources, month, today*/ 17664) day_changes.metadata = getDailyMetadata(/*sources*/ ctx[8], /*day*/ ctx[21], /*today*/ ctx[10]);
+ if (dirty & /*selectedId*/ 512) day_changes.selectedId = /*selectedId*/ ctx[9];
+ day.$set(day_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in(day.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out(day.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(first);
+ destroy_component(day, detaching);
+ }
+ };
+}
+
+// (73:6) {#each month as week (week.weekNum)}
+function create_each_block(key_1, ctx) {
+ let tr;
+ let t0;
+ let each_blocks = [];
+ let each_1_lookup = new Map();
+ let t1;
+ let current;
+ let if_block = /*showWeekNums*/ ctx[1] && create_if_block(ctx);
+ let each_value_1 = /*week*/ ctx[18].days;
+ const get_key = ctx => /*day*/ ctx[21].format();
+
+ for (let i = 0; i < each_value_1.length; i += 1) {
+ let child_ctx = get_each_context_1(ctx, each_value_1, i);
+ let key = get_key(child_ctx);
+ each_1_lookup.set(key, each_blocks[i] = create_each_block_1(key, child_ctx));
+ }
+
+ return {
+ key: key_1,
+ first: null,
+ c() {
+ tr = element("tr");
+ if (if_block) if_block.c();
+ t0 = space();
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].c();
+ }
+
+ t1 = space();
+ this.first = tr;
+ },
+ m(target, anchor) {
+ insert(target, tr, anchor);
+ if (if_block) if_block.m(tr, null);
+ append(tr, t0);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].m(tr, null);
+ }
+
+ append(tr, t1);
+ current = true;
+ },
+ p(new_ctx, dirty) {
+ ctx = new_ctx;
+
+ if (/*showWeekNums*/ ctx[1]) {
+ if (if_block) {
+ if_block.p(ctx, dirty);
+
+ if (dirty & /*showWeekNums*/ 2) {
+ transition_in(if_block, 1);
+ }
+ } else {
+ if_block = create_if_block(ctx);
+ if_block.c();
+ transition_in(if_block, 1);
+ if_block.m(tr, t0);
+ }
+ } else if (if_block) {
+ group_outros();
+
+ transition_out(if_block, 1, 1, () => {
+ if_block = null;
+ });
+
+ check_outros();
+ }
+
+ if (dirty & /*month, today, displayedMonth, onClickDay, onContextMenuDay, onHoverDay, getDailyMetadata, sources, selectedId*/ 18261) {
+ each_value_1 = /*week*/ ctx[18].days;
+ group_outros();
+ each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value_1, each_1_lookup, tr, outro_and_destroy_block, create_each_block_1, t1, get_each_context_1);
+ check_outros();
+ }
+ },
+ i(local) {
+ if (current) return;
+ transition_in(if_block);
+
+ for (let i = 0; i < each_value_1.length; i += 1) {
+ transition_in(each_blocks[i]);
+ }
+
+ current = true;
+ },
+ o(local) {
+ transition_out(if_block);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ transition_out(each_blocks[i]);
+ }
+
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(tr);
+ if (if_block) if_block.d();
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].d();
+ }
+ }
+ };
+}
+
+function create_fragment$7(ctx) {
+ let div;
+ let nav;
+ let t0;
+ let table;
+ let colgroup;
+ let t1;
+ let t2;
+ let thead;
+ let tr;
+ let t3;
+ let t4;
+ let tbody;
+ let each_blocks = [];
+ let each2_lookup = new Map();
+ let current;
+
+ nav = new Nav({
+ props: {
+ today: /*today*/ ctx[10],
+ displayedMonth: /*displayedMonth*/ ctx[0],
+ incrementDisplayedMonth: /*incrementDisplayedMonth*/ ctx[11],
+ decrementDisplayedMonth: /*decrementDisplayedMonth*/ ctx[12],
+ resetDisplayedMonth: /*resetDisplayedMonth*/ ctx[13]
+ }
+ });
+
+ let if_block0 = /*showWeekNums*/ ctx[1] && create_if_block_2();
+ let each_value_3 = /*month*/ ctx[14][1].days;
+ let each_blocks_2 = [];
+
+ for (let i = 0; i < each_value_3.length; i += 1) {
+ each_blocks_2[i] = create_each_block_3(get_each_context_3(ctx, each_value_3, i));
+ }
+
+ let if_block1 = /*showWeekNums*/ ctx[1] && create_if_block_1();
+ let each_value_2 = /*daysOfWeek*/ ctx[15];
+ let each_blocks_1 = [];
+
+ for (let i = 0; i < each_value_2.length; i += 1) {
+ each_blocks_1[i] = create_each_block_2(get_each_context_2(ctx, each_value_2, i));
+ }
+
+ let each_value = /*month*/ ctx[14];
+ const get_key = ctx => /*week*/ ctx[18].weekNum;
+
+ for (let i = 0; i < each_value.length; i += 1) {
+ let child_ctx = get_each_context(ctx, each_value, i);
+ let key = get_key(child_ctx);
+ each2_lookup.set(key, each_blocks[i] = create_each_block(key, child_ctx));
+ }
+
+ return {
+ c() {
+ div = element("div");
+ create_component(nav.$$.fragment);
+ t0 = space();
+ table = element("table");
+ colgroup = element("colgroup");
+ if (if_block0) if_block0.c();
+ t1 = space();
+
+ for (let i = 0; i < each_blocks_2.length; i += 1) {
+ each_blocks_2[i].c();
+ }
+
+ t2 = space();
+ thead = element("thead");
+ tr = element("tr");
+ if (if_block1) if_block1.c();
+ t3 = space();
+
+ for (let i = 0; i < each_blocks_1.length; i += 1) {
+ each_blocks_1[i].c();
+ }
+
+ t4 = space();
+ tbody = element("tbody");
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].c();
+ }
+
+ attr(table, "class", "calendar svelte-pcimu8");
+ attr(div, "id", "calendar-container");
+ attr(div, "class", "container svelte-pcimu8");
+ toggle_class(div, "is-mobile", /*isMobile*/ ctx[16]);
+ },
+ m(target, anchor) {
+ insert(target, div, anchor);
+ mount_component(nav, div, null);
+ append(div, t0);
+ append(div, table);
+ append(table, colgroup);
+ if (if_block0) if_block0.m(colgroup, null);
+ append(colgroup, t1);
+
+ for (let i = 0; i < each_blocks_2.length; i += 1) {
+ each_blocks_2[i].m(colgroup, null);
+ }
+
+ append(table, t2);
+ append(table, thead);
+ append(thead, tr);
+ if (if_block1) if_block1.m(tr, null);
+ append(tr, t3);
+
+ for (let i = 0; i < each_blocks_1.length; i += 1) {
+ each_blocks_1[i].m(tr, null);
+ }
+
+ append(table, t4);
+ append(table, tbody);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].m(tbody, null);
+ }
+
+ current = true;
+ },
+ p(ctx, [dirty]) {
+ const nav_changes = {};
+ if (dirty & /*today*/ 1024) nav_changes.today = /*today*/ ctx[10];
+ if (dirty & /*displayedMonth*/ 1) nav_changes.displayedMonth = /*displayedMonth*/ ctx[0];
+ nav.$set(nav_changes);
+
+ if (/*showWeekNums*/ ctx[1]) {
+ if (if_block0) ; else {
+ if_block0 = create_if_block_2();
+ if_block0.c();
+ if_block0.m(colgroup, t1);
+ }
+ } else if (if_block0) {
+ if_block0.d(1);
+ if_block0 = null;
+ }
+
+ if (dirty & /*isWeekend, month*/ 16384) {
+ each_value_3 = /*month*/ ctx[14][1].days;
+ let i;
+
+ for (i = 0; i < each_value_3.length; i += 1) {
+ const child_ctx = get_each_context_3(ctx, each_value_3, i);
+
+ if (each_blocks_2[i]) {
+ each_blocks_2[i].p(child_ctx, dirty);
+ } else {
+ each_blocks_2[i] = create_each_block_3(child_ctx);
+ each_blocks_2[i].c();
+ each_blocks_2[i].m(colgroup, null);
+ }
+ }
+
+ for (; i < each_blocks_2.length; i += 1) {
+ each_blocks_2[i].d(1);
+ }
+
+ each_blocks_2.length = each_value_3.length;
+ }
+
+ if (/*showWeekNums*/ ctx[1]) {
+ if (if_block1) ; else {
+ if_block1 = create_if_block_1();
+ if_block1.c();
+ if_block1.m(tr, t3);
+ }
+ } else if (if_block1) {
+ if_block1.d(1);
+ if_block1 = null;
+ }
+
+ if (dirty & /*daysOfWeek*/ 32768) {
+ each_value_2 = /*daysOfWeek*/ ctx[15];
+ let i;
+
+ for (i = 0; i < each_value_2.length; i += 1) {
+ const child_ctx = get_each_context_2(ctx, each_value_2, i);
+
+ if (each_blocks_1[i]) {
+ each_blocks_1[i].p(child_ctx, dirty);
+ } else {
+ each_blocks_1[i] = create_each_block_2(child_ctx);
+ each_blocks_1[i].c();
+ each_blocks_1[i].m(tr, null);
+ }
+ }
+
+ for (; i < each_blocks_1.length; i += 1) {
+ each_blocks_1[i].d(1);
+ }
+
+ each_blocks_1.length = each_value_2.length;
+ }
+
+ if (dirty & /*month, today, displayedMonth, onClickDay, onContextMenuDay, onHoverDay, getDailyMetadata, sources, selectedId, getWeeklyMetadata, onClickWeek, onContextMenuWeek, onHoverWeek, showWeekNums*/ 18431) {
+ each_value = /*month*/ ctx[14];
+ group_outros();
+ each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each2_lookup, tbody, outro_and_destroy_block, create_each_block, null, get_each_context);
+ check_outros();
+ }
+ },
+ i(local) {
+ if (current) return;
+ transition_in(nav.$$.fragment, local);
+
+ for (let i = 0; i < each_value.length; i += 1) {
+ transition_in(each_blocks[i]);
+ }
+
+ current = true;
+ },
+ o(local) {
+ transition_out(nav.$$.fragment, local);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ transition_out(each_blocks[i]);
+ }
+
+ current = false;
+ },
+ d(detaching) {
+ if (detaching) detach(div);
+ destroy_component(nav);
+ if (if_block0) if_block0.d();
+ destroy_each(each_blocks_2, detaching);
+ if (if_block1) if_block1.d();
+ destroy_each(each_blocks_1, detaching);
+
+ for (let i = 0; i < each_blocks.length; i += 1) {
+ each_blocks[i].d();
+ }
+ }
+ };
+}
+
+function instance$7($$self, $$props, $$invalidate) {
+
+
+ let { localeData } = $$props;
+ let { showWeekNums = false } = $$props;
+ let { onHoverDay } = $$props;
+ let { onHoverWeek } = $$props;
+ let { onContextMenuDay } = $$props;
+ let { onContextMenuWeek } = $$props;
+ let { onClickDay } = $$props;
+ let { onClickWeek } = $$props;
+ let { sources = [] } = $$props;
+ let { selectedId } = $$props;
+ let { today = window.moment() } = $$props;
+ let { displayedMonth = today } = $$props;
+ let month;
+ let daysOfWeek;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let isMobile = window.app.isMobile;
+
+ function incrementDisplayedMonth() {
+ $$invalidate(0, displayedMonth = displayedMonth.clone().add(1, "month"));
+ }
+
+ function decrementDisplayedMonth() {
+ $$invalidate(0, displayedMonth = displayedMonth.clone().subtract(1, "month"));
+ }
+
+ function resetDisplayedMonth() {
+ $$invalidate(0, displayedMonth = today.clone());
+ }
+
+ $$self.$$set = $$props => {
+ if ("localeData" in $$props) $$invalidate(17, localeData = $$props.localeData);
+ if ("showWeekNums" in $$props) $$invalidate(1, showWeekNums = $$props.showWeekNums);
+ if ("onHoverDay" in $$props) $$invalidate(2, onHoverDay = $$props.onHoverDay);
+ if ("onHoverWeek" in $$props) $$invalidate(3, onHoverWeek = $$props.onHoverWeek);
+ if ("onContextMenuDay" in $$props) $$invalidate(4, onContextMenuDay = $$props.onContextMenuDay);
+ if ("onContextMenuWeek" in $$props) $$invalidate(5, onContextMenuWeek = $$props.onContextMenuWeek);
+ if ("onClickDay" in $$props) $$invalidate(6, onClickDay = $$props.onClickDay);
+ if ("onClickWeek" in $$props) $$invalidate(7, onClickWeek = $$props.onClickWeek);
+ if ("sources" in $$props) $$invalidate(8, sources = $$props.sources);
+ if ("selectedId" in $$props) $$invalidate(9, selectedId = $$props.selectedId);
+ if ("today" in $$props) $$invalidate(10, today = $$props.today);
+ if ("displayedMonth" in $$props) $$invalidate(0, displayedMonth = $$props.displayedMonth);
+ };
+
+ $$self.$$.update = () => {
+ if ($$self.$$.dirty & /*displayedMonth, localeData*/ 131073) {
+ $$invalidate(14, month = getMonth(displayedMonth, localeData));
+ }
+
+ if ($$self.$$.dirty & /*today, localeData*/ 132096) {
+ $$invalidate(15, daysOfWeek = getDaysOfWeek(today, localeData));
+ }
+ };
+
+ return [
+ displayedMonth,
+ showWeekNums,
+ onHoverDay,
+ onHoverWeek,
+ onContextMenuDay,
+ onContextMenuWeek,
+ onClickDay,
+ onClickWeek,
+ sources,
+ selectedId,
+ today,
+ incrementDisplayedMonth,
+ decrementDisplayedMonth,
+ resetDisplayedMonth,
+ month,
+ daysOfWeek,
+ isMobile,
+ localeData
+ ];
+}
+
+class Calendar$1 extends SvelteComponent {
+ constructor(options) {
+ super();
+ if (!document.getElementById("svelte-pcimu8-style")) add_css();
+
+ init(this, options, instance$7, create_fragment$7, not_equal, {
+ localeData: 17,
+ showWeekNums: 1,
+ onHoverDay: 2,
+ onHoverWeek: 3,
+ onContextMenuDay: 4,
+ onContextMenuWeek: 5,
+ onClickDay: 6,
+ onClickWeek: 7,
+ sources: 8,
+ selectedId: 9,
+ today: 10,
+ displayedMonth: 0,
+ incrementDisplayedMonth: 11,
+ decrementDisplayedMonth: 12,
+ resetDisplayedMonth: 13
+ });
+ }
+
+ get incrementDisplayedMonth() {
+ return this.$$.ctx[11];
+ }
+
+ get decrementDisplayedMonth() {
+ return this.$$.ctx[12];
+ }
+
+ get resetDisplayedMonth() {
+ return this.$$.ctx[13];
+ }
+}
+
+const langToMomentLocale = {
+ en: "en-gb",
+ zh: "zh-cn",
+ "zh-TW": "zh-tw",
+ ru: "ru",
+ ko: "ko",
+ it: "it",
+ id: "id",
+ ro: "ro",
+ "pt-BR": "pt-br",
+ cz: "cs",
+ da: "da",
+ de: "de",
+ es: "es",
+ fr: "fr",
+ no: "nn",
+ pl: "pl",
+ pt: "pt",
+ tr: "tr",
+ hi: "hi",
+ nl: "nl",
+ ar: "ar",
+ ja: "ja",
+};
+const weekdays = [
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday",
+];
+function overrideGlobalMomentWeekStart(weekStart) {
+ const { moment } = window;
+ const currentLocale = moment.locale();
+ // Save the initial locale weekspec so that we can restore
+ // it when toggling between the different options in settings.
+ if (!window._bundledLocaleWeekSpec) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ window._bundledLocaleWeekSpec = moment.localeData()._week;
+ }
+ if (weekStart === "locale") {
+ moment.updateLocale(currentLocale, {
+ week: window._bundledLocaleWeekSpec,
+ });
+ }
+ else {
+ moment.updateLocale(currentLocale, {
+ week: {
+ dow: weekdays.indexOf(weekStart) || 0,
+ },
+ });
+ }
+}
+/**
+ * Sets the locale used by the calendar. This allows the calendar to
+ * default to the user's locale (e.g. Start Week on Sunday/Monday/Friday)
+ *
+ * @param localeOverride locale string (e.g. "en-US")
+ */
+function configureGlobalMomentLocale(localeOverride = "system-default", weekStart = "locale") {
+ var _a;
+ const obsidianLang = localStorage.getItem("language") || "en";
+ const systemLang = (_a = navigator.language) === null || _a === void 0 ? void 0 : _a.toLowerCase();
+ let momentLocale = langToMomentLocale[obsidianLang];
+ if (localeOverride !== "system-default") {
+ momentLocale = localeOverride;
+ }
+ else if (systemLang.startsWith(obsidianLang)) {
+ // If the system locale is more specific (en-gb vs en), use the system locale.
+ momentLocale = systemLang;
+ }
+ const currentLocale = window.moment.locale(momentLocale);
+ console.debug(`[Calendar] Trying to switch Moment.js global locale to ${momentLocale}, got ${currentLocale}`);
+ overrideGlobalMomentWeekStart(weekStart);
+ return currentLocale;
+}
+
+/* src/ui/Calendar.svelte generated by Svelte v3.35.0 */
+
+function create_fragment(ctx) {
+ let calendarbase;
+ let updating_displayedMonth;
+ let current;
+
+ function calendarbase_displayedMonth_binding(value) {
+ /*calendarbase_displayedMonth_binding*/ ctx[12](value);
+ }
+
+ let calendarbase_props = {
+ sources: /*sources*/ ctx[1],
+ today: /*today*/ ctx[9],
+ onHoverDay: /*onHoverDay*/ ctx[2],
+ onHoverWeek: /*onHoverWeek*/ ctx[3],
+ onContextMenuDay: /*onContextMenuDay*/ ctx[6],
+ onContextMenuWeek: /*onContextMenuWeek*/ ctx[7],
+ onClickDay: /*onClickDay*/ ctx[4],
+ onClickWeek: /*onClickWeek*/ ctx[5],
+ localeData: /*today*/ ctx[9].localeData(),
+ selectedId: /*$activeFile*/ ctx[10],
+ showWeekNums: /*$settings*/ ctx[8].showWeeklyNote
+ };
+
+ if (/*displayedMonth*/ ctx[0] !== void 0) {
+ calendarbase_props.displayedMonth = /*displayedMonth*/ ctx[0];
+ }
+
+ calendarbase = new Calendar$1({ props: calendarbase_props });
+ binding_callbacks$1.push(() => bind(calendarbase, "displayedMonth", calendarbase_displayedMonth_binding));
+
+ return {
+ c() {
+ create_component$1(calendarbase.$$.fragment);
+ },
+ m(target, anchor) {
+ mount_component$1(calendarbase, target, anchor);
+ current = true;
+ },
+ p(ctx, [dirty]) {
+ const calendarbase_changes = {};
+ if (dirty & /*sources*/ 2) calendarbase_changes.sources = /*sources*/ ctx[1];
+ if (dirty & /*today*/ 512) calendarbase_changes.today = /*today*/ ctx[9];
+ if (dirty & /*onHoverDay*/ 4) calendarbase_changes.onHoverDay = /*onHoverDay*/ ctx[2];
+ if (dirty & /*onHoverWeek*/ 8) calendarbase_changes.onHoverWeek = /*onHoverWeek*/ ctx[3];
+ if (dirty & /*onContextMenuDay*/ 64) calendarbase_changes.onContextMenuDay = /*onContextMenuDay*/ ctx[6];
+ if (dirty & /*onContextMenuWeek*/ 128) calendarbase_changes.onContextMenuWeek = /*onContextMenuWeek*/ ctx[7];
+ if (dirty & /*onClickDay*/ 16) calendarbase_changes.onClickDay = /*onClickDay*/ ctx[4];
+ if (dirty & /*onClickWeek*/ 32) calendarbase_changes.onClickWeek = /*onClickWeek*/ ctx[5];
+ if (dirty & /*today*/ 512) calendarbase_changes.localeData = /*today*/ ctx[9].localeData();
+ if (dirty & /*$activeFile*/ 1024) calendarbase_changes.selectedId = /*$activeFile*/ ctx[10];
+ if (dirty & /*$settings*/ 256) calendarbase_changes.showWeekNums = /*$settings*/ ctx[8].showWeeklyNote;
+
+ if (!updating_displayedMonth && dirty & /*displayedMonth*/ 1) {
+ updating_displayedMonth = true;
+ calendarbase_changes.displayedMonth = /*displayedMonth*/ ctx[0];
+ add_flush_callback(() => updating_displayedMonth = false);
+ }
+
+ calendarbase.$set(calendarbase_changes);
+ },
+ i(local) {
+ if (current) return;
+ transition_in$1(calendarbase.$$.fragment, local);
+ current = true;
+ },
+ o(local) {
+ transition_out$1(calendarbase.$$.fragment, local);
+ current = false;
+ },
+ d(detaching) {
+ destroy_component$1(calendarbase, detaching);
+ }
+ };
+}
+
+function instance($$self, $$props, $$invalidate) {
+ let $settings;
+ let $activeFile;
+ component_subscribe($$self, settings, $$value => $$invalidate(8, $settings = $$value));
+ component_subscribe($$self, activeFile, $$value => $$invalidate(10, $activeFile = $$value));
+
+
+ let today;
+ let { displayedMonth = today } = $$props;
+ let { sources } = $$props;
+ let { onHoverDay } = $$props;
+ let { onHoverWeek } = $$props;
+ let { onClickDay } = $$props;
+ let { onClickWeek } = $$props;
+ let { onContextMenuDay } = $$props;
+ let { onContextMenuWeek } = $$props;
+
+ function tick() {
+ $$invalidate(9, today = window.moment());
+ }
+
+ function getToday(settings) {
+ configureGlobalMomentLocale(settings.localeOverride, settings.weekStart);
+ dailyNotes.reindex();
+ weeklyNotes.reindex();
+ return window.moment();
+ }
+
+ // 1 minute heartbeat to keep `today` reflecting the current day
+ let heartbeat = setInterval(
+ () => {
+ tick();
+ const isViewingCurrentMonth = displayedMonth.isSame(today, "day");
+
+ if (isViewingCurrentMonth) {
+ // if it's midnight on the last day of the month, this will
+ // update the display to show the new month.
+ $$invalidate(0, displayedMonth = today);
+ }
+ },
+ 1000 * 60
+ );
+
+ onDestroy(() => {
+ clearInterval(heartbeat);
+ });
+
+ function calendarbase_displayedMonth_binding(value) {
+ displayedMonth = value;
+ $$invalidate(0, displayedMonth);
+ }
+
+ $$self.$$set = $$props => {
+ if ("displayedMonth" in $$props) $$invalidate(0, displayedMonth = $$props.displayedMonth);
+ if ("sources" in $$props) $$invalidate(1, sources = $$props.sources);
+ if ("onHoverDay" in $$props) $$invalidate(2, onHoverDay = $$props.onHoverDay);
+ if ("onHoverWeek" in $$props) $$invalidate(3, onHoverWeek = $$props.onHoverWeek);
+ if ("onClickDay" in $$props) $$invalidate(4, onClickDay = $$props.onClickDay);
+ if ("onClickWeek" in $$props) $$invalidate(5, onClickWeek = $$props.onClickWeek);
+ if ("onContextMenuDay" in $$props) $$invalidate(6, onContextMenuDay = $$props.onContextMenuDay);
+ if ("onContextMenuWeek" in $$props) $$invalidate(7, onContextMenuWeek = $$props.onContextMenuWeek);
+ };
+
+ $$self.$$.update = () => {
+ if ($$self.$$.dirty & /*$settings*/ 256) {
+ $$invalidate(9, today = getToday($settings));
+ }
+ };
+
+ return [
+ displayedMonth,
+ sources,
+ onHoverDay,
+ onHoverWeek,
+ onClickDay,
+ onClickWeek,
+ onContextMenuDay,
+ onContextMenuWeek,
+ $settings,
+ today,
+ $activeFile,
+ tick,
+ calendarbase_displayedMonth_binding
+ ];
+}
+
+class Calendar extends SvelteComponent$1 {
+ constructor(options) {
+ super();
+
+ init$1(this, options, instance, create_fragment, not_equal$1, {
+ displayedMonth: 0,
+ sources: 1,
+ onHoverDay: 2,
+ onHoverWeek: 3,
+ onClickDay: 4,
+ onClickWeek: 5,
+ onContextMenuDay: 6,
+ onContextMenuWeek: 7,
+ tick: 11
+ });
+ }
+
+ get tick() {
+ return this.$$.ctx[11];
+ }
+}
+
+function showFileMenu(app, file, position) {
+ const fileMenu = new obsidian.Menu(app);
+ fileMenu.addItem((item) => item
+ .setTitle("Delete")
+ .setIcon("trash")
+ .onClick(() => {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ app.fileManager.promptForFileDeletion(file);
+ }));
+ app.workspace.trigger("file-menu", fileMenu, file, "calendar-context-menu", null);
+ fileMenu.showAtPosition(position);
+}
+
+const getStreakClasses = (file) => {
+ return classList({
+ "has-note": !!file,
+ });
+};
+const streakSource = {
+ getDailyMetadata: async (date) => {
+ const file = getDailyNote_1(date, get_store_value(dailyNotes));
+ return {
+ classes: getStreakClasses(file),
+ dots: [],
+ };
+ },
+ getWeeklyMetadata: async (date) => {
+ const file = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ return {
+ classes: getStreakClasses(file),
+ dots: [],
+ };
+ },
+};
+
+function getNoteTags(note) {
+ var _a;
+ if (!note) {
+ return [];
+ }
+ const { metadataCache } = window.app;
+ const frontmatter = (_a = metadataCache.getFileCache(note)) === null || _a === void 0 ? void 0 : _a.frontmatter;
+ const tags = [];
+ if (frontmatter) {
+ const frontmatterTags = obsidian.parseFrontMatterTags(frontmatter) || [];
+ tags.push(...frontmatterTags);
+ }
+ // strip the '#' at the beginning
+ return tags.map((tag) => tag.substring(1));
+}
+function getFormattedTagAttributes(note) {
+ const attrs = {};
+ const tags = getNoteTags(note);
+ const [emojiTags, nonEmojiTags] = partition(tags, (tag) => /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/.test(tag));
+ if (nonEmojiTags) {
+ attrs["data-tags"] = nonEmojiTags.join(" ");
+ }
+ if (emojiTags) {
+ attrs["data-emoji-tag"] = emojiTags[0];
+ }
+ return attrs;
+}
+const customTagsSource = {
+ getDailyMetadata: async (date) => {
+ const file = getDailyNote_1(date, get_store_value(dailyNotes));
+ return {
+ dataAttributes: getFormattedTagAttributes(file),
+ dots: [],
+ };
+ },
+ getWeeklyMetadata: async (date) => {
+ const file = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ return {
+ dataAttributes: getFormattedTagAttributes(file),
+ dots: [],
+ };
+ },
+};
+
+async function getNumberOfRemainingTasks(note) {
+ if (!note) {
+ return 0;
+ }
+ const { vault } = window.app;
+ const fileContents = await vault.cachedRead(note);
+ return (fileContents.match(/(-|\*) \[ \]/g) || []).length;
+}
+async function getDotsForDailyNote$1(dailyNote) {
+ if (!dailyNote) {
+ return [];
+ }
+ const numTasks = await getNumberOfRemainingTasks(dailyNote);
+ const dots = [];
+ if (numTasks) {
+ dots.push({
+ className: "task",
+ color: "default",
+ isFilled: false,
+ });
+ }
+ return dots;
+}
+const tasksSource = {
+ getDailyMetadata: async (date) => {
+ const file = getDailyNote_1(date, get_store_value(dailyNotes));
+ const dots = await getDotsForDailyNote$1(file);
+ return {
+ dots,
+ };
+ },
+ getWeeklyMetadata: async (date) => {
+ const file = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ const dots = await getDotsForDailyNote$1(file);
+ return {
+ dots,
+ };
+ },
+};
+
+const NUM_MAX_DOTS = 5;
+async function getWordLengthAsDots(note) {
+ const { wordsPerDot = DEFAULT_WORDS_PER_DOT } = get_store_value(settings);
+ if (!note || wordsPerDot <= 0) {
+ return 0;
+ }
+ const fileContents = await window.app.vault.cachedRead(note);
+ const wordCount = getWordCount(fileContents);
+ const numDots = wordCount / wordsPerDot;
+ return clamp(Math.floor(numDots), 1, NUM_MAX_DOTS);
+}
+async function getDotsForDailyNote(dailyNote) {
+ if (!dailyNote) {
+ return [];
+ }
+ const numSolidDots = await getWordLengthAsDots(dailyNote);
+ const dots = [];
+ for (let i = 0; i < numSolidDots; i++) {
+ dots.push({
+ color: "default",
+ isFilled: true,
+ });
+ }
+ return dots;
+}
+const wordCountSource = {
+ getDailyMetadata: async (date) => {
+ const file = getDailyNote_1(date, get_store_value(dailyNotes));
+ const dots = await getDotsForDailyNote(file);
+ return {
+ dots,
+ };
+ },
+ getWeeklyMetadata: async (date) => {
+ const file = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ const dots = await getDotsForDailyNote(file);
+ return {
+ dots,
+ };
+ },
+};
+
+class CalendarView extends obsidian.ItemView {
+ constructor(leaf) {
+ super(leaf);
+ this.openOrCreateDailyNote = this.openOrCreateDailyNote.bind(this);
+ this.openOrCreateWeeklyNote = this.openOrCreateWeeklyNote.bind(this);
+ this.onNoteSettingsUpdate = this.onNoteSettingsUpdate.bind(this);
+ this.onFileCreated = this.onFileCreated.bind(this);
+ this.onFileDeleted = this.onFileDeleted.bind(this);
+ this.onFileModified = this.onFileModified.bind(this);
+ this.onFileOpen = this.onFileOpen.bind(this);
+ this.onHoverDay = this.onHoverDay.bind(this);
+ this.onHoverWeek = this.onHoverWeek.bind(this);
+ this.onContextMenuDay = this.onContextMenuDay.bind(this);
+ this.onContextMenuWeek = this.onContextMenuWeek.bind(this);
+ this.registerEvent(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ this.app.workspace.on("periodic-notes:settings-updated", this.onNoteSettingsUpdate));
+ this.registerEvent(this.app.vault.on("create", this.onFileCreated));
+ this.registerEvent(this.app.vault.on("delete", this.onFileDeleted));
+ this.registerEvent(this.app.vault.on("modify", this.onFileModified));
+ this.registerEvent(this.app.workspace.on("file-open", this.onFileOpen));
+ this.settings = null;
+ settings.subscribe((val) => {
+ this.settings = val;
+ // Refresh the calendar if settings change
+ if (this.calendar) {
+ this.calendar.tick();
+ }
+ });
+ }
+ getViewType() {
+ return VIEW_TYPE_CALENDAR;
+ }
+ getDisplayText() {
+ return "Calendar";
+ }
+ getIcon() {
+ return "calendar-with-checkmark";
+ }
+ onClose() {
+ if (this.calendar) {
+ this.calendar.$destroy();
+ }
+ return Promise.resolve();
+ }
+ async onOpen() {
+ // Integration point: external plugins can listen for `calendar:open`
+ // to feed in additional sources.
+ const sources = [
+ customTagsSource,
+ streakSource,
+ wordCountSource,
+ tasksSource,
+ ];
+ this.app.workspace.trigger(TRIGGER_ON_OPEN, sources);
+ this.calendar = new Calendar({
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ target: this.contentEl,
+ props: {
+ onClickDay: this.openOrCreateDailyNote,
+ onClickWeek: this.openOrCreateWeeklyNote,
+ onHoverDay: this.onHoverDay,
+ onHoverWeek: this.onHoverWeek,
+ onContextMenuDay: this.onContextMenuDay,
+ onContextMenuWeek: this.onContextMenuWeek,
+ sources,
+ },
+ });
+ }
+ onHoverDay(date, targetEl, isMetaPressed) {
+ if (!isMetaPressed) {
+ return;
+ }
+ const { format } = getDailyNoteSettings_1();
+ const note = getDailyNote_1(date, get_store_value(dailyNotes));
+ this.app.workspace.trigger("link-hover", this, targetEl, date.format(format), note === null || note === void 0 ? void 0 : note.path);
+ }
+ onHoverWeek(date, targetEl, isMetaPressed) {
+ if (!isMetaPressed) {
+ return;
+ }
+ const note = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ const { format } = getWeeklyNoteSettings_1();
+ this.app.workspace.trigger("link-hover", this, targetEl, date.format(format), note === null || note === void 0 ? void 0 : note.path);
+ }
+ onContextMenuDay(date, event) {
+ const note = getDailyNote_1(date, get_store_value(dailyNotes));
+ if (!note) {
+ // If no file exists for a given day, show nothing.
+ return;
+ }
+ showFileMenu(this.app, note, {
+ x: event.pageX,
+ y: event.pageY,
+ });
+ }
+ onContextMenuWeek(date, event) {
+ const note = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ if (!note) {
+ // If no file exists for a given day, show nothing.
+ return;
+ }
+ showFileMenu(this.app, note, {
+ x: event.pageX,
+ y: event.pageY,
+ });
+ }
+ onNoteSettingsUpdate() {
+ dailyNotes.reindex();
+ weeklyNotes.reindex();
+ this.updateActiveFile();
+ }
+ async onFileDeleted(file) {
+ if (getDateFromFile_1(file, "day")) {
+ dailyNotes.reindex();
+ this.updateActiveFile();
+ }
+ if (getDateFromFile_1(file, "week")) {
+ weeklyNotes.reindex();
+ this.updateActiveFile();
+ }
+ }
+ async onFileModified(file) {
+ const date = getDateFromFile_1(file, "day") || getDateFromFile_1(file, "week");
+ if (date && this.calendar) {
+ this.calendar.tick();
+ }
+ }
+ onFileCreated(file) {
+ if (this.app.workspace.layoutReady && this.calendar) {
+ if (getDateFromFile_1(file, "day")) {
+ dailyNotes.reindex();
+ this.calendar.tick();
+ }
+ if (getDateFromFile_1(file, "week")) {
+ weeklyNotes.reindex();
+ this.calendar.tick();
+ }
+ }
+ }
+ onFileOpen(_file) {
+ if (this.app.workspace.layoutReady) {
+ this.updateActiveFile();
+ }
+ }
+ updateActiveFile() {
+ const { view } = this.app.workspace.activeLeaf;
+ let file = null;
+ if (view instanceof obsidian.FileView) {
+ file = view.file;
+ }
+ activeFile.setFile(file);
+ if (this.calendar) {
+ this.calendar.tick();
+ }
+ }
+ revealActiveNote() {
+ const { moment } = window;
+ const { activeLeaf } = this.app.workspace;
+ if (activeLeaf.view instanceof obsidian.FileView) {
+ // Check to see if the active note is a daily-note
+ let date = getDateFromFile_1(activeLeaf.view.file, "day");
+ if (date) {
+ this.calendar.$set({ displayedMonth: date });
+ return;
+ }
+ // Check to see if the active note is a weekly-note
+ const { format } = getWeeklyNoteSettings_1();
+ date = moment(activeLeaf.view.file.basename, format, true);
+ if (date.isValid()) {
+ this.calendar.$set({ displayedMonth: date });
+ return;
+ }
+ }
+ }
+ async openOrCreateWeeklyNote(date, inNewSplit) {
+ const { workspace } = this.app;
+ const startOfWeek = date.clone().startOf("week");
+ const existingFile = getWeeklyNote_1(date, get_store_value(weeklyNotes));
+ if (!existingFile) {
+ // File doesn't exist
+ tryToCreateWeeklyNote(startOfWeek, inNewSplit, this.settings, (file) => {
+ activeFile.setFile(file);
+ });
+ return;
+ }
+ const leaf = inNewSplit
+ ? workspace.splitActiveLeaf()
+ : workspace.getUnpinnedLeaf();
+ await leaf.openFile(existingFile);
+ activeFile.setFile(existingFile);
+ }
+ async openOrCreateDailyNote(date, inNewSplit) {
+ const { workspace } = this.app;
+ const existingFile = getDailyNote_1(date, get_store_value(dailyNotes));
+ if (!existingFile) {
+ // File doesn't exist
+ tryToCreateDailyNote(date, inNewSplit, this.settings, (dailyNote) => {
+ activeFile.setFile(dailyNote);
+ });
+ return;
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const mode = this.app.vault.getConfig("defaultViewMode");
+ const leaf = inNewSplit
+ ? workspace.splitActiveLeaf()
+ : workspace.getUnpinnedLeaf();
+ await leaf.openFile(existingFile, { mode });
+ activeFile.setFile(existingFile);
+ }
+}
+
+class CalendarPlugin extends obsidian.Plugin {
+ onunload() {
+ this.app.workspace
+ .getLeavesOfType(VIEW_TYPE_CALENDAR)
+ .forEach((leaf) => leaf.detach());
+ }
+ async onload() {
+ this.register(settings.subscribe((value) => {
+ this.options = value;
+ }));
+ this.registerView(VIEW_TYPE_CALENDAR, (leaf) => (this.view = new CalendarView(leaf)));
+ this.addCommand({
+ id: "show-calendar-view",
+ name: "Open view",
+ checkCallback: (checking) => {
+ if (checking) {
+ return (this.app.workspace.getLeavesOfType(VIEW_TYPE_CALENDAR).length === 0);
+ }
+ this.initLeaf();
+ },
+ });
+ this.addCommand({
+ id: "open-weekly-note",
+ name: "Open Weekly Note",
+ checkCallback: (checking) => {
+ if (checking) {
+ return !appHasPeriodicNotesPluginLoaded();
+ }
+ this.view.openOrCreateWeeklyNote(window.moment(), false);
+ },
+ });
+ this.addCommand({
+ id: "reveal-active-note",
+ name: "Reveal active note",
+ callback: () => this.view.revealActiveNote(),
+ });
+ await this.loadOptions();
+ this.addSettingTab(new CalendarSettingsTab(this.app, this));
+ if (this.app.workspace.layoutReady) {
+ this.initLeaf();
+ }
+ else {
+ this.registerEvent(this.app.workspace.on("layout-ready", this.initLeaf.bind(this)));
+ }
+ }
+ initLeaf() {
+ if (this.app.workspace.getLeavesOfType(VIEW_TYPE_CALENDAR).length) {
+ return;
+ }
+ this.app.workspace.getRightLeaf(false).setViewState({
+ type: VIEW_TYPE_CALENDAR,
+ });
+ }
+ async loadOptions() {
+ const options = await this.loadData();
+ settings.update((old) => {
+ return Object.assign(Object.assign({}, old), (options || {}));
+ });
+ await this.saveData(this.options);
+ }
+ async writeOptions(changeOpts) {
+ settings.update((old) => (Object.assign(Object.assign({}, old), changeOpts(old))));
+ await this.saveData(this.options);
+ }
+}
+
+module.exports = CalendarPlugin;
diff --git a/.obsidian/plugins/calendar/manifest.json b/.obsidian/plugins/calendar/manifest.json
new file mode 100644
index 00000000..028bfa50
--- /dev/null
+++ b/.obsidian/plugins/calendar/manifest.json
@@ -0,0 +1,10 @@
+{
+ "id": "calendar",
+ "name": "Calendar",
+ "description": "Calendar view of your daily notes",
+ "version": "1.5.10",
+ "author": "Liam Cain",
+ "authorUrl": "https://github.com/liamcain/",
+ "isDesktopOnly": false,
+ "minAppVersion": "0.9.11"
+}
diff --git a/.obsidian/plugins/obsidian-outliner/data.json b/.obsidian/plugins/obsidian-outliner/data.json
new file mode 100644
index 00000000..556e13cc
--- /dev/null
+++ b/.obsidian/plugins/obsidian-outliner/data.json
@@ -0,0 +1,10 @@
+{
+ "styleLists": true,
+ "debug": false,
+ "stickCursor": true,
+ "betterEnter": true,
+ "betterTab": true,
+ "selectAll": true,
+ "listLines": true,
+ "listLineAction": "toggle-folding"
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-outliner/main.js b/.obsidian/plugins/obsidian-outliner/main.js
new file mode 100644
index 00000000..99c7398b
--- /dev/null
+++ b/.obsidian/plugins/obsidian-outliner/main.js
@@ -0,0 +1,2569 @@
+'use strict';
+
+var obsidian = require('obsidian');
+var view = require('@codemirror/view');
+var state = require('@codemirror/state');
+var language = require('@codemirror/language');
+
+/******************************************************************************
+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());
+ });
+}
+
+function recalculateNumericBullets(root) {
+ function visit(parent) {
+ let index = 1;
+ for (const child of parent.getChildren()) {
+ if (/\d+\./.test(child.getBullet())) {
+ child.replateBullet(`${index++}.`);
+ }
+ visit(child);
+ }
+ }
+ visit(root);
+}
+
+class DeleteAndMergeWithPreviousLineOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ const list = root.getListUnderCursor();
+ const cursor = root.getCursor();
+ const lines = list.getLinesInfo();
+ const lineNo = lines.findIndex((l) => cursor.ch === l.from.ch && cursor.line === l.from.line);
+ if (lineNo === 0) {
+ this.mergeWithPreviousItem(root, cursor, list);
+ }
+ else if (lineNo > 0) {
+ this.mergeNotes(root, cursor, list, lines, lineNo);
+ }
+ }
+ mergeNotes(root, cursor, list, lines, lineNo) {
+ this.stopPropagation = true;
+ this.updated = true;
+ const prevLineNo = lineNo - 1;
+ root.replaceCursor({
+ line: cursor.line - 1,
+ ch: lines[prevLineNo].text.length + lines[prevLineNo].from.ch,
+ });
+ lines[prevLineNo].text += lines[lineNo].text;
+ lines.splice(lineNo, 1);
+ list.replaceLines(lines.map((l) => l.text));
+ }
+ mergeWithPreviousItem(root, cursor, list) {
+ if (root.getChildren()[0] === list && list.getChildren().length === 0) {
+ return;
+ }
+ this.stopPropagation = true;
+ const prev = root.getListUnderLine(cursor.line - 1);
+ if (!prev) {
+ return;
+ }
+ const bothAreEmpty = prev.isEmpty() && list.isEmpty();
+ const prevIsEmptyAndSameLevel = prev.isEmpty() && !list.isEmpty() && prev.getLevel() == list.getLevel();
+ const listIsEmptyAndPrevIsParent = list.isEmpty() && prev.getLevel() == list.getLevel() - 1;
+ if (bothAreEmpty || prevIsEmptyAndSameLevel || listIsEmptyAndPrevIsParent) {
+ this.updated = true;
+ const parent = list.getParent();
+ const prevEnd = prev.getLastLineContentEnd();
+ if (!prev.getNotesIndent() && list.getNotesIndent()) {
+ prev.setNotesIndent(prev.getFirstLineIndent() +
+ list.getNotesIndent().slice(list.getFirstLineIndent().length));
+ }
+ const oldLines = prev.getLines();
+ const newLines = list.getLines();
+ oldLines[oldLines.length - 1] += newLines[0];
+ const resultLines = oldLines.concat(newLines.slice(1));
+ prev.replaceLines(resultLines);
+ parent.removeChild(list);
+ for (const c of list.getChildren()) {
+ list.removeChild(c);
+ prev.addAfterAll(c);
+ }
+ root.replaceCursor(prevEnd);
+ recalculateNumericBullets(root);
+ }
+ }
+}
+
+class DeleteAndMergeWithNextLineOperation {
+ constructor(root) {
+ this.root = root;
+ this.deleteAndMergeWithPrevious =
+ new DeleteAndMergeWithPreviousLineOperation(root);
+ }
+ shouldStopPropagation() {
+ return this.deleteAndMergeWithPrevious.shouldStopPropagation();
+ }
+ shouldUpdate() {
+ return this.deleteAndMergeWithPrevious.shouldUpdate();
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ const list = root.getListUnderCursor();
+ const cursor = root.getCursor();
+ const lines = list.getLinesInfo();
+ const lineNo = lines.findIndex((l) => cursor.ch === l.to.ch && cursor.line === l.to.line);
+ if (lineNo === lines.length - 1) {
+ const nextLine = lines[lineNo].to.line + 1;
+ const nextList = root.getListUnderLine(nextLine);
+ if (!nextList) {
+ return;
+ }
+ root.replaceCursor(nextList.getFirstLineContentStart());
+ this.deleteAndMergeWithPrevious.perform();
+ }
+ else if (lineNo >= 0) {
+ root.replaceCursor(lines[lineNo + 1].from);
+ this.deleteAndMergeWithPrevious.perform();
+ }
+ }
+}
+
+class DeleteTillLineStartOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ this.updated = true;
+ const cursor = root.getCursor();
+ const list = root.getListUnderCursor();
+ const lines = list.getLinesInfo();
+ const lineNo = lines.findIndex((l) => l.from.line === cursor.line);
+ lines[lineNo].text = lines[lineNo].text.slice(cursor.ch - lines[lineNo].from.ch);
+ list.replaceLines(lines.map((l) => l.text));
+ root.replaceCursor(lines[lineNo].from);
+ }
+}
+
+class DeleteShouldIgnoreBulletsFeature {
+ constructor(plugin, settings, ime, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.stickCursor && !this.ime.isIMEOpened();
+ };
+ this.deleteAndMergeWithPreviousLine = (editor) => {
+ return this.performOperation.performOperation((root) => new DeleteAndMergeWithPreviousLineOperation(root), editor);
+ };
+ this.deleteTillLineStart = (editor) => {
+ return this.performOperation.performOperation((root) => new DeleteTillLineStartOperation(root), editor);
+ };
+ this.deleteAndMergeWithNextLine = (editor) => {
+ return this.performOperation.performOperation((root) => new DeleteAndMergeWithNextLineOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(view.keymap.of([
+ {
+ key: "Backspace",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.deleteAndMergeWithPreviousLine,
+ }),
+ },
+ {
+ key: "Delete",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.deleteAndMergeWithNextLine,
+ }),
+ },
+ {
+ mac: "m-Backspace",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.deleteTillLineStart,
+ }),
+ },
+ ]));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class EnsureCursorInListContentOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ const cursor = root.getCursor();
+ const list = root.getListUnderCursor();
+ const contentStart = list.getFirstLineContentStart();
+ const linePrefix = contentStart.line === cursor.line
+ ? contentStart.ch + list.getCheckboxLength()
+ : list.getNotesIndent().length;
+ if (cursor.ch < linePrefix) {
+ this.updated = true;
+ root.replaceCursor({
+ line: cursor.line,
+ ch: linePrefix,
+ });
+ }
+ }
+}
+
+class EnsureCursorIsInUnfoldedLineOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ const cursor = root.getCursor();
+ const list = root.getListUnderCursor();
+ if (!list.isFolded()) {
+ return;
+ }
+ const foldRoot = list.getTopFoldRoot();
+ const firstLineEnd = foldRoot.getLinesInfo()[0].to;
+ if (cursor.line > firstLineEnd.line) {
+ this.updated = true;
+ root.replaceCursor(firstLineEnd);
+ }
+ }
+}
+
+class EnsureCursorInListContentFeature {
+ constructor(plugin, settings, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.transactionExtender = (tr) => {
+ if (!this.settings.stickCursor || !tr.selection) {
+ return null;
+ }
+ const editor = this.obsidian.getEditorFromState(tr.startState);
+ setTimeout(() => {
+ this.handleCursorActivity(editor);
+ }, 0);
+ return null;
+ };
+ this.handleCursorActivity = (editor) => {
+ this.performOperation.performOperation((root) => new EnsureCursorIsInUnfoldedLineOperation(root), editor);
+ this.performOperation.performOperation((root) => new EnsureCursorInListContentOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(state.EditorState.transactionExtender.of(this.transactionExtender));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class MoveLeftOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ const list = root.getListUnderCursor();
+ const parent = list.getParent();
+ const grandParent = parent.getParent();
+ if (!grandParent) {
+ return;
+ }
+ this.updated = true;
+ const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
+ const indentRmFrom = parent.getFirstLineIndent().length;
+ const indentRmTill = list.getFirstLineIndent().length;
+ parent.removeChild(list);
+ grandParent.addAfter(parent, list);
+ list.unindentContent(indentRmFrom, indentRmTill);
+ const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
+ const lineDiff = listStartLineAfter - listStartLineBefore;
+ const chDiff = indentRmTill - indentRmFrom;
+ const cursor = root.getCursor();
+ root.replaceCursor({
+ line: cursor.line + lineDiff,
+ ch: cursor.ch - chDiff,
+ });
+ recalculateNumericBullets(root);
+ }
+}
+
+function isEmptyLineOrEmptyCheckbox(line) {
+ return line === "" || line === "[ ] ";
+}
+
+class OutdentIfLineIsEmptyOperation {
+ constructor(root) {
+ this.root = root;
+ this.moveLeftOp = new MoveLeftOperation(root);
+ }
+ shouldStopPropagation() {
+ return this.moveLeftOp.shouldStopPropagation();
+ }
+ shouldUpdate() {
+ return this.moveLeftOp.shouldUpdate();
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ const list = root.getListUnderCursor();
+ const lines = list.getLines();
+ if (lines.length > 1 ||
+ !isEmptyLineOrEmptyCheckbox(lines[0]) ||
+ list.getLevel() === 1) {
+ return;
+ }
+ this.moveLeftOp.perform();
+ }
+}
+
+class EnterOutdentIfLineIsEmptyFeature {
+ constructor(plugin, settings, ime, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.betterEnter && !this.ime.isIMEOpened();
+ };
+ this.run = (editor) => {
+ return this.performOperation.performOperation((root) => new OutdentIfLineIsEmptyOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(state.Prec.highest(view.keymap.of([
+ {
+ key: "Enter",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ ])));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+function cmpPos(a, b) {
+ return a.line - b.line || a.ch - b.ch;
+}
+function maxPos(a, b) {
+ return cmpPos(a, b) < 0 ? b : a;
+}
+function minPos(a, b) {
+ return cmpPos(a, b) < 0 ? a : b;
+}
+class List {
+ constructor(root, indent, bullet, checkboxLength, spaceAfterBullet, firstLine, foldRoot) {
+ this.root = root;
+ this.indent = indent;
+ this.bullet = bullet;
+ this.checkboxLength = checkboxLength;
+ this.spaceAfterBullet = spaceAfterBullet;
+ this.foldRoot = foldRoot;
+ this.parent = null;
+ this.children = [];
+ this.notesIndent = null;
+ this.lines = [];
+ this.lines.push(firstLine);
+ }
+ getNotesIndent() {
+ return this.notesIndent;
+ }
+ setNotesIndent(notesIndent) {
+ if (this.notesIndent !== null) {
+ throw new Error(`Notes indent already provided`);
+ }
+ this.notesIndent = notesIndent;
+ }
+ addLine(text) {
+ if (this.notesIndent === null) {
+ throw new Error(`Unable to add line, notes indent should be provided first`);
+ }
+ this.lines.push(text);
+ }
+ replaceLines(lines) {
+ if (lines.length > 1 && this.notesIndent === null) {
+ throw new Error(`Unable to add line, notes indent should be provided first`);
+ }
+ this.lines = lines;
+ }
+ getLineCount() {
+ return this.lines.length;
+ }
+ getRoot() {
+ return this.root;
+ }
+ getChildren() {
+ return this.children.concat();
+ }
+ getLinesInfo() {
+ const startLine = this.root.getContentLinesRangeOf(this)[0];
+ return this.lines.map((row, i) => {
+ const line = startLine + i;
+ const startCh = i === 0 ? this.getContentStartCh() : this.notesIndent.length;
+ const endCh = startCh + row.length;
+ return {
+ text: row,
+ from: { line, ch: startCh },
+ to: { line, ch: endCh },
+ };
+ });
+ }
+ getLines() {
+ return this.lines.concat();
+ }
+ getFirstLineContentStart() {
+ const startLine = this.root.getContentLinesRangeOf(this)[0];
+ return {
+ line: startLine,
+ ch: this.getContentStartCh(),
+ };
+ }
+ getLastLineContentEnd() {
+ const endLine = this.root.getContentLinesRangeOf(this)[1];
+ const endCh = this.lines.length === 1
+ ? this.getContentStartCh() + this.lines[0].length
+ : this.notesIndent.length + this.lines[this.lines.length - 1].length;
+ return {
+ line: endLine,
+ ch: endCh,
+ };
+ }
+ getContentStartCh() {
+ return this.indent.length + this.bullet.length + 1;
+ }
+ isFolded() {
+ if (this.foldRoot) {
+ return true;
+ }
+ if (this.parent) {
+ return this.parent.isFolded();
+ }
+ return false;
+ }
+ isFoldRoot() {
+ return this.foldRoot;
+ }
+ getTopFoldRoot() {
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ let tmp = this;
+ let foldRoot = null;
+ while (tmp) {
+ if (tmp.isFoldRoot()) {
+ foldRoot = tmp;
+ }
+ tmp = tmp.parent;
+ }
+ return foldRoot;
+ }
+ getLevel() {
+ if (!this.parent) {
+ return 0;
+ }
+ return this.parent.getLevel() + 1;
+ }
+ unindentContent(from, till) {
+ this.indent = this.indent.slice(0, from) + this.indent.slice(till);
+ if (this.notesIndent !== null) {
+ this.notesIndent =
+ this.notesIndent.slice(0, from) + this.notesIndent.slice(till);
+ }
+ for (const child of this.children) {
+ child.unindentContent(from, till);
+ }
+ }
+ indentContent(indentPos, indentChars) {
+ this.indent =
+ this.indent.slice(0, indentPos) +
+ indentChars +
+ this.indent.slice(indentPos);
+ if (this.notesIndent !== null) {
+ this.notesIndent =
+ this.notesIndent.slice(0, indentPos) +
+ indentChars +
+ this.notesIndent.slice(indentPos);
+ }
+ for (const child of this.children) {
+ child.indentContent(indentPos, indentChars);
+ }
+ }
+ getFirstLineIndent() {
+ return this.indent;
+ }
+ getBullet() {
+ return this.bullet;
+ }
+ getSpaceAfterBullet() {
+ return this.spaceAfterBullet;
+ }
+ getCheckboxLength() {
+ return this.checkboxLength;
+ }
+ replateBullet(bullet) {
+ this.bullet = bullet;
+ }
+ getParent() {
+ return this.parent;
+ }
+ addBeforeAll(list) {
+ this.children.unshift(list);
+ list.parent = this;
+ }
+ addAfterAll(list) {
+ this.children.push(list);
+ list.parent = this;
+ }
+ removeChild(list) {
+ const i = this.children.indexOf(list);
+ this.children.splice(i, 1);
+ list.parent = null;
+ }
+ addBefore(before, list) {
+ const i = this.children.indexOf(before);
+ this.children.splice(i, 0, list);
+ list.parent = this;
+ }
+ addAfter(before, list) {
+ const i = this.children.indexOf(before);
+ this.children.splice(i + 1, 0, list);
+ list.parent = this;
+ }
+ getPrevSiblingOf(list) {
+ const i = this.children.indexOf(list);
+ return i > 0 ? this.children[i - 1] : null;
+ }
+ getNextSiblingOf(list) {
+ const i = this.children.indexOf(list);
+ return i >= 0 && i < this.children.length ? this.children[i + 1] : null;
+ }
+ isEmpty() {
+ return this.children.length === 0;
+ }
+ print() {
+ let res = "";
+ for (let i = 0; i < this.lines.length; i++) {
+ res +=
+ i === 0
+ ? this.indent + this.bullet + this.spaceAfterBullet
+ : this.notesIndent;
+ res += this.lines[i];
+ res += "\n";
+ }
+ for (const child of this.children) {
+ res += child.print();
+ }
+ return res;
+ }
+}
+class Root {
+ constructor(start, end, selections) {
+ this.start = start;
+ this.end = end;
+ this.rootList = new List(this, "", "", 0, "", "", false);
+ this.selections = [];
+ this.replaceSelections(selections);
+ }
+ getRootList() {
+ return this.rootList;
+ }
+ getRange() {
+ return [Object.assign({}, this.start), Object.assign({}, this.end)];
+ }
+ getSelections() {
+ return this.selections.map((s) => ({
+ anchor: Object.assign({}, s.anchor),
+ head: Object.assign({}, s.head),
+ }));
+ }
+ hasSingleCursor() {
+ if (!this.hasSingleSelection()) {
+ return false;
+ }
+ const selection = this.selections[0];
+ return (selection.anchor.line === selection.head.line &&
+ selection.anchor.ch === selection.head.ch);
+ }
+ hasSingleSelection() {
+ return this.selections.length === 1;
+ }
+ getSelection() {
+ const selection = this.selections[this.selections.length - 1];
+ const from = selection.anchor.ch > selection.head.ch
+ ? selection.head.ch
+ : selection.anchor.ch;
+ const to = selection.anchor.ch > selection.head.ch
+ ? selection.anchor.ch
+ : selection.head.ch;
+ return Object.assign(Object.assign({}, selection), { from,
+ to });
+ }
+ getCursor() {
+ return Object.assign({}, this.selections[this.selections.length - 1].head);
+ }
+ replaceCursor(cursor) {
+ this.selections = [{ anchor: cursor, head: cursor }];
+ }
+ replaceSelections(selections) {
+ if (selections.length < 1) {
+ throw new Error(`Unable to create Root without selections`);
+ }
+ this.selections = selections;
+ }
+ getListUnderCursor() {
+ return this.getListUnderLine(this.getCursor().line);
+ }
+ getListUnderLine(line) {
+ if (line < this.start.line || line > this.end.line) {
+ return;
+ }
+ let result = null;
+ let index = this.start.line;
+ const visitArr = (ll) => {
+ for (const l of ll) {
+ const listFromLine = index;
+ const listTillLine = listFromLine + l.getLineCount() - 1;
+ if (line >= listFromLine && line <= listTillLine) {
+ result = l;
+ }
+ else {
+ index = listTillLine + 1;
+ visitArr(l.getChildren());
+ }
+ if (result !== null) {
+ return;
+ }
+ }
+ };
+ visitArr(this.rootList.getChildren());
+ return result;
+ }
+ getContentLinesRangeOf(list) {
+ let result = null;
+ let line = this.start.line;
+ const visitArr = (ll) => {
+ for (const l of ll) {
+ const listFromLine = line;
+ const listTillLine = listFromLine + l.getLineCount() - 1;
+ if (l === list) {
+ result = [listFromLine, listTillLine];
+ }
+ else {
+ line = listTillLine + 1;
+ visitArr(l.getChildren());
+ }
+ if (result !== null) {
+ return;
+ }
+ }
+ };
+ visitArr(this.rootList.getChildren());
+ return result;
+ }
+ getChildren() {
+ return this.rootList.getChildren();
+ }
+ print() {
+ let res = "";
+ for (const child of this.rootList.getChildren()) {
+ res += child.print();
+ }
+ return res.replace(/\n$/, "");
+ }
+}
+
+class CreateNewItemOperation {
+ constructor(root, defaultIndentChars, getZoomRange) {
+ this.root = root;
+ this.defaultIndentChars = defaultIndentChars;
+ this.getZoomRange = getZoomRange;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleSelection()) {
+ return;
+ }
+ const selection = root.getSelection();
+ if (!selection || selection.anchor.line !== selection.head.line) {
+ return;
+ }
+ const list = root.getListUnderCursor();
+ const lines = list.getLinesInfo();
+ if (lines.length === 1 && isEmptyLineOrEmptyCheckbox(lines[0].text)) {
+ return;
+ }
+ const cursor = root.getCursor();
+ const lineUnderCursor = lines.find((l) => l.from.line === cursor.line);
+ if (cursor.ch < lineUnderCursor.from.ch) {
+ return;
+ }
+ const { oldLines, newLines } = lines.reduce((acc, line) => {
+ if (cursor.line > line.from.line) {
+ acc.oldLines.push(line.text);
+ }
+ else if (cursor.line === line.from.line) {
+ const left = line.text.slice(0, selection.from - line.from.ch);
+ const right = line.text.slice(selection.to - line.from.ch);
+ acc.oldLines.push(left);
+ acc.newLines.push(right);
+ }
+ else if (cursor.line < line.from.line) {
+ acc.newLines.push(line.text);
+ }
+ return acc;
+ }, {
+ oldLines: [],
+ newLines: [],
+ });
+ const codeBlockBacticks = oldLines.join("\n").split("```").length - 1;
+ const isInsideCodeblock = codeBlockBacticks > 0 && codeBlockBacticks % 2 !== 0;
+ if (isInsideCodeblock) {
+ return;
+ }
+ this.stopPropagation = true;
+ this.updated = true;
+ const zoomRange = this.getZoomRange.getZoomRange();
+ const listIsZoomingRoot = Boolean(zoomRange &&
+ list.getFirstLineContentStart().line >= zoomRange.from.line &&
+ list.getLastLineContentEnd().line <= zoomRange.from.line);
+ const hasChildren = !list.isEmpty();
+ const childIsFolded = list.isFoldRoot();
+ const endPos = list.getLastLineContentEnd();
+ const endOfLine = cursor.line === endPos.line && cursor.ch === endPos.ch;
+ const onChildLevel = listIsZoomingRoot || (hasChildren && !childIsFolded && endOfLine);
+ const indent = onChildLevel
+ ? hasChildren
+ ? list.getChildren()[0].getFirstLineIndent()
+ : list.getFirstLineIndent() + this.defaultIndentChars
+ : list.getFirstLineIndent();
+ const bullet = onChildLevel && hasChildren
+ ? list.getChildren()[0].getBullet()
+ : list.getBullet();
+ const spaceAfterBullet = onChildLevel && hasChildren
+ ? list.getChildren()[0].getSpaceAfterBullet()
+ : list.getSpaceAfterBullet();
+ const prefix = oldLines[0].match(/^\[.\]/) ? "[ ] " : "";
+ const newList = new List(list.getRoot(), indent, bullet, prefix.length, spaceAfterBullet, prefix + newLines.shift(), false);
+ if (newLines.length > 0) {
+ newList.setNotesIndent(list.getNotesIndent());
+ for (const line of newLines) {
+ newList.addLine(line);
+ }
+ }
+ if (onChildLevel) {
+ list.addBeforeAll(newList);
+ }
+ else {
+ if (!childIsFolded || !endOfLine) {
+ const children = list.getChildren();
+ for (const child of children) {
+ list.removeChild(child);
+ newList.addAfterAll(child);
+ }
+ }
+ list.getParent().addAfter(list, newList);
+ }
+ list.replaceLines(oldLines);
+ const newListStart = newList.getFirstLineContentStart();
+ root.replaceCursor({
+ line: newListStart.line,
+ ch: newListStart.ch + prefix.length,
+ });
+ recalculateNumericBullets(root);
+ }
+}
+
+class EnterShouldCreateNewItemFeature {
+ constructor(plugin, settings, ime, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.betterEnter && !this.ime.isIMEOpened();
+ };
+ this.run = (editor) => {
+ const zoomRange = editor.getZoomRange();
+ const res = this.performOperation.performOperation((root) => new CreateNewItemOperation(root, this.obsidian.getDefaultIndentChars(), {
+ getZoomRange: () => zoomRange,
+ }), editor);
+ if (res.shouldUpdate && zoomRange) {
+ editor.zoomIn(zoomRange.from.line);
+ }
+ return res;
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(state.Prec.highest(view.keymap.of([
+ {
+ key: "Enter",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ ])));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class FoldFeature {
+ constructor(plugin, obsidian) {
+ this.plugin = plugin;
+ this.obsidian = obsidian;
+ this.fold = (editor) => {
+ return this.setFold(editor, "fold");
+ };
+ this.unfold = (editor) => {
+ return this.setFold(editor, "unfold");
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.addCommand({
+ id: "fold",
+ icon: "chevrons-down-up",
+ name: "Fold the list",
+ editorCallback: this.obsidian.createEditorCallback(this.fold),
+ hotkeys: [
+ {
+ modifiers: ["Mod"],
+ key: "ArrowUp",
+ },
+ ],
+ });
+ this.plugin.addCommand({
+ id: "unfold",
+ icon: "chevrons-up-down",
+ name: "Unfold the list",
+ editorCallback: this.obsidian.createEditorCallback(this.unfold),
+ hotkeys: [
+ {
+ modifiers: ["Mod"],
+ key: "ArrowDown",
+ },
+ ],
+ });
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+ setFold(editor, type) {
+ if (!this.obsidian.getObsidianFoldSettings().foldIndent) {
+ new obsidian.Notice(`Unable to ${type} because folding is disabled. Please enable "Fold indent" in Obsidian settings.`, 5000);
+ return true;
+ }
+ const cursor = editor.getCursor();
+ if (type === "fold") {
+ editor.fold(cursor.line);
+ }
+ else {
+ editor.unfold(cursor.line);
+ }
+ return true;
+ }
+}
+
+function foldInside(view, from, to) {
+ let found = null;
+ language.foldedRanges(view.state).between(from, to, (from, to) => {
+ if (!found || found.from > from)
+ found = { from, to };
+ });
+ return found;
+}
+class MyEditor {
+ constructor(e) {
+ this.e = e;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ this.view = this.e.cm;
+ }
+ getCursor() {
+ return this.e.getCursor();
+ }
+ getLine(n) {
+ return this.e.getLine(n);
+ }
+ lastLine() {
+ return this.e.lastLine();
+ }
+ listSelections() {
+ return this.e.listSelections();
+ }
+ getRange(from, to) {
+ return this.e.getRange(from, to);
+ }
+ replaceRange(replacement, from, to) {
+ return this.e.replaceRange(replacement, from, to);
+ }
+ setSelections(selections) {
+ this.e.setSelections(selections);
+ }
+ setValue(text) {
+ this.e.setValue(text);
+ }
+ getValue() {
+ return this.e.getValue();
+ }
+ offsetToPos(offset) {
+ return this.e.offsetToPos(offset);
+ }
+ posToOffset(pos) {
+ return this.e.posToOffset(pos);
+ }
+ fold(n) {
+ const { view } = this;
+ const l = view.lineBlockAt(view.state.doc.line(n + 1).from);
+ const range = language.foldable(view.state, l.from, l.to);
+ if (!range || range.from === range.to) {
+ return;
+ }
+ view.dispatch({ effects: [language.foldEffect.of(range)] });
+ }
+ unfold(n) {
+ const { view } = this;
+ const l = view.lineBlockAt(view.state.doc.line(n + 1).from);
+ const range = foldInside(view, l.from, l.to);
+ if (!range) {
+ return;
+ }
+ view.dispatch({ effects: [language.unfoldEffect.of(range)] });
+ }
+ getAllFoldedLines() {
+ const c = language.foldedRanges(this.view.state).iter();
+ const res = [];
+ while (c.value) {
+ res.push(this.offsetToPos(c.from).line);
+ c.next();
+ }
+ return res;
+ }
+ triggerOnKeyDown(e) {
+ view.runScopeHandlers(this.view, e, "editor");
+ }
+ getZoomRange() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const api = window.ObsidianZoomPlugin;
+ if (!api || !api.getZoomRange) {
+ return null;
+ }
+ return api.getZoomRange(this.e);
+ }
+ zoomOut() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const api = window.ObsidianZoomPlugin;
+ if (!api || !api.zoomOut) {
+ return;
+ }
+ api.zoomOut(this.e);
+ }
+ zoomIn(line) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const api = window.ObsidianZoomPlugin;
+ if (!api || !api.zoomIn) {
+ return;
+ }
+ api.zoomIn(this.e, line);
+ }
+}
+
+class ListLinesViewPluginValue {
+ constructor(settings, obsidian$1, parser, view) {
+ this.settings = settings;
+ this.obsidian = obsidian$1;
+ this.parser = parser;
+ this.view = view;
+ this.lineElements = [];
+ this.waitForEditor = () => {
+ const oe = this.view.state.field(obsidian.editorInfoField).editor;
+ if (!oe) {
+ setTimeout(this.waitForEditor, 0);
+ return;
+ }
+ this.editor = new MyEditor(oe);
+ this.scheduleRecalculate();
+ };
+ this.onScroll = (e) => {
+ const { scrollLeft, scrollTop } = e.target;
+ this.scroller.scrollTo(scrollLeft, scrollTop);
+ };
+ this.scheduleRecalculate = () => {
+ clearTimeout(this.scheduled);
+ this.scheduled = setTimeout(this.calculate, 0);
+ };
+ this.calculate = () => {
+ this.lines = [];
+ if (this.settings.listLines &&
+ this.obsidian.isDefaultThemeEnabled() &&
+ this.view.viewportLineBlocks.length > 0 &&
+ this.view.visibleRanges.length > 0) {
+ const fromLine = this.editor.offsetToPos(this.view.viewport.from).line;
+ const toLine = this.editor.offsetToPos(this.view.viewport.to).line;
+ const lists = this.parser.parseRange(this.editor, fromLine, toLine);
+ for (const list of lists) {
+ this.lastLine = list.getRange()[1].line;
+ for (const c of list.getChildren()) {
+ this.recursive(c);
+ }
+ }
+ this.lines.sort((a, b) => a.top === b.top ? a.left - b.left : a.top - b.top);
+ }
+ this.updateDom();
+ };
+ this.onClick = (e) => {
+ e.preventDefault();
+ const line = this.lines[Number(e.target.dataset.index)];
+ switch (this.settings.listLineAction) {
+ case "zoom-in":
+ this.zoomIn(line);
+ break;
+ case "toggle-folding":
+ this.toggleFolding(line);
+ break;
+ }
+ };
+ this.view.scrollDOM.addEventListener("scroll", this.onScroll);
+ this.settings.onChange("listLines", this.scheduleRecalculate);
+ this.prepareDom();
+ this.waitForEditor();
+ }
+ prepareDom() {
+ this.contentContainer = document.createElement("div");
+ this.contentContainer.classList.add("outliner-plugin-list-lines-content-container");
+ this.scroller = document.createElement("div");
+ this.scroller.classList.add("outliner-plugin-list-lines-scroller");
+ this.scroller.appendChild(this.contentContainer);
+ this.view.dom.appendChild(this.scroller);
+ }
+ update(update) {
+ if (update.docChanged ||
+ update.viewportChanged ||
+ update.geometryChanged ||
+ update.transactions.some((tr) => tr.reconfigured)) {
+ this.scheduleRecalculate();
+ }
+ }
+ getNextSibling(list) {
+ let listTmp = list;
+ let p = listTmp.getParent();
+ while (p) {
+ const nextSibling = p.getNextSiblingOf(listTmp);
+ if (nextSibling) {
+ return nextSibling;
+ }
+ listTmp = p;
+ p = listTmp.getParent();
+ }
+ return null;
+ }
+ recursive(list, parentCtx = {}) {
+ const children = list.getChildren();
+ if (children.length === 0) {
+ return;
+ }
+ const fromOffset = this.editor.posToOffset({
+ line: list.getFirstLineContentStart().line,
+ ch: list.getFirstLineIndent().length,
+ });
+ const nextSibling = this.getNextSibling(list);
+ const tillOffset = this.editor.posToOffset({
+ line: nextSibling
+ ? nextSibling.getFirstLineContentStart().line - 1
+ : this.lastLine,
+ ch: 0,
+ });
+ let visibleFrom = this.view.visibleRanges[0].from;
+ let visibleTo = this.view.visibleRanges[this.view.visibleRanges.length - 1].to;
+ const zoomRange = this.editor.getZoomRange();
+ if (zoomRange) {
+ visibleFrom = Math.max(visibleFrom, this.editor.posToOffset(zoomRange.from));
+ visibleTo = Math.min(visibleTo, this.editor.posToOffset(zoomRange.to));
+ }
+ if (fromOffset > visibleTo || tillOffset < visibleFrom) {
+ return;
+ }
+ const coords = this.view.coordsAtPos(fromOffset, 1);
+ if (parentCtx.rootLeft === undefined) {
+ parentCtx.rootLeft = coords.left;
+ }
+ const left = Math.floor(coords.right - parentCtx.rootLeft);
+ const top = visibleFrom > 0 && fromOffset < visibleFrom
+ ? -20
+ : this.view.lineBlockAt(fromOffset).top;
+ const bottom = tillOffset > visibleTo
+ ? this.view.lineBlockAt(visibleTo - 1).bottom
+ : this.view.lineBlockAt(tillOffset).bottom;
+ const height = bottom - top;
+ if (height > 0 && !list.isFolded()) {
+ const nextSibling = list.getParent().getNextSiblingOf(list);
+ const hasNextSibling = !!nextSibling &&
+ this.editor.posToOffset(nextSibling.getFirstLineContentStart()) <=
+ visibleTo;
+ this.lines.push({
+ top,
+ left,
+ height: `calc(${height}px ${hasNextSibling ? "- 1.5em" : "- 2em"})`,
+ list,
+ });
+ }
+ for (const child of children) {
+ if (!child.isEmpty()) {
+ this.recursive(child, parentCtx);
+ }
+ }
+ }
+ zoomIn(line) {
+ const editor = new MyEditor(this.view.state.field(obsidian.editorInfoField).editor);
+ editor.zoomIn(line.list.getFirstLineContentStart().line);
+ }
+ toggleFolding(line) {
+ const { list } = line;
+ if (list.isEmpty()) {
+ return;
+ }
+ let needToUnfold = true;
+ const linesToToggle = [];
+ for (const c of list.getChildren()) {
+ if (c.isEmpty()) {
+ continue;
+ }
+ if (!c.isFolded()) {
+ needToUnfold = false;
+ }
+ linesToToggle.push(c.getFirstLineContentStart().line);
+ }
+ const editor = new MyEditor(this.view.state.field(obsidian.editorInfoField).editor);
+ for (const l of linesToToggle) {
+ if (needToUnfold) {
+ editor.unfold(l);
+ }
+ else {
+ editor.fold(l);
+ }
+ }
+ }
+ updateDom() {
+ const cmScroll = this.view.scrollDOM;
+ const cmContent = this.view.contentDOM;
+ const cmContentContainer = cmContent.parentElement;
+ const cmSizer = cmContentContainer.parentElement;
+ /**
+ * Obsidian can add additional elements into Content Manager.
+ * The most obvious case is the 'embedded-backlinks' core plugin that adds a menu inside a Content Manager.
+ * We must take heights of all of these elements into account
+ * to be able to calculate the correct size of lines' container.
+ */
+ let cmSizerChildrenSumHeight = 0;
+ for (let i = 0; i < cmSizer.children.length; i++) {
+ cmSizerChildrenSumHeight += cmSizer.children[i].clientHeight;
+ }
+ this.scroller.style.top = cmScroll.offsetTop + "px";
+ this.contentContainer.style.height = cmSizerChildrenSumHeight + "px";
+ this.contentContainer.style.marginLeft =
+ cmContentContainer.offsetLeft + "px";
+ this.contentContainer.style.marginTop =
+ cmContent.firstElementChild.offsetTop - 24 + "px";
+ for (let i = 0; i < this.lines.length; i++) {
+ if (this.lineElements.length === i) {
+ const e = document.createElement("div");
+ e.classList.add("outliner-plugin-list-line");
+ e.dataset.index = String(i);
+ e.addEventListener("mousedown", this.onClick);
+ this.contentContainer.appendChild(e);
+ this.lineElements.push(e);
+ }
+ const l = this.lines[i];
+ const e = this.lineElements[i];
+ e.style.top = l.top + "px";
+ e.style.left = l.left + "px";
+ e.style.height = l.height;
+ e.style.display = "block";
+ }
+ for (let i = this.lines.length; i < this.lineElements.length; i++) {
+ const e = this.lineElements[i];
+ e.style.top = "0px";
+ e.style.left = "0px";
+ e.style.height = "0px";
+ e.style.display = "none";
+ }
+ }
+ destroy() {
+ this.settings.removeCallback("listLines", this.scheduleRecalculate);
+ this.view.scrollDOM.removeEventListener("scroll", this.onScroll);
+ this.view.dom.removeChild(this.scroller);
+ clearTimeout(this.scheduled);
+ }
+}
+class LinesFeature {
+ constructor(plugin, settings, obsidian, parser) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.obsidian = obsidian;
+ this.parser = parser;
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(view.ViewPlugin.define((view) => new ListLinesViewPluginValue(this.settings, this.obsidian, this.parser, view)));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+const BETTER_LISTS_CLASS = "outliner-plugin-better-lists";
+const BETTER_BULLETS_CLASS = "outliner-plugin-better-bullets";
+const VERTICAL_LINES = "outliner-plugin-vertical-lines";
+const KNOWN_CLASSES = [
+ BETTER_LISTS_CLASS,
+ BETTER_BULLETS_CLASS,
+ VERTICAL_LINES,
+];
+class ListsStylesFeature {
+ constructor(settings, obsidian) {
+ this.settings = settings;
+ this.obsidian = obsidian;
+ this.syncListsStyles = () => {
+ const classes = [];
+ if (this.obsidian.isDefaultThemeEnabled()) {
+ if (this.settings.styleLists) {
+ classes.push(BETTER_LISTS_CLASS);
+ classes.push(BETTER_BULLETS_CLASS);
+ }
+ if (this.settings.listLines) {
+ classes.push(VERTICAL_LINES);
+ }
+ }
+ this.applyListsStyles(classes);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.syncListsStyles();
+ this.interval = window.setInterval(() => {
+ this.syncListsStyles();
+ }, 1000);
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () {
+ clearInterval(this.interval);
+ this.applyListsStyles([]);
+ });
+ }
+ applyListsStyles(classes) {
+ const toKeep = classes.filter((c) => KNOWN_CLASSES.contains(c));
+ const toRemove = KNOWN_CLASSES.filter((c) => !toKeep.contains(c));
+ for (const c of toKeep) {
+ if (!document.body.classList.contains(c)) {
+ document.body.classList.add(c);
+ }
+ }
+ for (const c of toRemove) {
+ if (document.body.classList.contains(c)) {
+ document.body.classList.remove(c);
+ }
+ }
+ }
+}
+
+class MoveCursorToPreviousUnfoldedLineOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ const list = this.root.getListUnderCursor();
+ const cursor = this.root.getCursor();
+ const lines = list.getLinesInfo();
+ const lineNo = lines.findIndex((l) => cursor.ch === l.from.ch + list.getCheckboxLength() &&
+ cursor.line === l.from.line);
+ if (lineNo === 0) {
+ this.moveCursorToPreviousUnfoldedItem(root, cursor);
+ }
+ else if (lineNo > 0) {
+ this.moveCursorToPreviousNoteLine(root, lines, lineNo);
+ }
+ }
+ moveCursorToPreviousNoteLine(root, lines, lineNo) {
+ this.stopPropagation = true;
+ this.updated = true;
+ root.replaceCursor(lines[lineNo - 1].to);
+ }
+ moveCursorToPreviousUnfoldedItem(root, cursor) {
+ const prev = root.getListUnderLine(cursor.line - 1);
+ if (!prev) {
+ return;
+ }
+ this.stopPropagation = true;
+ this.updated = true;
+ if (prev.isFolded()) {
+ const foldRoot = prev.getTopFoldRoot();
+ const firstLineEnd = foldRoot.getLinesInfo()[0].to;
+ root.replaceCursor(firstLineEnd);
+ }
+ else {
+ root.replaceCursor(prev.getLastLineContentEnd());
+ }
+ }
+}
+
+class MoveCursorToPreviousUnfoldedLineFeature {
+ constructor(plugin, settings, ime, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.stickCursor && !this.ime.isIMEOpened();
+ };
+ this.run = (editor) => {
+ return this.performOperation.performOperation((root) => new MoveCursorToPreviousUnfoldedLineOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(view.keymap.of([
+ {
+ key: "ArrowLeft",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ {
+ win: "c-ArrowLeft",
+ linux: "c-ArrowLeft",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ ]));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class MoveDownOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ const list = root.getListUnderCursor();
+ const parent = list.getParent();
+ const grandParent = parent.getParent();
+ const next = parent.getNextSiblingOf(list);
+ const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
+ if (!next && grandParent) {
+ const newParent = grandParent.getNextSiblingOf(parent);
+ if (newParent) {
+ this.updated = true;
+ parent.removeChild(list);
+ newParent.addBeforeAll(list);
+ }
+ }
+ else if (next) {
+ this.updated = true;
+ parent.removeChild(list);
+ parent.addAfter(next, list);
+ }
+ if (!this.updated) {
+ return;
+ }
+ const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
+ const lineDiff = listStartLineAfter - listStartLineBefore;
+ const cursor = root.getCursor();
+ root.replaceCursor({
+ line: cursor.line + lineDiff,
+ ch: cursor.ch,
+ });
+ recalculateNumericBullets(root);
+ }
+}
+
+class MoveRightOperation {
+ constructor(root, defaultIndentChars) {
+ this.root = root;
+ this.defaultIndentChars = defaultIndentChars;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ const list = root.getListUnderCursor();
+ const parent = list.getParent();
+ const prev = parent.getPrevSiblingOf(list);
+ if (!prev) {
+ return;
+ }
+ this.updated = true;
+ const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
+ const indentPos = list.getFirstLineIndent().length;
+ let indentChars = "";
+ if (indentChars === "" && !prev.isEmpty()) {
+ indentChars = prev
+ .getChildren()[0]
+ .getFirstLineIndent()
+ .slice(prev.getFirstLineIndent().length);
+ }
+ if (indentChars === "") {
+ indentChars = list
+ .getFirstLineIndent()
+ .slice(parent.getFirstLineIndent().length);
+ }
+ if (indentChars === "" && !list.isEmpty()) {
+ indentChars = list.getChildren()[0].getFirstLineIndent();
+ }
+ if (indentChars === "") {
+ indentChars = this.defaultIndentChars;
+ }
+ parent.removeChild(list);
+ prev.addAfterAll(list);
+ list.indentContent(indentPos, indentChars);
+ const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
+ const lineDiff = listStartLineAfter - listStartLineBefore;
+ const cursor = root.getCursor();
+ root.replaceCursor({
+ line: cursor.line + lineDiff,
+ ch: cursor.ch + indentChars.length,
+ });
+ recalculateNumericBullets(root);
+ }
+}
+
+class MoveUpOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ const list = root.getListUnderCursor();
+ const parent = list.getParent();
+ const grandParent = parent.getParent();
+ const prev = parent.getPrevSiblingOf(list);
+ const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
+ if (!prev && grandParent) {
+ const newParent = grandParent.getPrevSiblingOf(parent);
+ if (newParent) {
+ this.updated = true;
+ parent.removeChild(list);
+ newParent.addAfterAll(list);
+ }
+ }
+ else if (prev) {
+ this.updated = true;
+ parent.removeChild(list);
+ parent.addBefore(prev, list);
+ }
+ if (!this.updated) {
+ return;
+ }
+ const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
+ const lineDiff = listStartLineAfter - listStartLineBefore;
+ const cursor = root.getCursor();
+ root.replaceCursor({
+ line: cursor.line + lineDiff,
+ ch: cursor.ch,
+ });
+ recalculateNumericBullets(root);
+ }
+}
+
+class MoveItemsFeature {
+ constructor(plugin, ime, obsidian, settings, performOperation) {
+ this.plugin = plugin;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.settings = settings;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.betterTab && !this.ime.isIMEOpened();
+ };
+ this.moveListElementDownCommand = (editor) => {
+ const { shouldStopPropagation } = this.performOperation.performOperation((root) => new MoveDownOperation(root), editor);
+ return shouldStopPropagation;
+ };
+ this.moveListElementUpCommand = (editor) => {
+ const { shouldStopPropagation } = this.performOperation.performOperation((root) => new MoveUpOperation(root), editor);
+ return shouldStopPropagation;
+ };
+ this.moveListElementRightCommand = (editor) => {
+ if (this.ime.isIMEOpened()) {
+ return true;
+ }
+ return this.moveListElementRight(editor).shouldStopPropagation;
+ };
+ this.moveListElementRight = (editor) => {
+ return this.performOperation.performOperation((root) => new MoveRightOperation(root, this.obsidian.getDefaultIndentChars()), editor);
+ };
+ this.moveListElementLeftCommand = (editor) => {
+ if (this.ime.isIMEOpened()) {
+ return true;
+ }
+ return this.moveListElementLeft(editor).shouldStopPropagation;
+ };
+ this.moveListElementLeft = (editor) => {
+ return this.performOperation.performOperation((root) => new MoveLeftOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.addCommand({
+ id: "move-list-item-up",
+ icon: "arrow-up",
+ name: "Move list and sublists up",
+ editorCallback: this.obsidian.createEditorCallback(this.moveListElementUpCommand),
+ hotkeys: [
+ {
+ modifiers: ["Mod", "Shift"],
+ key: "ArrowUp",
+ },
+ ],
+ });
+ this.plugin.addCommand({
+ id: "move-list-item-down",
+ icon: "arrow-down",
+ name: "Move list and sublists down",
+ editorCallback: this.obsidian.createEditorCallback(this.moveListElementDownCommand),
+ hotkeys: [
+ {
+ modifiers: ["Mod", "Shift"],
+ key: "ArrowDown",
+ },
+ ],
+ });
+ this.plugin.addCommand({
+ id: "indent-list",
+ icon: "indent",
+ name: "Indent the list and sublists",
+ editorCallback: this.obsidian.createEditorCallback(this.moveListElementRightCommand),
+ hotkeys: [],
+ });
+ this.plugin.addCommand({
+ id: "outdent-list",
+ icon: "outdent",
+ name: "Outdent the list and sublists",
+ editorCallback: this.obsidian.createEditorCallback(this.moveListElementLeftCommand),
+ hotkeys: [],
+ });
+ this.plugin.registerEditorExtension(state.Prec.highest(view.keymap.of([
+ {
+ key: "Tab",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.moveListElementRight,
+ }),
+ },
+ {
+ key: "s-Tab",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.moveListElementLeft,
+ }),
+ },
+ ])));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class SelectAllOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleSelection()) {
+ return;
+ }
+ const selection = root.getSelections()[0];
+ const [rootStart, rootEnd] = root.getRange();
+ const selectionFrom = minPos(selection.anchor, selection.head);
+ const selectionTo = maxPos(selection.anchor, selection.head);
+ if (selectionFrom.line < rootStart.line ||
+ selectionTo.line > rootEnd.line) {
+ return false;
+ }
+ if (selectionFrom.line === rootStart.line &&
+ selectionFrom.ch === rootStart.ch &&
+ selectionTo.line === rootEnd.line &&
+ selectionTo.ch === rootEnd.ch) {
+ return false;
+ }
+ const list = root.getListUnderCursor();
+ const contentStart = list.getFirstLineContentStart();
+ const contentEnd = list.getLastLineContentEnd();
+ if (selectionFrom.line < contentStart.line ||
+ selectionTo.line > contentEnd.line) {
+ return false;
+ }
+ this.stopPropagation = true;
+ this.updated = true;
+ if (selectionFrom.line === contentStart.line &&
+ selectionFrom.ch === contentStart.ch &&
+ selectionTo.line === contentEnd.line &&
+ selectionTo.ch === contentEnd.ch) {
+ // select all list
+ root.replaceSelections([{ anchor: rootStart, head: rootEnd }]);
+ }
+ else {
+ // select all line
+ root.replaceSelections([{ anchor: contentStart, head: contentEnd }]);
+ }
+ return true;
+ }
+}
+
+class SelectAllFeature {
+ constructor(plugin, settings, ime, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.selectAll && !this.ime.isIMEOpened();
+ };
+ this.run = (editor) => {
+ return this.performOperation.performOperation((root) => new SelectAllOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(view.keymap.of([
+ {
+ key: "c-a",
+ mac: "m-a",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ ]));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class SelectTillLineStartOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ this.stopPropagation = true;
+ this.updated = true;
+ const cursor = root.getCursor();
+ const list = root.getListUnderCursor();
+ const lines = list.getLinesInfo();
+ const lineNo = lines.findIndex((l) => l.from.line === cursor.line);
+ root.replaceSelections([{ head: lines[lineNo].from, anchor: cursor }]);
+ }
+}
+
+class SelectionShouldIgnoreBulletsFeature {
+ constructor(plugin, settings, ime, obsidian, performOperation) {
+ this.plugin = plugin;
+ this.settings = settings;
+ this.ime = ime;
+ this.obsidian = obsidian;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.stickCursor && !this.ime.isIMEOpened();
+ };
+ this.run = (editor) => {
+ return this.performOperation.performOperation((root) => new SelectTillLineStartOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(view.keymap.of([
+ {
+ key: "m-s-ArrowLeft",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ ]));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class ObsidianOutlinerPluginSettingTab extends obsidian.PluginSettingTab {
+ constructor(app, plugin, settings) {
+ super(app, plugin);
+ this.settings = settings;
+ }
+ display() {
+ const { containerEl } = this;
+ containerEl.empty();
+ new obsidian.Setting(containerEl)
+ .setName("Improve the style of your lists")
+ .setDesc("Styles are only compatible with built-in Obsidian themes and may not be compatible with other themes.")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.styleLists).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.styleLists = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Draw vertical indentation lines")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.listLines).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.listLines = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Vertical indentation line click action")
+ .addDropdown((dropdown) => {
+ dropdown
+ .addOptions({
+ none: "None",
+ "zoom-in": "Zoom In",
+ "toggle-folding": "Toggle Folding",
+ })
+ .setValue(this.settings.listLineAction)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.listLineAction = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Stick the cursor to the content")
+ .setDesc("Don't let the cursor move to the bullet position.")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.stickCursor).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.stickCursor = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Enhance the Enter key")
+ .setDesc("Make the Enter key behave the same as other outliners.")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.betterEnter).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.betterEnter = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Enhance the Tab key")
+ .setDesc("Make Tab and Shift-Tab behave the same as other outliners.")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.betterTab).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.betterTab = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Enhance the Ctrl+A or Cmd+A behavior")
+ .setDesc("Press the hotkey once to select the current list item. Press the hotkey twice to select the entire list.")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.selectAll).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.selectAll = value;
+ yield this.settings.save();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName("Debug mode")
+ .setDesc("Open DevTools (Command+Option+I or Control+Shift+I) to copy the debug logs.")
+ .addToggle((toggle) => {
+ toggle.setValue(this.settings.debug).onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.settings.debug = value;
+ yield this.settings.save();
+ }));
+ });
+ }
+}
+class SettingsTabFeature {
+ constructor(plugin, settings) {
+ this.plugin = plugin;
+ this.settings = settings;
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.addSettingTab(new ObsidianOutlinerPluginSettingTab(this.plugin.app, this.plugin, this.settings));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class CreateNoteLineOperation {
+ constructor(root) {
+ this.root = root;
+ this.stopPropagation = false;
+ this.updated = false;
+ }
+ shouldStopPropagation() {
+ return this.stopPropagation;
+ }
+ shouldUpdate() {
+ return this.updated;
+ }
+ perform() {
+ const { root } = this;
+ if (!root.hasSingleCursor()) {
+ return;
+ }
+ const cursor = root.getCursor();
+ const list = root.getListUnderCursor();
+ const lineUnderCursor = list
+ .getLinesInfo()
+ .find((l) => l.from.line === cursor.line);
+ if (cursor.ch < lineUnderCursor.from.ch) {
+ return;
+ }
+ this.stopPropagation = true;
+ this.updated = true;
+ if (!list.getNotesIndent()) {
+ list.setNotesIndent(list.getFirstLineIndent() + " ");
+ }
+ const lines = list.getLinesInfo().reduce((acc, line) => {
+ if (cursor.line === line.from.line) {
+ acc.push(line.text.slice(0, cursor.ch - line.from.ch));
+ acc.push(line.text.slice(cursor.ch - line.from.ch));
+ }
+ else {
+ acc.push(line.text);
+ }
+ return acc;
+ }, []);
+ list.replaceLines(lines);
+ root.replaceCursor({
+ line: cursor.line + 1,
+ ch: list.getNotesIndent().length,
+ });
+ }
+}
+
+class ShiftEnterShouldCreateNoteFeature {
+ constructor(plugin, obsidian, settings, ime, performOperation) {
+ this.plugin = plugin;
+ this.obsidian = obsidian;
+ this.settings = settings;
+ this.ime = ime;
+ this.performOperation = performOperation;
+ this.check = () => {
+ return this.settings.betterEnter && !this.ime.isIMEOpened();
+ };
+ this.run = (editor) => {
+ return this.performOperation.performOperation((root) => new CreateNoteLineOperation(root), editor);
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.plugin.registerEditorExtension(view.keymap.of([
+ {
+ key: "s-Enter",
+ run: this.obsidian.createKeymapRunCallback({
+ check: this.check,
+ run: this.run,
+ }),
+ },
+ ]));
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () { });
+ }
+}
+
+class ApplyChangesService {
+ applyChanges(editor, root) {
+ const rootRange = root.getRange();
+ const oldString = editor.getRange(rootRange[0], rootRange[1]);
+ const newString = root.print();
+ const fromLine = rootRange[0].line;
+ const toLine = rootRange[1].line;
+ for (let l = fromLine; l <= toLine; l++) {
+ editor.unfold(l);
+ }
+ const changeFrom = Object.assign({}, rootRange[0]);
+ const changeTo = Object.assign({}, rootRange[1]);
+ let oldTmp = oldString;
+ let newTmp = newString;
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ const nlIndex = oldTmp.lastIndexOf("\n");
+ if (nlIndex < 0) {
+ break;
+ }
+ const oldLine = oldTmp.slice(nlIndex);
+ const newLine = newTmp.slice(-oldLine.length);
+ if (oldLine !== newLine) {
+ break;
+ }
+ oldTmp = oldTmp.slice(0, -oldLine.length);
+ newTmp = newTmp.slice(0, -oldLine.length);
+ const nlIndex2 = oldTmp.lastIndexOf("\n");
+ changeTo.ch =
+ nlIndex2 >= 0 ? oldTmp.length - nlIndex2 - 1 : oldTmp.length;
+ changeTo.line--;
+ }
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ const nlIndex = oldTmp.indexOf("\n");
+ if (nlIndex < 0) {
+ break;
+ }
+ const oldLine = oldTmp.slice(0, nlIndex + 1);
+ const newLine = newTmp.slice(0, oldLine.length);
+ if (oldLine !== newLine) {
+ break;
+ }
+ changeFrom.line++;
+ oldTmp = oldTmp.slice(oldLine.length);
+ newTmp = newTmp.slice(oldLine.length);
+ }
+ if (oldTmp !== newTmp) {
+ editor.replaceRange(newTmp, changeFrom, changeTo);
+ }
+ editor.setSelections(root.getSelections());
+ function recursive(list) {
+ for (const c of list.getChildren()) {
+ recursive(c);
+ }
+ if (list.isFoldRoot()) {
+ editor.fold(list.getFirstLineContentStart().line);
+ }
+ }
+ for (const c of root.getChildren()) {
+ recursive(c);
+ }
+ }
+}
+
+class IMEService {
+ constructor() {
+ this.composition = false;
+ this.onCompositionStart = () => {
+ this.composition = true;
+ };
+ this.onCompositionEnd = () => {
+ this.composition = false;
+ };
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ document.addEventListener("compositionstart", this.onCompositionStart);
+ document.addEventListener("compositionend", this.onCompositionEnd);
+ });
+ }
+ unload() {
+ return __awaiter(this, void 0, void 0, function* () {
+ document.removeEventListener("compositionend", this.onCompositionEnd);
+ document.removeEventListener("compositionstart", this.onCompositionStart);
+ });
+ }
+ isIMEOpened() {
+ return this.composition && obsidian.Platform.isDesktop;
+ }
+}
+
+class LoggerService {
+ constructor(settings) {
+ this.settings = settings;
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ log(method, ...args) {
+ if (!this.settings.debug) {
+ return;
+ }
+ console.info(method, ...args);
+ }
+ bind(method) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return (...args) => this.log(method, ...args);
+ }
+}
+
+class ObsidianService {
+ constructor(app) {
+ this.app = app;
+ }
+ isLegacyEditorEnabled() {
+ const config = Object.assign({ legacyEditor: false }, this.app.vault.config);
+ return config.legacyEditor;
+ }
+ isDefaultThemeEnabled() {
+ const config = Object.assign({ cssTheme: "" }, this.app.vault.config);
+ return config.cssTheme === "";
+ }
+ getObsidianTabsSettings() {
+ return Object.assign({ useTab: true, tabSize: 4 }, this.app.vault.config);
+ }
+ getObsidianFoldSettings() {
+ return Object.assign({ foldIndent: true }, this.app.vault.config);
+ }
+ getDefaultIndentChars() {
+ const { useTab, tabSize } = this.getObsidianTabsSettings();
+ return useTab ? "\t" : new Array(tabSize).fill(" ").join("");
+ }
+ getEditorFromState(state) {
+ return new MyEditor(state.field(obsidian.editorInfoField).editor);
+ }
+ createKeymapRunCallback(config) {
+ const check = config.check || (() => true);
+ const { run } = config;
+ return (view) => {
+ const editor = this.getEditorFromState(view.state);
+ if (!check(editor)) {
+ return false;
+ }
+ const { shouldUpdate, shouldStopPropagation } = run(editor);
+ return shouldUpdate || shouldStopPropagation;
+ };
+ }
+ createEditorCallback(cb) {
+ return (editor) => {
+ const myEditor = new MyEditor(editor);
+ const shouldStopPropagation = cb(myEditor);
+ if (!shouldStopPropagation &&
+ window.event &&
+ window.event.type === "keydown") {
+ myEditor.triggerOnKeyDown(window.event);
+ }
+ };
+ }
+}
+
+const bulletSign = `(?:[-*+]|\\d+\\.)`;
+const optionalCheckbox = `(?:\\[[ xX]\\]( |\t))?`;
+const listItemWithoutSpacesRe = new RegExp(`^${bulletSign}( |\t)`);
+const listItemRe = new RegExp(`^[ \t]*${bulletSign}( |\t)`);
+const stringWithSpacesRe = new RegExp(`^[ \t]+`);
+const parseListItemRe = new RegExp(`^([ \t]*)(${bulletSign})( |\t)((${optionalCheckbox}).*)$`);
+class ParserService {
+ constructor(logger) {
+ this.logger = logger;
+ }
+ parseRange(editor, fromLine = 0, toLine = editor.lastLine()) {
+ const lists = [];
+ for (let i = fromLine; i <= toLine; i++) {
+ const line = editor.getLine(i);
+ if (i === fromLine || this.isListItem(line)) {
+ const list = this.parseWithLimits(editor, i, fromLine, toLine);
+ if (list) {
+ lists.push(list);
+ i = list.getRange()[1].line;
+ }
+ }
+ }
+ return lists;
+ }
+ parse(editor, cursor = editor.getCursor()) {
+ return this.parseWithLimits(editor, cursor.line, 0, editor.lastLine());
+ }
+ parseWithLimits(editor, parsingStartLine, limitFrom, limitTo) {
+ const d = this.logger.bind("parseList");
+ const error = (msg) => {
+ d(msg);
+ return null;
+ };
+ const line = editor.getLine(parsingStartLine);
+ let listLookingPos = null;
+ if (this.isListItem(line)) {
+ listLookingPos = parsingStartLine;
+ }
+ else if (this.isLineWithIndent(line)) {
+ let listLookingPosSearch = parsingStartLine - 1;
+ while (listLookingPosSearch >= 0) {
+ const line = editor.getLine(listLookingPosSearch);
+ if (this.isListItem(line)) {
+ listLookingPos = listLookingPosSearch;
+ break;
+ }
+ else if (this.isLineWithIndent(line)) {
+ listLookingPosSearch--;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if (listLookingPos == null) {
+ return null;
+ }
+ let listStartLine = null;
+ let listStartLineLookup = listLookingPos;
+ while (listStartLineLookup >= 0) {
+ const line = editor.getLine(listStartLineLookup);
+ if (!this.isListItem(line) && !this.isLineWithIndent(line)) {
+ break;
+ }
+ if (this.isListItemWithoutSpaces(line)) {
+ listStartLine = listStartLineLookup;
+ if (listStartLineLookup <= limitFrom) {
+ break;
+ }
+ }
+ listStartLineLookup--;
+ }
+ if (listStartLine === null) {
+ return null;
+ }
+ let listEndLine = listLookingPos;
+ let listEndLineLookup = listLookingPos;
+ while (listEndLineLookup <= editor.lastLine()) {
+ const line = editor.getLine(listEndLineLookup);
+ if (!this.isListItem(line) && !this.isLineWithIndent(line)) {
+ break;
+ }
+ if (!this.isEmptyLine(line)) {
+ listEndLine = listEndLineLookup;
+ }
+ if (listEndLineLookup >= limitTo) {
+ listEndLine = limitTo;
+ break;
+ }
+ listEndLineLookup++;
+ }
+ if (listStartLine > parsingStartLine || listEndLine < parsingStartLine) {
+ return null;
+ }
+ const root = new Root({ line: listStartLine, ch: 0 }, { line: listEndLine, ch: editor.getLine(listEndLine).length }, editor.listSelections().map((r) => ({
+ anchor: { line: r.anchor.line, ch: r.anchor.ch },
+ head: { line: r.head.line, ch: r.head.ch },
+ })));
+ let currentParent = root.getRootList();
+ let currentList = null;
+ let currentIndent = "";
+ const foldedLines = editor.getAllFoldedLines();
+ for (let l = listStartLine; l <= listEndLine; l++) {
+ const line = editor.getLine(l);
+ const matches = parseListItemRe.exec(line);
+ if (matches) {
+ const [, indent, bullet, spaceAfterBullet, content, optionalCheckbox] = matches;
+ const compareLength = Math.min(currentIndent.length, indent.length);
+ const indentSlice = indent.slice(0, compareLength);
+ const currentIndentSlice = currentIndent.slice(0, compareLength);
+ if (indentSlice !== currentIndentSlice) {
+ const expected = currentIndentSlice
+ .replace(/ /g, "S")
+ .replace(/\t/g, "T");
+ const got = indentSlice.replace(/ /g, "S").replace(/\t/g, "T");
+ return error(`Unable to parse list: expected indent "${expected}", got "${got}"`);
+ }
+ if (indent.length > currentIndent.length) {
+ currentParent = currentList;
+ currentIndent = indent;
+ }
+ else if (indent.length < currentIndent.length) {
+ while (currentParent.getFirstLineIndent().length >= indent.length &&
+ currentParent.getParent()) {
+ currentParent = currentParent.getParent();
+ }
+ currentIndent = indent;
+ }
+ const foldRoot = foldedLines.includes(l);
+ currentList = new List(root, indent, bullet, optionalCheckbox.length, spaceAfterBullet, content, foldRoot);
+ currentParent.addAfterAll(currentList);
+ }
+ else if (this.isLineWithIndent(line)) {
+ if (!currentList) {
+ return error(`Unable to parse list: expected list item, got empty line`);
+ }
+ const indentToCheck = currentList.getNotesIndent() || currentIndent;
+ if (line.indexOf(indentToCheck) !== 0) {
+ const expected = indentToCheck.replace(/ /g, "S").replace(/\t/g, "T");
+ const got = line
+ .match(/^[ \t]*/)[0]
+ .replace(/ /g, "S")
+ .replace(/\t/g, "T");
+ return error(`Unable to parse list: expected indent "${expected}", got "${got}"`);
+ }
+ if (!currentList.getNotesIndent()) {
+ const matches = line.match(/^[ \t]+/);
+ if (!matches || matches[0].length <= currentIndent.length) {
+ if (/^\s+$/.test(line)) {
+ continue;
+ }
+ return error(`Unable to parse list: expected some indent, got no indent`);
+ }
+ currentList.setNotesIndent(matches[0]);
+ }
+ currentList.addLine(line.slice(currentList.getNotesIndent().length));
+ }
+ else {
+ return error(`Unable to parse list: expected list item or note, got "${line}"`);
+ }
+ }
+ return root;
+ }
+ isEmptyLine(line) {
+ return line.length === 0;
+ }
+ isLineWithIndent(line) {
+ return stringWithSpacesRe.test(line);
+ }
+ isListItem(line) {
+ return listItemRe.test(line);
+ }
+ isListItemWithoutSpaces(line) {
+ return listItemWithoutSpacesRe.test(line);
+ }
+}
+
+class PerformOperationService {
+ constructor(parser, applyChanges) {
+ this.parser = parser;
+ this.applyChanges = applyChanges;
+ }
+ evalOperation(root, op, editor) {
+ op.perform();
+ if (op.shouldUpdate()) {
+ this.applyChanges.applyChanges(editor, root);
+ }
+ return {
+ shouldUpdate: op.shouldUpdate(),
+ shouldStopPropagation: op.shouldStopPropagation(),
+ };
+ }
+ performOperation(cb, editor, cursor = editor.getCursor()) {
+ const root = this.parser.parse(editor, cursor);
+ if (!root) {
+ return { shouldUpdate: false, shouldStopPropagation: false };
+ }
+ const op = cb(root);
+ return this.evalOperation(root, op, editor);
+ }
+}
+
+const DEFAULT_SETTINGS = {
+ styleLists: true,
+ debug: false,
+ stickCursor: true,
+ betterEnter: true,
+ betterTab: true,
+ selectAll: true,
+ listLines: false,
+ listLineAction: "toggle-folding",
+};
+class SettingsService {
+ constructor(storage) {
+ this.storage = storage;
+ this.handlers = new Map();
+ }
+ get styleLists() {
+ return this.values.styleLists;
+ }
+ set styleLists(value) {
+ this.set("styleLists", value);
+ }
+ get debug() {
+ return this.values.debug;
+ }
+ set debug(value) {
+ this.set("debug", value);
+ }
+ get stickCursor() {
+ return this.values.stickCursor;
+ }
+ set stickCursor(value) {
+ this.set("stickCursor", value);
+ }
+ get betterEnter() {
+ return this.values.betterEnter;
+ }
+ set betterEnter(value) {
+ this.set("betterEnter", value);
+ }
+ get betterTab() {
+ return this.values.betterTab;
+ }
+ set betterTab(value) {
+ this.set("betterTab", value);
+ }
+ get selectAll() {
+ return this.values.selectAll;
+ }
+ set selectAll(value) {
+ this.set("selectAll", value);
+ }
+ get listLines() {
+ return this.values.listLines;
+ }
+ set listLines(value) {
+ this.set("listLines", value);
+ }
+ get listLineAction() {
+ return this.values.listLineAction;
+ }
+ set listLineAction(value) {
+ this.set("listLineAction", value);
+ }
+ onChange(key, cb) {
+ if (!this.handlers.has(key)) {
+ this.handlers.set(key, new Set());
+ }
+ this.handlers.get(key).add(cb);
+ }
+ removeCallback(key, cb) {
+ const handlers = this.handlers.get(key);
+ if (handlers) {
+ handlers.delete(cb);
+ }
+ }
+ reset() {
+ for (const [k, v] of Object.entries(DEFAULT_SETTINGS)) {
+ this.set(k, v);
+ }
+ }
+ load() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.values = Object.assign({}, DEFAULT_SETTINGS, yield this.storage.loadData());
+ });
+ }
+ save() {
+ return __awaiter(this, void 0, void 0, function* () {
+ yield this.storage.saveData(this.values);
+ });
+ }
+ set(key, value) {
+ this.values[key] = value;
+ const callbacks = this.handlers.get(key);
+ if (!callbacks) {
+ return;
+ }
+ for (const cb of callbacks.values()) {
+ cb(value);
+ }
+ }
+}
+
+class ObsidianOutlinerPlugin extends obsidian.Plugin {
+ onload() {
+ return __awaiter(this, void 0, void 0, function* () {
+ console.log(`Loading obsidian-outliner`);
+ this.obsidian = new ObsidianService(this.app);
+ this.settings = new SettingsService(this);
+ yield this.settings.load();
+ this.logger = new LoggerService(this.settings);
+ this.parser = new ParserService(this.logger);
+ this.applyChanges = new ApplyChangesService();
+ this.performOperation = new PerformOperationService(this.parser, this.applyChanges);
+ this.ime = new IMEService();
+ yield this.ime.load();
+ this.features = [
+ new SettingsTabFeature(this, this.settings),
+ new ListsStylesFeature(this.settings, this.obsidian),
+ new EnterOutdentIfLineIsEmptyFeature(this, this.settings, this.ime, this.obsidian, this.performOperation),
+ new EnterShouldCreateNewItemFeature(this, this.settings, this.ime, this.obsidian, this.performOperation),
+ new EnsureCursorInListContentFeature(this, this.settings, this.obsidian, this.performOperation),
+ new MoveCursorToPreviousUnfoldedLineFeature(this, this.settings, this.ime, this.obsidian, this.performOperation),
+ new DeleteShouldIgnoreBulletsFeature(this, this.settings, this.ime, this.obsidian, this.performOperation),
+ new SelectionShouldIgnoreBulletsFeature(this, this.settings, this.ime, this.obsidian, this.performOperation),
+ new FoldFeature(this, this.obsidian),
+ new SelectAllFeature(this, this.settings, this.ime, this.obsidian, this.performOperation),
+ new MoveItemsFeature(this, this.ime, this.obsidian, this.settings, this.performOperation),
+ new ShiftEnterShouldCreateNoteFeature(this, this.obsidian, this.settings, this.ime, this.performOperation),
+ new LinesFeature(this, this.settings, this.obsidian, this.parser),
+ ];
+ for (const feature of this.features) {
+ yield feature.load();
+ }
+ });
+ }
+ onunload() {
+ return __awaiter(this, void 0, void 0, function* () {
+ console.log(`Unloading obsidian-outliner`);
+ yield this.ime.unload();
+ for (const feature of this.features) {
+ yield feature.unload();
+ }
+ });
+ }
+}
+
+module.exports = ObsidianOutlinerPlugin;
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9yb290L3JlY2FsY3VsYXRlTnVtZXJpY0J1bGxldHMudHMiLCJzcmMvb3BlcmF0aW9ucy9EZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91c0xpbmVPcGVyYXRpb24udHMiLCJzcmMvb3BlcmF0aW9ucy9EZWxldGVBbmRNZXJnZVdpdGhOZXh0TGluZU9wZXJhdGlvbi50cyIsInNyYy9vcGVyYXRpb25zL0RlbGV0ZVRpbGxMaW5lU3RhcnRPcGVyYXRpb24udHMiLCJzcmMvZmVhdHVyZXMvRGVsZXRlU2hvdWxkSWdub3JlQnVsbGV0c0ZlYXR1cmUudHMiLCJzcmMvb3BlcmF0aW9ucy9FbnN1cmVDdXJzb3JJbkxpc3RDb250ZW50T3BlcmF0aW9uLnRzIiwic3JjL29wZXJhdGlvbnMvRW5zdXJlQ3Vyc29ySXNJblVuZm9sZGVkTGluZU9wZXJhdGlvbi50cyIsInNyYy9mZWF0dXJlcy9FbnN1cmVDdXJzb3JJbkxpc3RDb250ZW50RmVhdHVyZS50cyIsInNyYy9vcGVyYXRpb25zL01vdmVMZWZ0T3BlcmF0aW9uLnRzIiwic3JjL3V0aWxzL2lzRW1wdHlMaW5lT3JFbXB0eUNoZWNrYm94LnRzIiwic3JjL29wZXJhdGlvbnMvT3V0ZGVudElmTGluZUlzRW1wdHlPcGVyYXRpb24udHMiLCJzcmMvZmVhdHVyZXMvRW50ZXJPdXRkZW50SWZMaW5lSXNFbXB0eUZlYXR1cmUudHMiLCJzcmMvcm9vdC9pbmRleC50cyIsInNyYy9vcGVyYXRpb25zL0NyZWF0ZU5ld0l0ZW1PcGVyYXRpb24udHMiLCJzcmMvZmVhdHVyZXMvRW50ZXJTaG91bGRDcmVhdGVOZXdJdGVtT25DaGlsZExldmVsRmVhdHVyZS50cyIsInNyYy9mZWF0dXJlcy9Gb2xkRmVhdHVyZS50cyIsInNyYy9NeUVkaXRvci50cyIsInNyYy9mZWF0dXJlcy9MaW5lc0ZlYXR1cmUudHMiLCJzcmMvZmVhdHVyZXMvTGlzdHNTdHlsZXNGZWF0dXJlLnRzIiwic3JjL29wZXJhdGlvbnMvTW92ZUN1cnNvclRvUHJldmlvdXNVbmZvbGRlZExpbmVPcGVyYXRpb24udHMiLCJzcmMvZmVhdHVyZXMvTW92ZUN1cnNvclRvUHJldmlvdXNVbmZvbGRlZExpbmVGZWF0dXJlLnRzIiwic3JjL29wZXJhdGlvbnMvTW92ZURvd25PcGVyYXRpb24udHMiLCJzcmMvb3BlcmF0aW9ucy9Nb3ZlUmlnaHRPcGVyYXRpb24udHMiLCJzcmMvb3BlcmF0aW9ucy9Nb3ZlVXBPcGVyYXRpb24udHMiLCJzcmMvZmVhdHVyZXMvTW92ZUl0ZW1zRmVhdHVyZS50cyIsInNyYy9vcGVyYXRpb25zL1NlbGVjdEFsbE9wZXJhdGlvbi50cyIsInNyYy9mZWF0dXJlcy9TZWxlY3RBbGxGZWF0dXJlLnRzIiwic3JjL29wZXJhdGlvbnMvU2VsZWN0VGlsbExpbmVTdGFydE9wZXJhdGlvbi50cyIsInNyYy9mZWF0dXJlcy9TZWxlY3Rpb25TaG91bGRJZ25vcmVCdWxsZXRzRmVhdHVyZS50cyIsInNyYy9mZWF0dXJlcy9TZXR0aW5nc1RhYkZlYXR1cmUudHMiLCJzcmMvb3BlcmF0aW9ucy9DcmVhdGVOb3RlTGluZU9wZXJhdGlvbi50cyIsInNyYy9mZWF0dXJlcy9TaGlmdEVudGVyU2hvdWxkQ3JlYXRlTm90ZUZlYXR1cmUudHMiLCJzcmMvc2VydmljZXMvQXBwbHlDaGFuZ2VzU2VydmljZS50cyIsInNyYy9zZXJ2aWNlcy9JTUVTZXJ2aWNlLnRzIiwic3JjL3NlcnZpY2VzL0xvZ2dlclNlcnZpY2UudHMiLCJzcmMvc2VydmljZXMvT2JzaWRpYW5TZXJ2aWNlLnRzIiwic3JjL3NlcnZpY2VzL1BhcnNlclNlcnZpY2UudHMiLCJzcmMvc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UudHMiLCJzcmMvc2VydmljZXMvU2V0dGluZ3NTZXJ2aWNlLnRzIiwic3JjL09ic2lkaWFuT3V0bGluZXJQbHVnaW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XHJcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xyXG4gICAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XHJcbiAgICB9XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBuID09PSBcInJldHVyblwiIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSBfX2NyZWF0ZUJpbmRpbmcocmVzdWx0LCBtb2QsIGspO1xyXG4gICAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEluKHN0YXRlLCByZWNlaXZlcikge1xyXG4gICAgaWYgKHJlY2VpdmVyID09PSBudWxsIHx8ICh0eXBlb2YgcmVjZWl2ZXIgIT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHJlY2VpdmVyICE9PSBcImZ1bmN0aW9uXCIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHVzZSAnaW4nIG9wZXJhdG9yIG9uIG5vbi1vYmplY3RcIik7XHJcbiAgICByZXR1cm4gdHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciA9PT0gc3RhdGUgOiBzdGF0ZS5oYXMocmVjZWl2ZXIpO1xyXG59XHJcbiIsImltcG9ydCB7IExpc3QsIFJvb3QgfSBmcm9tIFwiLlwiO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0cyhyb290OiBSb290KSB7XG4gIGZ1bmN0aW9uIHZpc2l0KHBhcmVudDogUm9vdCB8IExpc3QpIHtcbiAgICBsZXQgaW5kZXggPSAxO1xuXG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBwYXJlbnQuZ2V0Q2hpbGRyZW4oKSkge1xuICAgICAgaWYgKC9cXGQrXFwuLy50ZXN0KGNoaWxkLmdldEJ1bGxldCgpKSkge1xuICAgICAgICBjaGlsZC5yZXBsYXRlQnVsbGV0KGAke2luZGV4Kyt9LmApO1xuICAgICAgfVxuXG4gICAgICB2aXNpdChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgdmlzaXQocm9vdCk7XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgTGlzdCwgTGlzdExpbmUsIFBvc2l0aW9uLCBSb290IH0gZnJvbSBcIi4uL3Jvb3RcIjtcbmltcG9ydCB7IHJlY2FsY3VsYXRlTnVtZXJpY0J1bGxldHMgfSBmcm9tIFwiLi4vcm9vdC9yZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzXCI7XG5cbmV4cG9ydCBjbGFzcyBEZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91c0xpbmVPcGVyYXRpb24gaW1wbGVtZW50cyBPcGVyYXRpb24ge1xuICBwcml2YXRlIHN0b3BQcm9wYWdhdGlvbiA9IGZhbHNlO1xuICBwcml2YXRlIHVwZGF0ZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJvb3Q6IFJvb3QpIHt9XG5cbiAgc2hvdWxkU3RvcFByb3BhZ2F0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnN0b3BQcm9wYWdhdGlvbjtcbiAgfVxuXG4gIHNob3VsZFVwZGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy51cGRhdGVkO1xuICB9XG5cbiAgcGVyZm9ybSgpIHtcbiAgICBjb25zdCB7IHJvb3QgfSA9IHRoaXM7XG5cbiAgICBpZiAoIXJvb3QuaGFzU2luZ2xlQ3Vyc29yKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsaXN0ID0gcm9vdC5nZXRMaXN0VW5kZXJDdXJzb3IoKTtcbiAgICBjb25zdCBjdXJzb3IgPSByb290LmdldEN1cnNvcigpO1xuICAgIGNvbnN0IGxpbmVzID0gbGlzdC5nZXRMaW5lc0luZm8oKTtcblxuICAgIGNvbnN0IGxpbmVObyA9IGxpbmVzLmZpbmRJbmRleChcbiAgICAgIChsKSA9PiBjdXJzb3IuY2ggPT09IGwuZnJvbS5jaCAmJiBjdXJzb3IubGluZSA9PT0gbC5mcm9tLmxpbmVcbiAgICApO1xuXG4gICAgaWYgKGxpbmVObyA9PT0gMCkge1xuICAgICAgdGhpcy5tZXJnZVdpdGhQcmV2aW91c0l0ZW0ocm9vdCwgY3Vyc29yLCBsaXN0KTtcbiAgICB9IGVsc2UgaWYgKGxpbmVObyA+IDApIHtcbiAgICAgIHRoaXMubWVyZ2VOb3Rlcyhyb290LCBjdXJzb3IsIGxpc3QsIGxpbmVzLCBsaW5lTm8pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWVyZ2VOb3RlcyhcbiAgICByb290OiBSb290LFxuICAgIGN1cnNvcjogUG9zaXRpb24sXG4gICAgbGlzdDogTGlzdCxcbiAgICBsaW5lczogTGlzdExpbmVbXSxcbiAgICBsaW5lTm86IG51bWJlclxuICApIHtcbiAgICB0aGlzLnN0b3BQcm9wYWdhdGlvbiA9IHRydWU7XG4gICAgdGhpcy51cGRhdGVkID0gdHJ1ZTtcblxuICAgIGNvbnN0IHByZXZMaW5lTm8gPSBsaW5lTm8gLSAxO1xuXG4gICAgcm9vdC5yZXBsYWNlQ3Vyc29yKHtcbiAgICAgIGxpbmU6IGN1cnNvci5saW5lIC0gMSxcbiAgICAgIGNoOiBsaW5lc1twcmV2TGluZU5vXS50ZXh0Lmxlbmd0aCArIGxpbmVzW3ByZXZMaW5lTm9dLmZyb20uY2gsXG4gICAgfSk7XG5cbiAgICBsaW5lc1twcmV2TGluZU5vXS50ZXh0ICs9IGxpbmVzW2xpbmVOb10udGV4dDtcbiAgICBsaW5lcy5zcGxpY2UobGluZU5vLCAxKTtcblxuICAgIGxpc3QucmVwbGFjZUxpbmVzKGxpbmVzLm1hcCgobCkgPT4gbC50ZXh0KSk7XG4gIH1cblxuICBwcml2YXRlIG1lcmdlV2l0aFByZXZpb3VzSXRlbShyb290OiBSb290LCBjdXJzb3I6IFBvc2l0aW9uLCBsaXN0OiBMaXN0KSB7XG4gICAgaWYgKHJvb3QuZ2V0Q2hpbGRyZW4oKVswXSA9PT0gbGlzdCAmJiBsaXN0LmdldENoaWxkcmVuKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuXG4gICAgY29uc3QgcHJldiA9IHJvb3QuZ2V0TGlzdFVuZGVyTGluZShjdXJzb3IubGluZSAtIDEpO1xuXG4gICAgaWYgKCFwcmV2KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYm90aEFyZUVtcHR5ID0gcHJldi5pc0VtcHR5KCkgJiYgbGlzdC5pc0VtcHR5KCk7XG4gICAgY29uc3QgcHJldklzRW1wdHlBbmRTYW1lTGV2ZWwgPVxuICAgICAgcHJldi5pc0VtcHR5KCkgJiYgIWxpc3QuaXNFbXB0eSgpICYmIHByZXYuZ2V0TGV2ZWwoKSA9PSBsaXN0LmdldExldmVsKCk7XG4gICAgY29uc3QgbGlzdElzRW1wdHlBbmRQcmV2SXNQYXJlbnQgPVxuICAgICAgbGlzdC5pc0VtcHR5KCkgJiYgcHJldi5nZXRMZXZlbCgpID09IGxpc3QuZ2V0TGV2ZWwoKSAtIDE7XG5cbiAgICBpZiAoYm90aEFyZUVtcHR5IHx8IHByZXZJc0VtcHR5QW5kU2FtZUxldmVsIHx8IGxpc3RJc0VtcHR5QW5kUHJldklzUGFyZW50KSB7XG4gICAgICB0aGlzLnVwZGF0ZWQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBwYXJlbnQgPSBsaXN0LmdldFBhcmVudCgpO1xuICAgICAgY29uc3QgcHJldkVuZCA9IHByZXYuZ2V0TGFzdExpbmVDb250ZW50RW5kKCk7XG5cbiAgICAgIGlmICghcHJldi5nZXROb3Rlc0luZGVudCgpICYmIGxpc3QuZ2V0Tm90ZXNJbmRlbnQoKSkge1xuICAgICAgICBwcmV2LnNldE5vdGVzSW5kZW50KFxuICAgICAgICAgIHByZXYuZ2V0Rmlyc3RMaW5lSW5kZW50KCkgK1xuICAgICAgICAgICAgbGlzdC5nZXROb3Rlc0luZGVudCgpLnNsaWNlKGxpc3QuZ2V0Rmlyc3RMaW5lSW5kZW50KCkubGVuZ3RoKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvbGRMaW5lcyA9IHByZXYuZ2V0TGluZXMoKTtcbiAgICAgIGNvbnN0IG5ld0xpbmVzID0gbGlzdC5nZXRMaW5lcygpO1xuICAgICAgb2xkTGluZXNbb2xkTGluZXMubGVuZ3RoIC0gMV0gKz0gbmV3TGluZXNbMF07XG4gICAgICBjb25zdCByZXN1bHRMaW5lcyA9IG9sZExpbmVzLmNvbmNhdChuZXdMaW5lcy5zbGljZSgxKSk7XG5cbiAgICAgIHByZXYucmVwbGFjZUxpbmVzKHJlc3VsdExpbmVzKTtcbiAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChsaXN0KTtcblxuICAgICAgZm9yIChjb25zdCBjIG9mIGxpc3QuZ2V0Q2hpbGRyZW4oKSkge1xuICAgICAgICBsaXN0LnJlbW92ZUNoaWxkKGMpO1xuICAgICAgICBwcmV2LmFkZEFmdGVyQWxsKGMpO1xuICAgICAgfVxuXG4gICAgICByb290LnJlcGxhY2VDdXJzb3IocHJldkVuZCk7XG5cbiAgICAgIHJlY2FsY3VsYXRlTnVtZXJpY0J1bGxldHMocm9vdCk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBEZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91c0xpbmVPcGVyYXRpb24gfSBmcm9tIFwiLi9EZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91c0xpbmVPcGVyYXRpb25cIjtcbmltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gXCIuL09wZXJhdGlvblwiO1xuXG5pbXBvcnQgeyBSb290IH0gZnJvbSBcIi4uL3Jvb3RcIjtcblxuZXhwb3J0IGNsYXNzIERlbGV0ZUFuZE1lcmdlV2l0aE5leHRMaW5lT3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBkZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91czogRGVsZXRlQW5kTWVyZ2VXaXRoUHJldmlvdXNMaW5lT3BlcmF0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcm9vdDogUm9vdCkge1xuICAgIHRoaXMuZGVsZXRlQW5kTWVyZ2VXaXRoUHJldmlvdXMgPVxuICAgICAgbmV3IERlbGV0ZUFuZE1lcmdlV2l0aFByZXZpb3VzTGluZU9wZXJhdGlvbihyb290KTtcbiAgfVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5kZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91cy5zaG91bGRTdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIHNob3VsZFVwZGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5kZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91cy5zaG91bGRVcGRhdGUoKTtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbGlzdCA9IHJvb3QuZ2V0TGlzdFVuZGVyQ3Vyc29yKCk7XG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcbiAgICBjb25zdCBsaW5lcyA9IGxpc3QuZ2V0TGluZXNJbmZvKCk7XG5cbiAgICBjb25zdCBsaW5lTm8gPSBsaW5lcy5maW5kSW5kZXgoXG4gICAgICAobCkgPT4gY3Vyc29yLmNoID09PSBsLnRvLmNoICYmIGN1cnNvci5saW5lID09PSBsLnRvLmxpbmVcbiAgICApO1xuXG4gICAgaWYgKGxpbmVObyA9PT0gbGluZXMubGVuZ3RoIC0gMSkge1xuICAgICAgY29uc3QgbmV4dExpbmUgPSBsaW5lc1tsaW5lTm9dLnRvLmxpbmUgKyAxO1xuICAgICAgY29uc3QgbmV4dExpc3QgPSByb290LmdldExpc3RVbmRlckxpbmUobmV4dExpbmUpO1xuICAgICAgaWYgKCFuZXh0TGlzdCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByb290LnJlcGxhY2VDdXJzb3IobmV4dExpc3QuZ2V0Rmlyc3RMaW5lQ29udGVudFN0YXJ0KCkpO1xuICAgICAgdGhpcy5kZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91cy5wZXJmb3JtKCk7XG4gICAgfSBlbHNlIGlmIChsaW5lTm8gPj0gMCkge1xuICAgICAgcm9vdC5yZXBsYWNlQ3Vyc29yKGxpbmVzW2xpbmVObyArIDFdLmZyb20pO1xuICAgICAgdGhpcy5kZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91cy5wZXJmb3JtKCk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5cbmV4cG9ydCBjbGFzcyBEZWxldGVUaWxsTGluZVN0YXJ0T3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICBjb25zdCBjdXJzb3IgPSByb290LmdldEN1cnNvcigpO1xuICAgIGNvbnN0IGxpc3QgPSByb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGNvbnN0IGxpbmVzID0gbGlzdC5nZXRMaW5lc0luZm8oKTtcbiAgICBjb25zdCBsaW5lTm8gPSBsaW5lcy5maW5kSW5kZXgoKGwpID0+IGwuZnJvbS5saW5lID09PSBjdXJzb3IubGluZSk7XG5cbiAgICBsaW5lc1tsaW5lTm9dLnRleHQgPSBsaW5lc1tsaW5lTm9dLnRleHQuc2xpY2UoXG4gICAgICBjdXJzb3IuY2ggLSBsaW5lc1tsaW5lTm9dLmZyb20uY2hcbiAgICApO1xuXG4gICAgbGlzdC5yZXBsYWNlTGluZXMobGluZXMubWFwKChsKSA9PiBsLnRleHQpKTtcbiAgICByb290LnJlcGxhY2VDdXJzb3IobGluZXNbbGluZU5vXS5mcm9tKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgUGx1Z2luXzIgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IHsga2V5bWFwIH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcblxuaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuL0ZlYXR1cmVcIjtcblxuaW1wb3J0IHsgTXlFZGl0b3IgfSBmcm9tIFwiLi4vTXlFZGl0b3JcIjtcbmltcG9ydCB7IERlbGV0ZUFuZE1lcmdlV2l0aE5leHRMaW5lT3BlcmF0aW9uIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvRGVsZXRlQW5kTWVyZ2VXaXRoTmV4dExpbmVPcGVyYXRpb25cIjtcbmltcG9ydCB7IERlbGV0ZUFuZE1lcmdlV2l0aFByZXZpb3VzTGluZU9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL0RlbGV0ZUFuZE1lcmdlV2l0aFByZXZpb3VzTGluZU9wZXJhdGlvblwiO1xuaW1wb3J0IHsgRGVsZXRlVGlsbExpbmVTdGFydE9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL0RlbGV0ZVRpbGxMaW5lU3RhcnRPcGVyYXRpb25cIjtcbmltcG9ydCB7IElNRVNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvSU1FU2VydmljZVwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIERlbGV0ZVNob3VsZElnbm9yZUJ1bGxldHNGZWF0dXJlIGltcGxlbWVudHMgRmVhdHVyZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcGx1Z2luOiBQbHVnaW5fMixcbiAgICBwcml2YXRlIHNldHRpbmdzOiBTZXR0aW5nc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBpbWU6IElNRVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgcGVyZm9ybU9wZXJhdGlvbjogUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24oXG4gICAgICBrZXltYXAub2YoW1xuICAgICAgICB7XG4gICAgICAgICAga2V5OiBcIkJhY2tzcGFjZVwiLFxuICAgICAgICAgIHJ1bjogdGhpcy5vYnNpZGlhbi5jcmVhdGVLZXltYXBSdW5DYWxsYmFjayh7XG4gICAgICAgICAgICBjaGVjazogdGhpcy5jaGVjayxcbiAgICAgICAgICAgIHJ1bjogdGhpcy5kZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91c0xpbmUsXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6IFwiRGVsZXRlXCIsXG4gICAgICAgICAgcnVuOiB0aGlzLm9ic2lkaWFuLmNyZWF0ZUtleW1hcFJ1bkNhbGxiYWNrKHtcbiAgICAgICAgICAgIGNoZWNrOiB0aGlzLmNoZWNrLFxuICAgICAgICAgICAgcnVuOiB0aGlzLmRlbGV0ZUFuZE1lcmdlV2l0aE5leHRMaW5lLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbWFjOiBcIm0tQmFja3NwYWNlXCIsXG4gICAgICAgICAgcnVuOiB0aGlzLm9ic2lkaWFuLmNyZWF0ZUtleW1hcFJ1bkNhbGxiYWNrKHtcbiAgICAgICAgICAgIGNoZWNrOiB0aGlzLmNoZWNrLFxuICAgICAgICAgICAgcnVuOiB0aGlzLmRlbGV0ZVRpbGxMaW5lU3RhcnQsXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICBdKVxuICAgICk7XG4gIH1cblxuICBhc3luYyB1bmxvYWQoKSB7fVxuXG4gIHByaXZhdGUgY2hlY2sgPSAoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0dGluZ3Muc3RpY2tDdXJzb3IgJiYgIXRoaXMuaW1lLmlzSU1FT3BlbmVkKCk7XG4gIH07XG5cbiAgcHJpdmF0ZSBkZWxldGVBbmRNZXJnZVdpdGhQcmV2aW91c0xpbmUgPSAoZWRpdG9yOiBNeUVkaXRvcikgPT4ge1xuICAgIHJldHVybiB0aGlzLnBlcmZvcm1PcGVyYXRpb24ucGVyZm9ybU9wZXJhdGlvbihcbiAgICAgIChyb290KSA9PiBuZXcgRGVsZXRlQW5kTWVyZ2VXaXRoUHJldmlvdXNMaW5lT3BlcmF0aW9uKHJvb3QpLFxuICAgICAgZWRpdG9yXG4gICAgKTtcbiAgfTtcblxuICBwcml2YXRlIGRlbGV0ZVRpbGxMaW5lU3RhcnQgPSAoZWRpdG9yOiBNeUVkaXRvcikgPT4ge1xuICAgIHJldHVybiB0aGlzLnBlcmZvcm1PcGVyYXRpb24ucGVyZm9ybU9wZXJhdGlvbihcbiAgICAgIChyb290KSA9PiBuZXcgRGVsZXRlVGlsbExpbmVTdGFydE9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG4gIH07XG5cbiAgcHJpdmF0ZSBkZWxldGVBbmRNZXJnZVdpdGhOZXh0TGluZSA9IChlZGl0b3I6IE15RWRpdG9yKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucGVyZm9ybU9wZXJhdGlvbi5wZXJmb3JtT3BlcmF0aW9uKFxuICAgICAgKHJvb3QpID0+IG5ldyBEZWxldGVBbmRNZXJnZVdpdGhOZXh0TGluZU9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5cbmV4cG9ydCBjbGFzcyBFbnN1cmVDdXJzb3JJbkxpc3RDb250ZW50T3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuXG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcbiAgICBjb25zdCBsaXN0ID0gcm9vdC5nZXRMaXN0VW5kZXJDdXJzb3IoKTtcbiAgICBjb25zdCBjb250ZW50U3RhcnQgPSBsaXN0LmdldEZpcnN0TGluZUNvbnRlbnRTdGFydCgpO1xuICAgIGNvbnN0IGxpbmVQcmVmaXggPVxuICAgICAgY29udGVudFN0YXJ0LmxpbmUgPT09IGN1cnNvci5saW5lXG4gICAgICAgID8gY29udGVudFN0YXJ0LmNoICsgbGlzdC5nZXRDaGVja2JveExlbmd0aCgpXG4gICAgICAgIDogbGlzdC5nZXROb3Rlc0luZGVudCgpLmxlbmd0aDtcblxuICAgIGlmIChjdXJzb3IuY2ggPCBsaW5lUHJlZml4KSB7XG4gICAgICB0aGlzLnVwZGF0ZWQgPSB0cnVlO1xuICAgICAgcm9vdC5yZXBsYWNlQ3Vyc29yKHtcbiAgICAgICAgbGluZTogY3Vyc29yLmxpbmUsXG4gICAgICAgIGNoOiBsaW5lUHJlZml4LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5cbmV4cG9ydCBjbGFzcyBFbnN1cmVDdXJzb3JJc0luVW5mb2xkZWRMaW5lT3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuXG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcblxuICAgIGNvbnN0IGxpc3QgPSByb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGlmICghbGlzdC5pc0ZvbGRlZCgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZm9sZFJvb3QgPSBsaXN0LmdldFRvcEZvbGRSb290KCk7XG4gICAgY29uc3QgZmlyc3RMaW5lRW5kID0gZm9sZFJvb3QuZ2V0TGluZXNJbmZvKClbMF0udG87XG5cbiAgICBpZiAoY3Vyc29yLmxpbmUgPiBmaXJzdExpbmVFbmQubGluZSkge1xuICAgICAgdGhpcy51cGRhdGVkID0gdHJ1ZTtcbiAgICAgIHJvb3QucmVwbGFjZUN1cnNvcihmaXJzdExpbmVFbmQpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHsgUGx1Z2luXzIgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IHsgRWRpdG9yU3RhdGUsIFRyYW5zYWN0aW9uIH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5cbmltcG9ydCB7IE15RWRpdG9yIH0gZnJvbSBcIi4uL015RWRpdG9yXCI7XG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4uL2ZlYXR1cmVzL0ZlYXR1cmVcIjtcbmltcG9ydCB7IEVuc3VyZUN1cnNvckluTGlzdENvbnRlbnRPcGVyYXRpb24gfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9FbnN1cmVDdXJzb3JJbkxpc3RDb250ZW50T3BlcmF0aW9uXCI7XG5pbXBvcnQgeyBFbnN1cmVDdXJzb3JJc0luVW5mb2xkZWRMaW5lT3BlcmF0aW9uIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvRW5zdXJlQ3Vyc29ySXNJblVuZm9sZGVkTGluZU9wZXJhdGlvblwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIEVuc3VyZUN1cnNvckluTGlzdENvbnRlbnRGZWF0dXJlIGltcGxlbWVudHMgRmVhdHVyZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcGx1Z2luOiBQbHVnaW5fMixcbiAgICBwcml2YXRlIHNldHRpbmdzOiBTZXR0aW5nc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgcGVyZm9ybU9wZXJhdGlvbjogUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24oXG4gICAgICBFZGl0b3JTdGF0ZS50cmFuc2FjdGlvbkV4dGVuZGVyLm9mKHRoaXMudHJhbnNhY3Rpb25FeHRlbmRlcilcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgdW5sb2FkKCkge31cblxuICBwcml2YXRlIHRyYW5zYWN0aW9uRXh0ZW5kZXIgPSAodHI6IFRyYW5zYWN0aW9uKTogbnVsbCA9PiB7XG4gICAgaWYgKCF0aGlzLnNldHRpbmdzLnN0aWNrQ3Vyc29yIHx8ICF0ci5zZWxlY3Rpb24pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGVkaXRvciA9IHRoaXMub2JzaWRpYW4uZ2V0RWRpdG9yRnJvbVN0YXRlKHRyLnN0YXJ0U3RhdGUpO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLmhhbmRsZUN1cnNvckFjdGl2aXR5KGVkaXRvcik7XG4gICAgfSwgMCk7XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfTtcblxuICBwcml2YXRlIGhhbmRsZUN1cnNvckFjdGl2aXR5ID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICB0aGlzLnBlcmZvcm1PcGVyYXRpb24ucGVyZm9ybU9wZXJhdGlvbihcbiAgICAgIChyb290KSA9PiBuZXcgRW5zdXJlQ3Vyc29ySXNJblVuZm9sZGVkTGluZU9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG5cbiAgICB0aGlzLnBlcmZvcm1PcGVyYXRpb24ucGVyZm9ybU9wZXJhdGlvbihcbiAgICAgIChyb290KSA9PiBuZXcgRW5zdXJlQ3Vyc29ySW5MaXN0Q29udGVudE9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5pbXBvcnQgeyByZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzIH0gZnJvbSBcIi4uL3Jvb3QvcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0c1wiO1xuXG5leHBvcnQgY2xhc3MgTW92ZUxlZnRPcGVyYXRpb24gaW1wbGVtZW50cyBPcGVyYXRpb24ge1xuICBwcml2YXRlIHN0b3BQcm9wYWdhdGlvbiA9IGZhbHNlO1xuICBwcml2YXRlIHVwZGF0ZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJvb3Q6IFJvb3QpIHt9XG5cbiAgc2hvdWxkU3RvcFByb3BhZ2F0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnN0b3BQcm9wYWdhdGlvbjtcbiAgfVxuXG4gIHNob3VsZFVwZGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy51cGRhdGVkO1xuICB9XG5cbiAgcGVyZm9ybSgpIHtcbiAgICBjb25zdCB7IHJvb3QgfSA9IHRoaXM7XG5cbiAgICBpZiAoIXJvb3QuaGFzU2luZ2xlQ3Vyc29yKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnN0b3BQcm9wYWdhdGlvbiA9IHRydWU7XG5cbiAgICBjb25zdCBsaXN0ID0gcm9vdC5nZXRMaXN0VW5kZXJDdXJzb3IoKTtcbiAgICBjb25zdCBwYXJlbnQgPSBsaXN0LmdldFBhcmVudCgpO1xuICAgIGNvbnN0IGdyYW5kUGFyZW50ID0gcGFyZW50LmdldFBhcmVudCgpO1xuXG4gICAgaWYgKCFncmFuZFBhcmVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICBjb25zdCBsaXN0U3RhcnRMaW5lQmVmb3JlID0gcm9vdC5nZXRDb250ZW50TGluZXNSYW5nZU9mKGxpc3QpWzBdO1xuICAgIGNvbnN0IGluZGVudFJtRnJvbSA9IHBhcmVudC5nZXRGaXJzdExpbmVJbmRlbnQoKS5sZW5ndGg7XG4gICAgY29uc3QgaW5kZW50Um1UaWxsID0gbGlzdC5nZXRGaXJzdExpbmVJbmRlbnQoKS5sZW5ndGg7XG5cbiAgICBwYXJlbnQucmVtb3ZlQ2hpbGQobGlzdCk7XG4gICAgZ3JhbmRQYXJlbnQuYWRkQWZ0ZXIocGFyZW50LCBsaXN0KTtcbiAgICBsaXN0LnVuaW5kZW50Q29udGVudChpbmRlbnRSbUZyb20sIGluZGVudFJtVGlsbCk7XG5cbiAgICBjb25zdCBsaXN0U3RhcnRMaW5lQWZ0ZXIgPSByb290LmdldENvbnRlbnRMaW5lc1JhbmdlT2YobGlzdClbMF07XG4gICAgY29uc3QgbGluZURpZmYgPSBsaXN0U3RhcnRMaW5lQWZ0ZXIgLSBsaXN0U3RhcnRMaW5lQmVmb3JlO1xuICAgIGNvbnN0IGNoRGlmZiA9IGluZGVudFJtVGlsbCAtIGluZGVudFJtRnJvbTtcblxuICAgIGNvbnN0IGN1cnNvciA9IHJvb3QuZ2V0Q3Vyc29yKCk7XG4gICAgcm9vdC5yZXBsYWNlQ3Vyc29yKHtcbiAgICAgIGxpbmU6IGN1cnNvci5saW5lICsgbGluZURpZmYsXG4gICAgICBjaDogY3Vyc29yLmNoIC0gY2hEaWZmLFxuICAgIH0pO1xuXG4gICAgcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0cyhyb290KTtcbiAgfVxufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIGlzRW1wdHlMaW5lT3JFbXB0eUNoZWNrYm94KGxpbmU6IHN0cmluZykge1xuICByZXR1cm4gbGluZSA9PT0gXCJcIiB8fCBsaW5lID09PSBcIlsgXSBcIjtcbn1cbiIsImltcG9ydCB7IE1vdmVMZWZ0T3BlcmF0aW9uIH0gZnJvbSBcIi4vTW92ZUxlZnRPcGVyYXRpb25cIjtcbmltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gXCIuL09wZXJhdGlvblwiO1xuXG5pbXBvcnQgeyBSb290IH0gZnJvbSBcIi4uL3Jvb3RcIjtcbmltcG9ydCB7IGlzRW1wdHlMaW5lT3JFbXB0eUNoZWNrYm94IH0gZnJvbSBcIi4uL3V0aWxzL2lzRW1wdHlMaW5lT3JFbXB0eUNoZWNrYm94XCI7XG5cbmV4cG9ydCBjbGFzcyBPdXRkZW50SWZMaW5lSXNFbXB0eU9wZXJhdGlvbiBpbXBsZW1lbnRzIE9wZXJhdGlvbiB7XG4gIHByaXZhdGUgbW92ZUxlZnRPcDogTW92ZUxlZnRPcGVyYXRpb247XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7XG4gICAgdGhpcy5tb3ZlTGVmdE9wID0gbmV3IE1vdmVMZWZ0T3BlcmF0aW9uKHJvb3QpO1xuICB9XG5cbiAgc2hvdWxkU3RvcFByb3BhZ2F0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLm1vdmVMZWZ0T3Auc2hvdWxkU3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMubW92ZUxlZnRPcC5zaG91bGRVcGRhdGUoKTtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbGlzdCA9IHJvb3QuZ2V0TGlzdFVuZGVyQ3Vyc29yKCk7XG4gICAgY29uc3QgbGluZXMgPSBsaXN0LmdldExpbmVzKCk7XG5cbiAgICBpZiAoXG4gICAgICBsaW5lcy5sZW5ndGggPiAxIHx8XG4gICAgICAhaXNFbXB0eUxpbmVPckVtcHR5Q2hlY2tib3gobGluZXNbMF0pIHx8XG4gICAgICBsaXN0LmdldExldmVsKCkgPT09IDFcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLm1vdmVMZWZ0T3AucGVyZm9ybSgpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQbHVnaW5fMiB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5pbXBvcnQgeyBQcmVjIH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5pbXBvcnQgeyBrZXltYXAgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuLi9mZWF0dXJlcy9GZWF0dXJlXCI7XG5pbXBvcnQgeyBPdXRkZW50SWZMaW5lSXNFbXB0eU9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL091dGRlbnRJZkxpbmVJc0VtcHR5T3BlcmF0aW9uXCI7XG5pbXBvcnQgeyBJTUVTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL0lNRVNlcnZpY2VcIjtcbmltcG9ydCB7IE9ic2lkaWFuU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9PYnNpZGlhblNlcnZpY2VcIjtcbmltcG9ydCB7IFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL1BlcmZvcm1PcGVyYXRpb25TZXJ2aWNlXCI7XG5pbXBvcnQgeyBTZXR0aW5nc1NlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvU2V0dGluZ3NTZXJ2aWNlXCI7XG5cbmV4cG9ydCBjbGFzcyBFbnRlck91dGRlbnRJZkxpbmVJc0VtcHR5RmVhdHVyZSBpbXBsZW1lbnRzIEZlYXR1cmUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBsdWdpbjogUGx1Z2luXzIsXG4gICAgcHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlLFxuICAgIHByaXZhdGUgaW1lOiBJTUVTZXJ2aWNlLFxuICAgIHByaXZhdGUgb2JzaWRpYW46IE9ic2lkaWFuU2VydmljZSxcbiAgICBwcml2YXRlIHBlcmZvcm1PcGVyYXRpb246IFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlXG4gICkge31cblxuICBhc3luYyBsb2FkKCkge1xuICAgIHRoaXMucGx1Z2luLnJlZ2lzdGVyRWRpdG9yRXh0ZW5zaW9uKFxuICAgICAgUHJlYy5oaWdoZXN0KFxuICAgICAgICBrZXltYXAub2YoW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGtleTogXCJFbnRlclwiLFxuICAgICAgICAgICAgcnVuOiB0aGlzLm9ic2lkaWFuLmNyZWF0ZUtleW1hcFJ1bkNhbGxiYWNrKHtcbiAgICAgICAgICAgICAgY2hlY2s6IHRoaXMuY2hlY2ssXG4gICAgICAgICAgICAgIHJ1bjogdGhpcy5ydW4sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICBdKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBhc3luYyB1bmxvYWQoKSB7fVxuXG4gIHByaXZhdGUgY2hlY2sgPSAoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0dGluZ3MuYmV0dGVyRW50ZXIgJiYgIXRoaXMuaW1lLmlzSU1FT3BlbmVkKCk7XG4gIH07XG5cbiAgcHJpdmF0ZSBydW4gPSAoZWRpdG9yOiBNeUVkaXRvcikgPT4ge1xuICAgIHJldHVybiB0aGlzLnBlcmZvcm1PcGVyYXRpb24ucGVyZm9ybU9wZXJhdGlvbihcbiAgICAgIChyb290KSA9PiBuZXcgT3V0ZGVudElmTGluZUlzRW1wdHlPcGVyYXRpb24ocm9vdCksXG4gICAgICBlZGl0b3JcbiAgICApO1xuICB9O1xufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIGNtcFBvcyhhOiBQb3NpdGlvbiwgYjogUG9zaXRpb24pIHtcbiAgcmV0dXJuIGEubGluZSAtIGIubGluZSB8fCBhLmNoIC0gYi5jaDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1heFBvcyhhOiBQb3NpdGlvbiwgYjogUG9zaXRpb24pIHtcbiAgcmV0dXJuIGNtcFBvcyhhLCBiKSA8IDAgPyBiIDogYTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1pblBvcyhhOiBQb3NpdGlvbiwgYjogUG9zaXRpb24pIHtcbiAgcmV0dXJuIGNtcFBvcyhhLCBiKSA8IDAgPyBhIDogYjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQb3NpdGlvbiB7XG4gIGNoOiBudW1iZXI7XG4gIGxpbmU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMaXN0TGluZSB7XG4gIHRleHQ6IHN0cmluZztcbiAgZnJvbTogUG9zaXRpb247XG4gIHRvOiBQb3NpdGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSYW5nZSB7XG4gIGFuY2hvcjogUG9zaXRpb247XG4gIGhlYWQ6IFBvc2l0aW9uO1xufVxuXG5leHBvcnQgY2xhc3MgTGlzdCB7XG4gIHByaXZhdGUgcGFyZW50OiBMaXN0IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY2hpbGRyZW46IExpc3RbXSA9IFtdO1xuICBwcml2YXRlIG5vdGVzSW5kZW50OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsaW5lczogc3RyaW5nW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJvb3Q6IFJvb3QsXG4gICAgcHJpdmF0ZSBpbmRlbnQ6IHN0cmluZyxcbiAgICBwcml2YXRlIGJ1bGxldDogc3RyaW5nLFxuICAgIHByaXZhdGUgY2hlY2tib3hMZW5ndGg6IG51bWJlcixcbiAgICBwcml2YXRlIHNwYWNlQWZ0ZXJCdWxsZXQ6IHN0cmluZyxcbiAgICBmaXJzdExpbmU6IHN0cmluZyxcbiAgICBwcml2YXRlIGZvbGRSb290OiBib29sZWFuXG4gICkge1xuICAgIHRoaXMubGluZXMucHVzaChmaXJzdExpbmUpO1xuICB9XG5cbiAgZ2V0Tm90ZXNJbmRlbnQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMubm90ZXNJbmRlbnQ7XG4gIH1cblxuICBzZXROb3Rlc0luZGVudChub3Rlc0luZGVudDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMubm90ZXNJbmRlbnQgIT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm90ZXMgaW5kZW50IGFscmVhZHkgcHJvdmlkZWRgKTtcbiAgICB9XG4gICAgdGhpcy5ub3Rlc0luZGVudCA9IG5vdGVzSW5kZW50O1xuICB9XG5cbiAgYWRkTGluZSh0ZXh0OiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5ub3Rlc0luZGVudCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5hYmxlIHRvIGFkZCBsaW5lLCBub3RlcyBpbmRlbnQgc2hvdWxkIGJlIHByb3ZpZGVkIGZpcnN0YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpbmVzLnB1c2godGV4dCk7XG4gIH1cblxuICByZXBsYWNlTGluZXMobGluZXM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKGxpbmVzLmxlbmd0aCA+IDEgJiYgdGhpcy5ub3Rlc0luZGVudCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5hYmxlIHRvIGFkZCBsaW5lLCBub3RlcyBpbmRlbnQgc2hvdWxkIGJlIHByb3ZpZGVkIGZpcnN0YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpbmVzID0gbGluZXM7XG4gIH1cblxuICBnZXRMaW5lQ291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMubGluZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0Um9vdCgpIHtcbiAgICByZXR1cm4gdGhpcy5yb290O1xuICB9XG5cbiAgZ2V0Q2hpbGRyZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hpbGRyZW4uY29uY2F0KCk7XG4gIH1cblxuICBnZXRMaW5lc0luZm8oKTogTGlzdExpbmVbXSB7XG4gICAgY29uc3Qgc3RhcnRMaW5lID0gdGhpcy5yb290LmdldENvbnRlbnRMaW5lc1JhbmdlT2YodGhpcylbMF07XG5cbiAgICByZXR1cm4gdGhpcy5saW5lcy5tYXAoKHJvdywgaSkgPT4ge1xuICAgICAgY29uc3QgbGluZSA9IHN0YXJ0TGluZSArIGk7XG4gICAgICBjb25zdCBzdGFydENoID1cbiAgICAgICAgaSA9PT0gMCA/IHRoaXMuZ2V0Q29udGVudFN0YXJ0Q2goKSA6IHRoaXMubm90ZXNJbmRlbnQubGVuZ3RoO1xuICAgICAgY29uc3QgZW5kQ2ggPSBzdGFydENoICsgcm93Lmxlbmd0aDtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdGV4dDogcm93LFxuICAgICAgICBmcm9tOiB7IGxpbmUsIGNoOiBzdGFydENoIH0sXG4gICAgICAgIHRvOiB7IGxpbmUsIGNoOiBlbmRDaCB9LFxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldExpbmVzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5saW5lcy5jb25jYXQoKTtcbiAgfVxuXG4gIGdldEZpcnN0TGluZUNvbnRlbnRTdGFydCgpIHtcbiAgICBjb25zdCBzdGFydExpbmUgPSB0aGlzLnJvb3QuZ2V0Q29udGVudExpbmVzUmFuZ2VPZih0aGlzKVswXTtcblxuICAgIHJldHVybiB7XG4gICAgICBsaW5lOiBzdGFydExpbmUsXG4gICAgICBjaDogdGhpcy5nZXRDb250ZW50U3RhcnRDaCgpLFxuICAgIH07XG4gIH1cblxuICBnZXRMYXN0TGluZUNvbnRlbnRFbmQoKSB7XG4gICAgY29uc3QgZW5kTGluZSA9IHRoaXMucm9vdC5nZXRDb250ZW50TGluZXNSYW5nZU9mKHRoaXMpWzFdO1xuICAgIGNvbnN0IGVuZENoID1cbiAgICAgIHRoaXMubGluZXMubGVuZ3RoID09PSAxXG4gICAgICAgID8gdGhpcy5nZXRDb250ZW50U3RhcnRDaCgpICsgdGhpcy5saW5lc1swXS5sZW5ndGhcbiAgICAgICAgOiB0aGlzLm5vdGVzSW5kZW50Lmxlbmd0aCArIHRoaXMubGluZXNbdGhpcy5saW5lcy5sZW5ndGggLSAxXS5sZW5ndGg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGluZTogZW5kTGluZSxcbiAgICAgIGNoOiBlbmRDaCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb250ZW50U3RhcnRDaCgpIHtcbiAgICByZXR1cm4gdGhpcy5pbmRlbnQubGVuZ3RoICsgdGhpcy5idWxsZXQubGVuZ3RoICsgMTtcbiAgfVxuXG4gIGlzRm9sZGVkKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmZvbGRSb290KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYXJlbnQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcmVudC5pc0ZvbGRlZCgpO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlzRm9sZFJvb3QoKSB7XG4gICAgcmV0dXJuIHRoaXMuZm9sZFJvb3Q7XG4gIH1cblxuICBnZXRUb3BGb2xkUm9vdCgpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBsZXQgdG1wOiBMaXN0ID0gdGhpcztcbiAgICBsZXQgZm9sZFJvb3Q6IExpc3QgfCBudWxsID0gbnVsbDtcbiAgICB3aGlsZSAodG1wKSB7XG4gICAgICBpZiAodG1wLmlzRm9sZFJvb3QoKSkge1xuICAgICAgICBmb2xkUm9vdCA9IHRtcDtcbiAgICAgIH1cbiAgICAgIHRtcCA9IHRtcC5wYXJlbnQ7XG4gICAgfVxuICAgIHJldHVybiBmb2xkUm9vdDtcbiAgfVxuXG4gIGdldExldmVsKCk6IG51bWJlciB7XG4gICAgaWYgKCF0aGlzLnBhcmVudCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGFyZW50LmdldExldmVsKCkgKyAxO1xuICB9XG5cbiAgdW5pbmRlbnRDb250ZW50KGZyb206IG51bWJlciwgdGlsbDogbnVtYmVyKSB7XG4gICAgdGhpcy5pbmRlbnQgPSB0aGlzLmluZGVudC5zbGljZSgwLCBmcm9tKSArIHRoaXMuaW5kZW50LnNsaWNlKHRpbGwpO1xuICAgIGlmICh0aGlzLm5vdGVzSW5kZW50ICE9PSBudWxsKSB7XG4gICAgICB0aGlzLm5vdGVzSW5kZW50ID1cbiAgICAgICAgdGhpcy5ub3Rlc0luZGVudC5zbGljZSgwLCBmcm9tKSArIHRoaXMubm90ZXNJbmRlbnQuc2xpY2UodGlsbCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzLmNoaWxkcmVuKSB7XG4gICAgICBjaGlsZC51bmluZGVudENvbnRlbnQoZnJvbSwgdGlsbCk7XG4gICAgfVxuICB9XG5cbiAgaW5kZW50Q29udGVudChpbmRlbnRQb3M6IG51bWJlciwgaW5kZW50Q2hhcnM6IHN0cmluZykge1xuICAgIHRoaXMuaW5kZW50ID1cbiAgICAgIHRoaXMuaW5kZW50LnNsaWNlKDAsIGluZGVudFBvcykgK1xuICAgICAgaW5kZW50Q2hhcnMgK1xuICAgICAgdGhpcy5pbmRlbnQuc2xpY2UoaW5kZW50UG9zKTtcbiAgICBpZiAodGhpcy5ub3Rlc0luZGVudCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5ub3Rlc0luZGVudCA9XG4gICAgICAgIHRoaXMubm90ZXNJbmRlbnQuc2xpY2UoMCwgaW5kZW50UG9zKSArXG4gICAgICAgIGluZGVudENoYXJzICtcbiAgICAgICAgdGhpcy5ub3Rlc0luZGVudC5zbGljZShpbmRlbnRQb3MpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5jaGlsZHJlbikge1xuICAgICAgY2hpbGQuaW5kZW50Q29udGVudChpbmRlbnRQb3MsIGluZGVudENoYXJzKTtcbiAgICB9XG4gIH1cblxuICBnZXRGaXJzdExpbmVJbmRlbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW5kZW50O1xuICB9XG5cbiAgZ2V0QnVsbGV0KCkge1xuICAgIHJldHVybiB0aGlzLmJ1bGxldDtcbiAgfVxuXG4gIGdldFNwYWNlQWZ0ZXJCdWxsZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3BhY2VBZnRlckJ1bGxldDtcbiAgfVxuXG4gIGdldENoZWNrYm94TGVuZ3RoKCkge1xuICAgIHJldHVybiB0aGlzLmNoZWNrYm94TGVuZ3RoO1xuICB9XG5cbiAgcmVwbGF0ZUJ1bGxldChidWxsZXQ6IHN0cmluZykge1xuICAgIHRoaXMuYnVsbGV0ID0gYnVsbGV0O1xuICB9XG5cbiAgZ2V0UGFyZW50KCkge1xuICAgIHJldHVybiB0aGlzLnBhcmVudDtcbiAgfVxuXG4gIGFkZEJlZm9yZUFsbChsaXN0OiBMaXN0KSB7XG4gICAgdGhpcy5jaGlsZHJlbi51bnNoaWZ0KGxpc3QpO1xuICAgIGxpc3QucGFyZW50ID0gdGhpcztcbiAgfVxuXG4gIGFkZEFmdGVyQWxsKGxpc3Q6IExpc3QpIHtcbiAgICB0aGlzLmNoaWxkcmVuLnB1c2gobGlzdCk7XG4gICAgbGlzdC5wYXJlbnQgPSB0aGlzO1xuICB9XG5cbiAgcmVtb3ZlQ2hpbGQobGlzdDogTGlzdCkge1xuICAgIGNvbnN0IGkgPSB0aGlzLmNoaWxkcmVuLmluZGV4T2YobGlzdCk7XG4gICAgdGhpcy5jaGlsZHJlbi5zcGxpY2UoaSwgMSk7XG4gICAgbGlzdC5wYXJlbnQgPSBudWxsO1xuICB9XG5cbiAgYWRkQmVmb3JlKGJlZm9yZTogTGlzdCwgbGlzdDogTGlzdCkge1xuICAgIGNvbnN0IGkgPSB0aGlzLmNoaWxkcmVuLmluZGV4T2YoYmVmb3JlKTtcbiAgICB0aGlzLmNoaWxkcmVuLnNwbGljZShpLCAwLCBsaXN0KTtcbiAgICBsaXN0LnBhcmVudCA9IHRoaXM7XG4gIH1cblxuICBhZGRBZnRlcihiZWZvcmU6IExpc3QsIGxpc3Q6IExpc3QpIHtcbiAgICBjb25zdCBpID0gdGhpcy5jaGlsZHJlbi5pbmRleE9mKGJlZm9yZSk7XG4gICAgdGhpcy5jaGlsZHJlbi5zcGxpY2UoaSArIDEsIDAsIGxpc3QpO1xuICAgIGxpc3QucGFyZW50ID0gdGhpcztcbiAgfVxuXG4gIGdldFByZXZTaWJsaW5nT2YobGlzdDogTGlzdCkge1xuICAgIGNvbnN0IGkgPSB0aGlzLmNoaWxkcmVuLmluZGV4T2YobGlzdCk7XG4gICAgcmV0dXJuIGkgPiAwID8gdGhpcy5jaGlsZHJlbltpIC0gMV0gOiBudWxsO1xuICB9XG5cbiAgZ2V0TmV4dFNpYmxpbmdPZihsaXN0OiBMaXN0KSB7XG4gICAgY29uc3QgaSA9IHRoaXMuY2hpbGRyZW4uaW5kZXhPZihsaXN0KTtcbiAgICByZXR1cm4gaSA+PSAwICYmIGkgPCB0aGlzLmNoaWxkcmVuLmxlbmd0aCA/IHRoaXMuY2hpbGRyZW5baSArIDFdIDogbnVsbDtcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hpbGRyZW4ubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcHJpbnQoKSB7XG4gICAgbGV0IHJlcyA9IFwiXCI7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlcyArPVxuICAgICAgICBpID09PSAwXG4gICAgICAgICAgPyB0aGlzLmluZGVudCArIHRoaXMuYnVsbGV0ICsgdGhpcy5zcGFjZUFmdGVyQnVsbGV0XG4gICAgICAgICAgOiB0aGlzLm5vdGVzSW5kZW50O1xuICAgICAgcmVzICs9IHRoaXMubGluZXNbaV07XG4gICAgICByZXMgKz0gXCJcXG5cIjtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXMuY2hpbGRyZW4pIHtcbiAgICAgIHJlcyArPSBjaGlsZC5wcmludCgpO1xuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFJvb3Qge1xuICBwcml2YXRlIHJvb3RMaXN0ID0gbmV3IExpc3QodGhpcywgXCJcIiwgXCJcIiwgMCwgXCJcIiwgXCJcIiwgZmFsc2UpO1xuICBwcml2YXRlIHNlbGVjdGlvbnM6IFJhbmdlW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHN0YXJ0OiBQb3NpdGlvbixcbiAgICBwcml2YXRlIGVuZDogUG9zaXRpb24sXG4gICAgc2VsZWN0aW9uczogUmFuZ2VbXVxuICApIHtcbiAgICB0aGlzLnJlcGxhY2VTZWxlY3Rpb25zKHNlbGVjdGlvbnMpO1xuICB9XG5cbiAgZ2V0Um9vdExpc3QoKSB7XG4gICAgcmV0dXJuIHRoaXMucm9vdExpc3Q7XG4gIH1cblxuICBnZXRSYW5nZSgpOiBbUG9zaXRpb24sIFBvc2l0aW9uXSB7XG4gICAgcmV0dXJuIFt7IC4uLnRoaXMuc3RhcnQgfSwgeyAuLi50aGlzLmVuZCB9XTtcbiAgfVxuXG4gIGdldFNlbGVjdGlvbnMoKTogUmFuZ2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9ucy5tYXAoKHMpID0+ICh7XG4gICAgICBhbmNob3I6IHsgLi4ucy5hbmNob3IgfSxcbiAgICAgIGhlYWQ6IHsgLi4ucy5oZWFkIH0sXG4gICAgfSkpO1xuICB9XG5cbiAgaGFzU2luZ2xlQ3Vyc29yKCkge1xuICAgIGlmICghdGhpcy5oYXNTaW5nbGVTZWxlY3Rpb24oKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHNlbGVjdGlvbiA9IHRoaXMuc2VsZWN0aW9uc1swXTtcblxuICAgIHJldHVybiAoXG4gICAgICBzZWxlY3Rpb24uYW5jaG9yLmxpbmUgPT09IHNlbGVjdGlvbi5oZWFkLmxpbmUgJiZcbiAgICAgIHNlbGVjdGlvbi5hbmNob3IuY2ggPT09IHNlbGVjdGlvbi5oZWFkLmNoXG4gICAgKTtcbiAgfVxuXG4gIGhhc1NpbmdsZVNlbGVjdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3Rpb25zLmxlbmd0aCA9PT0gMTtcbiAgfVxuXG4gIGdldFNlbGVjdGlvbigpIHtcbiAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLnNlbGVjdGlvbnNbdGhpcy5zZWxlY3Rpb25zLmxlbmd0aCAtIDFdO1xuXG4gICAgY29uc3QgZnJvbSA9XG4gICAgICBzZWxlY3Rpb24uYW5jaG9yLmNoID4gc2VsZWN0aW9uLmhlYWQuY2hcbiAgICAgICAgPyBzZWxlY3Rpb24uaGVhZC5jaFxuICAgICAgICA6IHNlbGVjdGlvbi5hbmNob3IuY2g7XG4gICAgY29uc3QgdG8gPVxuICAgICAgc2VsZWN0aW9uLmFuY2hvci5jaCA+IHNlbGVjdGlvbi5oZWFkLmNoXG4gICAgICAgID8gc2VsZWN0aW9uLmFuY2hvci5jaFxuICAgICAgICA6IHNlbGVjdGlvbi5oZWFkLmNoO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnNlbGVjdGlvbixcbiAgICAgIGZyb20sXG4gICAgICB0byxcbiAgICB9O1xuICB9XG5cbiAgZ2V0Q3Vyc29yKCkge1xuICAgIHJldHVybiB7IC4uLnRoaXMuc2VsZWN0aW9uc1t0aGlzLnNlbGVjdGlvbnMubGVuZ3RoIC0gMV0uaGVhZCB9O1xuICB9XG5cbiAgcmVwbGFjZUN1cnNvcihjdXJzb3I6IFBvc2l0aW9uKSB7XG4gICAgdGhpcy5zZWxlY3Rpb25zID0gW3sgYW5jaG9yOiBjdXJzb3IsIGhlYWQ6IGN1cnNvciB9XTtcbiAgfVxuXG4gIHJlcGxhY2VTZWxlY3Rpb25zKHNlbGVjdGlvbnM6IFJhbmdlW10pIHtcbiAgICBpZiAoc2VsZWN0aW9ucy5sZW5ndGggPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBjcmVhdGUgUm9vdCB3aXRob3V0IHNlbGVjdGlvbnNgKTtcbiAgICB9XG4gICAgdGhpcy5zZWxlY3Rpb25zID0gc2VsZWN0aW9ucztcbiAgfVxuXG4gIGdldExpc3RVbmRlckN1cnNvcigpOiBMaXN0IHtcbiAgICByZXR1cm4gdGhpcy5nZXRMaXN0VW5kZXJMaW5lKHRoaXMuZ2V0Q3Vyc29yKCkubGluZSk7XG4gIH1cblxuICBnZXRMaXN0VW5kZXJMaW5lKGxpbmU6IG51bWJlcikge1xuICAgIGlmIChsaW5lIDwgdGhpcy5zdGFydC5saW5lIHx8IGxpbmUgPiB0aGlzLmVuZC5saW5lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHJlc3VsdDogTGlzdCA9IG51bGw7XG4gICAgbGV0IGluZGV4OiBudW1iZXIgPSB0aGlzLnN0YXJ0LmxpbmU7XG5cbiAgICBjb25zdCB2aXNpdEFyciA9IChsbDogTGlzdFtdKSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGwgb2YgbGwpIHtcbiAgICAgICAgY29uc3QgbGlzdEZyb21MaW5lID0gaW5kZXg7XG4gICAgICAgIGNvbnN0IGxpc3RUaWxsTGluZSA9IGxpc3RGcm9tTGluZSArIGwuZ2V0TGluZUNvdW50KCkgLSAxO1xuXG4gICAgICAgIGlmIChsaW5lID49IGxpc3RGcm9tTGluZSAmJiBsaW5lIDw9IGxpc3RUaWxsTGluZSkge1xuICAgICAgICAgIHJlc3VsdCA9IGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaW5kZXggPSBsaXN0VGlsbExpbmUgKyAxO1xuICAgICAgICAgIHZpc2l0QXJyKGwuZ2V0Q2hpbGRyZW4oKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB2aXNpdEFycih0aGlzLnJvb3RMaXN0LmdldENoaWxkcmVuKCkpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGdldENvbnRlbnRMaW5lc1JhbmdlT2YobGlzdDogTGlzdCk6IFtudW1iZXIsIG51bWJlcl0gfCBudWxsIHtcbiAgICBsZXQgcmVzdWx0OiBbbnVtYmVyLCBudW1iZXJdIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGxpbmU6IG51bWJlciA9IHRoaXMuc3RhcnQubGluZTtcblxuICAgIGNvbnN0IHZpc2l0QXJyID0gKGxsOiBMaXN0W10pID0+IHtcbiAgICAgIGZvciAoY29uc3QgbCBvZiBsbCkge1xuICAgICAgICBjb25zdCBsaXN0RnJvbUxpbmUgPSBsaW5lO1xuICAgICAgICBjb25zdCBsaXN0VGlsbExpbmUgPSBsaXN0RnJvbUxpbmUgKyBsLmdldExpbmVDb3VudCgpIC0gMTtcblxuICAgICAgICBpZiAobCA9PT0gbGlzdCkge1xuICAgICAgICAgIHJlc3VsdCA9IFtsaXN0RnJvbUxpbmUsIGxpc3RUaWxsTGluZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbGluZSA9IGxpc3RUaWxsTGluZSArIDE7XG4gICAgICAgICAgdmlzaXRBcnIobC5nZXRDaGlsZHJlbigpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQgIT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdmlzaXRBcnIodGhpcy5yb290TGlzdC5nZXRDaGlsZHJlbigpKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBnZXRDaGlsZHJlbigpIHtcbiAgICByZXR1cm4gdGhpcy5yb290TGlzdC5nZXRDaGlsZHJlbigpO1xuICB9XG5cbiAgcHJpbnQoKSB7XG4gICAgbGV0IHJlcyA9IFwiXCI7XG5cbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXMucm9vdExpc3QuZ2V0Q2hpbGRyZW4oKSkge1xuICAgICAgcmVzICs9IGNoaWxkLnByaW50KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcy5yZXBsYWNlKC9cXG4kLywgXCJcIik7XG4gIH1cbn1cbiIsImltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gXCIuL09wZXJhdGlvblwiO1xuXG5pbXBvcnQgeyBMaXN0LCBQb3NpdGlvbiwgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5pbXBvcnQgeyByZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzIH0gZnJvbSBcIi4uL3Jvb3QvcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0c1wiO1xuaW1wb3J0IHsgaXNFbXB0eUxpbmVPckVtcHR5Q2hlY2tib3ggfSBmcm9tIFwiLi4vdXRpbHMvaXNFbXB0eUxpbmVPckVtcHR5Q2hlY2tib3hcIjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRab29tUmFuZ2Uge1xuICBnZXRab29tUmFuZ2UoKTogeyBmcm9tOiBQb3NpdGlvbjsgdG86IFBvc2l0aW9uIH0gfCBudWxsO1xufVxuXG5leHBvcnQgY2xhc3MgQ3JlYXRlTmV3SXRlbU9wZXJhdGlvbiBpbXBsZW1lbnRzIE9wZXJhdGlvbiB7XG4gIHByaXZhdGUgc3RvcFByb3BhZ2F0aW9uID0gZmFsc2U7XG4gIHByaXZhdGUgdXBkYXRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcm9vdDogUm9vdCxcbiAgICBwcml2YXRlIGRlZmF1bHRJbmRlbnRDaGFyczogc3RyaW5nLFxuICAgIHByaXZhdGUgZ2V0Wm9vbVJhbmdlOiBHZXRab29tUmFuZ2VcbiAgKSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZVNlbGVjdGlvbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2VsZWN0aW9uID0gcm9vdC5nZXRTZWxlY3Rpb24oKTtcbiAgICBpZiAoIXNlbGVjdGlvbiB8fCBzZWxlY3Rpb24uYW5jaG9yLmxpbmUgIT09IHNlbGVjdGlvbi5oZWFkLmxpbmUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsaXN0ID0gcm9vdC5nZXRMaXN0VW5kZXJDdXJzb3IoKTtcbiAgICBjb25zdCBsaW5lcyA9IGxpc3QuZ2V0TGluZXNJbmZvKCk7XG5cbiAgICBpZiAobGluZXMubGVuZ3RoID09PSAxICYmIGlzRW1wdHlMaW5lT3JFbXB0eUNoZWNrYm94KGxpbmVzWzBdLnRleHQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcbiAgICBjb25zdCBsaW5lVW5kZXJDdXJzb3IgPSBsaW5lcy5maW5kKChsKSA9PiBsLmZyb20ubGluZSA9PT0gY3Vyc29yLmxpbmUpO1xuXG4gICAgaWYgKGN1cnNvci5jaCA8IGxpbmVVbmRlckN1cnNvci5mcm9tLmNoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBvbGRMaW5lcywgbmV3TGluZXMgfSA9IGxpbmVzLnJlZHVjZShcbiAgICAgIChhY2MsIGxpbmUpID0+IHtcbiAgICAgICAgaWYgKGN1cnNvci5saW5lID4gbGluZS5mcm9tLmxpbmUpIHtcbiAgICAgICAgICBhY2Mub2xkTGluZXMucHVzaChsaW5lLnRleHQpO1xuICAgICAgICB9IGVsc2UgaWYgKGN1cnNvci5saW5lID09PSBsaW5lLmZyb20ubGluZSkge1xuICAgICAgICAgIGNvbnN0IGxlZnQgPSBsaW5lLnRleHQuc2xpY2UoMCwgc2VsZWN0aW9uLmZyb20gLSBsaW5lLmZyb20uY2gpO1xuICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gbGluZS50ZXh0LnNsaWNlKHNlbGVjdGlvbi50byAtIGxpbmUuZnJvbS5jaCk7XG4gICAgICAgICAgYWNjLm9sZExpbmVzLnB1c2gobGVmdCk7XG4gICAgICAgICAgYWNjLm5ld0xpbmVzLnB1c2gocmlnaHQpO1xuICAgICAgICB9IGVsc2UgaWYgKGN1cnNvci5saW5lIDwgbGluZS5mcm9tLmxpbmUpIHtcbiAgICAgICAgICBhY2MubmV3TGluZXMucHVzaChsaW5lLnRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG9sZExpbmVzOiBbXSxcbiAgICAgICAgbmV3TGluZXM6IFtdLFxuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCBjb2RlQmxvY2tCYWN0aWNrcyA9IG9sZExpbmVzLmpvaW4oXCJcXG5cIikuc3BsaXQoXCJgYGBcIikubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBpc0luc2lkZUNvZGVibG9jayA9XG4gICAgICBjb2RlQmxvY2tCYWN0aWNrcyA+IDAgJiYgY29kZUJsb2NrQmFjdGlja3MgJSAyICE9PSAwO1xuXG4gICAgaWYgKGlzSW5zaWRlQ29kZWJsb2NrKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICBjb25zdCB6b29tUmFuZ2UgPSB0aGlzLmdldFpvb21SYW5nZS5nZXRab29tUmFuZ2UoKTtcbiAgICBjb25zdCBsaXN0SXNab29taW5nUm9vdCA9IEJvb2xlYW4oXG4gICAgICB6b29tUmFuZ2UgJiZcbiAgICAgICAgbGlzdC5nZXRGaXJzdExpbmVDb250ZW50U3RhcnQoKS5saW5lID49IHpvb21SYW5nZS5mcm9tLmxpbmUgJiZcbiAgICAgICAgbGlzdC5nZXRMYXN0TGluZUNvbnRlbnRFbmQoKS5saW5lIDw9IHpvb21SYW5nZS5mcm9tLmxpbmVcbiAgICApO1xuXG4gICAgY29uc3QgaGFzQ2hpbGRyZW4gPSAhbGlzdC5pc0VtcHR5KCk7XG4gICAgY29uc3QgY2hpbGRJc0ZvbGRlZCA9IGxpc3QuaXNGb2xkUm9vdCgpO1xuICAgIGNvbnN0IGVuZFBvcyA9IGxpc3QuZ2V0TGFzdExpbmVDb250ZW50RW5kKCk7XG4gICAgY29uc3QgZW5kT2ZMaW5lID0gY3Vyc29yLmxpbmUgPT09IGVuZFBvcy5saW5lICYmIGN1cnNvci5jaCA9PT0gZW5kUG9zLmNoO1xuXG4gICAgY29uc3Qgb25DaGlsZExldmVsID1cbiAgICAgIGxpc3RJc1pvb21pbmdSb290IHx8IChoYXNDaGlsZHJlbiAmJiAhY2hpbGRJc0ZvbGRlZCAmJiBlbmRPZkxpbmUpO1xuXG4gICAgY29uc3QgaW5kZW50ID0gb25DaGlsZExldmVsXG4gICAgICA/IGhhc0NoaWxkcmVuXG4gICAgICAgID8gbGlzdC5nZXRDaGlsZHJlbigpWzBdLmdldEZpcnN0TGluZUluZGVudCgpXG4gICAgICAgIDogbGlzdC5nZXRGaXJzdExpbmVJbmRlbnQoKSArIHRoaXMuZGVmYXVsdEluZGVudENoYXJzXG4gICAgICA6IGxpc3QuZ2V0Rmlyc3RMaW5lSW5kZW50KCk7XG5cbiAgICBjb25zdCBidWxsZXQgPVxuICAgICAgb25DaGlsZExldmVsICYmIGhhc0NoaWxkcmVuXG4gICAgICAgID8gbGlzdC5nZXRDaGlsZHJlbigpWzBdLmdldEJ1bGxldCgpXG4gICAgICAgIDogbGlzdC5nZXRCdWxsZXQoKTtcblxuICAgIGNvbnN0IHNwYWNlQWZ0ZXJCdWxsZXQgPVxuICAgICAgb25DaGlsZExldmVsICYmIGhhc0NoaWxkcmVuXG4gICAgICAgID8gbGlzdC5nZXRDaGlsZHJlbigpWzBdLmdldFNwYWNlQWZ0ZXJCdWxsZXQoKVxuICAgICAgICA6IGxpc3QuZ2V0U3BhY2VBZnRlckJ1bGxldCgpO1xuXG4gICAgY29uc3QgcHJlZml4ID0gb2xkTGluZXNbMF0ubWF0Y2goL15cXFsuXFxdLykgPyBcIlsgXSBcIiA6IFwiXCI7XG5cbiAgICBjb25zdCBuZXdMaXN0ID0gbmV3IExpc3QoXG4gICAgICBsaXN0LmdldFJvb3QoKSxcbiAgICAgIGluZGVudCxcbiAgICAgIGJ1bGxldCxcbiAgICAgIHByZWZpeC5sZW5ndGgsXG4gICAgICBzcGFjZUFmdGVyQnVsbGV0LFxuICAgICAgcHJlZml4ICsgbmV3TGluZXMuc2hpZnQoKSxcbiAgICAgIGZhbHNlXG4gICAgKTtcblxuICAgIGlmIChuZXdMaW5lcy5sZW5ndGggPiAwKSB7XG4gICAgICBuZXdMaXN0LnNldE5vdGVzSW5kZW50KGxpc3QuZ2V0Tm90ZXNJbmRlbnQoKSk7XG4gICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbmV3TGluZXMpIHtcbiAgICAgICAgbmV3TGlzdC5hZGRMaW5lKGxpbmUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChvbkNoaWxkTGV2ZWwpIHtcbiAgICAgIGxpc3QuYWRkQmVmb3JlQWxsKG5ld0xpc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWNoaWxkSXNGb2xkZWQgfHwgIWVuZE9mTGluZSkge1xuICAgICAgICBjb25zdCBjaGlsZHJlbiA9IGxpc3QuZ2V0Q2hpbGRyZW4oKTtcbiAgICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZHJlbikge1xuICAgICAgICAgIGxpc3QucmVtb3ZlQ2hpbGQoY2hpbGQpO1xuICAgICAgICAgIG5ld0xpc3QuYWRkQWZ0ZXJBbGwoY2hpbGQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxpc3QuZ2V0UGFyZW50KCkuYWRkQWZ0ZXIobGlzdCwgbmV3TGlzdCk7XG4gICAgfVxuXG4gICAgbGlzdC5yZXBsYWNlTGluZXMob2xkTGluZXMpO1xuXG4gICAgY29uc3QgbmV3TGlzdFN0YXJ0ID0gbmV3TGlzdC5nZXRGaXJzdExpbmVDb250ZW50U3RhcnQoKTtcbiAgICByb290LnJlcGxhY2VDdXJzb3Ioe1xuICAgICAgbGluZTogbmV3TGlzdFN0YXJ0LmxpbmUsXG4gICAgICBjaDogbmV3TGlzdFN0YXJ0LmNoICsgcHJlZml4Lmxlbmd0aCxcbiAgICB9KTtcblxuICAgIHJlY2FsY3VsYXRlTnVtZXJpY0J1bGxldHMocm9vdCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFBsdWdpbl8yIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmltcG9ydCB7IFByZWMgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivc3RhdGVcIjtcbmltcG9ydCB7IGtleW1hcCB9IGZyb20gXCJAY29kZW1pcnJvci92aWV3XCI7XG5cbmltcG9ydCB7IE15RWRpdG9yIH0gZnJvbSBcIi4uL015RWRpdG9yXCI7XG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4uL2ZlYXR1cmVzL0ZlYXR1cmVcIjtcbmltcG9ydCB7IENyZWF0ZU5ld0l0ZW1PcGVyYXRpb24gfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9DcmVhdGVOZXdJdGVtT3BlcmF0aW9uXCI7XG5pbXBvcnQgeyBJTUVTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL0lNRVNlcnZpY2VcIjtcbmltcG9ydCB7IE9ic2lkaWFuU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9PYnNpZGlhblNlcnZpY2VcIjtcbmltcG9ydCB7IFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL1BlcmZvcm1PcGVyYXRpb25TZXJ2aWNlXCI7XG5pbXBvcnQgeyBTZXR0aW5nc1NlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvU2V0dGluZ3NTZXJ2aWNlXCI7XG5cbmV4cG9ydCBjbGFzcyBFbnRlclNob3VsZENyZWF0ZU5ld0l0ZW1GZWF0dXJlIGltcGxlbWVudHMgRmVhdHVyZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcGx1Z2luOiBQbHVnaW5fMixcbiAgICBwcml2YXRlIHNldHRpbmdzOiBTZXR0aW5nc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBpbWU6IElNRVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgcGVyZm9ybU9wZXJhdGlvbjogUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24oXG4gICAgICBQcmVjLmhpZ2hlc3QoXG4gICAgICAgIGtleW1hcC5vZihbXG4gICAgICAgICAge1xuICAgICAgICAgICAga2V5OiBcIkVudGVyXCIsXG4gICAgICAgICAgICBydW46IHRoaXMub2JzaWRpYW4uY3JlYXRlS2V5bWFwUnVuQ2FsbGJhY2soe1xuICAgICAgICAgICAgICBjaGVjazogdGhpcy5jaGVjayxcbiAgICAgICAgICAgICAgcnVuOiB0aGlzLnJ1bixcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHVubG9hZCgpIHt9XG5cbiAgcHJpdmF0ZSBjaGVjayA9ICgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5zZXR0aW5ncy5iZXR0ZXJFbnRlciAmJiAhdGhpcy5pbWUuaXNJTUVPcGVuZWQoKTtcbiAgfTtcblxuICBwcml2YXRlIHJ1biA9IChlZGl0b3I6IE15RWRpdG9yKSA9PiB7XG4gICAgY29uc3Qgem9vbVJhbmdlID0gZWRpdG9yLmdldFpvb21SYW5nZSgpO1xuXG4gICAgY29uc3QgcmVzID0gdGhpcy5wZXJmb3JtT3BlcmF0aW9uLnBlcmZvcm1PcGVyYXRpb24oXG4gICAgICAocm9vdCkgPT5cbiAgICAgICAgbmV3IENyZWF0ZU5ld0l0ZW1PcGVyYXRpb24oXG4gICAgICAgICAgcm9vdCxcbiAgICAgICAgICB0aGlzLm9ic2lkaWFuLmdldERlZmF1bHRJbmRlbnRDaGFycygpLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGdldFpvb21SYW5nZTogKCkgPT4gem9vbVJhbmdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKSxcbiAgICAgIGVkaXRvclxuICAgICk7XG5cbiAgICBpZiAocmVzLnNob3VsZFVwZGF0ZSAmJiB6b29tUmFuZ2UpIHtcbiAgICAgIGVkaXRvci56b29tSW4oem9vbVJhbmdlLmZyb20ubGluZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbiAgfTtcbn1cbiIsImltcG9ydCB7IE5vdGljZSwgUGx1Z2luXzIgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuL0ZlYXR1cmVcIjtcblxuaW1wb3J0IHsgTXlFZGl0b3IgfSBmcm9tIFwiLi4vTXlFZGl0b3JcIjtcbmltcG9ydCB7IE9ic2lkaWFuU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9PYnNpZGlhblNlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIEZvbGRGZWF0dXJlIGltcGxlbWVudHMgRmVhdHVyZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcGx1Z2luOiBQbHVnaW5fMiwgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlKSB7fVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgdGhpcy5wbHVnaW4uYWRkQ29tbWFuZCh7XG4gICAgICBpZDogXCJmb2xkXCIsXG4gICAgICBpY29uOiBcImNoZXZyb25zLWRvd24tdXBcIixcbiAgICAgIG5hbWU6IFwiRm9sZCB0aGUgbGlzdFwiLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IHRoaXMub2JzaWRpYW4uY3JlYXRlRWRpdG9yQ2FsbGJhY2sodGhpcy5mb2xkKSxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogW1wiTW9kXCJdLFxuICAgICAgICAgIGtleTogXCJBcnJvd1VwXCIsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgdGhpcy5wbHVnaW4uYWRkQ29tbWFuZCh7XG4gICAgICBpZDogXCJ1bmZvbGRcIixcbiAgICAgIGljb246IFwiY2hldnJvbnMtdXAtZG93blwiLFxuICAgICAgbmFtZTogXCJVbmZvbGQgdGhlIGxpc3RcIixcbiAgICAgIGVkaXRvckNhbGxiYWNrOiB0aGlzLm9ic2lkaWFuLmNyZWF0ZUVkaXRvckNhbGxiYWNrKHRoaXMudW5mb2xkKSxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogW1wiTW9kXCJdLFxuICAgICAgICAgIGtleTogXCJBcnJvd0Rvd25cIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyB1bmxvYWQoKSB7fVxuXG4gIHByaXZhdGUgc2V0Rm9sZChlZGl0b3I6IE15RWRpdG9yLCB0eXBlOiBcImZvbGRcIiB8IFwidW5mb2xkXCIpIHtcbiAgICBpZiAoIXRoaXMub2JzaWRpYW4uZ2V0T2JzaWRpYW5Gb2xkU2V0dGluZ3MoKS5mb2xkSW5kZW50KSB7XG4gICAgICBuZXcgTm90aWNlKFxuICAgICAgICBgVW5hYmxlIHRvICR7dHlwZX0gYmVjYXVzZSBmb2xkaW5nIGlzIGRpc2FibGVkLiBQbGVhc2UgZW5hYmxlIFwiRm9sZCBpbmRlbnRcIiBpbiBPYnNpZGlhbiBzZXR0aW5ncy5gLFxuICAgICAgICA1MDAwXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgY3Vyc29yID0gZWRpdG9yLmdldEN1cnNvcigpO1xuXG4gICAgaWYgKHR5cGUgPT09IFwiZm9sZFwiKSB7XG4gICAgICBlZGl0b3IuZm9sZChjdXJzb3IubGluZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVkaXRvci51bmZvbGQoY3Vyc29yLmxpbmUpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBmb2xkID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRGb2xkKGVkaXRvciwgXCJmb2xkXCIpO1xuICB9O1xuXG4gIHByaXZhdGUgdW5mb2xkID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRGb2xkKGVkaXRvciwgXCJ1bmZvbGRcIik7XG4gIH07XG59XG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi9cbmltcG9ydCB7IEVkaXRvciB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5pbXBvcnQge1xuICBmb2xkRWZmZWN0LFxuICBmb2xkYWJsZSxcbiAgZm9sZGVkUmFuZ2VzLFxuICB1bmZvbGRFZmZlY3QsXG59IGZyb20gXCJAY29kZW1pcnJvci9sYW5ndWFnZVwiO1xuaW1wb3J0IHsgRWRpdG9yVmlldywgcnVuU2NvcGVIYW5kbGVycyB9IGZyb20gXCJAY29kZW1pcnJvci92aWV3XCI7XG5cbmV4cG9ydCBjbGFzcyBNeUVkaXRvclBvc2l0aW9uIHtcbiAgbGluZTogbnVtYmVyO1xuICBjaDogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgTXlFZGl0b3JSYW5nZSB7XG4gIGZyb206IE15RWRpdG9yUG9zaXRpb247XG4gIHRvOiBNeUVkaXRvclBvc2l0aW9uO1xufVxuXG5leHBvcnQgY2xhc3MgTXlFZGl0b3JTZWxlY3Rpb24ge1xuICBhbmNob3I6IE15RWRpdG9yUG9zaXRpb247XG4gIGhlYWQ6IE15RWRpdG9yUG9zaXRpb247XG59XG5cbmZ1bmN0aW9uIGZvbGRJbnNpZGUodmlldzogRWRpdG9yVmlldywgZnJvbTogbnVtYmVyLCB0bzogbnVtYmVyKSB7XG4gIGxldCBmb3VuZDogeyBmcm9tOiBudW1iZXI7IHRvOiBudW1iZXIgfSB8IG51bGwgPSBudWxsO1xuICBmb2xkZWRSYW5nZXModmlldy5zdGF0ZSkuYmV0d2Vlbihmcm9tLCB0bywgKGZyb20sIHRvKSA9PiB7XG4gICAgaWYgKCFmb3VuZCB8fCBmb3VuZC5mcm9tID4gZnJvbSkgZm91bmQgPSB7IGZyb20sIHRvIH07XG4gIH0pO1xuICByZXR1cm4gZm91bmQ7XG59XG5cbmV4cG9ydCBjbGFzcyBNeUVkaXRvciB7XG4gIHByaXZhdGUgdmlldzogRWRpdG9yVmlldztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGU6IEVkaXRvcikge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgdGhpcy52aWV3ID0gKHRoaXMuZSBhcyBhbnkpLmNtO1xuICB9XG5cbiAgZ2V0Q3Vyc29yKCk6IE15RWRpdG9yUG9zaXRpb24ge1xuICAgIHJldHVybiB0aGlzLmUuZ2V0Q3Vyc29yKCk7XG4gIH1cblxuICBnZXRMaW5lKG46IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZS5nZXRMaW5lKG4pO1xuICB9XG5cbiAgbGFzdExpbmUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5lLmxhc3RMaW5lKCk7XG4gIH1cblxuICBsaXN0U2VsZWN0aW9ucygpOiBNeUVkaXRvclNlbGVjdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5lLmxpc3RTZWxlY3Rpb25zKCk7XG4gIH1cblxuICBnZXRSYW5nZShmcm9tOiBNeUVkaXRvclBvc2l0aW9uLCB0bzogTXlFZGl0b3JQb3NpdGlvbik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZS5nZXRSYW5nZShmcm9tLCB0byk7XG4gIH1cblxuICByZXBsYWNlUmFuZ2UoXG4gICAgcmVwbGFjZW1lbnQ6IHN0cmluZyxcbiAgICBmcm9tOiBNeUVkaXRvclBvc2l0aW9uLFxuICAgIHRvOiBNeUVkaXRvclBvc2l0aW9uXG4gICk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmUucmVwbGFjZVJhbmdlKHJlcGxhY2VtZW50LCBmcm9tLCB0byk7XG4gIH1cblxuICBzZXRTZWxlY3Rpb25zKHNlbGVjdGlvbnM6IE15RWRpdG9yU2VsZWN0aW9uW10pOiB2b2lkIHtcbiAgICB0aGlzLmUuc2V0U2VsZWN0aW9ucyhzZWxlY3Rpb25zKTtcbiAgfVxuXG4gIHNldFZhbHVlKHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZS5zZXRWYWx1ZSh0ZXh0KTtcbiAgfVxuXG4gIGdldFZhbHVlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZS5nZXRWYWx1ZSgpO1xuICB9XG5cbiAgb2Zmc2V0VG9Qb3Mob2Zmc2V0OiBudW1iZXIpOiBNeUVkaXRvclBvc2l0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5lLm9mZnNldFRvUG9zKG9mZnNldCk7XG4gIH1cblxuICBwb3NUb09mZnNldChwb3M6IE15RWRpdG9yUG9zaXRpb24pOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmUucG9zVG9PZmZzZXQocG9zKTtcbiAgfVxuXG4gIGZvbGQobjogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgeyB2aWV3IH0gPSB0aGlzO1xuICAgIGNvbnN0IGwgPSB2aWV3LmxpbmVCbG9ja0F0KHZpZXcuc3RhdGUuZG9jLmxpbmUobiArIDEpLmZyb20pO1xuICAgIGNvbnN0IHJhbmdlID0gZm9sZGFibGUodmlldy5zdGF0ZSwgbC5mcm9tLCBsLnRvKTtcblxuICAgIGlmICghcmFuZ2UgfHwgcmFuZ2UuZnJvbSA9PT0gcmFuZ2UudG8pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2aWV3LmRpc3BhdGNoKHsgZWZmZWN0czogW2ZvbGRFZmZlY3Qub2YocmFuZ2UpXSB9KTtcbiAgfVxuXG4gIHVuZm9sZChuOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCB7IHZpZXcgfSA9IHRoaXM7XG4gICAgY29uc3QgbCA9IHZpZXcubGluZUJsb2NrQXQodmlldy5zdGF0ZS5kb2MubGluZShuICsgMSkuZnJvbSk7XG4gICAgY29uc3QgcmFuZ2UgPSBmb2xkSW5zaWRlKHZpZXcsIGwuZnJvbSwgbC50byk7XG5cbiAgICBpZiAoIXJhbmdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmlldy5kaXNwYXRjaCh7IGVmZmVjdHM6IFt1bmZvbGRFZmZlY3Qub2YocmFuZ2UpXSB9KTtcbiAgfVxuXG4gIGdldEFsbEZvbGRlZExpbmVzKCk6IG51bWJlcltdIHtcbiAgICBjb25zdCBjID0gZm9sZGVkUmFuZ2VzKHRoaXMudmlldy5zdGF0ZSkuaXRlcigpO1xuICAgIGNvbnN0IHJlczogbnVtYmVyW10gPSBbXTtcbiAgICB3aGlsZSAoYy52YWx1ZSkge1xuICAgICAgcmVzLnB1c2godGhpcy5vZmZzZXRUb1BvcyhjLmZyb20pLmxpbmUpO1xuICAgICAgYy5uZXh0KCk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICB0cmlnZ2VyT25LZXlEb3duKGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBydW5TY29wZUhhbmRsZXJzKHRoaXMudmlldywgZSwgXCJlZGl0b3JcIik7XG4gIH1cblxuICBnZXRab29tUmFuZ2UoKTogTXlFZGl0b3JSYW5nZSB8IG51bGwge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3QgYXBpID0gKHdpbmRvdyBhcyBhbnkpLk9ic2lkaWFuWm9vbVBsdWdpbjtcblxuICAgIGlmICghYXBpIHx8ICFhcGkuZ2V0Wm9vbVJhbmdlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpLmdldFpvb21SYW5nZSh0aGlzLmUpO1xuICB9XG5cbiAgem9vbU91dCgpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIGNvbnN0IGFwaSA9ICh3aW5kb3cgYXMgYW55KS5PYnNpZGlhblpvb21QbHVnaW47XG5cbiAgICBpZiAoIWFwaSB8fCAhYXBpLnpvb21PdXQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhcGkuem9vbU91dCh0aGlzLmUpO1xuICB9XG5cbiAgem9vbUluKGxpbmU6IG51bWJlcikge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3QgYXBpID0gKHdpbmRvdyBhcyBhbnkpLk9ic2lkaWFuWm9vbVBsdWdpbjtcblxuICAgIGlmICghYXBpIHx8ICFhcGkuem9vbUluKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgYXBpLnpvb21Jbih0aGlzLmUsIGxpbmUpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQbHVnaW5fMiwgZWRpdG9ySW5mb0ZpZWxkIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmltcG9ydCB7XG4gIEVkaXRvclZpZXcsXG4gIFBsdWdpblZhbHVlLFxuICBWaWV3UGx1Z2luLFxuICBWaWV3VXBkYXRlLFxufSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuXG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4vRmVhdHVyZVwiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuaW1wb3J0IHsgTGlzdCB9IGZyb20gXCIuLi9yb290XCI7XG5pbXBvcnQgeyBPYnNpZGlhblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvT2JzaWRpYW5TZXJ2aWNlXCI7XG5pbXBvcnQgeyBQYXJzZXJTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL1BhcnNlclNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuaW50ZXJmYWNlIExpbmVEYXRhIHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbiAgaGVpZ2h0OiBzdHJpbmc7XG4gIGxpc3Q6IExpc3Q7XG59XG5cbmNsYXNzIExpc3RMaW5lc1ZpZXdQbHVnaW5WYWx1ZSBpbXBsZW1lbnRzIFBsdWdpblZhbHVlIHtcbiAgcHJpdmF0ZSBzY2hlZHVsZWQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+O1xuICBwcml2YXRlIHNjcm9sbGVyOiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSBjb250ZW50Q29udGFpbmVyOiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSBlZGl0b3I6IE15RWRpdG9yO1xuICBwcml2YXRlIGxhc3RMaW5lOiBudW1iZXI7XG4gIHByaXZhdGUgbGluZXM6IExpbmVEYXRhW107XG4gIHByaXZhdGUgbGluZUVsZW1lbnRzOiBIVE1MRWxlbWVudFtdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlLFxuICAgIHByaXZhdGUgb2JzaWRpYW46IE9ic2lkaWFuU2VydmljZSxcbiAgICBwcml2YXRlIHBhcnNlcjogUGFyc2VyU2VydmljZSxcbiAgICBwcml2YXRlIHZpZXc6IEVkaXRvclZpZXdcbiAgKSB7XG4gICAgdGhpcy52aWV3LnNjcm9sbERPTS5hZGRFdmVudExpc3RlbmVyKFwic2Nyb2xsXCIsIHRoaXMub25TY3JvbGwpO1xuICAgIHRoaXMuc2V0dGluZ3Mub25DaGFuZ2UoXCJsaXN0TGluZXNcIiwgdGhpcy5zY2hlZHVsZVJlY2FsY3VsYXRlKTtcblxuICAgIHRoaXMucHJlcGFyZURvbSgpO1xuICAgIHRoaXMud2FpdEZvckVkaXRvcigpO1xuICB9XG5cbiAgcHJpdmF0ZSB3YWl0Rm9yRWRpdG9yID0gKCkgPT4ge1xuICAgIGNvbnN0IG9lID0gdGhpcy52aWV3LnN0YXRlLmZpZWxkKGVkaXRvckluZm9GaWVsZCkuZWRpdG9yO1xuICAgIGlmICghb2UpIHtcbiAgICAgIHNldFRpbWVvdXQodGhpcy53YWl0Rm9yRWRpdG9yLCAwKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5lZGl0b3IgPSBuZXcgTXlFZGl0b3Iob2UpO1xuICAgIHRoaXMuc2NoZWR1bGVSZWNhbGN1bGF0ZSgpO1xuICB9O1xuXG4gIHByaXZhdGUgcHJlcGFyZURvbSgpIHtcbiAgICB0aGlzLmNvbnRlbnRDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgIHRoaXMuY29udGVudENvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFxuICAgICAgXCJvdXRsaW5lci1wbHVnaW4tbGlzdC1saW5lcy1jb250ZW50LWNvbnRhaW5lclwiXG4gICAgKTtcblxuICAgIHRoaXMuc2Nyb2xsZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgIHRoaXMuc2Nyb2xsZXIuY2xhc3NMaXN0LmFkZChcIm91dGxpbmVyLXBsdWdpbi1saXN0LWxpbmVzLXNjcm9sbGVyXCIpO1xuXG4gICAgdGhpcy5zY3JvbGxlci5hcHBlbmRDaGlsZCh0aGlzLmNvbnRlbnRDb250YWluZXIpO1xuICAgIHRoaXMudmlldy5kb20uYXBwZW5kQ2hpbGQodGhpcy5zY3JvbGxlcik7XG4gIH1cblxuICBwcml2YXRlIG9uU2Nyb2xsID0gKGU6IEV2ZW50KSA9PiB7XG4gICAgY29uc3QgeyBzY3JvbGxMZWZ0LCBzY3JvbGxUb3AgfSA9IGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIHRoaXMuc2Nyb2xsZXIuc2Nyb2xsVG8oc2Nyb2xsTGVmdCwgc2Nyb2xsVG9wKTtcbiAgfTtcblxuICBwcml2YXRlIHNjaGVkdWxlUmVjYWxjdWxhdGUgPSAoKSA9PiB7XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuc2NoZWR1bGVkKTtcbiAgICB0aGlzLnNjaGVkdWxlZCA9IHNldFRpbWVvdXQodGhpcy5jYWxjdWxhdGUsIDApO1xuICB9O1xuXG4gIHVwZGF0ZSh1cGRhdGU6IFZpZXdVcGRhdGUpIHtcbiAgICBpZiAoXG4gICAgICB1cGRhdGUuZG9jQ2hhbmdlZCB8fFxuICAgICAgdXBkYXRlLnZpZXdwb3J0Q2hhbmdlZCB8fFxuICAgICAgdXBkYXRlLmdlb21ldHJ5Q2hhbmdlZCB8fFxuICAgICAgdXBkYXRlLnRyYW5zYWN0aW9ucy5zb21lKCh0cikgPT4gdHIucmVjb25maWd1cmVkKVxuICAgICkge1xuICAgICAgdGhpcy5zY2hlZHVsZVJlY2FsY3VsYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjYWxjdWxhdGUgPSAoKSA9PiB7XG4gICAgdGhpcy5saW5lcyA9IFtdO1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy5zZXR0aW5ncy5saXN0TGluZXMgJiZcbiAgICAgIHRoaXMub2JzaWRpYW4uaXNEZWZhdWx0VGhlbWVFbmFibGVkKCkgJiZcbiAgICAgIHRoaXMudmlldy52aWV3cG9ydExpbmVCbG9ja3MubGVuZ3RoID4gMCAmJlxuICAgICAgdGhpcy52aWV3LnZpc2libGVSYW5nZXMubGVuZ3RoID4gMFxuICAgICkge1xuICAgICAgY29uc3QgZnJvbUxpbmUgPSB0aGlzLmVkaXRvci5vZmZzZXRUb1Bvcyh0aGlzLnZpZXcudmlld3BvcnQuZnJvbSkubGluZTtcbiAgICAgIGNvbnN0IHRvTGluZSA9IHRoaXMuZWRpdG9yLm9mZnNldFRvUG9zKHRoaXMudmlldy52aWV3cG9ydC50bykubGluZTtcbiAgICAgIGNvbnN0IGxpc3RzID0gdGhpcy5wYXJzZXIucGFyc2VSYW5nZSh0aGlzLmVkaXRvciwgZnJvbUxpbmUsIHRvTGluZSk7XG5cbiAgICAgIGZvciAoY29uc3QgbGlzdCBvZiBsaXN0cykge1xuICAgICAgICB0aGlzLmxhc3RMaW5lID0gbGlzdC5nZXRSYW5nZSgpWzFdLmxpbmU7XG5cbiAgICAgICAgZm9yIChjb25zdCBjIG9mIGxpc3QuZ2V0Q2hpbGRyZW4oKSkge1xuICAgICAgICAgIHRoaXMucmVjdXJzaXZlKGMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGluZXMuc29ydCgoYSwgYikgPT5cbiAgICAgICAgYS50b3AgPT09IGIudG9wID8gYS5sZWZ0IC0gYi5sZWZ0IDogYS50b3AgLSBiLnRvcFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZURvbSgpO1xuICB9O1xuXG4gIHByaXZhdGUgZ2V0TmV4dFNpYmxpbmcobGlzdDogTGlzdCk6IExpc3QgfCBudWxsIHtcbiAgICBsZXQgbGlzdFRtcCA9IGxpc3Q7XG4gICAgbGV0IHAgPSBsaXN0VG1wLmdldFBhcmVudCgpO1xuICAgIHdoaWxlIChwKSB7XG4gICAgICBjb25zdCBuZXh0U2libGluZyA9IHAuZ2V0TmV4dFNpYmxpbmdPZihsaXN0VG1wKTtcbiAgICAgIGlmIChuZXh0U2libGluZykge1xuICAgICAgICByZXR1cm4gbmV4dFNpYmxpbmc7XG4gICAgICB9XG4gICAgICBsaXN0VG1wID0gcDtcbiAgICAgIHAgPSBsaXN0VG1wLmdldFBhcmVudCgpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgcmVjdXJzaXZlKGxpc3Q6IExpc3QsIHBhcmVudEN0eDogeyByb290TGVmdD86IG51bWJlciB9ID0ge30pIHtcbiAgICBjb25zdCBjaGlsZHJlbiA9IGxpc3QuZ2V0Q2hpbGRyZW4oKTtcblxuICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmcm9tT2Zmc2V0ID0gdGhpcy5lZGl0b3IucG9zVG9PZmZzZXQoe1xuICAgICAgbGluZTogbGlzdC5nZXRGaXJzdExpbmVDb250ZW50U3RhcnQoKS5saW5lLFxuICAgICAgY2g6IGxpc3QuZ2V0Rmlyc3RMaW5lSW5kZW50KCkubGVuZ3RoLFxuICAgIH0pO1xuICAgIGNvbnN0IG5leHRTaWJsaW5nID0gdGhpcy5nZXROZXh0U2libGluZyhsaXN0KTtcbiAgICBjb25zdCB0aWxsT2Zmc2V0ID0gdGhpcy5lZGl0b3IucG9zVG9PZmZzZXQoe1xuICAgICAgbGluZTogbmV4dFNpYmxpbmdcbiAgICAgICAgPyBuZXh0U2libGluZy5nZXRGaXJzdExpbmVDb250ZW50U3RhcnQoKS5saW5lIC0gMVxuICAgICAgICA6IHRoaXMubGFzdExpbmUsXG4gICAgICBjaDogMCxcbiAgICB9KTtcblxuICAgIGxldCB2aXNpYmxlRnJvbSA9IHRoaXMudmlldy52aXNpYmxlUmFuZ2VzWzBdLmZyb207XG4gICAgbGV0IHZpc2libGVUbyA9XG4gICAgICB0aGlzLnZpZXcudmlzaWJsZVJhbmdlc1t0aGlzLnZpZXcudmlzaWJsZVJhbmdlcy5sZW5ndGggLSAxXS50bztcbiAgICBjb25zdCB6b29tUmFuZ2UgPSB0aGlzLmVkaXRvci5nZXRab29tUmFuZ2UoKTtcbiAgICBpZiAoem9vbVJhbmdlKSB7XG4gICAgICB2aXNpYmxlRnJvbSA9IE1hdGgubWF4KFxuICAgICAgICB2aXNpYmxlRnJvbSxcbiAgICAgICAgdGhpcy5lZGl0b3IucG9zVG9PZmZzZXQoem9vbVJhbmdlLmZyb20pXG4gICAgICApO1xuICAgICAgdmlzaWJsZVRvID0gTWF0aC5taW4odmlzaWJsZVRvLCB0aGlzLmVkaXRvci5wb3NUb09mZnNldCh6b29tUmFuZ2UudG8pKTtcbiAgICB9XG5cbiAgICBpZiAoZnJvbU9mZnNldCA+IHZpc2libGVUbyB8fCB0aWxsT2Zmc2V0IDwgdmlzaWJsZUZyb20pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb29yZHMgPSB0aGlzLnZpZXcuY29vcmRzQXRQb3MoZnJvbU9mZnNldCwgMSk7XG4gICAgaWYgKHBhcmVudEN0eC5yb290TGVmdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXJlbnRDdHgucm9vdExlZnQgPSBjb29yZHMubGVmdDtcbiAgICB9XG4gICAgY29uc3QgbGVmdCA9IE1hdGguZmxvb3IoY29vcmRzLnJpZ2h0IC0gcGFyZW50Q3R4LnJvb3RMZWZ0KTtcblxuICAgIGNvbnN0IHRvcCA9XG4gICAgICB2aXNpYmxlRnJvbSA+IDAgJiYgZnJvbU9mZnNldCA8IHZpc2libGVGcm9tXG4gICAgICAgID8gLTIwXG4gICAgICAgIDogdGhpcy52aWV3LmxpbmVCbG9ja0F0KGZyb21PZmZzZXQpLnRvcDtcbiAgICBjb25zdCBib3R0b20gPVxuICAgICAgdGlsbE9mZnNldCA+IHZpc2libGVUb1xuICAgICAgICA/IHRoaXMudmlldy5saW5lQmxvY2tBdCh2aXNpYmxlVG8gLSAxKS5ib3R0b21cbiAgICAgICAgOiB0aGlzLnZpZXcubGluZUJsb2NrQXQodGlsbE9mZnNldCkuYm90dG9tO1xuICAgIGNvbnN0IGhlaWdodCA9IGJvdHRvbSAtIHRvcDtcblxuICAgIGlmIChoZWlnaHQgPiAwICYmICFsaXN0LmlzRm9sZGVkKCkpIHtcbiAgICAgIGNvbnN0IG5leHRTaWJsaW5nID0gbGlzdC5nZXRQYXJlbnQoKS5nZXROZXh0U2libGluZ09mKGxpc3QpO1xuICAgICAgY29uc3QgaGFzTmV4dFNpYmxpbmcgPVxuICAgICAgICAhIW5leHRTaWJsaW5nICYmXG4gICAgICAgIHRoaXMuZWRpdG9yLnBvc1RvT2Zmc2V0KG5leHRTaWJsaW5nLmdldEZpcnN0TGluZUNvbnRlbnRTdGFydCgpKSA8PVxuICAgICAgICAgIHZpc2libGVUbztcblxuICAgICAgdGhpcy5saW5lcy5wdXNoKHtcbiAgICAgICAgdG9wLFxuICAgICAgICBsZWZ0LFxuICAgICAgICBoZWlnaHQ6IGBjYWxjKCR7aGVpZ2h0fXB4ICR7aGFzTmV4dFNpYmxpbmcgPyBcIi0gMS41ZW1cIiA6IFwiLSAyZW1cIn0pYCxcbiAgICAgICAgbGlzdCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgY2hpbGRyZW4pIHtcbiAgICAgIGlmICghY2hpbGQuaXNFbXB0eSgpKSB7XG4gICAgICAgIHRoaXMucmVjdXJzaXZlKGNoaWxkLCBwYXJlbnRDdHgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgb25DbGljayA9IChlOiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgY29uc3QgbGluZSA9IHRoaXMubGluZXNbTnVtYmVyKChlLnRhcmdldCBhcyBIVE1MRWxlbWVudCkuZGF0YXNldC5pbmRleCldO1xuXG4gICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLmxpc3RMaW5lQWN0aW9uKSB7XG4gICAgICBjYXNlIFwiem9vbS1pblwiOlxuICAgICAgICB0aGlzLnpvb21JbihsaW5lKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJ0b2dnbGUtZm9sZGluZ1wiOlxuICAgICAgICB0aGlzLnRvZ2dsZUZvbGRpbmcobGluZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfTtcblxuICBwcml2YXRlIHpvb21JbihsaW5lOiBMaW5lRGF0YSkge1xuICAgIGNvbnN0IGVkaXRvciA9IG5ldyBNeUVkaXRvcih0aGlzLnZpZXcuc3RhdGUuZmllbGQoZWRpdG9ySW5mb0ZpZWxkKS5lZGl0b3IpO1xuXG4gICAgZWRpdG9yLnpvb21JbihsaW5lLmxpc3QuZ2V0Rmlyc3RMaW5lQ29udGVudFN0YXJ0KCkubGluZSk7XG4gIH1cblxuICBwcml2YXRlIHRvZ2dsZUZvbGRpbmcobGluZTogTGluZURhdGEpIHtcbiAgICBjb25zdCB7IGxpc3QgfSA9IGxpbmU7XG5cbiAgICBpZiAobGlzdC5pc0VtcHR5KCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgbmVlZFRvVW5mb2xkID0gdHJ1ZTtcbiAgICBjb25zdCBsaW5lc1RvVG9nZ2xlOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgYyBvZiBsaXN0LmdldENoaWxkcmVuKCkpIHtcbiAgICAgIGlmIChjLmlzRW1wdHkoKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmICghYy5pc0ZvbGRlZCgpKSB7XG4gICAgICAgIG5lZWRUb1VuZm9sZCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgbGluZXNUb1RvZ2dsZS5wdXNoKGMuZ2V0Rmlyc3RMaW5lQ29udGVudFN0YXJ0KCkubGluZSk7XG4gICAgfVxuXG4gICAgY29uc3QgZWRpdG9yID0gbmV3IE15RWRpdG9yKHRoaXMudmlldy5zdGF0ZS5maWVsZChlZGl0b3JJbmZvRmllbGQpLmVkaXRvcik7XG5cbiAgICBmb3IgKGNvbnN0IGwgb2YgbGluZXNUb1RvZ2dsZSkge1xuICAgICAgaWYgKG5lZWRUb1VuZm9sZCkge1xuICAgICAgICBlZGl0b3IudW5mb2xkKGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWRpdG9yLmZvbGQobCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVEb20oKSB7XG4gICAgY29uc3QgY21TY3JvbGwgPSB0aGlzLnZpZXcuc2Nyb2xsRE9NO1xuICAgIGNvbnN0IGNtQ29udGVudCA9IHRoaXMudmlldy5jb250ZW50RE9NO1xuICAgIGNvbnN0IGNtQ29udGVudENvbnRhaW5lciA9IGNtQ29udGVudC5wYXJlbnRFbGVtZW50O1xuICAgIGNvbnN0IGNtU2l6ZXIgPSBjbUNvbnRlbnRDb250YWluZXIucGFyZW50RWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIE9ic2lkaWFuIGNhbiBhZGQgYWRkaXRpb25hbCBlbGVtZW50cyBpbnRvIENvbnRlbnQgTWFuYWdlci5cbiAgICAgKiBUaGUgbW9zdCBvYnZpb3VzIGNhc2UgaXMgdGhlICdlbWJlZGRlZC1iYWNrbGlua3MnIGNvcmUgcGx1Z2luIHRoYXQgYWRkcyBhIG1lbnUgaW5zaWRlIGEgQ29udGVudCBNYW5hZ2VyLlxuICAgICAqIFdlIG11c3QgdGFrZSBoZWlnaHRzIG9mIGFsbCBvZiB0aGVzZSBlbGVtZW50cyBpbnRvIGFjY291bnRcbiAgICAgKiB0byBiZSBhYmxlIHRvIGNhbGN1bGF0ZSB0aGUgY29ycmVjdCBzaXplIG9mIGxpbmVzJyBjb250YWluZXIuXG4gICAgICovXG4gICAgbGV0IGNtU2l6ZXJDaGlsZHJlblN1bUhlaWdodCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjbVNpemVyLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjbVNpemVyQ2hpbGRyZW5TdW1IZWlnaHQgKz0gY21TaXplci5jaGlsZHJlbltpXS5jbGllbnRIZWlnaHQ7XG4gICAgfVxuXG4gICAgdGhpcy5zY3JvbGxlci5zdHlsZS50b3AgPSBjbVNjcm9sbC5vZmZzZXRUb3AgKyBcInB4XCI7XG4gICAgdGhpcy5jb250ZW50Q29udGFpbmVyLnN0eWxlLmhlaWdodCA9IGNtU2l6ZXJDaGlsZHJlblN1bUhlaWdodCArIFwicHhcIjtcbiAgICB0aGlzLmNvbnRlbnRDb250YWluZXIuc3R5bGUubWFyZ2luTGVmdCA9XG4gICAgICBjbUNvbnRlbnRDb250YWluZXIub2Zmc2V0TGVmdCArIFwicHhcIjtcbiAgICB0aGlzLmNvbnRlbnRDb250YWluZXIuc3R5bGUubWFyZ2luVG9wID1cbiAgICAgIChjbUNvbnRlbnQuZmlyc3RFbGVtZW50Q2hpbGQgYXMgSFRNTEVsZW1lbnQpLm9mZnNldFRvcCAtIDI0ICsgXCJweFwiO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5saW5lRWxlbWVudHMubGVuZ3RoID09PSBpKSB7XG4gICAgICAgIGNvbnN0IGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBlLmNsYXNzTGlzdC5hZGQoXCJvdXRsaW5lci1wbHVnaW4tbGlzdC1saW5lXCIpO1xuICAgICAgICBlLmRhdGFzZXQuaW5kZXggPSBTdHJpbmcoaSk7XG4gICAgICAgIGUuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlZG93blwiLCB0aGlzLm9uQ2xpY2spO1xuICAgICAgICB0aGlzLmNvbnRlbnRDb250YWluZXIuYXBwZW5kQ2hpbGQoZSk7XG4gICAgICAgIHRoaXMubGluZUVsZW1lbnRzLnB1c2goZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGwgPSB0aGlzLmxpbmVzW2ldO1xuICAgICAgY29uc3QgZSA9IHRoaXMubGluZUVsZW1lbnRzW2ldO1xuICAgICAgZS5zdHlsZS50b3AgPSBsLnRvcCArIFwicHhcIjtcbiAgICAgIGUuc3R5bGUubGVmdCA9IGwubGVmdCArIFwicHhcIjtcbiAgICAgIGUuc3R5bGUuaGVpZ2h0ID0gbC5oZWlnaHQ7XG4gICAgICBlLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IHRoaXMubGluZXMubGVuZ3RoOyBpIDwgdGhpcy5saW5lRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGUgPSB0aGlzLmxpbmVFbGVtZW50c1tpXTtcbiAgICAgIGUuc3R5bGUudG9wID0gXCIwcHhcIjtcbiAgICAgIGUuc3R5bGUubGVmdCA9IFwiMHB4XCI7XG4gICAgICBlLnN0eWxlLmhlaWdodCA9IFwiMHB4XCI7XG4gICAgICBlLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICB9XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIHRoaXMuc2V0dGluZ3MucmVtb3ZlQ2FsbGJhY2soXCJsaXN0TGluZXNcIiwgdGhpcy5zY2hlZHVsZVJlY2FsY3VsYXRlKTtcbiAgICB0aGlzLnZpZXcuc2Nyb2xsRE9NLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJzY3JvbGxcIiwgdGhpcy5vblNjcm9sbCk7XG4gICAgdGhpcy52aWV3LmRvbS5yZW1vdmVDaGlsZCh0aGlzLnNjcm9sbGVyKTtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5zY2hlZHVsZWQpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBMaW5lc0ZlYXR1cmUgaW1wbGVtZW50cyBGZWF0dXJlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBwbHVnaW46IFBsdWdpbl8yLFxuICAgIHByaXZhdGUgc2V0dGluZ3M6IFNldHRpbmdzU2VydmljZSxcbiAgICBwcml2YXRlIG9ic2lkaWFuOiBPYnNpZGlhblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwYXJzZXI6IFBhcnNlclNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24oXG4gICAgICBWaWV3UGx1Z2luLmRlZmluZShcbiAgICAgICAgKHZpZXcpID0+XG4gICAgICAgICAgbmV3IExpc3RMaW5lc1ZpZXdQbHVnaW5WYWx1ZShcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MsXG4gICAgICAgICAgICB0aGlzLm9ic2lkaWFuLFxuICAgICAgICAgICAgdGhpcy5wYXJzZXIsXG4gICAgICAgICAgICB2aWV3XG4gICAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBhc3luYyB1bmxvYWQoKSB7fVxufVxuIiwiaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuL0ZlYXR1cmVcIjtcblxuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL1NldHRpbmdzU2VydmljZVwiO1xuXG5jb25zdCBCRVRURVJfTElTVFNfQ0xBU1MgPSBcIm91dGxpbmVyLXBsdWdpbi1iZXR0ZXItbGlzdHNcIjtcbmNvbnN0IEJFVFRFUl9CVUxMRVRTX0NMQVNTID0gXCJvdXRsaW5lci1wbHVnaW4tYmV0dGVyLWJ1bGxldHNcIjtcbmNvbnN0IFZFUlRJQ0FMX0xJTkVTID0gXCJvdXRsaW5lci1wbHVnaW4tdmVydGljYWwtbGluZXNcIjtcbmNvbnN0IEtOT1dOX0NMQVNTRVMgPSBbXG4gIEJFVFRFUl9MSVNUU19DTEFTUyxcbiAgQkVUVEVSX0JVTExFVFNfQ0xBU1MsXG4gIFZFUlRJQ0FMX0xJTkVTLFxuXTtcblxuZXhwb3J0IGNsYXNzIExpc3RzU3R5bGVzRmVhdHVyZSBpbXBsZW1lbnRzIEZlYXR1cmUge1xuICBwcml2YXRlIGludGVydmFsOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlLFxuICAgIHByaXZhdGUgb2JzaWRpYW46IE9ic2lkaWFuU2VydmljZVxuICApIHt9XG5cbiAgYXN5bmMgbG9hZCgpIHtcbiAgICB0aGlzLnN5bmNMaXN0c1N0eWxlcygpO1xuICAgIHRoaXMuaW50ZXJ2YWwgPSB3aW5kb3cuc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgdGhpcy5zeW5jTGlzdHNTdHlsZXMoKTtcbiAgICB9LCAxMDAwKTtcbiAgfVxuXG4gIGFzeW5jIHVubG9hZCgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWwpO1xuICAgIHRoaXMuYXBwbHlMaXN0c1N0eWxlcyhbXSk7XG4gIH1cblxuICBwcml2YXRlIHN5bmNMaXN0c1N0eWxlcyA9ICgpID0+IHtcbiAgICBjb25zdCBjbGFzc2VzID0gW107XG5cbiAgICBpZiAodGhpcy5vYnNpZGlhbi5pc0RlZmF1bHRUaGVtZUVuYWJsZWQoKSkge1xuICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc3R5bGVMaXN0cykge1xuICAgICAgICBjbGFzc2VzLnB1c2goQkVUVEVSX0xJU1RTX0NMQVNTKTtcbiAgICAgICAgY2xhc3Nlcy5wdXNoKEJFVFRFUl9CVUxMRVRTX0NMQVNTKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubGlzdExpbmVzKSB7XG4gICAgICAgIGNsYXNzZXMucHVzaChWRVJUSUNBTF9MSU5FUyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5hcHBseUxpc3RzU3R5bGVzKGNsYXNzZXMpO1xuICB9O1xuXG4gIHByaXZhdGUgYXBwbHlMaXN0c1N0eWxlcyhjbGFzc2VzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IHRvS2VlcCA9IGNsYXNzZXMuZmlsdGVyKChjKSA9PiBLTk9XTl9DTEFTU0VTLmNvbnRhaW5zKGMpKTtcbiAgICBjb25zdCB0b1JlbW92ZSA9IEtOT1dOX0NMQVNTRVMuZmlsdGVyKChjKSA9PiAhdG9LZWVwLmNvbnRhaW5zKGMpKTtcblxuICAgIGZvciAoY29uc3QgYyBvZiB0b0tlZXApIHtcbiAgICAgIGlmICghZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoYykpIHtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKGMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgYyBvZiB0b1JlbW92ZSkge1xuICAgICAgaWYgKGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmNvbnRhaW5zKGMpKSB7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZShjKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gXCIuL09wZXJhdGlvblwiO1xuXG5pbXBvcnQgeyBMaXN0TGluZSwgUG9zaXRpb24sIFJvb3QgfSBmcm9tIFwiLi4vcm9vdFwiO1xuXG5leHBvcnQgY2xhc3MgTW92ZUN1cnNvclRvUHJldmlvdXNVbmZvbGRlZExpbmVPcGVyYXRpb24gaW1wbGVtZW50cyBPcGVyYXRpb24ge1xuICBwcml2YXRlIHN0b3BQcm9wYWdhdGlvbiA9IGZhbHNlO1xuICBwcml2YXRlIHVwZGF0ZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJvb3Q6IFJvb3QpIHt9XG5cbiAgc2hvdWxkU3RvcFByb3BhZ2F0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnN0b3BQcm9wYWdhdGlvbjtcbiAgfVxuXG4gIHNob3VsZFVwZGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy51cGRhdGVkO1xuICB9XG5cbiAgcGVyZm9ybSgpIHtcbiAgICBjb25zdCB7IHJvb3QgfSA9IHRoaXM7XG5cbiAgICBpZiAoIXJvb3QuaGFzU2luZ2xlQ3Vyc29yKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsaXN0ID0gdGhpcy5yb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGNvbnN0IGN1cnNvciA9IHRoaXMucm9vdC5nZXRDdXJzb3IoKTtcbiAgICBjb25zdCBsaW5lcyA9IGxpc3QuZ2V0TGluZXNJbmZvKCk7XG4gICAgY29uc3QgbGluZU5vID0gbGluZXMuZmluZEluZGV4KFxuICAgICAgKGwpID0+XG4gICAgICAgIGN1cnNvci5jaCA9PT0gbC5mcm9tLmNoICsgbGlzdC5nZXRDaGVja2JveExlbmd0aCgpICYmXG4gICAgICAgIGN1cnNvci5saW5lID09PSBsLmZyb20ubGluZVxuICAgICk7XG5cbiAgICBpZiAobGluZU5vID09PSAwKSB7XG4gICAgICB0aGlzLm1vdmVDdXJzb3JUb1ByZXZpb3VzVW5mb2xkZWRJdGVtKHJvb3QsIGN1cnNvcik7XG4gICAgfSBlbHNlIGlmIChsaW5lTm8gPiAwKSB7XG4gICAgICB0aGlzLm1vdmVDdXJzb3JUb1ByZXZpb3VzTm90ZUxpbmUocm9vdCwgbGluZXMsIGxpbmVObyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb3ZlQ3Vyc29yVG9QcmV2aW91c05vdGVMaW5lKFxuICAgIHJvb3Q6IFJvb3QsXG4gICAgbGluZXM6IExpc3RMaW5lW10sXG4gICAgbGluZU5vOiBudW1iZXJcbiAgKSB7XG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICByb290LnJlcGxhY2VDdXJzb3IobGluZXNbbGluZU5vIC0gMV0udG8pO1xuICB9XG5cbiAgcHJpdmF0ZSBtb3ZlQ3Vyc29yVG9QcmV2aW91c1VuZm9sZGVkSXRlbShyb290OiBSb290LCBjdXJzb3I6IFBvc2l0aW9uKSB7XG4gICAgY29uc3QgcHJldiA9IHJvb3QuZ2V0TGlzdFVuZGVyTGluZShjdXJzb3IubGluZSAtIDEpO1xuXG4gICAgaWYgKCFwcmV2KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICBpZiAocHJldi5pc0ZvbGRlZCgpKSB7XG4gICAgICBjb25zdCBmb2xkUm9vdCA9IHByZXYuZ2V0VG9wRm9sZFJvb3QoKTtcbiAgICAgIGNvbnN0IGZpcnN0TGluZUVuZCA9IGZvbGRSb290LmdldExpbmVzSW5mbygpWzBdLnRvO1xuICAgICAgcm9vdC5yZXBsYWNlQ3Vyc29yKGZpcnN0TGluZUVuZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJvb3QucmVwbGFjZUN1cnNvcihwcmV2LmdldExhc3RMaW5lQ29udGVudEVuZCgpKTtcbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IFBsdWdpbl8yIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmltcG9ydCB7IGtleW1hcCB9IGZyb20gXCJAY29kZW1pcnJvci92aWV3XCI7XG5cbmltcG9ydCB7IE15RWRpdG9yIH0gZnJvbSBcIi4uL015RWRpdG9yXCI7XG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4uL2ZlYXR1cmVzL0ZlYXR1cmVcIjtcbmltcG9ydCB7IE1vdmVDdXJzb3JUb1ByZXZpb3VzVW5mb2xkZWRMaW5lT3BlcmF0aW9uIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvTW92ZUN1cnNvclRvUHJldmlvdXNVbmZvbGRlZExpbmVPcGVyYXRpb25cIjtcbmltcG9ydCB7IElNRVNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvSU1FU2VydmljZVwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIE1vdmVDdXJzb3JUb1ByZXZpb3VzVW5mb2xkZWRMaW5lRmVhdHVyZSBpbXBsZW1lbnRzIEZlYXR1cmUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBsdWdpbjogUGx1Z2luXzIsXG4gICAgcHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlLFxuICAgIHByaXZhdGUgaW1lOiBJTUVTZXJ2aWNlLFxuICAgIHByaXZhdGUgb2JzaWRpYW46IE9ic2lkaWFuU2VydmljZSxcbiAgICBwcml2YXRlIHBlcmZvcm1PcGVyYXRpb246IFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlXG4gICkge31cblxuICBhc3luYyBsb2FkKCkge1xuICAgIHRoaXMucGx1Z2luLnJlZ2lzdGVyRWRpdG9yRXh0ZW5zaW9uKFxuICAgICAga2V5bWFwLm9mKFtcbiAgICAgICAge1xuICAgICAgICAgIGtleTogXCJBcnJvd0xlZnRcIixcbiAgICAgICAgICBydW46IHRoaXMub2JzaWRpYW4uY3JlYXRlS2V5bWFwUnVuQ2FsbGJhY2soe1xuICAgICAgICAgICAgY2hlY2s6IHRoaXMuY2hlY2ssXG4gICAgICAgICAgICBydW46IHRoaXMucnVuLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgd2luOiBcImMtQXJyb3dMZWZ0XCIsXG4gICAgICAgICAgbGludXg6IFwiYy1BcnJvd0xlZnRcIixcbiAgICAgICAgICBydW46IHRoaXMub2JzaWRpYW4uY3JlYXRlS2V5bWFwUnVuQ2FsbGJhY2soe1xuICAgICAgICAgICAgY2hlY2s6IHRoaXMuY2hlY2ssXG4gICAgICAgICAgICBydW46IHRoaXMucnVuLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgXSlcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgdW5sb2FkKCkge31cblxuICBwcml2YXRlIGNoZWNrID0gKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnNldHRpbmdzLnN0aWNrQ3Vyc29yICYmICF0aGlzLmltZS5pc0lNRU9wZW5lZCgpO1xuICB9O1xuXG4gIHByaXZhdGUgcnVuID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICByZXR1cm4gdGhpcy5wZXJmb3JtT3BlcmF0aW9uLnBlcmZvcm1PcGVyYXRpb24oXG4gICAgICAocm9vdCkgPT4gbmV3IE1vdmVDdXJzb3JUb1ByZXZpb3VzVW5mb2xkZWRMaW5lT3BlcmF0aW9uKHJvb3QpLFxuICAgICAgZWRpdG9yXG4gICAgKTtcbiAgfTtcbn1cbiIsImltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gXCIuL09wZXJhdGlvblwiO1xuXG5pbXBvcnQgeyBSb290IH0gZnJvbSBcIi4uL3Jvb3RcIjtcbmltcG9ydCB7IHJlY2FsY3VsYXRlTnVtZXJpY0J1bGxldHMgfSBmcm9tIFwiLi4vcm9vdC9yZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzXCI7XG5cbmV4cG9ydCBjbGFzcyBNb3ZlRG93bk9wZXJhdGlvbiBpbXBsZW1lbnRzIE9wZXJhdGlvbiB7XG4gIHByaXZhdGUgc3RvcFByb3BhZ2F0aW9uID0gZmFsc2U7XG4gIHByaXZhdGUgdXBkYXRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcm9vdDogUm9vdCkge31cblxuICBzaG91bGRTdG9wUHJvcGFnYXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcFByb3BhZ2F0aW9uO1xuICB9XG5cbiAgc2hvdWxkVXBkYXRlKCkge1xuICAgIHJldHVybiB0aGlzLnVwZGF0ZWQ7XG4gIH1cblxuICBwZXJmb3JtKCkge1xuICAgIGNvbnN0IHsgcm9vdCB9ID0gdGhpcztcblxuICAgIGlmICghcm9vdC5oYXNTaW5nbGVDdXJzb3IoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3RvcFByb3BhZ2F0aW9uID0gdHJ1ZTtcblxuICAgIGNvbnN0IGxpc3QgPSByb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGNvbnN0IHBhcmVudCA9IGxpc3QuZ2V0UGFyZW50KCk7XG4gICAgY29uc3QgZ3JhbmRQYXJlbnQgPSBwYXJlbnQuZ2V0UGFyZW50KCk7XG4gICAgY29uc3QgbmV4dCA9IHBhcmVudC5nZXROZXh0U2libGluZ09mKGxpc3QpO1xuXG4gICAgY29uc3QgbGlzdFN0YXJ0TGluZUJlZm9yZSA9IHJvb3QuZ2V0Q29udGVudExpbmVzUmFuZ2VPZihsaXN0KVswXTtcblxuICAgIGlmICghbmV4dCAmJiBncmFuZFBhcmVudCkge1xuICAgICAgY29uc3QgbmV3UGFyZW50ID0gZ3JhbmRQYXJlbnQuZ2V0TmV4dFNpYmxpbmdPZihwYXJlbnQpO1xuXG4gICAgICBpZiAobmV3UGFyZW50KSB7XG4gICAgICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG4gICAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChsaXN0KTtcbiAgICAgICAgbmV3UGFyZW50LmFkZEJlZm9yZUFsbChsaXN0KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG5leHQpIHtcbiAgICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG4gICAgICBwYXJlbnQucmVtb3ZlQ2hpbGQobGlzdCk7XG4gICAgICBwYXJlbnQuYWRkQWZ0ZXIobmV4dCwgbGlzdCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLnVwZGF0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsaXN0U3RhcnRMaW5lQWZ0ZXIgPSByb290LmdldENvbnRlbnRMaW5lc1JhbmdlT2YobGlzdClbMF07XG4gICAgY29uc3QgbGluZURpZmYgPSBsaXN0U3RhcnRMaW5lQWZ0ZXIgLSBsaXN0U3RhcnRMaW5lQmVmb3JlO1xuXG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcbiAgICByb290LnJlcGxhY2VDdXJzb3Ioe1xuICAgICAgbGluZTogY3Vyc29yLmxpbmUgKyBsaW5lRGlmZixcbiAgICAgIGNoOiBjdXJzb3IuY2gsXG4gICAgfSk7XG5cbiAgICByZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzKHJvb3QpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5pbXBvcnQgeyByZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzIH0gZnJvbSBcIi4uL3Jvb3QvcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0c1wiO1xuXG5leHBvcnQgY2xhc3MgTW92ZVJpZ2h0T3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290LCBwcml2YXRlIGRlZmF1bHRJbmRlbnRDaGFyczogc3RyaW5nKSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuXG4gICAgY29uc3QgbGlzdCA9IHJvb3QuZ2V0TGlzdFVuZGVyQ3Vyc29yKCk7XG4gICAgY29uc3QgcGFyZW50ID0gbGlzdC5nZXRQYXJlbnQoKTtcbiAgICBjb25zdCBwcmV2ID0gcGFyZW50LmdldFByZXZTaWJsaW5nT2YobGlzdCk7XG5cbiAgICBpZiAoIXByZXYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZWQgPSB0cnVlO1xuXG4gICAgY29uc3QgbGlzdFN0YXJ0TGluZUJlZm9yZSA9IHJvb3QuZ2V0Q29udGVudExpbmVzUmFuZ2VPZihsaXN0KVswXTtcblxuICAgIGNvbnN0IGluZGVudFBvcyA9IGxpc3QuZ2V0Rmlyc3RMaW5lSW5kZW50KCkubGVuZ3RoO1xuICAgIGxldCBpbmRlbnRDaGFycyA9IFwiXCI7XG5cbiAgICBpZiAoaW5kZW50Q2hhcnMgPT09IFwiXCIgJiYgIXByZXYuaXNFbXB0eSgpKSB7XG4gICAgICBpbmRlbnRDaGFycyA9IHByZXZcbiAgICAgICAgLmdldENoaWxkcmVuKClbMF1cbiAgICAgICAgLmdldEZpcnN0TGluZUluZGVudCgpXG4gICAgICAgIC5zbGljZShwcmV2LmdldEZpcnN0TGluZUluZGVudCgpLmxlbmd0aCk7XG4gICAgfVxuXG4gICAgaWYgKGluZGVudENoYXJzID09PSBcIlwiKSB7XG4gICAgICBpbmRlbnRDaGFycyA9IGxpc3RcbiAgICAgICAgLmdldEZpcnN0TGluZUluZGVudCgpXG4gICAgICAgIC5zbGljZShwYXJlbnQuZ2V0Rmlyc3RMaW5lSW5kZW50KCkubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBpZiAoaW5kZW50Q2hhcnMgPT09IFwiXCIgJiYgIWxpc3QuaXNFbXB0eSgpKSB7XG4gICAgICBpbmRlbnRDaGFycyA9IGxpc3QuZ2V0Q2hpbGRyZW4oKVswXS5nZXRGaXJzdExpbmVJbmRlbnQoKTtcbiAgICB9XG5cbiAgICBpZiAoaW5kZW50Q2hhcnMgPT09IFwiXCIpIHtcbiAgICAgIGluZGVudENoYXJzID0gdGhpcy5kZWZhdWx0SW5kZW50Q2hhcnM7XG4gICAgfVxuXG4gICAgcGFyZW50LnJlbW92ZUNoaWxkKGxpc3QpO1xuICAgIHByZXYuYWRkQWZ0ZXJBbGwobGlzdCk7XG4gICAgbGlzdC5pbmRlbnRDb250ZW50KGluZGVudFBvcywgaW5kZW50Q2hhcnMpO1xuXG4gICAgY29uc3QgbGlzdFN0YXJ0TGluZUFmdGVyID0gcm9vdC5nZXRDb250ZW50TGluZXNSYW5nZU9mKGxpc3QpWzBdO1xuICAgIGNvbnN0IGxpbmVEaWZmID0gbGlzdFN0YXJ0TGluZUFmdGVyIC0gbGlzdFN0YXJ0TGluZUJlZm9yZTtcblxuICAgIGNvbnN0IGN1cnNvciA9IHJvb3QuZ2V0Q3Vyc29yKCk7XG4gICAgcm9vdC5yZXBsYWNlQ3Vyc29yKHtcbiAgICAgIGxpbmU6IGN1cnNvci5saW5lICsgbGluZURpZmYsXG4gICAgICBjaDogY3Vyc29yLmNoICsgaW5kZW50Q2hhcnMubGVuZ3RoLFxuICAgIH0pO1xuXG4gICAgcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0cyhyb290KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgT3BlcmF0aW9uIH0gZnJvbSBcIi4vT3BlcmF0aW9uXCI7XG5cbmltcG9ydCB7IFJvb3QgfSBmcm9tIFwiLi4vcm9vdFwiO1xuaW1wb3J0IHsgcmVjYWxjdWxhdGVOdW1lcmljQnVsbGV0cyB9IGZyb20gXCIuLi9yb290L3JlY2FsY3VsYXRlTnVtZXJpY0J1bGxldHNcIjtcblxuZXhwb3J0IGNsYXNzIE1vdmVVcE9wZXJhdGlvbiBpbXBsZW1lbnRzIE9wZXJhdGlvbiB7XG4gIHByaXZhdGUgc3RvcFByb3BhZ2F0aW9uID0gZmFsc2U7XG4gIHByaXZhdGUgdXBkYXRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcm9vdDogUm9vdCkge31cblxuICBzaG91bGRTdG9wUHJvcGFnYXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcFByb3BhZ2F0aW9uO1xuICB9XG5cbiAgc2hvdWxkVXBkYXRlKCkge1xuICAgIHJldHVybiB0aGlzLnVwZGF0ZWQ7XG4gIH1cblxuICBwZXJmb3JtKCkge1xuICAgIGNvbnN0IHsgcm9vdCB9ID0gdGhpcztcblxuICAgIGlmICghcm9vdC5oYXNTaW5nbGVDdXJzb3IoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3RvcFByb3BhZ2F0aW9uID0gdHJ1ZTtcblxuICAgIGNvbnN0IGxpc3QgPSByb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGNvbnN0IHBhcmVudCA9IGxpc3QuZ2V0UGFyZW50KCk7XG4gICAgY29uc3QgZ3JhbmRQYXJlbnQgPSBwYXJlbnQuZ2V0UGFyZW50KCk7XG4gICAgY29uc3QgcHJldiA9IHBhcmVudC5nZXRQcmV2U2libGluZ09mKGxpc3QpO1xuXG4gICAgY29uc3QgbGlzdFN0YXJ0TGluZUJlZm9yZSA9IHJvb3QuZ2V0Q29udGVudExpbmVzUmFuZ2VPZihsaXN0KVswXTtcblxuICAgIGlmICghcHJldiAmJiBncmFuZFBhcmVudCkge1xuICAgICAgY29uc3QgbmV3UGFyZW50ID0gZ3JhbmRQYXJlbnQuZ2V0UHJldlNpYmxpbmdPZihwYXJlbnQpO1xuXG4gICAgICBpZiAobmV3UGFyZW50KSB7XG4gICAgICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG4gICAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChsaXN0KTtcbiAgICAgICAgbmV3UGFyZW50LmFkZEFmdGVyQWxsKGxpc3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocHJldikge1xuICAgICAgdGhpcy51cGRhdGVkID0gdHJ1ZTtcbiAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChsaXN0KTtcbiAgICAgIHBhcmVudC5hZGRCZWZvcmUocHJldiwgbGlzdCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLnVwZGF0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsaXN0U3RhcnRMaW5lQWZ0ZXIgPSByb290LmdldENvbnRlbnRMaW5lc1JhbmdlT2YobGlzdClbMF07XG4gICAgY29uc3QgbGluZURpZmYgPSBsaXN0U3RhcnRMaW5lQWZ0ZXIgLSBsaXN0U3RhcnRMaW5lQmVmb3JlO1xuXG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcbiAgICByb290LnJlcGxhY2VDdXJzb3Ioe1xuICAgICAgbGluZTogY3Vyc29yLmxpbmUgKyBsaW5lRGlmZixcbiAgICAgIGNoOiBjdXJzb3IuY2gsXG4gICAgfSk7XG5cbiAgICByZWNhbGN1bGF0ZU51bWVyaWNCdWxsZXRzKHJvb3QpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQbHVnaW5fMiB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5pbXBvcnQgeyBQcmVjIH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5pbXBvcnQgeyBrZXltYXAgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuLi9mZWF0dXJlcy9GZWF0dXJlXCI7XG5pbXBvcnQgeyBNb3ZlRG93bk9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL01vdmVEb3duT3BlcmF0aW9uXCI7XG5pbXBvcnQgeyBNb3ZlTGVmdE9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL01vdmVMZWZ0T3BlcmF0aW9uXCI7XG5pbXBvcnQgeyBNb3ZlUmlnaHRPcGVyYXRpb24gfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9Nb3ZlUmlnaHRPcGVyYXRpb25cIjtcbmltcG9ydCB7IE1vdmVVcE9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL01vdmVVcE9wZXJhdGlvblwiO1xuaW1wb3J0IHsgSU1FU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9JTUVTZXJ2aWNlXCI7XG5pbXBvcnQgeyBPYnNpZGlhblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvT2JzaWRpYW5TZXJ2aWNlXCI7XG5pbXBvcnQgeyBQZXJmb3JtT3BlcmF0aW9uU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9QZXJmb3JtT3BlcmF0aW9uU2VydmljZVwiO1xuaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL1NldHRpbmdzU2VydmljZVwiO1xuXG5leHBvcnQgY2xhc3MgTW92ZUl0ZW1zRmVhdHVyZSBpbXBsZW1lbnRzIEZlYXR1cmUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBsdWdpbjogUGx1Z2luXzIsXG4gICAgcHJpdmF0ZSBpbWU6IElNRVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgc2V0dGluZ3M6IFNldHRpbmdzU2VydmljZSxcbiAgICBwcml2YXRlIHBlcmZvcm1PcGVyYXRpb246IFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlXG4gICkge31cblxuICBhc3luYyBsb2FkKCkge1xuICAgIHRoaXMucGx1Z2luLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6IFwibW92ZS1saXN0LWl0ZW0tdXBcIixcbiAgICAgIGljb246IFwiYXJyb3ctdXBcIixcbiAgICAgIG5hbWU6IFwiTW92ZSBsaXN0IGFuZCBzdWJsaXN0cyB1cFwiLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IHRoaXMub2JzaWRpYW4uY3JlYXRlRWRpdG9yQ2FsbGJhY2soXG4gICAgICAgIHRoaXMubW92ZUxpc3RFbGVtZW50VXBDb21tYW5kXG4gICAgICApLFxuICAgICAgaG90a2V5czogW1xuICAgICAgICB7XG4gICAgICAgICAgbW9kaWZpZXJzOiBbXCJNb2RcIiwgXCJTaGlmdFwiXSxcbiAgICAgICAgICBrZXk6IFwiQXJyb3dVcFwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIHRoaXMucGx1Z2luLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6IFwibW92ZS1saXN0LWl0ZW0tZG93blwiLFxuICAgICAgaWNvbjogXCJhcnJvdy1kb3duXCIsXG4gICAgICBuYW1lOiBcIk1vdmUgbGlzdCBhbmQgc3VibGlzdHMgZG93blwiLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IHRoaXMub2JzaWRpYW4uY3JlYXRlRWRpdG9yQ2FsbGJhY2soXG4gICAgICAgIHRoaXMubW92ZUxpc3RFbGVtZW50RG93bkNvbW1hbmRcbiAgICAgICksXG4gICAgICBob3RrZXlzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtb2RpZmllcnM6IFtcIk1vZFwiLCBcIlNoaWZ0XCJdLFxuICAgICAgICAgIGtleTogXCJBcnJvd0Rvd25cIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICB0aGlzLnBsdWdpbi5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiBcImluZGVudC1saXN0XCIsXG4gICAgICBpY29uOiBcImluZGVudFwiLFxuICAgICAgbmFtZTogXCJJbmRlbnQgdGhlIGxpc3QgYW5kIHN1Ymxpc3RzXCIsXG4gICAgICBlZGl0b3JDYWxsYmFjazogdGhpcy5vYnNpZGlhbi5jcmVhdGVFZGl0b3JDYWxsYmFjayhcbiAgICAgICAgdGhpcy5tb3ZlTGlzdEVsZW1lbnRSaWdodENvbW1hbmRcbiAgICAgICksXG4gICAgICBob3RrZXlzOiBbXSxcbiAgICB9KTtcblxuICAgIHRoaXMucGx1Z2luLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6IFwib3V0ZGVudC1saXN0XCIsXG4gICAgICBpY29uOiBcIm91dGRlbnRcIixcbiAgICAgIG5hbWU6IFwiT3V0ZGVudCB0aGUgbGlzdCBhbmQgc3VibGlzdHNcIixcbiAgICAgIGVkaXRvckNhbGxiYWNrOiB0aGlzLm9ic2lkaWFuLmNyZWF0ZUVkaXRvckNhbGxiYWNrKFxuICAgICAgICB0aGlzLm1vdmVMaXN0RWxlbWVudExlZnRDb21tYW5kXG4gICAgICApLFxuICAgICAgaG90a2V5czogW10sXG4gICAgfSk7XG5cbiAgICB0aGlzLnBsdWdpbi5yZWdpc3RlckVkaXRvckV4dGVuc2lvbihcbiAgICAgIFByZWMuaGlnaGVzdChcbiAgICAgICAga2V5bWFwLm9mKFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBrZXk6IFwiVGFiXCIsXG4gICAgICAgICAgICBydW46IHRoaXMub2JzaWRpYW4uY3JlYXRlS2V5bWFwUnVuQ2FsbGJhY2soe1xuICAgICAgICAgICAgICBjaGVjazogdGhpcy5jaGVjayxcbiAgICAgICAgICAgICAgcnVuOiB0aGlzLm1vdmVMaXN0RWxlbWVudFJpZ2h0LFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBrZXk6IFwicy1UYWJcIixcbiAgICAgICAgICAgIHJ1bjogdGhpcy5vYnNpZGlhbi5jcmVhdGVLZXltYXBSdW5DYWxsYmFjayh7XG4gICAgICAgICAgICAgIGNoZWNrOiB0aGlzLmNoZWNrLFxuICAgICAgICAgICAgICBydW46IHRoaXMubW92ZUxpc3RFbGVtZW50TGVmdCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHVubG9hZCgpIHt9XG5cbiAgcHJpdmF0ZSBjaGVjayA9ICgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5zZXR0aW5ncy5iZXR0ZXJUYWIgJiYgIXRoaXMuaW1lLmlzSU1FT3BlbmVkKCk7XG4gIH07XG5cbiAgcHJpdmF0ZSBtb3ZlTGlzdEVsZW1lbnREb3duQ29tbWFuZCA9IChlZGl0b3I6IE15RWRpdG9yKSA9PiB7XG4gICAgY29uc3QgeyBzaG91bGRTdG9wUHJvcGFnYXRpb24gfSA9IHRoaXMucGVyZm9ybU9wZXJhdGlvbi5wZXJmb3JtT3BlcmF0aW9uKFxuICAgICAgKHJvb3QpID0+IG5ldyBNb3ZlRG93bk9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG5cbiAgICByZXR1cm4gc2hvdWxkU3RvcFByb3BhZ2F0aW9uO1xuICB9O1xuXG4gIHByaXZhdGUgbW92ZUxpc3RFbGVtZW50VXBDb21tYW5kID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICBjb25zdCB7IHNob3VsZFN0b3BQcm9wYWdhdGlvbiB9ID0gdGhpcy5wZXJmb3JtT3BlcmF0aW9uLnBlcmZvcm1PcGVyYXRpb24oXG4gICAgICAocm9vdCkgPT4gbmV3IE1vdmVVcE9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG5cbiAgICByZXR1cm4gc2hvdWxkU3RvcFByb3BhZ2F0aW9uO1xuICB9O1xuXG4gIHByaXZhdGUgbW92ZUxpc3RFbGVtZW50UmlnaHRDb21tYW5kID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICBpZiAodGhpcy5pbWUuaXNJTUVPcGVuZWQoKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubW92ZUxpc3RFbGVtZW50UmlnaHQoZWRpdG9yKS5zaG91bGRTdG9wUHJvcGFnYXRpb247XG4gIH07XG5cbiAgcHJpdmF0ZSBtb3ZlTGlzdEVsZW1lbnRSaWdodCA9IChlZGl0b3I6IE15RWRpdG9yKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucGVyZm9ybU9wZXJhdGlvbi5wZXJmb3JtT3BlcmF0aW9uKFxuICAgICAgKHJvb3QpID0+XG4gICAgICAgIG5ldyBNb3ZlUmlnaHRPcGVyYXRpb24ocm9vdCwgdGhpcy5vYnNpZGlhbi5nZXREZWZhdWx0SW5kZW50Q2hhcnMoKSksXG4gICAgICBlZGl0b3JcbiAgICApO1xuICB9O1xuXG4gIHByaXZhdGUgbW92ZUxpc3RFbGVtZW50TGVmdENvbW1hbmQgPSAoZWRpdG9yOiBNeUVkaXRvcikgPT4ge1xuICAgIGlmICh0aGlzLmltZS5pc0lNRU9wZW5lZCgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tb3ZlTGlzdEVsZW1lbnRMZWZ0KGVkaXRvcikuc2hvdWxkU3RvcFByb3BhZ2F0aW9uO1xuICB9O1xuXG4gIHByaXZhdGUgbW92ZUxpc3RFbGVtZW50TGVmdCA9IChlZGl0b3I6IE15RWRpdG9yKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucGVyZm9ybU9wZXJhdGlvbi5wZXJmb3JtT3BlcmF0aW9uKFxuICAgICAgKHJvb3QpID0+IG5ldyBNb3ZlTGVmdE9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCwgbWF4UG9zLCBtaW5Qb3MgfSBmcm9tIFwiLi4vcm9vdFwiO1xuXG5leHBvcnQgY2xhc3MgU2VsZWN0QWxsT3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZVNlbGVjdGlvbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2VsZWN0aW9uID0gcm9vdC5nZXRTZWxlY3Rpb25zKClbMF07XG4gICAgY29uc3QgW3Jvb3RTdGFydCwgcm9vdEVuZF0gPSByb290LmdldFJhbmdlKCk7XG5cbiAgICBjb25zdCBzZWxlY3Rpb25Gcm9tID0gbWluUG9zKHNlbGVjdGlvbi5hbmNob3IsIHNlbGVjdGlvbi5oZWFkKTtcbiAgICBjb25zdCBzZWxlY3Rpb25UbyA9IG1heFBvcyhzZWxlY3Rpb24uYW5jaG9yLCBzZWxlY3Rpb24uaGVhZCk7XG5cbiAgICBpZiAoXG4gICAgICBzZWxlY3Rpb25Gcm9tLmxpbmUgPCByb290U3RhcnQubGluZSB8fFxuICAgICAgc2VsZWN0aW9uVG8ubGluZSA+IHJvb3RFbmQubGluZVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHNlbGVjdGlvbkZyb20ubGluZSA9PT0gcm9vdFN0YXJ0LmxpbmUgJiZcbiAgICAgIHNlbGVjdGlvbkZyb20uY2ggPT09IHJvb3RTdGFydC5jaCAmJlxuICAgICAgc2VsZWN0aW9uVG8ubGluZSA9PT0gcm9vdEVuZC5saW5lICYmXG4gICAgICBzZWxlY3Rpb25Uby5jaCA9PT0gcm9vdEVuZC5jaFxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGxpc3QgPSByb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGNvbnN0IGNvbnRlbnRTdGFydCA9IGxpc3QuZ2V0Rmlyc3RMaW5lQ29udGVudFN0YXJ0KCk7XG4gICAgY29uc3QgY29udGVudEVuZCA9IGxpc3QuZ2V0TGFzdExpbmVDb250ZW50RW5kKCk7XG5cbiAgICBpZiAoXG4gICAgICBzZWxlY3Rpb25Gcm9tLmxpbmUgPCBjb250ZW50U3RhcnQubGluZSB8fFxuICAgICAgc2VsZWN0aW9uVG8ubGluZSA+IGNvbnRlbnRFbmQubGluZVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMuc3RvcFByb3BhZ2F0aW9uID0gdHJ1ZTtcbiAgICB0aGlzLnVwZGF0ZWQgPSB0cnVlO1xuXG4gICAgaWYgKFxuICAgICAgc2VsZWN0aW9uRnJvbS5saW5lID09PSBjb250ZW50U3RhcnQubGluZSAmJlxuICAgICAgc2VsZWN0aW9uRnJvbS5jaCA9PT0gY29udGVudFN0YXJ0LmNoICYmXG4gICAgICBzZWxlY3Rpb25Uby5saW5lID09PSBjb250ZW50RW5kLmxpbmUgJiZcbiAgICAgIHNlbGVjdGlvblRvLmNoID09PSBjb250ZW50RW5kLmNoXG4gICAgKSB7XG4gICAgICAvLyBzZWxlY3QgYWxsIGxpc3RcbiAgICAgIHJvb3QucmVwbGFjZVNlbGVjdGlvbnMoW3sgYW5jaG9yOiByb290U3RhcnQsIGhlYWQ6IHJvb3RFbmQgfV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBzZWxlY3QgYWxsIGxpbmVcbiAgICAgIHJvb3QucmVwbGFjZVNlbGVjdGlvbnMoW3sgYW5jaG9yOiBjb250ZW50U3RhcnQsIGhlYWQ6IGNvbnRlbnRFbmQgfV0pO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQbHVnaW5fMiB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5pbXBvcnQgeyBrZXltYXAgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuLi9mZWF0dXJlcy9GZWF0dXJlXCI7XG5pbXBvcnQgeyBTZWxlY3RBbGxPcGVyYXRpb24gfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9TZWxlY3RBbGxPcGVyYXRpb25cIjtcbmltcG9ydCB7IElNRVNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvSU1FU2VydmljZVwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIFNlbGVjdEFsbEZlYXR1cmUgaW1wbGVtZW50cyBGZWF0dXJlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBwbHVnaW46IFBsdWdpbl8yLFxuICAgIHByaXZhdGUgc2V0dGluZ3M6IFNldHRpbmdzU2VydmljZSxcbiAgICBwcml2YXRlIGltZTogSU1FU2VydmljZSxcbiAgICBwcml2YXRlIG9ic2lkaWFuOiBPYnNpZGlhblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwZXJmb3JtT3BlcmF0aW9uOiBQZXJmb3JtT3BlcmF0aW9uU2VydmljZVxuICApIHt9XG5cbiAgYXN5bmMgbG9hZCgpIHtcbiAgICB0aGlzLnBsdWdpbi5yZWdpc3RlckVkaXRvckV4dGVuc2lvbihcbiAgICAgIGtleW1hcC5vZihbXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6IFwiYy1hXCIsXG4gICAgICAgICAgbWFjOiBcIm0tYVwiLFxuICAgICAgICAgIHJ1bjogdGhpcy5vYnNpZGlhbi5jcmVhdGVLZXltYXBSdW5DYWxsYmFjayh7XG4gICAgICAgICAgICBjaGVjazogdGhpcy5jaGVjayxcbiAgICAgICAgICAgIHJ1bjogdGhpcy5ydW4sXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICBdKVxuICAgICk7XG4gIH1cblxuICBhc3luYyB1bmxvYWQoKSB7fVxuXG4gIHByaXZhdGUgY2hlY2sgPSAoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0dGluZ3Muc2VsZWN0QWxsICYmICF0aGlzLmltZS5pc0lNRU9wZW5lZCgpO1xuICB9O1xuXG4gIHByaXZhdGUgcnVuID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICByZXR1cm4gdGhpcy5wZXJmb3JtT3BlcmF0aW9uLnBlcmZvcm1PcGVyYXRpb24oXG4gICAgICAocm9vdCkgPT4gbmV3IFNlbGVjdEFsbE9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9PcGVyYXRpb25cIjtcblxuaW1wb3J0IHsgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5cbmV4cG9ydCBjbGFzcyBTZWxlY3RUaWxsTGluZVN0YXJ0T3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICBjb25zdCBjdXJzb3IgPSByb290LmdldEN1cnNvcigpO1xuICAgIGNvbnN0IGxpc3QgPSByb290LmdldExpc3RVbmRlckN1cnNvcigpO1xuICAgIGNvbnN0IGxpbmVzID0gbGlzdC5nZXRMaW5lc0luZm8oKTtcbiAgICBjb25zdCBsaW5lTm8gPSBsaW5lcy5maW5kSW5kZXgoKGwpID0+IGwuZnJvbS5saW5lID09PSBjdXJzb3IubGluZSk7XG5cbiAgICByb290LnJlcGxhY2VTZWxlY3Rpb25zKFt7IGhlYWQ6IGxpbmVzW2xpbmVOb10uZnJvbSwgYW5jaG9yOiBjdXJzb3IgfV0pO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQbHVnaW5fMiB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5pbXBvcnQgeyBrZXltYXAgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuXG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4vRmVhdHVyZVwiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuaW1wb3J0IHsgU2VsZWN0VGlsbExpbmVTdGFydE9wZXJhdGlvbiB9IGZyb20gXCIuLi9vcGVyYXRpb25zL1NlbGVjdFRpbGxMaW5lU3RhcnRPcGVyYXRpb25cIjtcbmltcG9ydCB7IElNRVNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvSU1FU2VydmljZVwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIFNlbGVjdGlvblNob3VsZElnbm9yZUJ1bGxldHNGZWF0dXJlIGltcGxlbWVudHMgRmVhdHVyZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcGx1Z2luOiBQbHVnaW5fMixcbiAgICBwcml2YXRlIHNldHRpbmdzOiBTZXR0aW5nc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBpbWU6IElNRVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgcGVyZm9ybU9wZXJhdGlvbjogUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24oXG4gICAgICBrZXltYXAub2YoW1xuICAgICAgICB7XG4gICAgICAgICAga2V5OiBcIm0tcy1BcnJvd0xlZnRcIixcbiAgICAgICAgICBydW46IHRoaXMub2JzaWRpYW4uY3JlYXRlS2V5bWFwUnVuQ2FsbGJhY2soe1xuICAgICAgICAgICAgY2hlY2s6IHRoaXMuY2hlY2ssXG4gICAgICAgICAgICBydW46IHRoaXMucnVuLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgXSlcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgdW5sb2FkKCkge31cblxuICBwcml2YXRlIGNoZWNrID0gKCkgPT4ge1xuICAgIHJldHVybiB0aGlzLnNldHRpbmdzLnN0aWNrQ3Vyc29yICYmICF0aGlzLmltZS5pc0lNRU9wZW5lZCgpO1xuICB9O1xuXG4gIHByaXZhdGUgcnVuID0gKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICByZXR1cm4gdGhpcy5wZXJmb3JtT3BlcmF0aW9uLnBlcmZvcm1PcGVyYXRpb24oXG4gICAgICAocm9vdCkgPT4gbmV3IFNlbGVjdFRpbGxMaW5lU3RhcnRPcGVyYXRpb24ocm9vdCksXG4gICAgICBlZGl0b3JcbiAgICApO1xuICB9O1xufVxuIiwiaW1wb3J0IHsgQXBwLCBQbHVnaW5TZXR0aW5nVGFiLCBQbHVnaW5fMiwgU2V0dGluZyB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4vRmVhdHVyZVwiO1xuXG5pbXBvcnQgeyBMaXN0TGluZUFjdGlvbiwgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL1NldHRpbmdzU2VydmljZVwiO1xuXG5jbGFzcyBPYnNpZGlhbk91dGxpbmVyUGx1Z2luU2V0dGluZ1RhYiBleHRlbmRzIFBsdWdpblNldHRpbmdUYWIge1xuICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBQbHVnaW5fMiwgcHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlKSB7XG4gICAgc3VwZXIoYXBwLCBwbHVnaW4pO1xuICB9XG5cbiAgZGlzcGxheSgpOiB2b2lkIHtcbiAgICBjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xuXG4gICAgY29udGFpbmVyRWwuZW1wdHkoKTtcblxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgLnNldE5hbWUoXCJJbXByb3ZlIHRoZSBzdHlsZSBvZiB5b3VyIGxpc3RzXCIpXG4gICAgICAuc2V0RGVzYyhcbiAgICAgICAgXCJTdHlsZXMgYXJlIG9ubHkgY29tcGF0aWJsZSB3aXRoIGJ1aWx0LWluIE9ic2lkaWFuIHRoZW1lcyBhbmQgbWF5IG5vdCBiZSBjb21wYXRpYmxlIHdpdGggb3RoZXIgdGhlbWVzLlwiXG4gICAgICApXG4gICAgICAuYWRkVG9nZ2xlKCh0b2dnbGUpID0+IHtcbiAgICAgICAgdG9nZ2xlLnNldFZhbHVlKHRoaXMuc2V0dGluZ3Muc3R5bGVMaXN0cykub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgdGhpcy5zZXR0aW5ncy5zdHlsZUxpc3RzID0gdmFsdWU7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5zYXZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgIC5zZXROYW1lKFwiRHJhdyB2ZXJ0aWNhbCBpbmRlbnRhdGlvbiBsaW5lc1wiKVxuICAgICAgLmFkZFRvZ2dsZSgodG9nZ2xlKSA9PiB7XG4gICAgICAgIHRvZ2dsZS5zZXRWYWx1ZSh0aGlzLnNldHRpbmdzLmxpc3RMaW5lcykub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgdGhpcy5zZXR0aW5ncy5saXN0TGluZXMgPSB2YWx1ZTtcbiAgICAgICAgICBhd2FpdCB0aGlzLnNldHRpbmdzLnNhdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgLnNldE5hbWUoXCJWZXJ0aWNhbCBpbmRlbnRhdGlvbiBsaW5lIGNsaWNrIGFjdGlvblwiKVxuICAgICAgLmFkZERyb3Bkb3duKChkcm9wZG93bikgPT4ge1xuICAgICAgICBkcm9wZG93blxuICAgICAgICAgIC5hZGRPcHRpb25zKHtcbiAgICAgICAgICAgIG5vbmU6IFwiTm9uZVwiLFxuICAgICAgICAgICAgXCJ6b29tLWluXCI6IFwiWm9vbSBJblwiLFxuICAgICAgICAgICAgXCJ0b2dnbGUtZm9sZGluZ1wiOiBcIlRvZ2dsZSBGb2xkaW5nXCIsXG4gICAgICAgICAgfSBhcyB7IFtrZXkgaW4gTGlzdExpbmVBY3Rpb25dOiBzdHJpbmcgfSlcbiAgICAgICAgICAuc2V0VmFsdWUodGhpcy5zZXR0aW5ncy5saXN0TGluZUFjdGlvbilcbiAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLmxpc3RMaW5lQWN0aW9uID0gdmFsdWUgYXMgTGlzdExpbmVBY3Rpb247XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNldHRpbmdzLnNhdmUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAuc2V0TmFtZShcIlN0aWNrIHRoZSBjdXJzb3IgdG8gdGhlIGNvbnRlbnRcIilcbiAgICAgIC5zZXREZXNjKFwiRG9uJ3QgbGV0IHRoZSBjdXJzb3IgbW92ZSB0byB0aGUgYnVsbGV0IHBvc2l0aW9uLlwiKVxuICAgICAgLmFkZFRvZ2dsZSgodG9nZ2xlKSA9PiB7XG4gICAgICAgIHRvZ2dsZS5zZXRWYWx1ZSh0aGlzLnNldHRpbmdzLnN0aWNrQ3Vyc29yKS5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcbiAgICAgICAgICB0aGlzLnNldHRpbmdzLnN0aWNrQ3Vyc29yID0gdmFsdWU7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5zYXZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgIC5zZXROYW1lKFwiRW5oYW5jZSB0aGUgRW50ZXIga2V5XCIpXG4gICAgICAuc2V0RGVzYyhcIk1ha2UgdGhlIEVudGVyIGtleSBiZWhhdmUgdGhlIHNhbWUgYXMgb3RoZXIgb3V0bGluZXJzLlwiKVxuICAgICAgLmFkZFRvZ2dsZSgodG9nZ2xlKSA9PiB7XG4gICAgICAgIHRvZ2dsZS5zZXRWYWx1ZSh0aGlzLnNldHRpbmdzLmJldHRlckVudGVyKS5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcbiAgICAgICAgICB0aGlzLnNldHRpbmdzLmJldHRlckVudGVyID0gdmFsdWU7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5zYXZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgIC5zZXROYW1lKFwiRW5oYW5jZSB0aGUgVGFiIGtleVwiKVxuICAgICAgLnNldERlc2MoXCJNYWtlIFRhYiBhbmQgU2hpZnQtVGFiIGJlaGF2ZSB0aGUgc2FtZSBhcyBvdGhlciBvdXRsaW5lcnMuXCIpXG4gICAgICAuYWRkVG9nZ2xlKCh0b2dnbGUpID0+IHtcbiAgICAgICAgdG9nZ2xlLnNldFZhbHVlKHRoaXMuc2V0dGluZ3MuYmV0dGVyVGFiKS5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcbiAgICAgICAgICB0aGlzLnNldHRpbmdzLmJldHRlclRhYiA9IHZhbHVlO1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2V0dGluZ3Muc2F2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAuc2V0TmFtZShcIkVuaGFuY2UgdGhlIEN0cmwrQSBvciBDbWQrQSBiZWhhdmlvclwiKVxuICAgICAgLnNldERlc2MoXG4gICAgICAgIFwiUHJlc3MgdGhlIGhvdGtleSBvbmNlIHRvIHNlbGVjdCB0aGUgY3VycmVudCBsaXN0IGl0ZW0uIFByZXNzIHRoZSBob3RrZXkgdHdpY2UgdG8gc2VsZWN0IHRoZSBlbnRpcmUgbGlzdC5cIlxuICAgICAgKVxuICAgICAgLmFkZFRvZ2dsZSgodG9nZ2xlKSA9PiB7XG4gICAgICAgIHRvZ2dsZS5zZXRWYWx1ZSh0aGlzLnNldHRpbmdzLnNlbGVjdEFsbCkub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgdGhpcy5zZXR0aW5ncy5zZWxlY3RBbGwgPSB2YWx1ZTtcbiAgICAgICAgICBhd2FpdCB0aGlzLnNldHRpbmdzLnNhdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgLnNldE5hbWUoXCJEZWJ1ZyBtb2RlXCIpXG4gICAgICAuc2V0RGVzYyhcbiAgICAgICAgXCJPcGVuIERldlRvb2xzIChDb21tYW5kK09wdGlvbitJIG9yIENvbnRyb2wrU2hpZnQrSSkgdG8gY29weSB0aGUgZGVidWcgbG9ncy5cIlxuICAgICAgKVxuICAgICAgLmFkZFRvZ2dsZSgodG9nZ2xlKSA9PiB7XG4gICAgICAgIHRvZ2dsZS5zZXRWYWx1ZSh0aGlzLnNldHRpbmdzLmRlYnVnKS5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcbiAgICAgICAgICB0aGlzLnNldHRpbmdzLmRlYnVnID0gdmFsdWU7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5zYXZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNldHRpbmdzVGFiRmVhdHVyZSBpbXBsZW1lbnRzIEZlYXR1cmUge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHBsdWdpbjogUGx1Z2luXzIsIHByaXZhdGUgc2V0dGluZ3M6IFNldHRpbmdzU2VydmljZSkge31cblxuICBhc3luYyBsb2FkKCkge1xuICAgIHRoaXMucGx1Z2luLmFkZFNldHRpbmdUYWIoXG4gICAgICBuZXcgT2JzaWRpYW5PdXRsaW5lclBsdWdpblNldHRpbmdUYWIoXG4gICAgICAgIHRoaXMucGx1Z2luLmFwcCxcbiAgICAgICAgdGhpcy5wbHVnaW4sXG4gICAgICAgIHRoaXMuc2V0dGluZ3NcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgdW5sb2FkKCkge31cbn1cbiIsImltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gXCIuL09wZXJhdGlvblwiO1xuXG5pbXBvcnQgeyBSb290IH0gZnJvbSBcIi4uL3Jvb3RcIjtcblxuZXhwb3J0IGNsYXNzIENyZWF0ZU5vdGVMaW5lT3BlcmF0aW9uIGltcGxlbWVudHMgT3BlcmF0aW9uIHtcbiAgcHJpdmF0ZSBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB1cGRhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByb290OiBSb290KSB7fVxuXG4gIHNob3VsZFN0b3BQcm9wYWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wUHJvcGFnYXRpb247XG4gIH1cblxuICBzaG91bGRVcGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlZDtcbiAgfVxuXG4gIHBlcmZvcm0oKSB7XG4gICAgY29uc3QgeyByb290IH0gPSB0aGlzO1xuXG4gICAgaWYgKCFyb290Lmhhc1NpbmdsZUN1cnNvcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY3Vyc29yID0gcm9vdC5nZXRDdXJzb3IoKTtcbiAgICBjb25zdCBsaXN0ID0gcm9vdC5nZXRMaXN0VW5kZXJDdXJzb3IoKTtcbiAgICBjb25zdCBsaW5lVW5kZXJDdXJzb3IgPSBsaXN0XG4gICAgICAuZ2V0TGluZXNJbmZvKClcbiAgICAgIC5maW5kKChsKSA9PiBsLmZyb20ubGluZSA9PT0gY3Vyc29yLmxpbmUpO1xuXG4gICAgaWYgKGN1cnNvci5jaCA8IGxpbmVVbmRlckN1cnNvci5mcm9tLmNoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wUHJvcGFnYXRpb24gPSB0cnVlO1xuICAgIHRoaXMudXBkYXRlZCA9IHRydWU7XG5cbiAgICBpZiAoIWxpc3QuZ2V0Tm90ZXNJbmRlbnQoKSkge1xuICAgICAgbGlzdC5zZXROb3Rlc0luZGVudChsaXN0LmdldEZpcnN0TGluZUluZGVudCgpICsgXCIgIFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBsaW5lcyA9IGxpc3QuZ2V0TGluZXNJbmZvKCkucmVkdWNlKChhY2MsIGxpbmUpID0+IHtcbiAgICAgIGlmIChjdXJzb3IubGluZSA9PT0gbGluZS5mcm9tLmxpbmUpIHtcbiAgICAgICAgYWNjLnB1c2gobGluZS50ZXh0LnNsaWNlKDAsIGN1cnNvci5jaCAtIGxpbmUuZnJvbS5jaCkpO1xuICAgICAgICBhY2MucHVzaChsaW5lLnRleHQuc2xpY2UoY3Vyc29yLmNoIC0gbGluZS5mcm9tLmNoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY2MucHVzaChsaW5lLnRleHQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIFtdIGFzIHN0cmluZ1tdKTtcblxuICAgIGxpc3QucmVwbGFjZUxpbmVzKGxpbmVzKTtcblxuICAgIHJvb3QucmVwbGFjZUN1cnNvcih7XG4gICAgICBsaW5lOiBjdXJzb3IubGluZSArIDEsXG4gICAgICBjaDogbGlzdC5nZXROb3Rlc0luZGVudCgpLmxlbmd0aCxcbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgUGx1Z2luXzIgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IHsga2V5bWFwIH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcblxuaW1wb3J0IHsgRmVhdHVyZSB9IGZyb20gXCIuL0ZlYXR1cmVcIjtcblxuaW1wb3J0IHsgTXlFZGl0b3IgfSBmcm9tIFwiLi4vTXlFZGl0b3JcIjtcbmltcG9ydCB7IENyZWF0ZU5vdGVMaW5lT3BlcmF0aW9uIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvQ3JlYXRlTm90ZUxpbmVPcGVyYXRpb25cIjtcbmltcG9ydCB7IElNRVNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvSU1FU2VydmljZVwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL09ic2lkaWFuU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvUGVyZm9ybU9wZXJhdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNldHRpbmdzU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9TZXR0aW5nc1NlcnZpY2VcIjtcblxuZXhwb3J0IGNsYXNzIFNoaWZ0RW50ZXJTaG91bGRDcmVhdGVOb3RlRmVhdHVyZSBpbXBsZW1lbnRzIEZlYXR1cmUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBsdWdpbjogUGx1Z2luXzIsXG4gICAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgc2V0dGluZ3M6IFNldHRpbmdzU2VydmljZSxcbiAgICBwcml2YXRlIGltZTogSU1FU2VydmljZSxcbiAgICBwcml2YXRlIHBlcmZvcm1PcGVyYXRpb246IFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlXG4gICkge31cblxuICBhc3luYyBsb2FkKCkge1xuICAgIHRoaXMucGx1Z2luLnJlZ2lzdGVyRWRpdG9yRXh0ZW5zaW9uKFxuICAgICAga2V5bWFwLm9mKFtcbiAgICAgICAge1xuICAgICAgICAgIGtleTogXCJzLUVudGVyXCIsXG4gICAgICAgICAgcnVuOiB0aGlzLm9ic2lkaWFuLmNyZWF0ZUtleW1hcFJ1bkNhbGxiYWNrKHtcbiAgICAgICAgICAgIGNoZWNrOiB0aGlzLmNoZWNrLFxuICAgICAgICAgICAgcnVuOiB0aGlzLnJ1bixcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgIF0pXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHVubG9hZCgpIHt9XG5cbiAgcHJpdmF0ZSBjaGVjayA9ICgpID0+IHtcbiAgICByZXR1cm4gdGhpcy5zZXR0aW5ncy5iZXR0ZXJFbnRlciAmJiAhdGhpcy5pbWUuaXNJTUVPcGVuZWQoKTtcbiAgfTtcblxuICBwcml2YXRlIHJ1biA9IChlZGl0b3I6IE15RWRpdG9yKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMucGVyZm9ybU9wZXJhdGlvbi5wZXJmb3JtT3BlcmF0aW9uKFxuICAgICAgKHJvb3QpID0+IG5ldyBDcmVhdGVOb3RlTGluZU9wZXJhdGlvbihyb290KSxcbiAgICAgIGVkaXRvclxuICAgICk7XG4gIH07XG59XG4iLCJleHBvcnQgaW50ZXJmYWNlIEFwcGx5Q2hhbmdlc0VkaXRvclBvc2l0aW9uIHtcbiAgbGluZTogbnVtYmVyO1xuICBjaDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFwcGx5Q2hhbmdlc0VkaXRvclNlbGVjdGlvbiB7XG4gIGFuY2hvcjogQXBwbHlDaGFuZ2VzRWRpdG9yUG9zaXRpb247XG4gIGhlYWQ6IEFwcGx5Q2hhbmdlc0VkaXRvclBvc2l0aW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFwcGx5Q2hhbmdlc0VkaXRvciB7XG4gIGdldFJhbmdlKFxuICAgIGZyb206IEFwcGx5Q2hhbmdlc0VkaXRvclBvc2l0aW9uLFxuICAgIHRvOiBBcHBseUNoYW5nZXNFZGl0b3JQb3NpdGlvblxuICApOiBzdHJpbmc7XG4gIHJlcGxhY2VSYW5nZShcbiAgICByZXBsYWNlbWVudDogc3RyaW5nLFxuICAgIGZyb206IEFwcGx5Q2hhbmdlc0VkaXRvclBvc2l0aW9uLFxuICAgIHRvOiBBcHBseUNoYW5nZXNFZGl0b3JQb3NpdGlvblxuICApOiB2b2lkO1xuICBzZXRTZWxlY3Rpb25zKHNlbGVjdGlvbnM6IEFwcGx5Q2hhbmdlc0VkaXRvclNlbGVjdGlvbltdKTogdm9pZDtcbiAgZm9sZChuOiBudW1iZXIpOiB2b2lkO1xuICB1bmZvbGQobjogbnVtYmVyKTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcHBseUNoYW5nZXNMaXN0IHtcbiAgaXNGb2xkUm9vdCgpOiBib29sZWFuO1xuICBnZXRDaGlsZHJlbigpOiBBcHBseUNoYW5nZXNMaXN0W107XG4gIGdldEZpcnN0TGluZUNvbnRlbnRTdGFydCgpOiB7IGxpbmU6IG51bWJlciB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFwcGx5Q2hhbmdlc1Jvb3Qge1xuICBnZXRSYW5nZSgpOiBbQXBwbHlDaGFuZ2VzRWRpdG9yUG9zaXRpb24sIEFwcGx5Q2hhbmdlc0VkaXRvclBvc2l0aW9uXTtcbiAgZ2V0U2VsZWN0aW9ucygpOiB7XG4gICAgYW5jaG9yOiBBcHBseUNoYW5nZXNFZGl0b3JQb3NpdGlvbjtcbiAgICBoZWFkOiBBcHBseUNoYW5nZXNFZGl0b3JQb3NpdGlvbjtcbiAgfVtdO1xuICBwcmludCgpOiBzdHJpbmc7XG4gIGdldENoaWxkcmVuKCk6IEFwcGx5Q2hhbmdlc0xpc3RbXTtcbn1cblxuZXhwb3J0IGNsYXNzIEFwcGx5Q2hhbmdlc1NlcnZpY2Uge1xuICBhcHBseUNoYW5nZXMoZWRpdG9yOiBBcHBseUNoYW5nZXNFZGl0b3IsIHJvb3Q6IEFwcGx5Q2hhbmdlc1Jvb3QpIHtcbiAgICBjb25zdCByb290UmFuZ2UgPSByb290LmdldFJhbmdlKCk7XG4gICAgY29uc3Qgb2xkU3RyaW5nID0gZWRpdG9yLmdldFJhbmdlKHJvb3RSYW5nZVswXSwgcm9vdFJhbmdlWzFdKTtcbiAgICBjb25zdCBuZXdTdHJpbmcgPSByb290LnByaW50KCk7XG5cbiAgICBjb25zdCBmcm9tTGluZSA9IHJvb3RSYW5nZVswXS5saW5lO1xuICAgIGNvbnN0IHRvTGluZSA9IHJvb3RSYW5nZVsxXS5saW5lO1xuXG4gICAgZm9yIChsZXQgbCA9IGZyb21MaW5lOyBsIDw9IHRvTGluZTsgbCsrKSB7XG4gICAgICBlZGl0b3IudW5mb2xkKGwpO1xuICAgIH1cblxuICAgIGNvbnN0IGNoYW5nZUZyb20gPSB7IC4uLnJvb3RSYW5nZVswXSB9O1xuICAgIGNvbnN0IGNoYW5nZVRvID0geyAuLi5yb290UmFuZ2VbMV0gfTtcbiAgICBsZXQgb2xkVG1wID0gb2xkU3RyaW5nO1xuICAgIGxldCBuZXdUbXAgPSBuZXdTdHJpbmc7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc3RhbnQtY29uZGl0aW9uXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IG5sSW5kZXggPSBvbGRUbXAubGFzdEluZGV4T2YoXCJcXG5cIik7XG4gICAgICBpZiAobmxJbmRleCA8IDApIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjb25zdCBvbGRMaW5lID0gb2xkVG1wLnNsaWNlKG5sSW5kZXgpO1xuICAgICAgY29uc3QgbmV3TGluZSA9IG5ld1RtcC5zbGljZSgtb2xkTGluZS5sZW5ndGgpO1xuICAgICAgaWYgKG9sZExpbmUgIT09IG5ld0xpbmUpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBvbGRUbXAgPSBvbGRUbXAuc2xpY2UoMCwgLW9sZExpbmUubGVuZ3RoKTtcbiAgICAgIG5ld1RtcCA9IG5ld1RtcC5zbGljZSgwLCAtb2xkTGluZS5sZW5ndGgpO1xuXG4gICAgICBjb25zdCBubEluZGV4MiA9IG9sZFRtcC5sYXN0SW5kZXhPZihcIlxcblwiKTtcbiAgICAgIGNoYW5nZVRvLmNoID1cbiAgICAgICAgbmxJbmRleDIgPj0gMCA/IG9sZFRtcC5sZW5ndGggLSBubEluZGV4MiAtIDEgOiBvbGRUbXAubGVuZ3RoO1xuICAgICAgY2hhbmdlVG8ubGluZS0tO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc3RhbnQtY29uZGl0aW9uXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IG5sSW5kZXggPSBvbGRUbXAuaW5kZXhPZihcIlxcblwiKTtcbiAgICAgIGlmIChubEluZGV4IDwgMCkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNvbnN0IG9sZExpbmUgPSBvbGRUbXAuc2xpY2UoMCwgbmxJbmRleCArIDEpO1xuICAgICAgY29uc3QgbmV3TGluZSA9IG5ld1RtcC5zbGljZSgwLCBvbGRMaW5lLmxlbmd0aCk7XG4gICAgICBpZiAob2xkTGluZSAhPT0gbmV3TGluZSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNoYW5nZUZyb20ubGluZSsrO1xuICAgICAgb2xkVG1wID0gb2xkVG1wLnNsaWNlKG9sZExpbmUubGVuZ3RoKTtcbiAgICAgIG5ld1RtcCA9IG5ld1RtcC5zbGljZShvbGRMaW5lLmxlbmd0aCk7XG4gICAgfVxuXG4gICAgaWYgKG9sZFRtcCAhPT0gbmV3VG1wKSB7XG4gICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKG5ld1RtcCwgY2hhbmdlRnJvbSwgY2hhbmdlVG8pO1xuICAgIH1cblxuICAgIGVkaXRvci5zZXRTZWxlY3Rpb25zKHJvb3QuZ2V0U2VsZWN0aW9ucygpKTtcblxuICAgIGZ1bmN0aW9uIHJlY3Vyc2l2ZShsaXN0OiBBcHBseUNoYW5nZXNMaXN0KSB7XG4gICAgICBmb3IgKGNvbnN0IGMgb2YgbGlzdC5nZXRDaGlsZHJlbigpKSB7XG4gICAgICAgIHJlY3Vyc2l2ZShjKTtcbiAgICAgIH1cbiAgICAgIGlmIChsaXN0LmlzRm9sZFJvb3QoKSkge1xuICAgICAgICBlZGl0b3IuZm9sZChsaXN0LmdldEZpcnN0TGluZUNvbnRlbnRTdGFydCgpLmxpbmUpO1xuICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IGMgb2Ygcm9vdC5nZXRDaGlsZHJlbigpKSB7XG4gICAgICByZWN1cnNpdmUoYyk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBQbGF0Zm9ybSB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5leHBvcnQgY2xhc3MgSU1FU2VydmljZSB7XG4gIHByaXZhdGUgY29tcG9zaXRpb24gPSBmYWxzZTtcblxuICBhc3luYyBsb2FkKCkge1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjb21wb3NpdGlvbnN0YXJ0XCIsIHRoaXMub25Db21wb3NpdGlvblN0YXJ0KTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiY29tcG9zaXRpb25lbmRcIiwgdGhpcy5vbkNvbXBvc2l0aW9uRW5kKTtcbiAgfVxuXG4gIGFzeW5jIHVubG9hZCgpIHtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY29tcG9zaXRpb25lbmRcIiwgdGhpcy5vbkNvbXBvc2l0aW9uRW5kKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY29tcG9zaXRpb25zdGFydFwiLCB0aGlzLm9uQ29tcG9zaXRpb25TdGFydCk7XG4gIH1cblxuICBpc0lNRU9wZW5lZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb3NpdGlvbiAmJiBQbGF0Zm9ybS5pc0Rlc2t0b3A7XG4gIH1cblxuICBwcml2YXRlIG9uQ29tcG9zaXRpb25TdGFydCA9ICgpID0+IHtcbiAgICB0aGlzLmNvbXBvc2l0aW9uID0gdHJ1ZTtcbiAgfTtcblxuICBwcml2YXRlIG9uQ29tcG9zaXRpb25FbmQgPSAoKSA9PiB7XG4gICAgdGhpcy5jb21wb3NpdGlvbiA9IGZhbHNlO1xuICB9O1xufVxuIiwiaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSBcIi4vU2V0dGluZ3NTZXJ2aWNlXCI7XG5cbmV4cG9ydCBjbGFzcyBMb2dnZXJTZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlKSB7fVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIGxvZyhtZXRob2Q6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgICBpZiAoIXRoaXMuc2V0dGluZ3MuZGVidWcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zb2xlLmluZm8obWV0aG9kLCAuLi5hcmdzKTtcbiAgfVxuXG4gIGJpbmQobWV0aG9kOiBzdHJpbmcpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIHJldHVybiAoLi4uYXJnczogYW55W10pID0+IHRoaXMubG9nKG1ldGhvZCwgLi4uYXJncyk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEFwcCwgRWRpdG9yLCBlZGl0b3JJbmZvRmllbGQgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IHsgRWRpdG9yU3RhdGUgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivc3RhdGVcIjtcbmltcG9ydCB7IEVkaXRvclZpZXcgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9ic2lkaWFuVGFic1NldHRpbmdzIHtcbiAgdXNlVGFiOiBib29sZWFuO1xuICB0YWJTaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT2JzaWRpYW5Gb2xkU2V0dGluZ3Mge1xuICBmb2xkSW5kZW50OiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgT2JzaWRpYW5TZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBhcHA6IEFwcCkge31cblxuICBpc0xlZ2FjeUVkaXRvckVuYWJsZWQoKSB7XG4gICAgY29uc3QgY29uZmlnOiB7IGxlZ2FjeUVkaXRvcjogYm9vbGVhbiB9ID0ge1xuICAgICAgbGVnYWN5RWRpdG9yOiBmYWxzZSxcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAuLi4odGhpcy5hcHAudmF1bHQgYXMgYW55KS5jb25maWcsXG4gICAgfTtcblxuICAgIHJldHVybiBjb25maWcubGVnYWN5RWRpdG9yO1xuICB9XG5cbiAgaXNEZWZhdWx0VGhlbWVFbmFibGVkKCkge1xuICAgIGNvbnN0IGNvbmZpZzogeyBjc3NUaGVtZTogc3RyaW5nIH0gPSB7XG4gICAgICBjc3NUaGVtZTogXCJcIixcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAuLi4odGhpcy5hcHAudmF1bHQgYXMgYW55KS5jb25maWcsXG4gICAgfTtcblxuICAgIHJldHVybiBjb25maWcuY3NzVGhlbWUgPT09IFwiXCI7XG4gIH1cblxuICBnZXRPYnNpZGlhblRhYnNTZXR0aW5ncygpOiBPYnNpZGlhblRhYnNTZXR0aW5ncyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZVRhYjogdHJ1ZSxcbiAgICAgIHRhYlNpemU6IDQsXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgLi4uKHRoaXMuYXBwLnZhdWx0IGFzIGFueSkuY29uZmlnLFxuICAgIH07XG4gIH1cblxuICBnZXRPYnNpZGlhbkZvbGRTZXR0aW5ncygpOiBPYnNpZGlhbkZvbGRTZXR0aW5ncyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZvbGRJbmRlbnQ6IHRydWUsXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgLi4uKHRoaXMuYXBwLnZhdWx0IGFzIGFueSkuY29uZmlnLFxuICAgIH07XG4gIH1cblxuICBnZXREZWZhdWx0SW5kZW50Q2hhcnMoKSB7XG4gICAgY29uc3QgeyB1c2VUYWIsIHRhYlNpemUgfSA9IHRoaXMuZ2V0T2JzaWRpYW5UYWJzU2V0dGluZ3MoKTtcblxuICAgIHJldHVybiB1c2VUYWIgPyBcIlxcdFwiIDogbmV3IEFycmF5KHRhYlNpemUpLmZpbGwoXCIgXCIpLmpvaW4oXCJcIik7XG4gIH1cblxuICBnZXRFZGl0b3JGcm9tU3RhdGUoc3RhdGU6IEVkaXRvclN0YXRlKSB7XG4gICAgcmV0dXJuIG5ldyBNeUVkaXRvcihzdGF0ZS5maWVsZChlZGl0b3JJbmZvRmllbGQpLmVkaXRvcik7XG4gIH1cblxuICBjcmVhdGVLZXltYXBSdW5DYWxsYmFjayhjb25maWc6IHtcbiAgICBjaGVjaz86IChlZGl0b3I6IE15RWRpdG9yKSA9PiBib29sZWFuO1xuICAgIHJ1bjogKGVkaXRvcjogTXlFZGl0b3IpID0+IHtcbiAgICAgIHNob3VsZFVwZGF0ZTogYm9vbGVhbjtcbiAgICAgIHNob3VsZFN0b3BQcm9wYWdhdGlvbjogYm9vbGVhbjtcbiAgICB9O1xuICB9KSB7XG4gICAgY29uc3QgY2hlY2sgPSBjb25maWcuY2hlY2sgfHwgKCgpID0+IHRydWUpO1xuICAgIGNvbnN0IHsgcnVuIH0gPSBjb25maWc7XG5cbiAgICByZXR1cm4gKHZpZXc6IEVkaXRvclZpZXcpOiBib29sZWFuID0+IHtcbiAgICAgIGNvbnN0IGVkaXRvciA9IHRoaXMuZ2V0RWRpdG9yRnJvbVN0YXRlKHZpZXcuc3RhdGUpO1xuXG4gICAgICBpZiAoIWNoZWNrKGVkaXRvcikpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IHNob3VsZFVwZGF0ZSwgc2hvdWxkU3RvcFByb3BhZ2F0aW9uIH0gPSBydW4oZWRpdG9yKTtcblxuICAgICAgcmV0dXJuIHNob3VsZFVwZGF0ZSB8fCBzaG91bGRTdG9wUHJvcGFnYXRpb247XG4gICAgfTtcbiAgfVxuXG4gIGNyZWF0ZUVkaXRvckNhbGxiYWNrKGNiOiAoZWRpdG9yOiBNeUVkaXRvcikgPT4gYm9vbGVhbikge1xuICAgIHJldHVybiAoZWRpdG9yOiBFZGl0b3IpID0+IHtcbiAgICAgIGNvbnN0IG15RWRpdG9yID0gbmV3IE15RWRpdG9yKGVkaXRvcik7XG4gICAgICBjb25zdCBzaG91bGRTdG9wUHJvcGFnYXRpb24gPSBjYihteUVkaXRvcik7XG5cbiAgICAgIGlmIChcbiAgICAgICAgIXNob3VsZFN0b3BQcm9wYWdhdGlvbiAmJlxuICAgICAgICB3aW5kb3cuZXZlbnQgJiZcbiAgICAgICAgd2luZG93LmV2ZW50LnR5cGUgPT09IFwia2V5ZG93blwiXG4gICAgICApIHtcbiAgICAgICAgbXlFZGl0b3IudHJpZ2dlck9uS2V5RG93bih3aW5kb3cuZXZlbnQgYXMgS2V5Ym9hcmRFdmVudCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTGlzdCwgUm9vdCB9IGZyb20gXCIuLi9yb290XCI7XG5pbXBvcnQgeyBMb2dnZXJTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL0xvZ2dlclNlcnZpY2VcIjtcblxuY29uc3QgYnVsbGV0U2lnbiA9IGAoPzpbLSorXXxcXFxcZCtcXFxcLilgO1xuY29uc3Qgb3B0aW9uYWxDaGVja2JveCA9IGAoPzpcXFxcW1sgeFhdXFxcXF0oIHxcXHQpKT9gO1xuXG5jb25zdCBsaXN0SXRlbVdpdGhvdXRTcGFjZXNSZSA9IG5ldyBSZWdFeHAoYF4ke2J1bGxldFNpZ259KCB8XFx0KWApO1xuY29uc3QgbGlzdEl0ZW1SZSA9IG5ldyBSZWdFeHAoYF5bIFxcdF0qJHtidWxsZXRTaWdufSggfFxcdClgKTtcbmNvbnN0IHN0cmluZ1dpdGhTcGFjZXNSZSA9IG5ldyBSZWdFeHAoYF5bIFxcdF0rYCk7XG5jb25zdCBwYXJzZUxpc3RJdGVtUmUgPSBuZXcgUmVnRXhwKFxuICBgXihbIFxcdF0qKSgke2J1bGxldFNpZ259KSggfFxcdCkoKCR7b3B0aW9uYWxDaGVja2JveH0pLiopJGBcbik7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVhZGVyUG9zaXRpb24ge1xuICBsaW5lOiBudW1iZXI7XG4gIGNoOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVhZGVyU2VsZWN0aW9uIHtcbiAgYW5jaG9yOiBSZWFkZXJQb3NpdGlvbjtcbiAgaGVhZDogUmVhZGVyUG9zaXRpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVhZGVyIHtcbiAgZ2V0Q3Vyc29yKCk6IFJlYWRlclBvc2l0aW9uO1xuICBnZXRMaW5lKG46IG51bWJlcik6IHN0cmluZztcbiAgbGFzdExpbmUoKTogbnVtYmVyO1xuICBsaXN0U2VsZWN0aW9ucygpOiBSZWFkZXJTZWxlY3Rpb25bXTtcbiAgZ2V0QWxsRm9sZGVkTGluZXMoKTogbnVtYmVyW107XG59XG5cbmludGVyZmFjZSBQYXJzZUxpc3RMaXN0IHtcbiAgZ2V0Rmlyc3RMaW5lSW5kZW50KCk6IHN0cmluZztcbiAgc2V0Tm90ZXNJbmRlbnQobm90ZXNJbmRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGdldE5vdGVzSW5kZW50KCk6IHN0cmluZyB8IG51bGw7XG4gIGFkZExpbmUodGV4dDogc3RyaW5nKTogdm9pZDtcbiAgZ2V0UGFyZW50KCk6IFBhcnNlTGlzdExpc3QgfCBudWxsO1xuICBhZGRBZnRlckFsbChsaXN0OiBQYXJzZUxpc3RMaXN0KTogdm9pZDtcbn1cblxuZXhwb3J0IGNsYXNzIFBhcnNlclNlcnZpY2Uge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGxvZ2dlcjogTG9nZ2VyU2VydmljZSkge31cblxuICBwYXJzZVJhbmdlKGVkaXRvcjogUmVhZGVyLCBmcm9tTGluZSA9IDAsIHRvTGluZSA9IGVkaXRvci5sYXN0TGluZSgpKTogUm9vdFtdIHtcbiAgICBjb25zdCBsaXN0czogUm9vdFtdID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gZnJvbUxpbmU7IGkgPD0gdG9MaW5lOyBpKyspIHtcbiAgICAgIGNvbnN0IGxpbmUgPSBlZGl0b3IuZ2V0TGluZShpKTtcblxuICAgICAgaWYgKGkgPT09IGZyb21MaW5lIHx8IHRoaXMuaXNMaXN0SXRlbShsaW5lKSkge1xuICAgICAgICBjb25zdCBsaXN0ID0gdGhpcy5wYXJzZVdpdGhMaW1pdHMoZWRpdG9yLCBpLCBmcm9tTGluZSwgdG9MaW5lKTtcblxuICAgICAgICBpZiAobGlzdCkge1xuICAgICAgICAgIGxpc3RzLnB1c2gobGlzdCk7XG4gICAgICAgICAgaSA9IGxpc3QuZ2V0UmFuZ2UoKVsxXS5saW5lO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpc3RzO1xuICB9XG5cbiAgcGFyc2UoZWRpdG9yOiBSZWFkZXIsIGN1cnNvciA9IGVkaXRvci5nZXRDdXJzb3IoKSk6IFJvb3QgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZVdpdGhMaW1pdHMoZWRpdG9yLCBjdXJzb3IubGluZSwgMCwgZWRpdG9yLmxhc3RMaW5lKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVdpdGhMaW1pdHMoXG4gICAgZWRpdG9yOiBSZWFkZXIsXG4gICAgcGFyc2luZ1N0YXJ0TGluZTogbnVtYmVyLFxuICAgIGxpbWl0RnJvbTogbnVtYmVyLFxuICAgIGxpbWl0VG86IG51bWJlclxuICApOiBSb290IHwgbnVsbCB7XG4gICAgY29uc3QgZCA9IHRoaXMubG9nZ2VyLmJpbmQoXCJwYXJzZUxpc3RcIik7XG4gICAgY29uc3QgZXJyb3IgPSAobXNnOiBzdHJpbmcpOiBudWxsID0+IHtcbiAgICAgIGQobXNnKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICBjb25zdCBsaW5lID0gZWRpdG9yLmdldExpbmUocGFyc2luZ1N0YXJ0TGluZSk7XG5cbiAgICBsZXQgbGlzdExvb2tpbmdQb3M6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gICAgaWYgKHRoaXMuaXNMaXN0SXRlbShsaW5lKSkge1xuICAgICAgbGlzdExvb2tpbmdQb3MgPSBwYXJzaW5nU3RhcnRMaW5lO1xuICAgIH0gZWxzZSBpZiAodGhpcy5pc0xpbmVXaXRoSW5kZW50KGxpbmUpKSB7XG4gICAgICBsZXQgbGlzdExvb2tpbmdQb3NTZWFyY2ggPSBwYXJzaW5nU3RhcnRMaW5lIC0gMTtcbiAgICAgIHdoaWxlIChsaXN0TG9va2luZ1Bvc1NlYXJjaCA+PSAwKSB7XG4gICAgICAgIGNvbnN0IGxpbmUgPSBlZGl0b3IuZ2V0TGluZShsaXN0TG9va2luZ1Bvc1NlYXJjaCk7XG4gICAgICAgIGlmICh0aGlzLmlzTGlzdEl0ZW0obGluZSkpIHtcbiAgICAgICAgICBsaXN0TG9va2luZ1BvcyA9IGxpc3RMb29raW5nUG9zU2VhcmNoO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNMaW5lV2l0aEluZGVudChsaW5lKSkge1xuICAgICAgICAgIGxpc3RMb29raW5nUG9zU2VhcmNoLS07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobGlzdExvb2tpbmdQb3MgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgbGV0IGxpc3RTdGFydExpbmU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIGxldCBsaXN0U3RhcnRMaW5lTG9va3VwID0gbGlzdExvb2tpbmdQb3M7XG4gICAgd2hpbGUgKGxpc3RTdGFydExpbmVMb29rdXAgPj0gMCkge1xuICAgICAgY29uc3QgbGluZSA9IGVkaXRvci5nZXRMaW5lKGxpc3RTdGFydExpbmVMb29rdXApO1xuICAgICAgaWYgKCF0aGlzLmlzTGlzdEl0ZW0obGluZSkgJiYgIXRoaXMuaXNMaW5lV2l0aEluZGVudChsaW5lKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmlzTGlzdEl0ZW1XaXRob3V0U3BhY2VzKGxpbmUpKSB7XG4gICAgICAgIGxpc3RTdGFydExpbmUgPSBsaXN0U3RhcnRMaW5lTG9va3VwO1xuICAgICAgICBpZiAobGlzdFN0YXJ0TGluZUxvb2t1cCA8PSBsaW1pdEZyb20pIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGlzdFN0YXJ0TGluZUxvb2t1cC0tO1xuICAgIH1cblxuICAgIGlmIChsaXN0U3RhcnRMaW5lID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBsZXQgbGlzdEVuZExpbmUgPSBsaXN0TG9va2luZ1BvcztcbiAgICBsZXQgbGlzdEVuZExpbmVMb29rdXAgPSBsaXN0TG9va2luZ1BvcztcbiAgICB3aGlsZSAobGlzdEVuZExpbmVMb29rdXAgPD0gZWRpdG9yLmxhc3RMaW5lKCkpIHtcbiAgICAgIGNvbnN0IGxpbmUgPSBlZGl0b3IuZ2V0TGluZShsaXN0RW5kTGluZUxvb2t1cCk7XG4gICAgICBpZiAoIXRoaXMuaXNMaXN0SXRlbShsaW5lKSAmJiAhdGhpcy5pc0xpbmVXaXRoSW5kZW50KGxpbmUpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKCF0aGlzLmlzRW1wdHlMaW5lKGxpbmUpKSB7XG4gICAgICAgIGxpc3RFbmRMaW5lID0gbGlzdEVuZExpbmVMb29rdXA7XG4gICAgICB9XG4gICAgICBpZiAobGlzdEVuZExpbmVMb29rdXAgPj0gbGltaXRUbykge1xuICAgICAgICBsaXN0RW5kTGluZSA9IGxpbWl0VG87XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgbGlzdEVuZExpbmVMb29rdXArKztcbiAgICB9XG5cbiAgICBpZiAobGlzdFN0YXJ0TGluZSA+IHBhcnNpbmdTdGFydExpbmUgfHwgbGlzdEVuZExpbmUgPCBwYXJzaW5nU3RhcnRMaW5lKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCByb290ID0gbmV3IFJvb3QoXG4gICAgICB7IGxpbmU6IGxpc3RTdGFydExpbmUsIGNoOiAwIH0sXG4gICAgICB7IGxpbmU6IGxpc3RFbmRMaW5lLCBjaDogZWRpdG9yLmdldExpbmUobGlzdEVuZExpbmUpLmxlbmd0aCB9LFxuICAgICAgZWRpdG9yLmxpc3RTZWxlY3Rpb25zKCkubWFwKChyKSA9PiAoe1xuICAgICAgICBhbmNob3I6IHsgbGluZTogci5hbmNob3IubGluZSwgY2g6IHIuYW5jaG9yLmNoIH0sXG4gICAgICAgIGhlYWQ6IHsgbGluZTogci5oZWFkLmxpbmUsIGNoOiByLmhlYWQuY2ggfSxcbiAgICAgIH0pKVxuICAgICk7XG5cbiAgICBsZXQgY3VycmVudFBhcmVudDogUGFyc2VMaXN0TGlzdCA9IHJvb3QuZ2V0Um9vdExpc3QoKTtcbiAgICBsZXQgY3VycmVudExpc3Q6IFBhcnNlTGlzdExpc3QgfCBudWxsID0gbnVsbDtcbiAgICBsZXQgY3VycmVudEluZGVudCA9IFwiXCI7XG5cbiAgICBjb25zdCBmb2xkZWRMaW5lcyA9IGVkaXRvci5nZXRBbGxGb2xkZWRMaW5lcygpO1xuXG4gICAgZm9yIChsZXQgbCA9IGxpc3RTdGFydExpbmU7IGwgPD0gbGlzdEVuZExpbmU7IGwrKykge1xuICAgICAgY29uc3QgbGluZSA9IGVkaXRvci5nZXRMaW5lKGwpO1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IHBhcnNlTGlzdEl0ZW1SZS5leGVjKGxpbmUpO1xuXG4gICAgICBpZiAobWF0Y2hlcykge1xuICAgICAgICBjb25zdCBbLCBpbmRlbnQsIGJ1bGxldCwgc3BhY2VBZnRlckJ1bGxldCwgY29udGVudCwgb3B0aW9uYWxDaGVja2JveF0gPVxuICAgICAgICAgIG1hdGNoZXM7XG5cbiAgICAgICAgY29uc3QgY29tcGFyZUxlbmd0aCA9IE1hdGgubWluKGN1cnJlbnRJbmRlbnQubGVuZ3RoLCBpbmRlbnQubGVuZ3RoKTtcbiAgICAgICAgY29uc3QgaW5kZW50U2xpY2UgPSBpbmRlbnQuc2xpY2UoMCwgY29tcGFyZUxlbmd0aCk7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRJbmRlbnRTbGljZSA9IGN1cnJlbnRJbmRlbnQuc2xpY2UoMCwgY29tcGFyZUxlbmd0aCk7XG5cbiAgICAgICAgaWYgKGluZGVudFNsaWNlICE9PSBjdXJyZW50SW5kZW50U2xpY2UpIHtcbiAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IGN1cnJlbnRJbmRlbnRTbGljZVxuICAgICAgICAgICAgLnJlcGxhY2UoLyAvZywgXCJTXCIpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFx0L2csIFwiVFwiKTtcbiAgICAgICAgICBjb25zdCBnb3QgPSBpbmRlbnRTbGljZS5yZXBsYWNlKC8gL2csIFwiU1wiKS5yZXBsYWNlKC9cXHQvZywgXCJUXCIpO1xuXG4gICAgICAgICAgcmV0dXJuIGVycm9yKFxuICAgICAgICAgICAgYFVuYWJsZSB0byBwYXJzZSBsaXN0OiBleHBlY3RlZCBpbmRlbnQgXCIke2V4cGVjdGVkfVwiLCBnb3QgXCIke2dvdH1cImBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZGVudC5sZW5ndGggPiBjdXJyZW50SW5kZW50Lmxlbmd0aCkge1xuICAgICAgICAgIGN1cnJlbnRQYXJlbnQgPSBjdXJyZW50TGlzdDtcbiAgICAgICAgICBjdXJyZW50SW5kZW50ID0gaW5kZW50O1xuICAgICAgICB9IGVsc2UgaWYgKGluZGVudC5sZW5ndGggPCBjdXJyZW50SW5kZW50Lmxlbmd0aCkge1xuICAgICAgICAgIHdoaWxlIChcbiAgICAgICAgICAgIGN1cnJlbnRQYXJlbnQuZ2V0Rmlyc3RMaW5lSW5kZW50KCkubGVuZ3RoID49IGluZGVudC5sZW5ndGggJiZcbiAgICAgICAgICAgIGN1cnJlbnRQYXJlbnQuZ2V0UGFyZW50KClcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGN1cnJlbnRQYXJlbnQgPSBjdXJyZW50UGFyZW50LmdldFBhcmVudCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjdXJyZW50SW5kZW50ID0gaW5kZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm9sZFJvb3QgPSBmb2xkZWRMaW5lcy5pbmNsdWRlcyhsKTtcblxuICAgICAgICBjdXJyZW50TGlzdCA9IG5ldyBMaXN0KFxuICAgICAgICAgIHJvb3QsXG4gICAgICAgICAgaW5kZW50LFxuICAgICAgICAgIGJ1bGxldCxcbiAgICAgICAgICBvcHRpb25hbENoZWNrYm94Lmxlbmd0aCxcbiAgICAgICAgICBzcGFjZUFmdGVyQnVsbGV0LFxuICAgICAgICAgIGNvbnRlbnQsXG4gICAgICAgICAgZm9sZFJvb3RcbiAgICAgICAgKTtcbiAgICAgICAgY3VycmVudFBhcmVudC5hZGRBZnRlckFsbChjdXJyZW50TGlzdCk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuaXNMaW5lV2l0aEluZGVudChsaW5lKSkge1xuICAgICAgICBpZiAoIWN1cnJlbnRMaXN0KSB7XG4gICAgICAgICAgcmV0dXJuIGVycm9yKFxuICAgICAgICAgICAgYFVuYWJsZSB0byBwYXJzZSBsaXN0OiBleHBlY3RlZCBsaXN0IGl0ZW0sIGdvdCBlbXB0eSBsaW5lYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpbmRlbnRUb0NoZWNrID0gY3VycmVudExpc3QuZ2V0Tm90ZXNJbmRlbnQoKSB8fCBjdXJyZW50SW5kZW50O1xuXG4gICAgICAgIGlmIChsaW5lLmluZGV4T2YoaW5kZW50VG9DaGVjaykgIT09IDApIHtcbiAgICAgICAgICBjb25zdCBleHBlY3RlZCA9IGluZGVudFRvQ2hlY2sucmVwbGFjZSgvIC9nLCBcIlNcIikucmVwbGFjZSgvXFx0L2csIFwiVFwiKTtcbiAgICAgICAgICBjb25zdCBnb3QgPSBsaW5lXG4gICAgICAgICAgICAubWF0Y2goL15bIFxcdF0qLylbMF1cbiAgICAgICAgICAgIC5yZXBsYWNlKC8gL2csIFwiU1wiKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xcdC9nLCBcIlRcIik7XG5cbiAgICAgICAgICByZXR1cm4gZXJyb3IoXG4gICAgICAgICAgICBgVW5hYmxlIHRvIHBhcnNlIGxpc3Q6IGV4cGVjdGVkIGluZGVudCBcIiR7ZXhwZWN0ZWR9XCIsIGdvdCBcIiR7Z290fVwiYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWN1cnJlbnRMaXN0LmdldE5vdGVzSW5kZW50KCkpIHtcbiAgICAgICAgICBjb25zdCBtYXRjaGVzID0gbGluZS5tYXRjaCgvXlsgXFx0XSsvKTtcblxuICAgICAgICAgIGlmICghbWF0Y2hlcyB8fCBtYXRjaGVzWzBdLmxlbmd0aCA8PSBjdXJyZW50SW5kZW50Lmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKC9eXFxzKyQvLnRlc3QobGluZSkpIHtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBlcnJvcihcbiAgICAgICAgICAgICAgYFVuYWJsZSB0byBwYXJzZSBsaXN0OiBleHBlY3RlZCBzb21lIGluZGVudCwgZ290IG5vIGluZGVudGBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY3VycmVudExpc3Quc2V0Tm90ZXNJbmRlbnQobWF0Y2hlc1swXSk7XG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50TGlzdC5hZGRMaW5lKGxpbmUuc2xpY2UoY3VycmVudExpc3QuZ2V0Tm90ZXNJbmRlbnQoKS5sZW5ndGgpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBlcnJvcihcbiAgICAgICAgICBgVW5hYmxlIHRvIHBhcnNlIGxpc3Q6IGV4cGVjdGVkIGxpc3QgaXRlbSBvciBub3RlLCBnb3QgXCIke2xpbmV9XCJgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvb3Q7XG4gIH1cblxuICBwcml2YXRlIGlzRW1wdHlMaW5lKGxpbmU6IHN0cmluZykge1xuICAgIHJldHVybiBsaW5lLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIHByaXZhdGUgaXNMaW5lV2l0aEluZGVudChsaW5lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gc3RyaW5nV2l0aFNwYWNlc1JlLnRlc3QobGluZSk7XG4gIH1cblxuICBwcml2YXRlIGlzTGlzdEl0ZW0obGluZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGxpc3RJdGVtUmUudGVzdChsaW5lKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNMaXN0SXRlbVdpdGhvdXRTcGFjZXMobGluZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGxpc3RJdGVtV2l0aG91dFNwYWNlc1JlLnRlc3QobGluZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEFwcGx5Q2hhbmdlc1NlcnZpY2UgfSBmcm9tIFwiLi9BcHBseUNoYW5nZXNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBQYXJzZXJTZXJ2aWNlIH0gZnJvbSBcIi4vUGFyc2VyU2VydmljZVwiO1xuXG5pbXBvcnQgeyBNeUVkaXRvciB9IGZyb20gXCIuLi9NeUVkaXRvclwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvT3BlcmF0aW9uXCI7XG5pbXBvcnQgeyBSb290IH0gZnJvbSBcIi4uL3Jvb3RcIjtcblxuZXhwb3J0IGNsYXNzIFBlcmZvcm1PcGVyYXRpb25TZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBwYXJzZXI6IFBhcnNlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhcHBseUNoYW5nZXM6IEFwcGx5Q2hhbmdlc1NlcnZpY2VcbiAgKSB7fVxuXG4gIGV2YWxPcGVyYXRpb24ocm9vdDogUm9vdCwgb3A6IE9wZXJhdGlvbiwgZWRpdG9yOiBNeUVkaXRvcikge1xuICAgIG9wLnBlcmZvcm0oKTtcblxuICAgIGlmIChvcC5zaG91bGRVcGRhdGUoKSkge1xuICAgICAgdGhpcy5hcHBseUNoYW5nZXMuYXBwbHlDaGFuZ2VzKGVkaXRvciwgcm9vdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHNob3VsZFVwZGF0ZTogb3Auc2hvdWxkVXBkYXRlKCksXG4gICAgICBzaG91bGRTdG9wUHJvcGFnYXRpb246IG9wLnNob3VsZFN0b3BQcm9wYWdhdGlvbigpLFxuICAgIH07XG4gIH1cblxuICBwZXJmb3JtT3BlcmF0aW9uKFxuICAgIGNiOiAocm9vdDogUm9vdCkgPT4gT3BlcmF0aW9uLFxuICAgIGVkaXRvcjogTXlFZGl0b3IsXG4gICAgY3Vyc29yID0gZWRpdG9yLmdldEN1cnNvcigpXG4gICkge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnBhcnNlci5wYXJzZShlZGl0b3IsIGN1cnNvcik7XG5cbiAgICBpZiAoIXJvb3QpIHtcbiAgICAgIHJldHVybiB7IHNob3VsZFVwZGF0ZTogZmFsc2UsIHNob3VsZFN0b3BQcm9wYWdhdGlvbjogZmFsc2UgfTtcbiAgICB9XG5cbiAgICBjb25zdCBvcCA9IGNiKHJvb3QpO1xuXG4gICAgcmV0dXJuIHRoaXMuZXZhbE9wZXJhdGlvbihyb290LCBvcCwgZWRpdG9yKTtcbiAgfVxufVxuIiwiZXhwb3J0IHR5cGUgTGlzdExpbmVBY3Rpb24gPSBcIm5vbmVcIiB8IFwiem9vbS1pblwiIHwgXCJ0b2dnbGUtZm9sZGluZ1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9ic2lkaWFuT3V0bGluZXJQbHVnaW5TZXR0aW5ncyB7XG4gIHN0eWxlTGlzdHM6IGJvb2xlYW47XG4gIGRlYnVnOiBib29sZWFuO1xuICBzdGlja0N1cnNvcjogYm9vbGVhbjtcbiAgYmV0dGVyRW50ZXI6IGJvb2xlYW47XG4gIGJldHRlclRhYjogYm9vbGVhbjtcbiAgc2VsZWN0QWxsOiBib29sZWFuO1xuICBsaXN0TGluZXM6IGJvb2xlYW47XG4gIGxpc3RMaW5lQWN0aW9uOiBMaXN0TGluZUFjdGlvbjtcbn1cblxuY29uc3QgREVGQVVMVF9TRVRUSU5HUzogT2JzaWRpYW5PdXRsaW5lclBsdWdpblNldHRpbmdzID0ge1xuICBzdHlsZUxpc3RzOiB0cnVlLFxuICBkZWJ1ZzogZmFsc2UsXG4gIHN0aWNrQ3Vyc29yOiB0cnVlLFxuICBiZXR0ZXJFbnRlcjogdHJ1ZSxcbiAgYmV0dGVyVGFiOiB0cnVlLFxuICBzZWxlY3RBbGw6IHRydWUsXG4gIGxpc3RMaW5lczogZmFsc2UsXG4gIGxpc3RMaW5lQWN0aW9uOiBcInRvZ2dsZS1mb2xkaW5nXCIsXG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIFN0b3JhZ2Uge1xuICBsb2FkRGF0YSgpOiBQcm9taXNlPE9ic2lkaWFuT3V0bGluZXJQbHVnaW5TZXR0aW5ncz47XG4gIHNhdmVEYXRhKHNldHRpZ25zOiBPYnNpZGlhbk91dGxpbmVyUGx1Z2luU2V0dGluZ3MpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG50eXBlIEsgPSBrZXlvZiBPYnNpZGlhbk91dGxpbmVyUGx1Z2luU2V0dGluZ3M7XG50eXBlIENhbGxiYWNrPFQgZXh0ZW5kcyBLPiA9IChjYjogT2JzaWRpYW5PdXRsaW5lclBsdWdpblNldHRpbmdzW1RdKSA9PiB2b2lkO1xuXG5leHBvcnQgY2xhc3MgU2V0dGluZ3NTZXJ2aWNlIGltcGxlbWVudHMgT2JzaWRpYW5PdXRsaW5lclBsdWdpblNldHRpbmdzIHtcbiAgcHJpdmF0ZSBzdG9yYWdlOiBTdG9yYWdlO1xuICBwcml2YXRlIHZhbHVlczogT2JzaWRpYW5PdXRsaW5lclBsdWdpblNldHRpbmdzO1xuICBwcml2YXRlIGhhbmRsZXJzOiBNYXA8SywgU2V0PENhbGxiYWNrPEs+Pj47XG5cbiAgY29uc3RydWN0b3Ioc3RvcmFnZTogU3RvcmFnZSkge1xuICAgIHRoaXMuc3RvcmFnZSA9IHN0b3JhZ2U7XG4gICAgdGhpcy5oYW5kbGVycyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIGdldCBzdHlsZUxpc3RzKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5zdHlsZUxpc3RzO1xuICB9XG4gIHNldCBzdHlsZUxpc3RzKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXQoXCJzdHlsZUxpc3RzXCIsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkZWJ1ZygpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMuZGVidWc7XG4gIH1cbiAgc2V0IGRlYnVnKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXQoXCJkZWJ1Z1wiLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgc3RpY2tDdXJzb3IoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLnN0aWNrQ3Vyc29yO1xuICB9XG4gIHNldCBzdGlja0N1cnNvcih2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuc2V0KFwic3RpY2tDdXJzb3JcIiwgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGJldHRlckVudGVyKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5iZXR0ZXJFbnRlcjtcbiAgfVxuICBzZXQgYmV0dGVyRW50ZXIodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldChcImJldHRlckVudGVyXCIsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBiZXR0ZXJUYWIoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmJldHRlclRhYjtcbiAgfVxuICBzZXQgYmV0dGVyVGFiKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXQoXCJiZXR0ZXJUYWJcIiwgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IHNlbGVjdEFsbCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMuc2VsZWN0QWxsO1xuICB9XG4gIHNldCBzZWxlY3RBbGwodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldChcInNlbGVjdEFsbFwiLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgbGlzdExpbmVzKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5saXN0TGluZXM7XG4gIH1cbiAgc2V0IGxpc3RMaW5lcyh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuc2V0KFwibGlzdExpbmVzXCIsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBsaXN0TGluZUFjdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMubGlzdExpbmVBY3Rpb247XG4gIH1cbiAgc2V0IGxpc3RMaW5lQWN0aW9uKHZhbHVlOiBMaXN0TGluZUFjdGlvbikge1xuICAgIHRoaXMuc2V0KFwibGlzdExpbmVBY3Rpb25cIiwgdmFsdWUpO1xuICB9XG5cbiAgb25DaGFuZ2U8VCBleHRlbmRzIEs+KGtleTogVCwgY2I6IENhbGxiYWNrPFQ+KSB7XG4gICAgaWYgKCF0aGlzLmhhbmRsZXJzLmhhcyhrZXkpKSB7XG4gICAgICB0aGlzLmhhbmRsZXJzLnNldChrZXksIG5ldyBTZXQoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5oYW5kbGVycy5nZXQoa2V5KS5hZGQoY2IpO1xuICB9XG5cbiAgcmVtb3ZlQ2FsbGJhY2s8VCBleHRlbmRzIEs+KGtleTogVCwgY2I6IENhbGxiYWNrPFQ+KTogdm9pZCB7XG4gICAgY29uc3QgaGFuZGxlcnMgPSB0aGlzLmhhbmRsZXJzLmdldChrZXkpO1xuXG4gICAgaWYgKGhhbmRsZXJzKSB7XG4gICAgICBoYW5kbGVycy5kZWxldGUoY2IpO1xuICAgIH1cbiAgfVxuXG4gIHJlc2V0KCkge1xuICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKERFRkFVTFRfU0VUVElOR1MpKSB7XG4gICAgICB0aGlzLnNldChrIGFzIGtleW9mIE9ic2lkaWFuT3V0bGluZXJQbHVnaW5TZXR0aW5ncywgdik7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgbG9hZCgpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICB7fSxcbiAgICAgIERFRkFVTFRfU0VUVElOR1MsXG4gICAgICBhd2FpdCB0aGlzLnN0b3JhZ2UubG9hZERhdGEoKVxuICAgICk7XG4gIH1cblxuICBhc3luYyBzYXZlKCkge1xuICAgIGF3YWl0IHRoaXMuc3RvcmFnZS5zYXZlRGF0YSh0aGlzLnZhbHVlcyk7XG4gIH1cblxuICBzZXQ8VCBleHRlbmRzIEs+KGtleTogVCwgdmFsdWU6IE9ic2lkaWFuT3V0bGluZXJQbHVnaW5TZXR0aW5nc1tUXSk6IHZvaWQge1xuICAgIHRoaXMudmFsdWVzW2tleV0gPSB2YWx1ZTtcbiAgICBjb25zdCBjYWxsYmFja3MgPSB0aGlzLmhhbmRsZXJzLmdldChrZXkpO1xuXG4gICAgaWYgKCFjYWxsYmFja3MpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGNiIG9mIGNhbGxiYWNrcy52YWx1ZXMoKSkge1xuICAgICAgY2IodmFsdWUpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHsgUGx1Z2luIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmltcG9ydCB7IERlbGV0ZVNob3VsZElnbm9yZUJ1bGxldHNGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvRGVsZXRlU2hvdWxkSWdub3JlQnVsbGV0c0ZlYXR1cmVcIjtcbmltcG9ydCB7IEVuc3VyZUN1cnNvckluTGlzdENvbnRlbnRGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvRW5zdXJlQ3Vyc29ySW5MaXN0Q29udGVudEZlYXR1cmVcIjtcbmltcG9ydCB7IEVudGVyT3V0ZGVudElmTGluZUlzRW1wdHlGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvRW50ZXJPdXRkZW50SWZMaW5lSXNFbXB0eUZlYXR1cmVcIjtcbmltcG9ydCB7IEVudGVyU2hvdWxkQ3JlYXRlTmV3SXRlbUZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9FbnRlclNob3VsZENyZWF0ZU5ld0l0ZW1PbkNoaWxkTGV2ZWxGZWF0dXJlXCI7XG5pbXBvcnQgeyBGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvRmVhdHVyZVwiO1xuaW1wb3J0IHsgRm9sZEZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9Gb2xkRmVhdHVyZVwiO1xuaW1wb3J0IHsgTGluZXNGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvTGluZXNGZWF0dXJlXCI7XG5pbXBvcnQgeyBMaXN0c1N0eWxlc0ZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9MaXN0c1N0eWxlc0ZlYXR1cmVcIjtcbmltcG9ydCB7IE1vdmVDdXJzb3JUb1ByZXZpb3VzVW5mb2xkZWRMaW5lRmVhdHVyZSB9IGZyb20gXCIuL2ZlYXR1cmVzL01vdmVDdXJzb3JUb1ByZXZpb3VzVW5mb2xkZWRMaW5lRmVhdHVyZVwiO1xuaW1wb3J0IHsgTW92ZUl0ZW1zRmVhdHVyZSB9IGZyb20gXCIuL2ZlYXR1cmVzL01vdmVJdGVtc0ZlYXR1cmVcIjtcbmltcG9ydCB7IFNlbGVjdEFsbEZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9TZWxlY3RBbGxGZWF0dXJlXCI7XG5pbXBvcnQgeyBTZWxlY3Rpb25TaG91bGRJZ25vcmVCdWxsZXRzRmVhdHVyZSB9IGZyb20gXCIuL2ZlYXR1cmVzL1NlbGVjdGlvblNob3VsZElnbm9yZUJ1bGxldHNGZWF0dXJlXCI7XG5pbXBvcnQgeyBTZXR0aW5nc1RhYkZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9TZXR0aW5nc1RhYkZlYXR1cmVcIjtcbmltcG9ydCB7IFNoaWZ0RW50ZXJTaG91bGRDcmVhdGVOb3RlRmVhdHVyZSB9IGZyb20gXCIuL2ZlYXR1cmVzL1NoaWZ0RW50ZXJTaG91bGRDcmVhdGVOb3RlRmVhdHVyZVwiO1xuaW1wb3J0IHsgQXBwbHlDaGFuZ2VzU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL0FwcGx5Q2hhbmdlc1NlcnZpY2VcIjtcbmltcG9ydCB7IElNRVNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9JTUVTZXJ2aWNlXCI7XG5pbXBvcnQgeyBMb2dnZXJTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvTG9nZ2VyU2VydmljZVwiO1xuaW1wb3J0IHsgT2JzaWRpYW5TZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvT2JzaWRpYW5TZXJ2aWNlXCI7XG5pbXBvcnQgeyBQYXJzZXJTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvUGFyc2VyU2VydmljZVwiO1xuaW1wb3J0IHsgUGVyZm9ybU9wZXJhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9QZXJmb3JtT3BlcmF0aW9uU2VydmljZVwiO1xuaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvU2V0dGluZ3NTZXJ2aWNlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE9ic2lkaWFuT3V0bGluZXJQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xuICBwcml2YXRlIGZlYXR1cmVzOiBGZWF0dXJlW107XG4gIHByb3RlY3RlZCBzZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlO1xuICBwcml2YXRlIGxvZ2dlcjogTG9nZ2VyU2VydmljZTtcbiAgcHJpdmF0ZSBvYnNpZGlhbjogT2JzaWRpYW5TZXJ2aWNlO1xuICBwcml2YXRlIHBhcnNlcjogUGFyc2VyU2VydmljZTtcbiAgcHJpdmF0ZSBhcHBseUNoYW5nZXM6IEFwcGx5Q2hhbmdlc1NlcnZpY2U7XG4gIHByaXZhdGUgcGVyZm9ybU9wZXJhdGlvbjogUGVyZm9ybU9wZXJhdGlvblNlcnZpY2U7XG4gIHByaXZhdGUgaW1lOiBJTUVTZXJ2aWNlO1xuXG4gIGFzeW5jIG9ubG9hZCgpIHtcbiAgICBjb25zb2xlLmxvZyhgTG9hZGluZyBvYnNpZGlhbi1vdXRsaW5lcmApO1xuXG4gICAgdGhpcy5vYnNpZGlhbiA9IG5ldyBPYnNpZGlhblNlcnZpY2UodGhpcy5hcHApO1xuXG4gICAgdGhpcy5zZXR0aW5ncyA9IG5ldyBTZXR0aW5nc1NlcnZpY2UodGhpcyk7XG4gICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5sb2FkKCk7XG5cbiAgICB0aGlzLmxvZ2dlciA9IG5ldyBMb2dnZXJTZXJ2aWNlKHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgdGhpcy5wYXJzZXIgPSBuZXcgUGFyc2VyU2VydmljZSh0aGlzLmxvZ2dlcik7XG4gICAgdGhpcy5hcHBseUNoYW5nZXMgPSBuZXcgQXBwbHlDaGFuZ2VzU2VydmljZSgpO1xuICAgIHRoaXMucGVyZm9ybU9wZXJhdGlvbiA9IG5ldyBQZXJmb3JtT3BlcmF0aW9uU2VydmljZShcbiAgICAgIHRoaXMucGFyc2VyLFxuICAgICAgdGhpcy5hcHBseUNoYW5nZXNcbiAgICApO1xuXG4gICAgdGhpcy5pbWUgPSBuZXcgSU1FU2VydmljZSgpO1xuICAgIGF3YWl0IHRoaXMuaW1lLmxvYWQoKTtcblxuICAgIHRoaXMuZmVhdHVyZXMgPSBbXG4gICAgICBuZXcgU2V0dGluZ3NUYWJGZWF0dXJlKHRoaXMsIHRoaXMuc2V0dGluZ3MpLFxuICAgICAgbmV3IExpc3RzU3R5bGVzRmVhdHVyZSh0aGlzLnNldHRpbmdzLCB0aGlzLm9ic2lkaWFuKSxcbiAgICAgIG5ldyBFbnRlck91dGRlbnRJZkxpbmVJc0VtcHR5RmVhdHVyZShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgdGhpcy5zZXR0aW5ncyxcbiAgICAgICAgdGhpcy5pbWUsXG4gICAgICAgIHRoaXMub2JzaWRpYW4sXG4gICAgICAgIHRoaXMucGVyZm9ybU9wZXJhdGlvblxuICAgICAgKSxcbiAgICAgIG5ldyBFbnRlclNob3VsZENyZWF0ZU5ld0l0ZW1GZWF0dXJlKFxuICAgICAgICB0aGlzLFxuICAgICAgICB0aGlzLnNldHRpbmdzLFxuICAgICAgICB0aGlzLmltZSxcbiAgICAgICAgdGhpcy5vYnNpZGlhbixcbiAgICAgICAgdGhpcy5wZXJmb3JtT3BlcmF0aW9uXG4gICAgICApLFxuICAgICAgbmV3IEVuc3VyZUN1cnNvckluTGlzdENvbnRlbnRGZWF0dXJlKFxuICAgICAgICB0aGlzLFxuICAgICAgICB0aGlzLnNldHRpbmdzLFxuICAgICAgICB0aGlzLm9ic2lkaWFuLFxuICAgICAgICB0aGlzLnBlcmZvcm1PcGVyYXRpb25cbiAgICAgICksXG4gICAgICBuZXcgTW92ZUN1cnNvclRvUHJldmlvdXNVbmZvbGRlZExpbmVGZWF0dXJlKFxuICAgICAgICB0aGlzLFxuICAgICAgICB0aGlzLnNldHRpbmdzLFxuICAgICAgICB0aGlzLmltZSxcbiAgICAgICAgdGhpcy5vYnNpZGlhbixcbiAgICAgICAgdGhpcy5wZXJmb3JtT3BlcmF0aW9uXG4gICAgICApLFxuICAgICAgbmV3IERlbGV0ZVNob3VsZElnbm9yZUJ1bGxldHNGZWF0dXJlKFxuICAgICAgICB0aGlzLFxuICAgICAgICB0aGlzLnNldHRpbmdzLFxuICAgICAgICB0aGlzLmltZSxcbiAgICAgICAgdGhpcy5vYnNpZGlhbixcbiAgICAgICAgdGhpcy5wZXJmb3JtT3BlcmF0aW9uXG4gICAgICApLFxuICAgICAgbmV3IFNlbGVjdGlvblNob3VsZElnbm9yZUJ1bGxldHNGZWF0dXJlKFxuICAgICAgICB0aGlzLFxuICAgICAgICB0aGlzLnNldHRpbmdzLFxuICAgICAgICB0aGlzLmltZSxcbiAgICAgICAgdGhpcy5vYnNpZGlhbixcbiAgICAgICAgdGhpcy5wZXJmb3JtT3BlcmF0aW9uXG4gICAgICApLFxuICAgICAgbmV3IEZvbGRGZWF0dXJlKHRoaXMsIHRoaXMub2JzaWRpYW4pLFxuICAgICAgbmV3IFNlbGVjdEFsbEZlYXR1cmUoXG4gICAgICAgIHRoaXMsXG4gICAgICAgIHRoaXMuc2V0dGluZ3MsXG4gICAgICAgIHRoaXMuaW1lLFxuICAgICAgICB0aGlzLm9ic2lkaWFuLFxuICAgICAgICB0aGlzLnBlcmZvcm1PcGVyYXRpb25cbiAgICAgICksXG4gICAgICBuZXcgTW92ZUl0ZW1zRmVhdHVyZShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgdGhpcy5pbWUsXG4gICAgICAgIHRoaXMub2JzaWRpYW4sXG4gICAgICAgIHRoaXMuc2V0dGluZ3MsXG4gICAgICAgIHRoaXMucGVyZm9ybU9wZXJhdGlvblxuICAgICAgKSxcbiAgICAgIG5ldyBTaGlmdEVudGVyU2hvdWxkQ3JlYXRlTm90ZUZlYXR1cmUoXG4gICAgICAgIHRoaXMsXG4gICAgICAgIHRoaXMub2JzaWRpYW4sXG4gICAgICAgIHRoaXMuc2V0dGluZ3MsXG4gICAgICAgIHRoaXMuaW1lLFxuICAgICAgICB0aGlzLnBlcmZvcm1PcGVyYXRpb25cbiAgICAgICksXG4gICAgICBuZXcgTGluZXNGZWF0dXJlKHRoaXMsIHRoaXMuc2V0dGluZ3MsIHRoaXMub2JzaWRpYW4sIHRoaXMucGFyc2VyKSxcbiAgICBdO1xuXG4gICAgZm9yIChjb25zdCBmZWF0dXJlIG9mIHRoaXMuZmVhdHVyZXMpIHtcbiAgICAgIGF3YWl0IGZlYXR1cmUubG9hZCgpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG9udW5sb2FkKCkge1xuICAgIGNvbnNvbGUubG9nKGBVbmxvYWRpbmcgb2JzaWRpYW4tb3V0bGluZXJgKTtcblxuICAgIGF3YWl0IHRoaXMuaW1lLnVubG9hZCgpO1xuXG4gICAgZm9yIChjb25zdCBmZWF0dXJlIG9mIHRoaXMuZmVhdHVyZXMpIHtcbiAgICAgIGF3YWl0IGZlYXR1cmUudW5sb2FkKCk7XG4gICAgfVxuICB9XG59XG4iXSwibmFtZXMiOlsia2V5bWFwIiwiRWRpdG9yU3RhdGUiLCJQcmVjIiwiTm90aWNlIiwiZm9sZGVkUmFuZ2VzIiwiZm9sZGFibGUiLCJmb2xkRWZmZWN0IiwidW5mb2xkRWZmZWN0IiwicnVuU2NvcGVIYW5kbGVycyIsIm9ic2lkaWFuIiwiZWRpdG9ySW5mb0ZpZWxkIiwiVmlld1Bs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LEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDMUI7QUFFRCxJQUFBLElBQUksV0FBVyxHQUFBO0FBQ2IsUUFBQSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO0tBQ2hDO0lBQ0QsSUFBSSxXQUFXLENBQUMsS0FBYyxFQUFBO0FBQzVCLFFBQUEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDaEM7QUFFRCxJQUFBLElBQUksV0FBVyxHQUFBO0FBQ2IsUUFBQSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO0tBQ2hDO0lBQ0QsSUFBSSxXQUFXLENBQUMsS0FBYyxFQUFBO0FBQzVCLFFBQUEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDaEM7QUFFRCxJQUFBLElBQUksU0FBUyxHQUFBO0FBQ1gsUUFBQSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO0tBQzlCO0lBQ0QsSUFBSSxTQUFTLENBQUMsS0FBYyxFQUFBO0FBQzFCLFFBQUEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDOUI7QUFFRCxJQUFBLElBQUksU0FBUyxHQUFBO0FBQ1gsUUFBQSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO0tBQzlCO0lBQ0QsSUFBSSxTQUFTLENBQUMsS0FBYyxFQUFBO0FBQzFCLFFBQUEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDOUI7QUFFRCxJQUFBLElBQUksU0FBUyxHQUFBO0FBQ1gsUUFBQSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO0tBQzlCO0lBQ0QsSUFBSSxTQUFTLENBQUMsS0FBYyxFQUFBO0FBQzFCLFFBQUEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDOUI7QUFFRCxJQUFBLElBQUksY0FBYyxHQUFBO0FBQ2hCLFFB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
diff --git a/.obsidian/plugins/obsidian-outliner/manifest.json b/.obsidian/plugins/obsidian-outliner/manifest.json
new file mode 100644
index 00000000..7934f617
--- /dev/null
+++ b/.obsidian/plugins/obsidian-outliner/manifest.json
@@ -0,0 +1,10 @@
+{
+ "id": "obsidian-outliner",
+ "name": "Outliner",
+ "version": "4.2.1",
+ "minAppVersion": "1.0.0",
+ "description": "Work with your lists like in Workflowy or RoamResearch.",
+ "author": "Viacheslav Slinko",
+ "authorUrl": "https://github.com/vslinko",
+ "isDesktopOnly": false
+}
diff --git a/.obsidian/plugins/obsidian-outliner/styles.css b/.obsidian/plugins/obsidian-outliner/styles.css
new file mode 100644
index 00000000..c2792286
--- /dev/null
+++ b/.obsidian/plugins/obsidian-outliner/styles.css
@@ -0,0 +1,71 @@
+/* lists */
+.outliner-plugin-better-lists .cm-s-obsidian .HyperMD-list-line {
+ padding-top: 0.4em;
+}
+
+/* bullets */
+.outliner-plugin-better-bullets .cm-formatting-list-ul {
+ margin-right: 0.3em;
+}
+
+.outliner-plugin-better-bullets .list-bullet::after {
+ width: 0.4em;
+ height: 0.4em;
+ background-color: var(--text-muted);
+}
+
+/* lines */
+.outliner-plugin-list-lines-scroller {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: var(--file-margins);
+ padding-left: 0;
+ pointer-events: none;
+ overflow: hidden;
+}
+
+.outliner-plugin-list-lines-content-container {
+ position: relative;
+}
+
+.outliner-plugin-list-line {
+ pointer-events: auto;
+ position: absolute;
+ width: 5px;
+ margin-left: 0.5ch;
+ margin-top: 1em;
+ z-index: 1;
+ cursor: pointer;
+ background: transparent;
+ background-image: linear-gradient(
+ to right,
+ var(--text-faint) 1px,
+ transparent 1px
+ );
+ background-position-x: 2px;
+ background-repeat: no-repeat;
+}
+
+.outliner-plugin-better-bullets .outliner-plugin-list-line {
+ margin-top: 1.4em;
+}
+
+.markdown-source-view.mod-cm6.is-readable-line-width
+ .outliner-plugin-list-lines-content-container {
+ max-width: 700px;
+ margin: auto;
+}
+
+.outliner-plugin-list-line:hover {
+ background: var(--text-faint);
+}
+
+.outliner-plugin-vertical-lines
+ .markdown-source-view.mod-cm6
+ .cm-hmd-list-indent
+ .cm-indent::before {
+ content: none;
+}
diff --git a/.obsidian/plugins/table-editor-obsidian/data.json b/.obsidian/plugins/table-editor-obsidian/data.json
new file mode 100644
index 00000000..90094659
--- /dev/null
+++ b/.obsidian/plugins/table-editor-obsidian/data.json
@@ -0,0 +1,6 @@
+{
+ "formatType": "normal",
+ "showRibbonIcon": true,
+ "bindEnter": true,
+ "bindTab": true
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/table-editor-obsidian/main.js b/.obsidian/plugins/table-editor-obsidian/main.js
new file mode 100644
index 00000000..81956cc0
--- /dev/null
+++ b/.obsidian/plugins/table-editor-obsidian/main.js
@@ -0,0 +1,24038 @@
+'use strict';
+
+var obsidian = require('obsidian');
+var state = require('@codemirror/state');
+var view = require('@codemirror/view');
+
+/*! *****************************************************************************
+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.
+***************************************************************************** */
+/* global Reflect, Promise */
+
+var extendStatics = function(d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+ return extendStatics(d, b);
+};
+
+function __extends(d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+}
+
+var __assign = function() {
+ __assign = Object.assign || function __assign(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+};
+
+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());
+ });
+}
+
+function __generator(thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (_) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+}
+
+var icons = {
+ spreadsheet: "\n",
+ alignLeft: "\n",
+ alignCenter: "\n",
+ alignRight: "\n",
+ deleteColumn: "\n",
+ deleteRow: "\n",
+ insertColumn: "\n",
+ insertRow: "\n",
+ moveColumnLeft: "\n",
+ moveColumnRight: "\n",
+ moveRowDown: "\n",
+ moveRowUp: "\n",
+ sortAsc: "\n",
+ sortDesc: "\n",
+ formula: "\n",
+ help: "\n",
+ csv: "\n",
+ arrowenter: "\n",
+ arrowtab: "\n",
+};
+var addIcons = function () {
+ Object.keys(icons).forEach(function (key) {
+ // Don't add the 'help' icon here as it will overwrite the native one.
+ if (key !== 'help') {
+ obsidian.addIcon(key, icons[key]);
+ }
+ });
+};
+
+var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
+
+function createCommonjsModule(fn, basedir, module) {
+ return module = {
+ path: basedir,
+ exports: {},
+ require: function (path, base) {
+ return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
+ }
+ }, fn(module, module.exports), module.exports;
+}
+
+function getAugmentedNamespace(n) {
+ if (n.__esModule) return n;
+ var a = Object.defineProperty({}, '__esModule', {value: true});
+ Object.keys(n).forEach(function (k) {
+ var d = Object.getOwnPropertyDescriptor(n, k);
+ Object.defineProperty(a, k, d.get ? d : {
+ enumerable: true,
+ get: function () {
+ return n[k];
+ }
+ });
+ });
+ return a;
+}
+
+function commonjsRequire () {
+ throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
+}
+
+var point = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Point = void 0;
+/**
+ * A `Point` represents a point in the text editor.
+ */
+class Point {
+ /**
+ * Creates a new `Point` object.
+ *
+ * @param row - Row of the point, starts from 0.
+ * @param column - Column of the point, starts from 0.
+ */
+ constructor(row, column) {
+ this.row = row;
+ this.column = column;
+ }
+ /**
+ * Checks if the point is equal to another point.
+ */
+ equals(point) {
+ return this.row === point.row && this.column === point.column;
+ }
+}
+exports.Point = Point;
+});
+
+var range = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Range = void 0;
+/**
+ * A `Range` object represents a range in the text editor.
+ */
+class Range {
+ /**
+ * Creates a new `Range` object.
+ *
+ * @param start - The start point of the range.
+ * @param end - The end point of the range.
+ */
+ constructor(start, end) {
+ this.start = start;
+ this.end = end;
+ }
+}
+exports.Range = Range;
+});
+
+var focus = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Focus = void 0;
+/**
+ * A `Focus` object represents which cell is focused in the table.
+ *
+ * Note that `row` and `column` properties specifiy a cell's position in the
+ * table, not the cursor's position in the text editor as {@link Point} class.
+ *
+ * @private
+ */
+class Focus {
+ /**
+ * Creates a new `Focus` object.
+ *
+ * @param row - Row of the focused cell.
+ * @param column - Column of the focused cell.
+ * @param offset - Raw offset in the cell.
+ */
+ constructor(row, column, offset) {
+ this.row = row;
+ this.column = column;
+ this.offset = offset;
+ }
+ /**
+ * Checks if two focuses point the same cell.
+ * Offsets are ignored.
+ */
+ posEquals(focus) {
+ return this.row === focus.row && this.column === focus.column;
+ }
+ /**
+ * Creates a copy of the focus object by setting its row to the specified value.
+ *
+ * @param row - Row of the focused cell.
+ * @returns A new focus object with the specified row.
+ */
+ setRow(row) {
+ return new Focus(row, this.column, this.offset);
+ }
+ /**
+ * Creates a copy of the focus object by setting its column to the specified value.
+ *
+ * @param column - Column of the focused cell.
+ * @returns A new focus object with the specified column.
+ */
+ setColumn(column) {
+ return new Focus(this.row, column, this.offset);
+ }
+ /**
+ * Creates a copy of the focus object by setting its offset to the specified value.
+ *
+ * @param offset - Offset in the focused cell.
+ * @returns A new focus object with the specified offset.
+ */
+ setOffset(offset) {
+ return new Focus(this.row, this.column, offset);
+ }
+}
+exports.Focus = Focus;
+});
+
+var alignment = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.HeaderAlignment = exports.DefaultAlignment = exports.Alignment = void 0;
+/**
+ * Represents column alignment.
+ *
+ * - `Alignment.NONE` - Use default alignment.
+ * - `Alignment.LEFT` - Align left.
+ * - `Alignment.RIGHT` - Align right.
+ * - `Alignment.CENTER` - Align center.
+ *
+ */
+var Alignment;
+(function (Alignment) {
+ Alignment["NONE"] = "none";
+ Alignment["LEFT"] = "left";
+ Alignment["RIGHT"] = "right";
+ Alignment["CENTER"] = "center";
+})(Alignment = exports.Alignment || (exports.Alignment = {}));
+/**
+ * Represents default column alignment
+ *
+ * - `DefaultAlignment.LEFT` - Align left.
+ * - `DefaultAlignment.RIGHT` - Align right.
+ * - `DefaultAlignment.CENTER` - Align center.
+ *
+ */
+var DefaultAlignment;
+(function (DefaultAlignment) {
+ DefaultAlignment["LEFT"] = "left";
+ DefaultAlignment["RIGHT"] = "right";
+ DefaultAlignment["CENTER"] = "center";
+})(DefaultAlignment = exports.DefaultAlignment || (exports.DefaultAlignment = {}));
+/**
+ * Represents alignment of header cells.
+ *
+ * - `HeaderAlignment.FOLLOW` - Follow column's alignment.
+ * - `HeaderAlignment.LEFT` - Align left.
+ * - `HeaderAlignment.RIGHT` - Align right.
+ * - `HeaderAlignment.CENTER` - Align center.
+ *
+ */
+var HeaderAlignment;
+(function (HeaderAlignment) {
+ HeaderAlignment["FOLLOW"] = "follow";
+ HeaderAlignment["LEFT"] = "left";
+ HeaderAlignment["RIGHT"] = "right";
+ HeaderAlignment["CENTER"] = "center";
+})(HeaderAlignment = exports.HeaderAlignment || (exports.HeaderAlignment = {}));
+});
+
+var tableCell = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TableCell = void 0;
+
+/**
+ * A `TableCell` object represents a table cell.
+ *
+ * @private
+ */
+class TableCell {
+ /**
+ * Creates a new `TableCell` object.
+ *
+ * @param rawContent - Raw content of the cell.
+ */
+ constructor(rawContent) {
+ this.rawContent = rawContent;
+ this.content = rawContent.trim();
+ this.paddingLeft =
+ this.content === ''
+ ? this.rawContent === ''
+ ? 0
+ : 1
+ : this.rawContent.length - this.rawContent.trimLeft().length;
+ this.paddingRight =
+ this.rawContent.length - this.content.length - this.paddingLeft;
+ }
+ /**
+ * Convers the cell to a text representation.
+ *
+ * @returns The raw content of the cell.
+ */
+ toText() {
+ return this.rawContent;
+ }
+ /**
+ * Checks if the cell is a delimiter i.e. it only contains hyphens `-` with optional one
+ * leading and trailing colons `:`.
+ *
+ * @returns `true` if the cell is a delimiter.
+ */
+ isDelimiter() {
+ return /^\s*:?-+:?\s*$/.test(this.rawContent);
+ }
+ /**
+ * Returns the alignment the cell represents.
+ *
+ * @returns The alignment the cell represents; `undefined` if the cell is not a delimiter.
+ */
+ getAlignment() {
+ if (!this.isDelimiter()) {
+ return undefined;
+ }
+ if (this.content[0] === ':') {
+ if (this.content[this.content.length - 1] === ':') {
+ return alignment.Alignment.CENTER;
+ }
+ return alignment.Alignment.LEFT;
+ }
+ if (this.content[this.content.length - 1] === ':') {
+ return alignment.Alignment.RIGHT;
+ }
+ return alignment.Alignment.NONE;
+ }
+ /**
+ * Computes a relative position in the trimmed content from that in the raw content.
+ *
+ * @param rawOffset - Relative position in the raw content.
+ * @returns - Relative position in the trimmed content.
+ */
+ computeContentOffset(rawOffset) {
+ if (this.content === '') {
+ return 0;
+ }
+ if (rawOffset < this.paddingLeft) {
+ return 0;
+ }
+ if (rawOffset < this.paddingLeft + this.content.length) {
+ return rawOffset - this.paddingLeft;
+ }
+ return this.content.length;
+ }
+ /**
+ * Computes a relative position in the raw content from that in the trimmed content.
+ *
+ * @param contentOffset - Relative position in the trimmed content.
+ * @returns - Relative position in the raw content.
+ */
+ computeRawOffset(contentOffset) {
+ return contentOffset + this.paddingLeft;
+ }
+}
+exports.TableCell = TableCell;
+});
+
+var tableRow = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TableRow = void 0;
+
+/**
+ * A `TableRow` object represents a table row.
+ *
+ * @private
+ */
+class TableRow {
+ /**
+ * Creates a new `TableRow` objec.
+ *
+ * @param cells - Cells that the row contains.
+ * @param marginLeft - Margin string at the left of the row.
+ * @param marginRight - Margin string at the right of the row.
+ */
+ constructor(cells, marginLeft, marginRight) {
+ this._cells = cells.slice();
+ this.marginLeft = marginLeft;
+ this.marginRight = marginRight;
+ }
+ /**
+ * Gets the number of the cells in the row.
+ */
+ getWidth() {
+ return this._cells.length;
+ }
+ /**
+ * Returns the cells that the row contains.
+ */
+ getCells() {
+ return this._cells.slice();
+ }
+ /**
+ * Gets a cell at the specified index.
+ *
+ * @param index - Index.
+ * @returns The cell at the specified index if exists; `undefined` if no cell is found.
+ */
+ getCellAt(index) {
+ return this._cells[index];
+ }
+ /**
+ * Sets a cell in the row to a new value, returning a copy of the row
+ * with the modified value.
+ *
+ * If an invalid index is provided, the row will be unchanged.
+ */
+ setCellAt(index, value) {
+ const cells = this.getCells(); // a copy
+ cells[index] = new tableCell.TableCell(value);
+ return new TableRow(cells, this.marginLeft, this.marginRight);
+ }
+ /**
+ * Convers the row to a text representation.
+ */
+ toText() {
+ if (this._cells.length === 0) {
+ return this.marginLeft;
+ }
+ const cells = this._cells.map((cell) => cell.toText()).join('|');
+ return `${this.marginLeft}|${cells}|${this.marginRight}`;
+ }
+ /**
+ * Checks if the row is a delimiter or not.
+ *
+ * @returns `true` if the row is a delimiter i.e. all the cells contained are delimiters.
+ */
+ isDelimiter() {
+ return this._cells.every((cell) => cell.isDelimiter());
+ }
+}
+exports.TableRow = TableRow;
+});
+
+var neverthrow = createCommonjsModule(function (module, exports) {
+/**
+ * Retrieved from
+ * https://github.com/supermacro/neverthrow
+ *
+ * MIT License
+ * Copyright (c) 2019 Giorgio Delgado
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Err = exports.Ok = exports.err = exports.ok = void 0;
+const ok = (value) => new Ok(value);
+exports.ok = ok;
+const err = (err) => new Err(err);
+exports.err = err;
+class Ok {
+ constructor(value) {
+ this.value = value;
+ this.match = (ok, _err) => ok(this.value);
+ }
+ isOk() {
+ return true;
+ }
+ isErr() {
+ return !this.isOk();
+ }
+ map(f) {
+ return exports.ok(f(this.value));
+ }
+ mapErr(_f) {
+ return exports.ok(this.value);
+ }
+ // add info on how this is really useful for converting a
+ // Result, E1>
+ // into a Result
+ andThen(f) {
+ return f(this.value);
+ }
+ unwrapOr(_v) {
+ return this.value;
+ }
+ _unsafeUnwrap() {
+ return this.value;
+ }
+ _unsafeUnwrapErr() {
+ throw new Error('Called `_unsafeUnwrapErr` on an Ok');
+ }
+}
+exports.Ok = Ok;
+class Err {
+ constructor(error) {
+ this.error = error;
+ this.match = (_ok, err) => err(this.error);
+ }
+ isOk() {
+ return false;
+ }
+ isErr() {
+ return !this.isOk();
+ }
+ map(_f) {
+ return exports.err(this.error);
+ }
+ mapErr(f) {
+ return exports.err(f(this.error));
+ }
+ andThen(_f) {
+ return exports.err(this.error);
+ }
+ unwrapOr(v) {
+ return v;
+ }
+ _unsafeUnwrap() {
+ throw new Error('Called `_unsafeUnwrap` on an Err');
+ }
+ _unsafeUnwrapErr() {
+ return this.error;
+ }
+}
+exports.Err = Err;
+});
+
+var ast_utils = createCommonjsModule(function (module, exports) {
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.prettyPrintAST = exports.checkChildLength = exports.checkType = exports.errRelativeReferenceIndex = exports.errIndex0 = void 0;
+exports.errIndex0 = new Error('Index 0 used to create a reference');
+exports.errRelativeReferenceIndex = new Error('Can not use relative reference where absolute reference is required');
+const checkType = (ast, ...expectedTypes) => {
+ if (expectedTypes.indexOf(ast.type) >= 0) {
+ return;
+ }
+ return new Error(`Formula element '${ast.text}' is a ${ast.type} but expected ` +
+ `one of ${expectedTypes} in this position.`);
+};
+exports.checkType = checkType;
+const checkChildLength = (ast, len) => {
+ if (ast.children.length === len) {
+ return;
+ }
+ return new Error(`Formula element '${ast.text}' was expected to have ${len} ` +
+ `elements, but had ${ast.children.length}`);
+};
+exports.checkChildLength = checkChildLength;
+const prettyPrintAST = (token, level = 0) => {
+ console.log(' '.repeat(level) +
+ `|-${token.type}${token.children.length === 0 ? '=' + token.text : ''}`);
+ if (token.children) {
+ token.children.forEach((c) => {
+ exports.prettyPrintAST(c, level + 1);
+ });
+ }
+};
+exports.prettyPrintAST = prettyPrintAST;
+});
+
+var lodash = createCommonjsModule(function (module, exports) {
+(function() {
+
+ /** Used as a safe reference for `undefined` in pre-ES5 environments. */
+ var undefined$1;
+
+ /** Used as the semantic version number. */
+ var VERSION = '4.17.20';
+
+ /** Used as the size to enable large array optimizations. */
+ var LARGE_ARRAY_SIZE = 200;
+
+ /** Error message constants. */
+ var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
+ FUNC_ERROR_TEXT = 'Expected a function';
+
+ /** Used to stand-in for `undefined` hash values. */
+ var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+ /** Used as the maximum memoize cache size. */
+ var MAX_MEMOIZE_SIZE = 500;
+
+ /** Used as the internal argument placeholder. */
+ var PLACEHOLDER = '__lodash_placeholder__';
+
+ /** Used to compose bitmasks for cloning. */
+ var CLONE_DEEP_FLAG = 1,
+ CLONE_FLAT_FLAG = 2,
+ CLONE_SYMBOLS_FLAG = 4;
+
+ /** Used to compose bitmasks for value comparisons. */
+ var COMPARE_PARTIAL_FLAG = 1,
+ COMPARE_UNORDERED_FLAG = 2;
+
+ /** Used to compose bitmasks for function metadata. */
+ var WRAP_BIND_FLAG = 1,
+ WRAP_BIND_KEY_FLAG = 2,
+ WRAP_CURRY_BOUND_FLAG = 4,
+ WRAP_CURRY_FLAG = 8,
+ WRAP_CURRY_RIGHT_FLAG = 16,
+ WRAP_PARTIAL_FLAG = 32,
+ WRAP_PARTIAL_RIGHT_FLAG = 64,
+ WRAP_ARY_FLAG = 128,
+ WRAP_REARG_FLAG = 256,
+ WRAP_FLIP_FLAG = 512;
+
+ /** Used as default options for `_.truncate`. */
+ var DEFAULT_TRUNC_LENGTH = 30,
+ DEFAULT_TRUNC_OMISSION = '...';
+
+ /** Used to detect hot functions by number of calls within a span of milliseconds. */
+ var HOT_COUNT = 800,
+ HOT_SPAN = 16;
+
+ /** Used to indicate the type of lazy iteratees. */
+ var LAZY_FILTER_FLAG = 1,
+ LAZY_MAP_FLAG = 2,
+ LAZY_WHILE_FLAG = 3;
+
+ /** Used as references for various `Number` constants. */
+ var INFINITY = 1 / 0,
+ MAX_SAFE_INTEGER = 9007199254740991,
+ MAX_INTEGER = 1.7976931348623157e+308,
+ NAN = 0 / 0;
+
+ /** Used as references for the maximum length and index of an array. */
+ var MAX_ARRAY_LENGTH = 4294967295,
+ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
+ HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+
+ /** Used to associate wrap methods with their bit flags. */
+ var wrapFlags = [
+ ['ary', WRAP_ARY_FLAG],
+ ['bind', WRAP_BIND_FLAG],
+ ['bindKey', WRAP_BIND_KEY_FLAG],
+ ['curry', WRAP_CURRY_FLAG],
+ ['curryRight', WRAP_CURRY_RIGHT_FLAG],
+ ['flip', WRAP_FLIP_FLAG],
+ ['partial', WRAP_PARTIAL_FLAG],
+ ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
+ ['rearg', WRAP_REARG_FLAG]
+ ];
+
+ /** `Object#toString` result references. */
+ var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ asyncTag = '[object AsyncFunction]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ domExcTag = '[object DOMException]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ nullTag = '[object Null]',
+ objectTag = '[object Object]',
+ promiseTag = '[object Promise]',
+ proxyTag = '[object Proxy]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]',
+ undefinedTag = '[object Undefined]',
+ weakMapTag = '[object WeakMap]',
+ weakSetTag = '[object WeakSet]';
+
+ var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+ /** Used to match empty string literals in compiled template source. */
+ var reEmptyStringLeading = /\b__p \+= '';/g,
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+ /** Used to match HTML entities and HTML characters. */
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
+ reUnescapedHtml = /[&<>"']/g,
+ reHasEscapedHtml = RegExp(reEscapedHtml.source),
+ reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+
+ /** Used to match template delimiters. */
+ var reEscape = /<%-([\s\S]+?)%>/g,
+ reEvaluate = /<%([\s\S]+?)%>/g,
+ reInterpolate = /<%=([\s\S]+?)%>/g;
+
+ /** Used to match property names within property paths. */
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
+ reIsPlainProp = /^\w*$/,
+ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
+
+ /**
+ * Used to match `RegExp`
+ * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
+ */
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
+ reHasRegExpChar = RegExp(reRegExpChar.source);
+
+ /** Used to match leading and trailing whitespace. */
+ var reTrim = /^\s+|\s+$/g,
+ reTrimStart = /^\s+/,
+ reTrimEnd = /\s+$/;
+
+ /** Used to match wrap detail comments. */
+ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
+ reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
+ reSplitDetails = /,? & /;
+
+ /** Used to match words composed of alphanumeric characters. */
+ var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
+
+ /** Used to match backslashes in property paths. */
+ var reEscapeChar = /\\(\\)?/g;
+
+ /**
+ * Used to match
+ * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
+ */
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+ /** Used to match `RegExp` flags from their coerced string values. */
+ var reFlags = /\w*$/;
+
+ /** Used to detect bad signed hexadecimal string values. */
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+ /** Used to detect binary string values. */
+ var reIsBinary = /^0b[01]+$/i;
+
+ /** Used to detect host constructors (Safari). */
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+ /** Used to detect octal string values. */
+ var reIsOctal = /^0o[0-7]+$/i;
+
+ /** Used to detect unsigned integer values. */
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
+
+ /** Used to match Latin Unicode letters (excluding mathematical operators). */
+ var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
+
+ /** Used to ensure capturing order of template delimiters. */
+ var reNoMatch = /($^)/;
+
+ /** Used to match unescaped characters in compiled string literals. */
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+
+ /** Used to compose unicode character classes. */
+ var rsAstralRange = '\\ud800-\\udfff',
+ rsComboMarksRange = '\\u0300-\\u036f',
+ reComboHalfMarksRange = '\\ufe20-\\ufe2f',
+ rsComboSymbolsRange = '\\u20d0-\\u20ff',
+ rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
+ rsDingbatRange = '\\u2700-\\u27bf',
+ rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
+ rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
+ rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
+ rsPunctuationRange = '\\u2000-\\u206f',
+ rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
+ rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
+ rsVarRange = '\\ufe0e\\ufe0f',
+ rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
+
+ /** Used to compose unicode capture groups. */
+ var rsApos = "['\u2019]",
+ rsAstral = '[' + rsAstralRange + ']',
+ rsBreak = '[' + rsBreakRange + ']',
+ rsCombo = '[' + rsComboRange + ']',
+ rsDigits = '\\d+',
+ rsDingbat = '[' + rsDingbatRange + ']',
+ rsLower = '[' + rsLowerRange + ']',
+ rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
+ rsFitz = '\\ud83c[\\udffb-\\udfff]',
+ rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
+ rsNonAstral = '[^' + rsAstralRange + ']',
+ rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
+ rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
+ rsUpper = '[' + rsUpperRange + ']',
+ rsZWJ = '\\u200d';
+
+ /** Used to compose unicode regexes. */
+ var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
+ rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
+ rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
+ rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
+ reOptMod = rsModifier + '?',
+ rsOptVar = '[' + rsVarRange + ']?',
+ rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
+ rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
+ rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
+ rsSeq = rsOptVar + reOptMod + rsOptJoin,
+ rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
+ rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
+
+ /** Used to match apostrophes. */
+ var reApos = RegExp(rsApos, 'g');
+
+ /**
+ * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
+ * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
+ */
+ var reComboMark = RegExp(rsCombo, 'g');
+
+ /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
+ var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
+
+ /** Used to match complex or compound words. */
+ var reUnicodeWord = RegExp([
+ rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
+ rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
+ rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
+ rsUpper + '+' + rsOptContrUpper,
+ rsOrdUpper,
+ rsOrdLower,
+ rsDigits,
+ rsEmoji
+ ].join('|'), 'g');
+
+ /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
+ var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
+
+ /** Used to detect strings that need a more robust regexp to match words. */
+ var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
+
+ /** Used to assign default `context` object properties. */
+ var contextProps = [
+ 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
+ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
+ 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
+ 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
+ '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
+ ];
+
+ /** Used to make template sourceURLs easier to identify. */
+ var templateCounter = -1;
+
+ /** Used to identify `toStringTag` values of typed arrays. */
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+ typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+ typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
+ typedArrayTags[errorTag] = typedArrayTags[funcTag] =
+ typedArrayTags[mapTag] = typedArrayTags[numberTag] =
+ typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
+ typedArrayTags[setTag] = typedArrayTags[stringTag] =
+ typedArrayTags[weakMapTag] = false;
+
+ /** Used to identify `toStringTag` values supported by `_.clone`. */
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] =
+ cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
+ cloneableTags[boolTag] = cloneableTags[dateTag] =
+ cloneableTags[float32Tag] = cloneableTags[float64Tag] =
+ cloneableTags[int8Tag] = cloneableTags[int16Tag] =
+ cloneableTags[int32Tag] = cloneableTags[mapTag] =
+ cloneableTags[numberTag] = cloneableTags[objectTag] =
+ cloneableTags[regexpTag] = cloneableTags[setTag] =
+ cloneableTags[stringTag] = cloneableTags[symbolTag] =
+ cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+ cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] =
+ cloneableTags[weakMapTag] = false;
+
+ /** Used to map Latin Unicode letters to basic Latin letters. */
+ var deburredLetters = {
+ // Latin-1 Supplement block.
+ '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+ '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+ '\xc7': 'C', '\xe7': 'c',
+ '\xd0': 'D', '\xf0': 'd',
+ '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+ '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+ '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+ '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
+ '\xd1': 'N', '\xf1': 'n',
+ '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+ '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+ '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+ '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
+ '\xc6': 'Ae', '\xe6': 'ae',
+ '\xde': 'Th', '\xfe': 'th',
+ '\xdf': 'ss',
+ // Latin Extended-A block.
+ '\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
+ '\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
+ '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
+ '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
+ '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
+ '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
+ '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
+ '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
+ '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
+ '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
+ '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
+ '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
+ '\u0134': 'J', '\u0135': 'j',
+ '\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
+ '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
+ '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
+ '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
+ '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
+ '\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
+ '\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
+ '\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
+ '\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
+ '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
+ '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
+ '\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
+ '\u0163': 't', '\u0165': 't', '\u0167': 't',
+ '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
+ '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
+ '\u0174': 'W', '\u0175': 'w',
+ '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
+ '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
+ '\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
+ '\u0132': 'IJ', '\u0133': 'ij',
+ '\u0152': 'Oe', '\u0153': 'oe',
+ '\u0149': "'n", '\u017f': 's'
+ };
+
+ /** Used to map characters to HTML entities. */
+ var htmlEscapes = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+
+ /** Used to map HTML entities to characters. */
+ var htmlUnescapes = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ ''': "'"
+ };
+
+ /** Used to escape characters for inclusion in compiled string literals. */
+ var stringEscapes = {
+ '\\': '\\',
+ "'": "'",
+ '\n': 'n',
+ '\r': 'r',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ /** Built-in method references without a dependency on `root`. */
+ var freeParseFloat = parseFloat,
+ freeParseInt = parseInt;
+
+ /** Detect free variable `global` from Node.js. */
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
+
+ /** Detect free variable `self`. */
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
+
+ /** Used as a reference to the global object. */
+ var root = freeGlobal || freeSelf || Function('return this')();
+
+ /** Detect free variable `exports`. */
+ var freeExports = exports && !exports.nodeType && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
+
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = freeModule && freeModule.exports === freeExports;
+
+ /** Detect free variable `process` from Node.js. */
+ var freeProcess = moduleExports && freeGlobal.process;
+
+ /** Used to access faster Node.js helpers. */
+ var nodeUtil = (function() {
+ try {
+ // Use `util.types` for Node.js 10+.
+ var types = freeModule && freeModule.require && freeModule.require('util').types;
+
+ if (types) {
+ return types;
+ }
+
+ // Legacy `process.binding('util')` for Node.js < 10.
+ return freeProcess && freeProcess.binding && freeProcess.binding('util');
+ } catch (e) {}
+ }());
+
+ /* Node.js helper references. */
+ var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
+ nodeIsDate = nodeUtil && nodeUtil.isDate,
+ nodeIsMap = nodeUtil && nodeUtil.isMap,
+ nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
+ nodeIsSet = nodeUtil && nodeUtil.isSet,
+ nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * A faster alternative to `Function#apply`, this function invokes `func`
+ * with the `this` binding of `thisArg` and the arguments of `args`.
+ *
+ * @private
+ * @param {Function} func The function to invoke.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} args The arguments to invoke `func` with.
+ * @returns {*} Returns the result of `func`.
+ */
+ function apply(func, thisArg, args) {
+ switch (args.length) {
+ case 0: return func.call(thisArg);
+ case 1: return func.call(thisArg, args[0]);
+ case 2: return func.call(thisArg, args[0], args[1]);
+ case 3: return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+ }
+
+ /**
+ * A specialized version of `baseAggregator` for arrays.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function arrayAggregator(array, setter, iteratee, accumulator) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ var value = array[index];
+ setter(accumulator, value, iteratee(value), array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.forEach` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.every` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `_.filter` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.includes` for arrays without support for
+ * specifying an index to search from.
+ *
+ * @private
+ * @param {Array} [array] The array to inspect.
+ * @param {*} target The value to search for.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+ function arrayIncludes(array, value) {
+ var length = array == null ? 0 : array.length;
+ return !!length && baseIndexOf(array, value, 0) > -1;
+ }
+
+ /**
+ * This function is like `arrayIncludes` except that it accepts a comparator.
+ *
+ * @private
+ * @param {Array} [array] The array to inspect.
+ * @param {*} target The value to search for.
+ * @param {Function} comparator The comparator invoked per element.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+ function arrayIncludesWith(array, value, comparator) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (comparator(value, array[index])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `_.map` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+
+ /**
+ * Appends the elements of `values` to `array`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to append.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayPush(array, values) {
+ var index = -1,
+ length = values.length,
+ offset = array.length;
+
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.reduce` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the first element of `array` as
+ * the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the last element of `array` as
+ * the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initAccum) {
+ var length = array == null ? 0 : array.length;
+ if (initAccum && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.some` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the size of an ASCII `string`.
+ *
+ * @private
+ * @param {string} string The string inspect.
+ * @returns {number} Returns the string size.
+ */
+ var asciiSize = baseProperty('length');
+
+ /**
+ * Converts an ASCII `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function asciiToArray(string) {
+ return string.split('');
+ }
+
+ /**
+ * Splits an ASCII `string` into an array of its words.
+ *
+ * @private
+ * @param {string} The string to inspect.
+ * @returns {Array} Returns the words of `string`.
+ */
+ function asciiWords(string) {
+ return string.match(reAsciiWord) || [];
+ }
+
+ /**
+ * The base implementation of methods like `_.findKey` and `_.findLastKey`,
+ * without support for iteratee shorthands, which iterates over `collection`
+ * using `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the found element or its key, else `undefined`.
+ */
+ function baseFindKey(collection, predicate, eachFunc) {
+ var result;
+ eachFunc(collection, function(value, key, collection) {
+ if (predicate(value, key, collection)) {
+ result = key;
+ return false;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseFindIndex(array, predicate, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 1 : -1);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOf(array, value, fromIndex) {
+ return value === value
+ ? strictIndexOf(array, value, fromIndex)
+ : baseFindIndex(array, baseIsNaN, fromIndex);
+ }
+
+ /**
+ * This function is like `baseIndexOf` except that it accepts a comparator.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @param {Function} comparator The comparator invoked per element.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOfWith(array, value, fromIndex, comparator) {
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (comparator(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.isNaN` without support for number objects.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ */
+ function baseIsNaN(value) {
+ return value !== value;
+ }
+
+ /**
+ * The base implementation of `_.mean` and `_.meanBy` without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the mean.
+ */
+ function baseMean(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+ return length ? (baseSum(array, iteratee) / length) : NAN;
+ }
+
+ /**
+ * The base implementation of `_.property` without support for deep paths.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ */
+ function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined$1 : object[key];
+ };
+ }
+
+ /**
+ * The base implementation of `_.propertyOf` without support for deep paths.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Function} Returns the new accessor function.
+ */
+ function basePropertyOf(object) {
+ return function(key) {
+ return object == null ? undefined$1 : object[key];
+ };
+ }
+
+ /**
+ * The base implementation of `_.reduce` and `_.reduceRight`, without support
+ * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} accumulator The initial value.
+ * @param {boolean} initAccum Specify using the first or last element of
+ * `collection` as the initial value.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the accumulated value.
+ */
+ function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
+ eachFunc(collection, function(value, index, collection) {
+ accumulator = initAccum
+ ? (initAccum = false, value)
+ : iteratee(accumulator, value, index, collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.sortBy` which uses `comparer` to define the
+ * sort order of `array` and replaces criteria objects with their corresponding
+ * values.
+ *
+ * @private
+ * @param {Array} array The array to sort.
+ * @param {Function} comparer The function to define sort order.
+ * @returns {Array} Returns `array`.
+ */
+ function baseSortBy(array, comparer) {
+ var length = array.length;
+
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.sum` and `_.sumBy` without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the sum.
+ */
+ function baseSum(array, iteratee) {
+ var result,
+ index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var current = iteratee(array[index]);
+ if (current !== undefined$1) {
+ result = result === undefined$1 ? current : (result + current);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.times` without support for iteratee shorthands
+ * or max array length checks.
+ *
+ * @private
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ */
+ function baseTimes(n, iteratee) {
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
+ * of key-value pairs for `object` corresponding to the property names of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the key-value pairs.
+ */
+ function baseToPairs(object, props) {
+ return arrayMap(props, function(key) {
+ return [key, object[key]];
+ });
+ }
+
+ /**
+ * The base implementation of `_.unary` without support for storing metadata.
+ *
+ * @private
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new capped function.
+ */
+ function baseUnary(func) {
+ return function(value) {
+ return func(value);
+ };
+ }
+
+ /**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+ function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+ }
+
+ /**
+ * Checks if a `cache` value for `key` exists.
+ *
+ * @private
+ * @param {Object} cache The cache to query.
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function cacheHas(cache, key) {
+ return cache.has(key);
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
+ * that is not found in the character symbols.
+ *
+ * @private
+ * @param {Array} strSymbols The string symbols to inspect.
+ * @param {Array} chrSymbols The character symbols to find.
+ * @returns {number} Returns the index of the first unmatched string symbol.
+ */
+ function charsStartIndex(strSymbols, chrSymbols) {
+ var index = -1,
+ length = strSymbols.length;
+
+ while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
+ * that is not found in the character symbols.
+ *
+ * @private
+ * @param {Array} strSymbols The string symbols to inspect.
+ * @param {Array} chrSymbols The character symbols to find.
+ * @returns {number} Returns the index of the last unmatched string symbol.
+ */
+ function charsEndIndex(strSymbols, chrSymbols) {
+ var index = strSymbols.length;
+
+ while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
+ return index;
+ }
+
+ /**
+ * Gets the number of `placeholder` occurrences in `array`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} placeholder The placeholder to search for.
+ * @returns {number} Returns the placeholder count.
+ */
+ function countHolders(array, placeholder) {
+ var length = array.length,
+ result = 0;
+
+ while (length--) {
+ if (array[length] === placeholder) {
+ ++result;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
+ * letters to basic Latin letters.
+ *
+ * @private
+ * @param {string} letter The matched letter to deburr.
+ * @returns {string} Returns the deburred letter.
+ */
+ var deburrLetter = basePropertyOf(deburredLetters);
+
+ /**
+ * Used by `_.escape` to convert characters to HTML entities.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ var escapeHtmlChar = basePropertyOf(htmlEscapes);
+
+ /**
+ * Used by `_.template` to escape characters for inclusion in compiled string literals.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeStringChar(chr) {
+ return '\\' + stringEscapes[chr];
+ }
+
+ /**
+ * Gets the value at `key` of `object`.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {string} key The key of the property to get.
+ * @returns {*} Returns the property value.
+ */
+ function getValue(object, key) {
+ return object == null ? undefined$1 : object[key];
+ }
+
+ /**
+ * Checks if `string` contains Unicode symbols.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {boolean} Returns `true` if a symbol is found, else `false`.
+ */
+ function hasUnicode(string) {
+ return reHasUnicode.test(string);
+ }
+
+ /**
+ * Checks if `string` contains a word composed of Unicode symbols.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {boolean} Returns `true` if a word is found, else `false`.
+ */
+ function hasUnicodeWord(string) {
+ return reHasUnicodeWord.test(string);
+ }
+
+ /**
+ * Converts `iterator` to an array.
+ *
+ * @private
+ * @param {Object} iterator The iterator to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function iteratorToArray(iterator) {
+ var data,
+ result = [];
+
+ while (!(data = iterator.next()).done) {
+ result.push(data.value);
+ }
+ return result;
+ }
+
+ /**
+ * Converts `map` to its key-value pairs.
+ *
+ * @private
+ * @param {Object} map The map to convert.
+ * @returns {Array} Returns the key-value pairs.
+ */
+ function mapToArray(map) {
+ var index = -1,
+ result = Array(map.size);
+
+ map.forEach(function(value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+ }
+
+ /**
+ * Creates a unary function that invokes `func` with its argument transformed.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {Function} transform The argument transform.
+ * @returns {Function} Returns the new function.
+ */
+ function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+ }
+
+ /**
+ * Replaces all `placeholder` elements in `array` with an internal placeholder
+ * and returns an array of their indexes.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {*} placeholder The placeholder to replace.
+ * @returns {Array} Returns the new array of placeholder indexes.
+ */
+ function replaceHolders(array, placeholder) {
+ var index = -1,
+ length = array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value === placeholder || value === PLACEHOLDER) {
+ array[index] = PLACEHOLDER;
+ result[resIndex++] = index;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts `set` to an array of its values.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the values.
+ */
+ function setToArray(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function(value) {
+ result[++index] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Converts `set` to its value-value pairs.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the value-value pairs.
+ */
+ function setToPairs(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function(value) {
+ result[++index] = [value, value];
+ });
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.indexOf` which performs strict equality
+ * comparisons of values, i.e. `===`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function strictIndexOf(array, value, fromIndex) {
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * A specialized version of `_.lastIndexOf` which performs strict equality
+ * comparisons of values, i.e. `===`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function strictLastIndexOf(array, value, fromIndex) {
+ var index = fromIndex + 1;
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Gets the number of symbols in `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the string size.
+ */
+ function stringSize(string) {
+ return hasUnicode(string)
+ ? unicodeSize(string)
+ : asciiSize(string);
+ }
+
+ /**
+ * Converts `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function stringToArray(string) {
+ return hasUnicode(string)
+ ? unicodeToArray(string)
+ : asciiToArray(string);
+ }
+
+ /**
+ * Used by `_.unescape` to convert HTML entities to characters.
+ *
+ * @private
+ * @param {string} chr The matched character to unescape.
+ * @returns {string} Returns the unescaped character.
+ */
+ var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
+
+ /**
+ * Gets the size of a Unicode `string`.
+ *
+ * @private
+ * @param {string} string The string inspect.
+ * @returns {number} Returns the string size.
+ */
+ function unicodeSize(string) {
+ var result = reUnicode.lastIndex = 0;
+ while (reUnicode.test(string)) {
+ ++result;
+ }
+ return result;
+ }
+
+ /**
+ * Converts a Unicode `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function unicodeToArray(string) {
+ return string.match(reUnicode) || [];
+ }
+
+ /**
+ * Splits a Unicode `string` into an array of its words.
+ *
+ * @private
+ * @param {string} The string to inspect.
+ * @returns {Array} Returns the words of `string`.
+ */
+ function unicodeWords(string) {
+ return string.match(reUnicodeWord) || [];
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Create a new pristine `lodash` function using the `context` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Util
+ * @param {Object} [context=root] The context object.
+ * @returns {Function} Returns a new `lodash` function.
+ * @example
+ *
+ * _.mixin({ 'foo': _.constant('foo') });
+ *
+ * var lodash = _.runInContext();
+ * lodash.mixin({ 'bar': lodash.constant('bar') });
+ *
+ * _.isFunction(_.foo);
+ * // => true
+ * _.isFunction(_.bar);
+ * // => false
+ *
+ * lodash.isFunction(lodash.foo);
+ * // => false
+ * lodash.isFunction(lodash.bar);
+ * // => true
+ *
+ * // Create a suped-up `defer` in Node.js.
+ * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
+ */
+ var runInContext = (function runInContext(context) {
+ context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
+
+ /** Built-in constructor references. */
+ var Array = context.Array,
+ Date = context.Date,
+ Error = context.Error,
+ Function = context.Function,
+ Math = context.Math,
+ Object = context.Object,
+ RegExp = context.RegExp,
+ String = context.String,
+ TypeError = context.TypeError;
+
+ /** Used for built-in method references. */
+ var arrayProto = Array.prototype,
+ funcProto = Function.prototype,
+ objectProto = Object.prototype;
+
+ /** Used to detect overreaching core-js shims. */
+ var coreJsData = context['__core-js_shared__'];
+
+ /** Used to resolve the decompiled source of functions. */
+ var funcToString = funcProto.toString;
+
+ /** Used to check objects for own properties. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to generate unique IDs. */
+ var idCounter = 0;
+
+ /** Used to detect methods masquerading as native. */
+ var maskSrcKey = (function() {
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
+ return uid ? ('Symbol(src)_1.' + uid) : '';
+ }());
+
+ /**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+ var nativeObjectToString = objectProto.toString;
+
+ /** Used to infer the `Object` constructor. */
+ var objectCtorString = funcToString.call(Object);
+
+ /** Used to restore the original `_` reference in `_.noConflict`. */
+ var oldDash = root._;
+
+ /** Used to detect if a method is native. */
+ var reIsNative = RegExp('^' +
+ funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+ );
+
+ /** Built-in value references. */
+ var Buffer = moduleExports ? context.Buffer : undefined$1,
+ Symbol = context.Symbol,
+ Uint8Array = context.Uint8Array,
+ allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined$1,
+ getPrototype = overArg(Object.getPrototypeOf, Object),
+ objectCreate = Object.create,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
+ splice = arrayProto.splice,
+ spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined$1,
+ symIterator = Symbol ? Symbol.iterator : undefined$1,
+ symToStringTag = Symbol ? Symbol.toStringTag : undefined$1;
+
+ var defineProperty = (function() {
+ try {
+ var func = getNative(Object, 'defineProperty');
+ func({}, '', {});
+ return func;
+ } catch (e) {}
+ }());
+
+ /** Mocked built-ins. */
+ var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
+ ctxNow = Date && Date.now !== root.Date.now && Date.now,
+ ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
+
+ /* Built-in method references for those with the same name as other `lodash` methods. */
+ var nativeCeil = Math.ceil,
+ nativeFloor = Math.floor,
+ nativeGetSymbols = Object.getOwnPropertySymbols,
+ nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined$1,
+ nativeIsFinite = context.isFinite,
+ nativeJoin = arrayProto.join,
+ nativeKeys = overArg(Object.keys, Object),
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeNow = Date.now,
+ nativeParseInt = context.parseInt,
+ nativeRandom = Math.random,
+ nativeReverse = arrayProto.reverse;
+
+ /* Built-in method references that are verified to be native. */
+ var DataView = getNative(context, 'DataView'),
+ Map = getNative(context, 'Map'),
+ Promise = getNative(context, 'Promise'),
+ Set = getNative(context, 'Set'),
+ WeakMap = getNative(context, 'WeakMap'),
+ nativeCreate = getNative(Object, 'create');
+
+ /** Used to store function metadata. */
+ var metaMap = WeakMap && new WeakMap;
+
+ /** Used to lookup unminified function names. */
+ var realNames = {};
+
+ /** Used to detect maps, sets, and weakmaps. */
+ var dataViewCtorString = toSource(DataView),
+ mapCtorString = toSource(Map),
+ promiseCtorString = toSource(Promise),
+ setCtorString = toSource(Set),
+ weakMapCtorString = toSource(WeakMap);
+
+ /** Used to convert symbols to primitives and strings. */
+ var symbolProto = Symbol ? Symbol.prototype : undefined$1,
+ symbolValueOf = symbolProto ? symbolProto.valueOf : undefined$1,
+ symbolToString = symbolProto ? symbolProto.toString : undefined$1;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` object which wraps `value` to enable implicit method
+ * chain sequences. Methods that operate on and return arrays, collections,
+ * and functions can be chained together. Methods that retrieve a single value
+ * or may return a primitive value will automatically end the chain sequence
+ * and return the unwrapped value. Otherwise, the value must be unwrapped
+ * with `_#value`.
+ *
+ * Explicit chain sequences, which must be unwrapped with `_#value`, may be
+ * enabled using `_.chain`.
+ *
+ * The execution of chained methods is lazy, that is, it's deferred until
+ * `_#value` is implicitly or explicitly called.
+ *
+ * Lazy evaluation allows several methods to support shortcut fusion.
+ * Shortcut fusion is an optimization to merge iteratee calls; this avoids
+ * the creation of intermediate arrays and can greatly reduce the number of
+ * iteratee executions. Sections of a chain sequence qualify for shortcut
+ * fusion if the section is applied to an array and iteratees accept only
+ * one argument. The heuristic for whether a section qualifies for shortcut
+ * fusion is subject to change.
+ *
+ * Chaining is supported in custom builds as long as the `_#value` method is
+ * directly or indirectly included in the build.
+ *
+ * In addition to lodash methods, wrappers have `Array` and `String` methods.
+ *
+ * The wrapper `Array` methods are:
+ * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
+ *
+ * The wrapper `String` methods are:
+ * `replace` and `split`
+ *
+ * The wrapper methods that support shortcut fusion are:
+ * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
+ * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
+ * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
+ *
+ * The chainable wrapper methods are:
+ * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
+ * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
+ * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
+ * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
+ * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
+ * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
+ * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
+ * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
+ * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
+ * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
+ * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
+ * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
+ * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
+ * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
+ * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
+ * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
+ * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
+ * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
+ * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
+ * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
+ * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
+ * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
+ * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
+ * `zipObject`, `zipObjectDeep`, and `zipWith`
+ *
+ * The wrapper methods that are **not** chainable by default are:
+ * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
+ * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
+ * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
+ * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
+ * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
+ * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
+ * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
+ * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
+ * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
+ * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
+ * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
+ * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
+ * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
+ * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
+ * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
+ * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
+ * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
+ * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
+ * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
+ * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
+ * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
+ * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
+ * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
+ * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
+ * `upperFirst`, `value`, and `words`
+ *
+ * @name _
+ * @constructor
+ * @category Seq
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var wrapped = _([1, 2, 3]);
+ *
+ * // Returns an unwrapped value.
+ * wrapped.reduce(_.add);
+ * // => 6
+ *
+ * // Returns a wrapped value.
+ * var squares = wrapped.map(square);
+ *
+ * _.isArray(squares);
+ * // => false
+ *
+ * _.isArray(squares.value());
+ * // => true
+ */
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, '__wrapped__')) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
+ }
+
+ /**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} proto The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+ var baseCreate = (function() {
+ function object() {}
+ return function(proto) {
+ if (!isObject(proto)) {
+ return {};
+ }
+ if (objectCreate) {
+ return objectCreate(proto);
+ }
+ object.prototype = proto;
+ var result = new object;
+ object.prototype = undefined$1;
+ return result;
+ };
+ }());
+
+ /**
+ * The function whose prototype chain sequence wrappers inherit from.
+ *
+ * @private
+ */
+ function baseLodash() {
+ // No operation performed.
+ }
+
+ /**
+ * The base constructor for creating `lodash` wrapper objects.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ * @param {boolean} [chainAll] Enable explicit method chain sequences.
+ */
+ function LodashWrapper(value, chainAll) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__chain__ = !!chainAll;
+ this.__index__ = 0;
+ this.__values__ = undefined$1;
+ }
+
+ /**
+ * By default, the template delimiters used by lodash are like those in
+ * embedded Ruby (ERB) as well as ES2015 template strings. Change the
+ * following template settings to use alternative delimiters.
+ *
+ * @static
+ * @memberOf _
+ * @type {Object}
+ */
+ lodash.templateSettings = {
+
+ /**
+ * Used to detect `data` property values to be HTML-escaped.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'escape': reEscape,
+
+ /**
+ * Used to detect code to be evaluated.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'evaluate': reEvaluate,
+
+ /**
+ * Used to detect `data` property values to inject.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'interpolate': reInterpolate,
+
+ /**
+ * Used to reference the data object in the template text.
+ *
+ * @memberOf _.templateSettings
+ * @type {string}
+ */
+ 'variable': '',
+
+ /**
+ * Used to import variables into the compiled template.
+ *
+ * @memberOf _.templateSettings
+ * @type {Object}
+ */
+ 'imports': {
+
+ /**
+ * A reference to the `lodash` function.
+ *
+ * @memberOf _.templateSettings.imports
+ * @type {Function}
+ */
+ '_': lodash
+ }
+ };
+
+ // Ensure wrappers are instances of `baseLodash`.
+ lodash.prototype = baseLodash.prototype;
+ lodash.prototype.constructor = lodash;
+
+ LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+ LodashWrapper.prototype.constructor = LodashWrapper;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+ *
+ * @private
+ * @constructor
+ * @param {*} value The value to wrap.
+ */
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__dir__ = 1;
+ this.__filtered__ = false;
+ this.__iteratees__ = [];
+ this.__takeCount__ = MAX_ARRAY_LENGTH;
+ this.__views__ = [];
+ }
+
+ /**
+ * Creates a clone of the lazy wrapper object.
+ *
+ * @private
+ * @name clone
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the cloned `LazyWrapper` object.
+ */
+ function lazyClone() {
+ var result = new LazyWrapper(this.__wrapped__);
+ result.__actions__ = copyArray(this.__actions__);
+ result.__dir__ = this.__dir__;
+ result.__filtered__ = this.__filtered__;
+ result.__iteratees__ = copyArray(this.__iteratees__);
+ result.__takeCount__ = this.__takeCount__;
+ result.__views__ = copyArray(this.__views__);
+ return result;
+ }
+
+ /**
+ * Reverses the direction of lazy iteration.
+ *
+ * @private
+ * @name reverse
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the new reversed `LazyWrapper` object.
+ */
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result = new LazyWrapper(this);
+ result.__dir__ = -1;
+ result.__filtered__ = true;
+ } else {
+ result = this.clone();
+ result.__dir__ *= -1;
+ }
+ return result;
+ }
+
+ /**
+ * Extracts the unwrapped value from its lazy wrapper.
+ *
+ * @private
+ * @name value
+ * @memberOf LazyWrapper
+ * @returns {*} Returns the unwrapped value.
+ */
+ function lazyValue() {
+ var array = this.__wrapped__.value(),
+ dir = this.__dir__,
+ isArr = isArray(array),
+ isRight = dir < 0,
+ arrLength = isArr ? array.length : 0,
+ view = getView(0, arrLength, this.__views__),
+ start = view.start,
+ end = view.end,
+ length = end - start,
+ index = isRight ? end : (start - 1),
+ iteratees = this.__iteratees__,
+ iterLength = iteratees.length,
+ resIndex = 0,
+ takeCount = nativeMin(length, this.__takeCount__);
+
+ if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
+ return baseWrapperValue(array, this.__actions__);
+ }
+ var result = [];
+
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
+
+ var iterIndex = -1,
+ value = array[index];
+
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex],
+ iteratee = data.iteratee,
+ type = data.type,
+ computed = iteratee(value);
+
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ result[resIndex++] = value;
+ }
+ return result;
+ }
+
+ // Ensure `LazyWrapper` is an instance of `baseLodash`.
+ LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+ LazyWrapper.prototype.constructor = LazyWrapper;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a hash object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function Hash(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the hash.
+ *
+ * @private
+ * @name clear
+ * @memberOf Hash
+ */
+ function hashClear() {
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
+ this.size = 0;
+ }
+
+ /**
+ * Removes `key` and its value from the hash.
+ *
+ * @private
+ * @name delete
+ * @memberOf Hash
+ * @param {Object} hash The hash to modify.
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function hashDelete(key) {
+ var result = this.has(key) && delete this.__data__[key];
+ this.size -= result ? 1 : 0;
+ return result;
+ }
+
+ /**
+ * Gets the hash value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Hash
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function hashGet(key) {
+ var data = this.__data__;
+ if (nativeCreate) {
+ var result = data[key];
+ return result === HASH_UNDEFINED ? undefined$1 : result;
+ }
+ return hasOwnProperty.call(data, key) ? data[key] : undefined$1;
+ }
+
+ /**
+ * Checks if a hash value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Hash
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function hashHas(key) {
+ var data = this.__data__;
+ return nativeCreate ? (data[key] !== undefined$1) : hasOwnProperty.call(data, key);
+ }
+
+ /**
+ * Sets the hash `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Hash
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the hash instance.
+ */
+ function hashSet(key, value) {
+ var data = this.__data__;
+ this.size += this.has(key) ? 0 : 1;
+ data[key] = (nativeCreate && value === undefined$1) ? HASH_UNDEFINED : value;
+ return this;
+ }
+
+ // Add methods to `Hash`.
+ Hash.prototype.clear = hashClear;
+ Hash.prototype['delete'] = hashDelete;
+ Hash.prototype.get = hashGet;
+ Hash.prototype.has = hashHas;
+ Hash.prototype.set = hashSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an list cache object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function ListCache(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the list cache.
+ *
+ * @private
+ * @name clear
+ * @memberOf ListCache
+ */
+ function listCacheClear() {
+ this.__data__ = [];
+ this.size = 0;
+ }
+
+ /**
+ * Removes `key` and its value from the list cache.
+ *
+ * @private
+ * @name delete
+ * @memberOf ListCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function listCacheDelete(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = data.length - 1;
+ if (index == lastIndex) {
+ data.pop();
+ } else {
+ splice.call(data, index, 1);
+ }
+ --this.size;
+ return true;
+ }
+
+ /**
+ * Gets the list cache value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf ListCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function listCacheGet(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ return index < 0 ? undefined$1 : data[index][1];
+ }
+
+ /**
+ * Checks if a list cache value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf ListCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function listCacheHas(key) {
+ return assocIndexOf(this.__data__, key) > -1;
+ }
+
+ /**
+ * Sets the list cache `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf ListCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the list cache instance.
+ */
+ function listCacheSet(key, value) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ ++this.size;
+ data.push([key, value]);
+ } else {
+ data[index][1] = value;
+ }
+ return this;
+ }
+
+ // Add methods to `ListCache`.
+ ListCache.prototype.clear = listCacheClear;
+ ListCache.prototype['delete'] = listCacheDelete;
+ ListCache.prototype.get = listCacheGet;
+ ListCache.prototype.has = listCacheHas;
+ ListCache.prototype.set = listCacheSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a map cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function MapCache(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the map.
+ *
+ * @private
+ * @name clear
+ * @memberOf MapCache
+ */
+ function mapCacheClear() {
+ this.size = 0;
+ this.__data__ = {
+ 'hash': new Hash,
+ 'map': new (Map || ListCache),
+ 'string': new Hash
+ };
+ }
+
+ /**
+ * Removes `key` and its value from the map.
+ *
+ * @private
+ * @name delete
+ * @memberOf MapCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function mapCacheDelete(key) {
+ var result = getMapData(this, key)['delete'](key);
+ this.size -= result ? 1 : 0;
+ return result;
+ }
+
+ /**
+ * Gets the map value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf MapCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function mapCacheGet(key) {
+ return getMapData(this, key).get(key);
+ }
+
+ /**
+ * Checks if a map value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf MapCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function mapCacheHas(key) {
+ return getMapData(this, key).has(key);
+ }
+
+ /**
+ * Sets the map `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf MapCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the map cache instance.
+ */
+ function mapCacheSet(key, value) {
+ var data = getMapData(this, key),
+ size = data.size;
+
+ data.set(key, value);
+ this.size += data.size == size ? 0 : 1;
+ return this;
+ }
+
+ // Add methods to `MapCache`.
+ MapCache.prototype.clear = mapCacheClear;
+ MapCache.prototype['delete'] = mapCacheDelete;
+ MapCache.prototype.get = mapCacheGet;
+ MapCache.prototype.has = mapCacheHas;
+ MapCache.prototype.set = mapCacheSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ *
+ * Creates an array cache object to store unique values.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [values] The values to cache.
+ */
+ function SetCache(values) {
+ var index = -1,
+ length = values == null ? 0 : values.length;
+
+ this.__data__ = new MapCache;
+ while (++index < length) {
+ this.add(values[index]);
+ }
+ }
+
+ /**
+ * Adds `value` to the array cache.
+ *
+ * @private
+ * @name add
+ * @memberOf SetCache
+ * @alias push
+ * @param {*} value The value to cache.
+ * @returns {Object} Returns the cache instance.
+ */
+ function setCacheAdd(value) {
+ this.__data__.set(value, HASH_UNDEFINED);
+ return this;
+ }
+
+ /**
+ * Checks if `value` is in the array cache.
+ *
+ * @private
+ * @name has
+ * @memberOf SetCache
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `true` if `value` is found, else `false`.
+ */
+ function setCacheHas(value) {
+ return this.__data__.has(value);
+ }
+
+ // Add methods to `SetCache`.
+ SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
+ SetCache.prototype.has = setCacheHas;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a stack cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+ function Stack(entries) {
+ var data = this.__data__ = new ListCache(entries);
+ this.size = data.size;
+ }
+
+ /**
+ * Removes all key-value entries from the stack.
+ *
+ * @private
+ * @name clear
+ * @memberOf Stack
+ */
+ function stackClear() {
+ this.__data__ = new ListCache;
+ this.size = 0;
+ }
+
+ /**
+ * Removes `key` and its value from the stack.
+ *
+ * @private
+ * @name delete
+ * @memberOf Stack
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function stackDelete(key) {
+ var data = this.__data__,
+ result = data['delete'](key);
+
+ this.size = data.size;
+ return result;
+ }
+
+ /**
+ * Gets the stack value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Stack
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function stackGet(key) {
+ return this.__data__.get(key);
+ }
+
+ /**
+ * Checks if a stack value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Stack
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function stackHas(key) {
+ return this.__data__.has(key);
+ }
+
+ /**
+ * Sets the stack `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Stack
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the stack cache instance.
+ */
+ function stackSet(key, value) {
+ var data = this.__data__;
+ if (data instanceof ListCache) {
+ var pairs = data.__data__;
+ if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
+ pairs.push([key, value]);
+ this.size = ++data.size;
+ return this;
+ }
+ data = this.__data__ = new MapCache(pairs);
+ }
+ data.set(key, value);
+ this.size = data.size;
+ return this;
+ }
+
+ // Add methods to `Stack`.
+ Stack.prototype.clear = stackClear;
+ Stack.prototype['delete'] = stackDelete;
+ Stack.prototype.get = stackGet;
+ Stack.prototype.has = stackHas;
+ Stack.prototype.set = stackSet;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of the enumerable property names of the array-like `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @param {boolean} inherited Specify returning inherited property names.
+ * @returns {Array} Returns the array of property names.
+ */
+ function arrayLikeKeys(value, inherited) {
+ var isArr = isArray(value),
+ isArg = !isArr && isArguments(value),
+ isBuff = !isArr && !isArg && isBuffer(value),
+ isType = !isArr && !isArg && !isBuff && isTypedArray(value),
+ skipIndexes = isArr || isArg || isBuff || isType,
+ result = skipIndexes ? baseTimes(value.length, String) : [],
+ length = result.length;
+
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) &&
+ !(skipIndexes && (
+ // Safari 9 has enumerable `arguments.length` in strict mode.
+ key == 'length' ||
+ // Node.js 0.10 has enumerable non-index properties on buffers.
+ (isBuff && (key == 'offset' || key == 'parent')) ||
+ // PhantomJS 2 has enumerable non-index properties on typed arrays.
+ (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
+ // Skip index properties.
+ isIndex(key, length)
+ ))) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.sample` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to sample.
+ * @returns {*} Returns the random element.
+ */
+ function arraySample(array) {
+ var length = array.length;
+ return length ? array[baseRandom(0, length - 1)] : undefined$1;
+ }
+
+ /**
+ * A specialized version of `_.sampleSize` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to sample.
+ * @param {number} n The number of elements to sample.
+ * @returns {Array} Returns the random elements.
+ */
+ function arraySampleSize(array, n) {
+ return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
+ }
+
+ /**
+ * A specialized version of `_.shuffle` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ */
+ function arrayShuffle(array) {
+ return shuffleSelf(copyArray(array));
+ }
+
+ /**
+ * This function is like `assignValue` except that it doesn't assign
+ * `undefined` values.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function assignMergeValue(object, key, value) {
+ if ((value !== undefined$1 && !eq(object[key], value)) ||
+ (value === undefined$1 && !(key in object))) {
+ baseAssignValue(object, key, value);
+ }
+ }
+
+ /**
+ * Assigns `value` to `key` of `object` if the existing value is not equivalent
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
+ (value === undefined$1 && !(key in object))) {
+ baseAssignValue(object, key, value);
+ }
+ }
+
+ /**
+ * Gets the index at which the `key` is found in `array` of key-value pairs.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} key The key to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Aggregates elements of `collection` on `accumulator` with keys transformed
+ * by `iteratee` and values set by `setter`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseAggregator(collection, setter, iteratee, accumulator) {
+ baseEach(collection, function(value, key, collection) {
+ setter(accumulator, value, iteratee(value), collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.assign` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+ }
+
+ /**
+ * The base implementation of `_.assignIn` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ function baseAssignIn(object, source) {
+ return object && copyObject(source, keysIn(source), object);
+ }
+
+ /**
+ * The base implementation of `assignValue` and `assignMergeValue` without
+ * value checks.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function baseAssignValue(object, key, value) {
+ if (key == '__proto__' && defineProperty) {
+ defineProperty(object, key, {
+ 'configurable': true,
+ 'enumerable': true,
+ 'value': value,
+ 'writable': true
+ });
+ } else {
+ object[key] = value;
+ }
+ }
+
+ /**
+ * The base implementation of `_.at` without support for individual paths.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {string[]} paths The property paths to pick.
+ * @returns {Array} Returns the picked elements.
+ */
+ function baseAt(object, paths) {
+ var index = -1,
+ length = paths.length,
+ result = Array(length),
+ skip = object == null;
+
+ while (++index < length) {
+ result[index] = skip ? undefined$1 : get(object, paths[index]);
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.clamp` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {number} number The number to clamp.
+ * @param {number} [lower] The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the clamped number.
+ */
+ function baseClamp(number, lower, upper) {
+ if (number === number) {
+ if (upper !== undefined$1) {
+ number = number <= upper ? number : upper;
+ }
+ if (lower !== undefined$1) {
+ number = number >= lower ? number : lower;
+ }
+ }
+ return number;
+ }
+
+ /**
+ * The base implementation of `_.clone` and `_.cloneDeep` which tracks
+ * traversed objects.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} bitmask The bitmask flags.
+ * 1 - Deep clone
+ * 2 - Flatten inherited properties
+ * 4 - Clone symbols
+ * @param {Function} [customizer] The function to customize cloning.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The parent object of `value`.
+ * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+ function baseClone(value, bitmask, customizer, key, object, stack) {
+ var result,
+ isDeep = bitmask & CLONE_DEEP_FLAG,
+ isFlat = bitmask & CLONE_FLAT_FLAG,
+ isFull = bitmask & CLONE_SYMBOLS_FLAG;
+
+ if (customizer) {
+ result = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result !== undefined$1) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result);
+ }
+ } else {
+ var tag = getTag(value),
+ isFunc = tag == funcTag || tag == genTag;
+
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ result = (isFlat || isFunc) ? {} : initCloneObject(value);
+ if (!isDeep) {
+ return isFlat
+ ? copySymbolsIn(value, baseAssignIn(result, value))
+ : copySymbols(value, baseAssign(result, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result = initCloneByTag(value, tag, isDeep);
+ }
+ }
+ // Check for circular references and return its corresponding clone.
+ stack || (stack = new Stack);
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result);
+
+ if (isSet(value)) {
+ value.forEach(function(subValue) {
+ result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
+ });
+ } else if (isMap(value)) {
+ value.forEach(function(subValue, key) {
+ result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
+ });
+ }
+
+ var keysFunc = isFull
+ ? (isFlat ? getAllKeysIn : getAllKeys)
+ : (isFlat ? keysIn : keys);
+
+ var props = isArr ? undefined$1 : keysFunc(value);
+ arrayEach(props || value, function(subValue, key) {
+ if (props) {
+ key = subValue;
+ subValue = value[key];
+ }
+ // Recursively populate clone (susceptible to call stack limits).
+ assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.conforms` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {Function} Returns the new spec function.
+ */
+ function baseConforms(source) {
+ var props = keys(source);
+ return function(object) {
+ return baseConformsTo(object, source, props);
+ };
+ }
+
+ /**
+ * The base implementation of `_.conformsTo` which accepts `props` to check.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {boolean} Returns `true` if `object` conforms, else `false`.
+ */
+ function baseConformsTo(object, source, props) {
+ var length = props.length;
+ if (object == null) {
+ return !length;
+ }
+ object = Object(object);
+ while (length--) {
+ var key = props[length],
+ predicate = source[key],
+ value = object[key];
+
+ if ((value === undefined$1 && !(key in object)) || !predicate(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The base implementation of `_.delay` and `_.defer` which accepts `args`
+ * to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {Array} args The arguments to provide to `func`.
+ * @returns {number|Object} Returns the timer id or timeout object.
+ */
+ function baseDelay(func, wait, args) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return setTimeout(function() { func.apply(undefined$1, args); }, wait);
+ }
+
+ /**
+ * The base implementation of methods like `_.difference` without support
+ * for excluding multiple arrays or iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Array} values The values to exclude.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ */
+ function baseDifference(array, values, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ isCommon = true,
+ length = array.length,
+ result = [],
+ valuesLength = values.length;
+
+ if (!length) {
+ return result;
+ }
+ if (iteratee) {
+ values = arrayMap(values, baseUnary(iteratee));
+ }
+ if (comparator) {
+ includes = arrayIncludesWith;
+ isCommon = false;
+ }
+ else if (values.length >= LARGE_ARRAY_SIZE) {
+ includes = cacheHas;
+ isCommon = false;
+ values = new SetCache(values);
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee == null ? value : iteratee(value);
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (isCommon && computed === computed) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values[valuesIndex] === computed) {
+ continue outer;
+ }
+ }
+ result.push(value);
+ }
+ else if (!includes(values, computed, comparator)) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.forEach` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+ var baseEach = createBaseEach(baseForOwn);
+
+ /**
+ * The base implementation of `_.forEachRight` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
+
+ /**
+ * The base implementation of `_.every` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`
+ */
+ function baseEvery(collection, predicate) {
+ var result = true;
+ baseEach(collection, function(value, index, collection) {
+ result = !!predicate(value, index, collection);
+ return result;
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of methods like `_.max` and `_.min` which accepts a
+ * `comparator` to determine the extremum value.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The iteratee invoked per iteration.
+ * @param {Function} comparator The comparator used to compare values.
+ * @returns {*} Returns the extremum value.
+ */
+ function baseExtremum(array, iteratee, comparator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index],
+ current = iteratee(value);
+
+ if (current != null && (computed === undefined$1
+ ? (current === current && !isSymbol(current))
+ : comparator(current, computed)
+ )) {
+ var computed = current,
+ result = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.fill` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ */
+ function baseFill(array, value, start, end) {
+ var length = array.length;
+
+ start = toInteger(start);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (end === undefined$1 || end > length) ? length : toInteger(end);
+ if (end < 0) {
+ end += length;
+ }
+ end = start > end ? 0 : toLength(end);
+ while (start < end) {
+ array[start++] = value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.filter` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function baseFilter(collection, predicate) {
+ var result = [];
+ baseEach(collection, function(value, index, collection) {
+ if (predicate(value, index, collection)) {
+ result.push(value);
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.flatten` with support for restricting flattening.
+ *
+ * @private
+ * @param {Array} array The array to flatten.
+ * @param {number} depth The maximum recursion depth.
+ * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
+ * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
+ * @param {Array} [result=[]] The initial result value.
+ * @returns {Array} Returns the new flattened array.
+ */
+ function baseFlatten(array, depth, predicate, isStrict, result) {
+ var index = -1,
+ length = array.length;
+
+ predicate || (predicate = isFlattenable);
+ result || (result = []);
+
+ while (++index < length) {
+ var value = array[index];
+ if (depth > 0 && predicate(value)) {
+ if (depth > 1) {
+ // Recursively flatten arrays (susceptible to call stack limits).
+ baseFlatten(value, depth - 1, predicate, isStrict, result);
+ } else {
+ arrayPush(result, value);
+ }
+ } else if (!isStrict) {
+ result[result.length] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `baseForOwn` which iterates over `object`
+ * properties returned by `keysFunc` and invokes `iteratee` for each property.
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseFor = createBaseFor();
+
+ /**
+ * This function is like `baseFor` except that it iterates over properties
+ * in the opposite order.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseForRight = createBaseFor(true);
+
+ /**
+ * The base implementation of `_.forOwn` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwn(object, iteratee) {
+ return object && baseFor(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwnRight(object, iteratee) {
+ return object && baseForRight(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.functions` which creates an array of
+ * `object` function property names filtered from `props`.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Array} props The property names to filter.
+ * @returns {Array} Returns the function names.
+ */
+ function baseFunctions(object, props) {
+ return arrayFilter(props, function(key) {
+ return isFunction(object[key]);
+ });
+ }
+
+ /**
+ * The base implementation of `_.get` without support for default values.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseGet(object, path) {
+ path = castPath(path, object);
+
+ var index = 0,
+ length = path.length;
+
+ while (object != null && index < length) {
+ object = object[toKey(path[index++])];
+ }
+ return (index && index == length) ? object : undefined$1;
+ }
+
+ /**
+ * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
+ * `keysFunc` and `symbolsFunc` to get the enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @param {Function} symbolsFunc The function to get the symbols of `object`.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+ function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+ var result = keysFunc(object);
+ return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
+ }
+
+ /**
+ * The base implementation of `getTag` without fallbacks for buggy environments.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+ function baseGetTag(value) {
+ if (value == null) {
+ return value === undefined$1 ? undefinedTag : nullTag;
+ }
+ return (symToStringTag && symToStringTag in Object(value))
+ ? getRawTag(value)
+ : objectToString(value);
+ }
+
+ /**
+ * The base implementation of `_.gt` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`,
+ * else `false`.
+ */
+ function baseGt(value, other) {
+ return value > other;
+ }
+
+ /**
+ * The base implementation of `_.has` without support for deep paths.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+ function baseHas(object, key) {
+ return object != null && hasOwnProperty.call(object, key);
+ }
+
+ /**
+ * The base implementation of `_.hasIn` without support for deep paths.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+ function baseHasIn(object, key) {
+ return object != null && key in Object(object);
+ }
+
+ /**
+ * The base implementation of `_.inRange` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {number} number The number to check.
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
+ */
+ function baseInRange(number, start, end) {
+ return number >= nativeMin(start, end) && number < nativeMax(start, end);
+ }
+
+ /**
+ * The base implementation of methods like `_.intersection`, without support
+ * for iteratee shorthands, that accepts an array of arrays to inspect.
+ *
+ * @private
+ * @param {Array} arrays The arrays to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of shared values.
+ */
+ function baseIntersection(arrays, iteratee, comparator) {
+ var includes = comparator ? arrayIncludesWith : arrayIncludes,
+ length = arrays[0].length,
+ othLength = arrays.length,
+ othIndex = othLength,
+ caches = Array(othLength),
+ maxLength = Infinity,
+ result = [];
+
+ while (othIndex--) {
+ var array = arrays[othIndex];
+ if (othIndex && iteratee) {
+ array = arrayMap(array, baseUnary(iteratee));
+ }
+ maxLength = nativeMin(array.length, maxLength);
+ caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
+ ? new SetCache(othIndex && array)
+ : undefined$1;
+ }
+ array = arrays[0];
+
+ var index = -1,
+ seen = caches[0];
+
+ outer:
+ while (++index < length && result.length < maxLength) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (!(seen
+ ? cacheHas(seen, computed)
+ : includes(result, computed, comparator)
+ )) {
+ othIndex = othLength;
+ while (--othIndex) {
+ var cache = caches[othIndex];
+ if (!(cache
+ ? cacheHas(cache, computed)
+ : includes(arrays[othIndex], computed, comparator))
+ ) {
+ continue outer;
+ }
+ }
+ if (seen) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.invert` and `_.invertBy` which inverts
+ * `object` with values transformed by `iteratee` and set by `setter`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform values.
+ * @param {Object} accumulator The initial inverted object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseInverter(object, setter, iteratee, accumulator) {
+ baseForOwn(object, function(value, key, object) {
+ setter(accumulator, iteratee(value), key, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.invoke` without support for individual
+ * method arguments.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {Array} args The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ */
+ function baseInvoke(object, path, args) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ var func = object == null ? object : object[toKey(last(path))];
+ return func == null ? undefined$1 : apply(func, object, args);
+ }
+
+ /**
+ * The base implementation of `_.isArguments`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ */
+ function baseIsArguments(value) {
+ return isObjectLike(value) && baseGetTag(value) == argsTag;
+ }
+
+ /**
+ * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
+ */
+ function baseIsArrayBuffer(value) {
+ return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
+ }
+
+ /**
+ * The base implementation of `_.isDate` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
+ */
+ function baseIsDate(value) {
+ return isObjectLike(value) && baseGetTag(value) == dateTag;
+ }
+
+ /**
+ * The base implementation of `_.isEqual` which supports partial comparisons
+ * and tracks traversed objects.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {boolean} bitmask The bitmask flags.
+ * 1 - Unordered comparison
+ * 2 - Partial comparison
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {Object} [stack] Tracks traversed `value` and `other` objects.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ */
+ function baseIsEqual(value, other, bitmask, customizer, stack) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
+ }
+
+ /**
+ * A specialized version of `baseIsEqual` for arrays and objects which performs
+ * deep comparisons and tracks traversed objects enabling objects with circular
+ * references to be compared.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} [stack] Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
+ var objIsArr = isArray(object),
+ othIsArr = isArray(other),
+ objTag = objIsArr ? arrayTag : getTag(object),
+ othTag = othIsArr ? arrayTag : getTag(other);
+
+ objTag = objTag == argsTag ? objectTag : objTag;
+ othTag = othTag == argsTag ? objectTag : othTag;
+
+ var objIsObj = objTag == objectTag,
+ othIsObj = othTag == objectTag,
+ isSameTag = objTag == othTag;
+
+ if (isSameTag && isBuffer(object)) {
+ if (!isBuffer(other)) {
+ return false;
+ }
+ objIsArr = true;
+ objIsObj = false;
+ }
+ if (isSameTag && !objIsObj) {
+ stack || (stack = new Stack);
+ return (objIsArr || isTypedArray(object))
+ ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
+ : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
+ }
+ if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
+ othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
+
+ if (objIsWrapped || othIsWrapped) {
+ var objUnwrapped = objIsWrapped ? object.value() : object,
+ othUnwrapped = othIsWrapped ? other.value() : other;
+
+ stack || (stack = new Stack);
+ return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ stack || (stack = new Stack);
+ return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
+ }
+
+ /**
+ * The base implementation of `_.isMap` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a map, else `false`.
+ */
+ function baseIsMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+ }
+
+ /**
+ * The base implementation of `_.isMatch` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Array} matchData The property names, values, and compare flags to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ */
+ function baseIsMatch(object, source, matchData, customizer) {
+ var index = matchData.length,
+ length = index,
+ noCustomizer = !customizer;
+
+ if (object == null) {
+ return !length;
+ }
+ object = Object(object);
+ while (index--) {
+ var data = matchData[index];
+ if ((noCustomizer && data[2])
+ ? data[1] !== object[data[0]]
+ : !(data[0] in object)
+ ) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0],
+ objValue = object[key],
+ srcValue = data[1];
+
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined$1 && !(key in object)) {
+ return false;
+ }
+ } else {
+ var stack = new Stack;
+ if (customizer) {
+ var result = customizer(objValue, srcValue, key, object, source, stack);
+ }
+ if (!(result === undefined$1
+ ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
+ : result
+ )) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The base implementation of `_.isNative` without bad shim checks.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function,
+ * else `false`.
+ */
+ function baseIsNative(value) {
+ if (!isObject(value) || isMasked(value)) {
+ return false;
+ }
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
+ return pattern.test(toSource(value));
+ }
+
+ /**
+ * The base implementation of `_.isRegExp` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
+ */
+ function baseIsRegExp(value) {
+ return isObjectLike(value) && baseGetTag(value) == regexpTag;
+ }
+
+ /**
+ * The base implementation of `_.isSet` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a set, else `false`.
+ */
+ function baseIsSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+ }
+
+ /**
+ * The base implementation of `_.isTypedArray` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ */
+ function baseIsTypedArray(value) {
+ return isObjectLike(value) &&
+ isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
+ }
+
+ /**
+ * The base implementation of `_.iteratee`.
+ *
+ * @private
+ * @param {*} [value=_.identity] The value to convert to an iteratee.
+ * @returns {Function} Returns the iteratee.
+ */
+ function baseIteratee(value) {
+ // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
+ // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
+ if (typeof value == 'function') {
+ return value;
+ }
+ if (value == null) {
+ return identity;
+ }
+ if (typeof value == 'object') {
+ return isArray(value)
+ ? baseMatchesProperty(value[0], value[1])
+ : baseMatches(value);
+ }
+ return property(value);
+ }
+
+ /**
+ * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result = [];
+ for (var key in Object(object)) {
+ if (hasOwnProperty.call(object, key) && key != 'constructor') {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function baseKeysIn(object) {
+ if (!isObject(object)) {
+ return nativeKeysIn(object);
+ }
+ var isProto = isPrototype(object),
+ result = [];
+
+ for (var key in object) {
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.lt` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`,
+ * else `false`.
+ */
+ function baseLt(value, other) {
+ return value < other;
+ }
+
+ /**
+ * The base implementation of `_.map` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function baseMap(collection, iteratee) {
+ var index = -1,
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = iteratee(value, key, collection);
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.matches` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new spec function.
+ */
+ function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ return matchesStrictComparable(matchData[0][0], matchData[0][1]);
+ }
+ return function(object) {
+ return object === source || baseIsMatch(object, source, matchData);
+ };
+ }
+
+ /**
+ * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
+ *
+ * @private
+ * @param {string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ */
+ function baseMatchesProperty(path, srcValue) {
+ if (isKey(path) && isStrictComparable(srcValue)) {
+ return matchesStrictComparable(toKey(path), srcValue);
+ }
+ return function(object) {
+ var objValue = get(object, path);
+ return (objValue === undefined$1 && objValue === srcValue)
+ ? hasIn(object, path)
+ : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
+ };
+ }
+
+ /**
+ * The base implementation of `_.merge` without support for multiple sources.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+ function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ baseFor(source, function(srcValue, key) {
+ stack || (stack = new Stack);
+ if (isObject(srcValue)) {
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ }
+ else {
+ var newValue = customizer
+ ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
+ : undefined$1;
+
+ if (newValue === undefined$1) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ }, keysIn);
+ }
+
+ /**
+ * A specialized version of `baseMerge` for arrays and objects which performs
+ * deep merges and tracks traversed objects enabling objects with circular
+ * references to be merged.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {string} key The key of the value to merge.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} mergeFunc The function to merge values.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = safeGet(object, key),
+ srcValue = safeGet(source, key),
+ stacked = stack.get(srcValue);
+
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
+ : undefined$1;
+
+ var isCommon = newValue === undefined$1;
+
+ if (isCommon) {
+ var isArr = isArray(srcValue),
+ isBuff = !isArr && isBuffer(srcValue),
+ isTyped = !isArr && !isBuff && isTypedArray(srcValue);
+
+ newValue = srcValue;
+ if (isArr || isBuff || isTyped) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ }
+ else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ }
+ else if (isBuff) {
+ isCommon = false;
+ newValue = cloneBuffer(srcValue, true);
+ }
+ else if (isTyped) {
+ isCommon = false;
+ newValue = cloneTypedArray(srcValue, true);
+ }
+ else {
+ newValue = [];
+ }
+ }
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ newValue = objValue;
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ }
+ else if (!isObject(objValue) || isFunction(objValue)) {
+ newValue = initCloneObject(srcValue);
+ }
+ }
+ else {
+ isCommon = false;
+ }
+ }
+ if (isCommon) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ stack.set(srcValue, newValue);
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ stack['delete'](srcValue);
+ }
+ assignMergeValue(object, key, newValue);
+ }
+
+ /**
+ * The base implementation of `_.nth` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {number} n The index of the element to return.
+ * @returns {*} Returns the nth element of `array`.
+ */
+ function baseNth(array, n) {
+ var length = array.length;
+ if (!length) {
+ return;
+ }
+ n += n < 0 ? length : 0;
+ return isIndex(n, length) ? array[n] : undefined$1;
+ }
+
+ /**
+ * The base implementation of `_.orderBy` without param guards.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {string[]} orders The sort orders of `iteratees`.
+ * @returns {Array} Returns the new sorted array.
+ */
+ function baseOrderBy(collection, iteratees, orders) {
+ if (iteratees.length) {
+ iteratees = arrayMap(iteratees, function(iteratee) {
+ if (isArray(iteratee)) {
+ return function(value) {
+ return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
+ }
+ }
+ return iteratee;
+ });
+ } else {
+ iteratees = [identity];
+ }
+
+ var index = -1;
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+
+ var result = baseMap(collection, function(value, key, collection) {
+ var criteria = arrayMap(iteratees, function(iteratee) {
+ return iteratee(value);
+ });
+ return { 'criteria': criteria, 'index': ++index, 'value': value };
+ });
+
+ return baseSortBy(result, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
+
+ /**
+ * The base implementation of `_.pick` without support for individual
+ * property identifiers.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} paths The property paths to pick.
+ * @returns {Object} Returns the new object.
+ */
+ function basePick(object, paths) {
+ return basePickBy(object, paths, function(value, path) {
+ return hasIn(object, path);
+ });
+ }
+
+ /**
+ * The base implementation of `_.pickBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} paths The property paths to pick.
+ * @param {Function} predicate The function invoked per property.
+ * @returns {Object} Returns the new object.
+ */
+ function basePickBy(object, paths, predicate) {
+ var index = -1,
+ length = paths.length,
+ result = {};
+
+ while (++index < length) {
+ var path = paths[index],
+ value = baseGet(object, path);
+
+ if (predicate(value, path)) {
+ baseSet(result, castPath(path, object), value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseProperty` which supports deep paths.
+ *
+ * @private
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ */
+ function basePropertyDeep(path) {
+ return function(object) {
+ return baseGet(object, path);
+ };
+ }
+
+ /**
+ * The base implementation of `_.pullAllBy` without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAll(array, values, iteratee, comparator) {
+ var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
+ index = -1,
+ length = values.length,
+ seen = array;
+
+ if (array === values) {
+ values = copyArray(values);
+ }
+ if (iteratee) {
+ seen = arrayMap(array, baseUnary(iteratee));
+ }
+ while (++index < length) {
+ var fromIndex = 0,
+ value = values[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
+ if (seen !== array) {
+ splice.call(seen, fromIndex, 1);
+ }
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.pullAt` without support for individual
+ * indexes or capturing the removed elements.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {number[]} indexes The indexes of elements to remove.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAt(array, indexes) {
+ var length = array ? indexes.length : 0,
+ lastIndex = length - 1;
+
+ while (length--) {
+ var index = indexes[length];
+ if (length == lastIndex || index !== previous) {
+ var previous = index;
+ if (isIndex(index)) {
+ splice.call(array, index, 1);
+ } else {
+ baseUnset(array, index);
+ }
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.random` without support for returning
+ * floating-point numbers.
+ *
+ * @private
+ * @param {number} lower The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the random number.
+ */
+ function baseRandom(lower, upper) {
+ return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
+ }
+
+ /**
+ * The base implementation of `_.range` and `_.rangeRight` which doesn't
+ * coerce arguments.
+ *
+ * @private
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} step The value to increment or decrement by.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the range of numbers.
+ */
+ function baseRange(start, end, step, fromRight) {
+ var index = -1,
+ length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
+ result = Array(length);
+
+ while (length--) {
+ result[fromRight ? length : ++index] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.repeat` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {string} string The string to repeat.
+ * @param {number} n The number of times to repeat the string.
+ * @returns {string} Returns the repeated string.
+ */
+ function baseRepeat(string, n) {
+ var result = '';
+ if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
+ return result;
+ }
+ // Leverage the exponentiation by squaring algorithm for a faster repeat.
+ // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
+ do {
+ if (n % 2) {
+ result += string;
+ }
+ n = nativeFloor(n / 2);
+ if (n) {
+ string += string;
+ }
+ } while (n);
+
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ */
+ function baseRest(func, start) {
+ return setToString(overRest(func, start, identity), func + '');
+ }
+
+ /**
+ * The base implementation of `_.sample`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to sample.
+ * @returns {*} Returns the random element.
+ */
+ function baseSample(collection) {
+ return arraySample(values(collection));
+ }
+
+ /**
+ * The base implementation of `_.sampleSize` without param guards.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to sample.
+ * @param {number} n The number of elements to sample.
+ * @returns {Array} Returns the random elements.
+ */
+ function baseSampleSize(collection, n) {
+ var array = values(collection);
+ return shuffleSelf(array, baseClamp(n, 0, array.length));
+ }
+
+ /**
+ * The base implementation of `_.set`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+ function baseSet(object, path, value, customizer) {
+ if (!isObject(object)) {
+ return object;
+ }
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ lastIndex = length - 1,
+ nested = object;
+
+ while (nested != null && ++index < length) {
+ var key = toKey(path[index]),
+ newValue = value;
+
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
+ return object;
+ }
+
+ if (index != lastIndex) {
+ var objValue = nested[key];
+ newValue = customizer ? customizer(objValue, key, nested) : undefined$1;
+ if (newValue === undefined$1) {
+ newValue = isObject(objValue)
+ ? objValue
+ : (isIndex(path[index + 1]) ? [] : {});
+ }
+ }
+ assignValue(nested, key, newValue);
+ nested = nested[key];
+ }
+ return object;
+ }
+
+ /**
+ * The base implementation of `setData` without support for hot loop shorting.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var baseSetData = !metaMap ? identity : function(func, data) {
+ metaMap.set(func, data);
+ return func;
+ };
+
+ /**
+ * The base implementation of `setToString` without support for hot loop shorting.
+ *
+ * @private
+ * @param {Function} func The function to modify.
+ * @param {Function} string The `toString` result.
+ * @returns {Function} Returns `func`.
+ */
+ var baseSetToString = !defineProperty ? identity : function(func, string) {
+ return defineProperty(func, 'toString', {
+ 'configurable': true,
+ 'enumerable': false,
+ 'value': constant(string),
+ 'writable': true
+ });
+ };
+
+ /**
+ * The base implementation of `_.shuffle`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ */
+ function baseShuffle(collection) {
+ return shuffleSelf(values(collection));
+ }
+
+ /**
+ * The base implementation of `_.slice` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseSlice(array, start, end) {
+ var index = -1,
+ length = array.length;
+
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = end > length ? length : end;
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : ((end - start) >>> 0);
+ start >>>= 0;
+
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.some` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function baseSome(collection, predicate) {
+ var result;
+
+ baseEach(collection, function(value, index, collection) {
+ result = predicate(value, index, collection);
+ return !result;
+ });
+ return !!result;
+ }
+
+ /**
+ * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
+ * performs a binary search of `array` to determine the index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function baseSortedIndex(array, value, retHighest) {
+ var low = 0,
+ high = array == null ? low : array.length;
+
+ if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = (low + high) >>> 1,
+ computed = array[mid];
+
+ if (computed !== null && !isSymbol(computed) &&
+ (retHighest ? (computed <= value) : (computed < value))) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return baseSortedIndexBy(array, value, identity, retHighest);
+ }
+
+ /**
+ * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
+ * which invokes `iteratee` for `value` and each element of `array` to compute
+ * their sort ranking. The iteratee is invoked with one argument; (value).
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} iteratee The iteratee invoked per element.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function baseSortedIndexBy(array, value, iteratee, retHighest) {
+ var low = 0,
+ high = array == null ? 0 : array.length;
+ if (high === 0) {
+ return 0;
+ }
+
+ value = iteratee(value);
+ var valIsNaN = value !== value,
+ valIsNull = value === null,
+ valIsSymbol = isSymbol(value),
+ valIsUndefined = value === undefined$1;
+
+ while (low < high) {
+ var mid = nativeFloor((low + high) / 2),
+ computed = iteratee(array[mid]),
+ othIsDefined = computed !== undefined$1,
+ othIsNull = computed === null,
+ othIsReflexive = computed === computed,
+ othIsSymbol = isSymbol(computed);
+
+ if (valIsNaN) {
+ var setLow = retHighest || othIsReflexive;
+ } else if (valIsUndefined) {
+ setLow = othIsReflexive && (retHighest || othIsDefined);
+ } else if (valIsNull) {
+ setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
+ } else if (valIsSymbol) {
+ setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
+ } else if (othIsNull || othIsSymbol) {
+ setLow = false;
+ } else {
+ setLow = retHighest ? (computed <= value) : (computed < value);
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
+
+ /**
+ * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseSortedUniq(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ if (!index || !eq(computed, seen)) {
+ var seen = computed;
+ result[resIndex++] = value === 0 ? 0 : value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.toNumber` which doesn't ensure correct
+ * conversions of binary, hexadecimal, or octal string values.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ */
+ function baseToNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ return +value;
+ }
+
+ /**
+ * The base implementation of `_.toString` which doesn't convert nullish
+ * values to empty strings.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ */
+ function baseToString(value) {
+ // Exit early for strings to avoid a performance hit in some environments.
+ if (typeof value == 'string') {
+ return value;
+ }
+ if (isArray(value)) {
+ // Recursively convert values (susceptible to call stack limits).
+ return arrayMap(value, baseToString) + '';
+ }
+ if (isSymbol(value)) {
+ return symbolToString ? symbolToString.call(value) : '';
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+ }
+
+ /**
+ * The base implementation of `_.uniqBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseUniq(array, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ length = array.length,
+ isCommon = true,
+ result = [],
+ seen = result;
+
+ if (comparator) {
+ isCommon = false;
+ includes = arrayIncludesWith;
+ }
+ else if (length >= LARGE_ARRAY_SIZE) {
+ var set = iteratee ? null : createSet(array);
+ if (set) {
+ return setToArray(set);
+ }
+ isCommon = false;
+ includes = cacheHas;
+ seen = new SetCache;
+ }
+ else {
+ seen = iteratee ? [] : result;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (isCommon && computed === computed) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ else if (!includes(seen, computed, comparator)) {
+ if (seen !== result) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.unset`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The property path to unset.
+ * @returns {boolean} Returns `true` if the property is deleted, else `false`.
+ */
+ function baseUnset(object, path) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ return object == null || delete object[toKey(last(path))];
+ }
+
+ /**
+ * The base implementation of `_.update`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to update.
+ * @param {Function} updater The function to produce the updated value.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+ function baseUpdate(object, path, updater, customizer) {
+ return baseSet(object, path, updater(baseGet(object, path)), customizer);
+ }
+
+ /**
+ * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
+ * without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length) &&
+ predicate(array[index], index, array)) {}
+
+ return isDrop
+ ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
+ : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
+ }
+
+ /**
+ * The base implementation of `wrapperValue` which returns the result of
+ * performing a sequence of actions on the unwrapped `value`, where each
+ * successive action is supplied the return value of the previous.
+ *
+ * @private
+ * @param {*} value The unwrapped value.
+ * @param {Array} actions Actions to perform to resolve the unwrapped value.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseWrapperValue(value, actions) {
+ var result = value;
+ if (result instanceof LazyWrapper) {
+ result = result.value();
+ }
+ return arrayReduce(actions, function(result, action) {
+ return action.func.apply(action.thisArg, arrayPush([result], action.args));
+ }, result);
+ }
+
+ /**
+ * The base implementation of methods like `_.xor`, without support for
+ * iteratee shorthands, that accepts an array of arrays to inspect.
+ *
+ * @private
+ * @param {Array} arrays The arrays to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of values.
+ */
+ function baseXor(arrays, iteratee, comparator) {
+ var length = arrays.length;
+ if (length < 2) {
+ return length ? baseUniq(arrays[0]) : [];
+ }
+ var index = -1,
+ result = Array(length);
+
+ while (++index < length) {
+ var array = arrays[index],
+ othIndex = -1;
+
+ while (++othIndex < length) {
+ if (othIndex != index) {
+ result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
+ }
+ }
+ }
+ return baseUniq(baseFlatten(result, 1), iteratee, comparator);
+ }
+
+ /**
+ * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
+ *
+ * @private
+ * @param {Array} props The property identifiers.
+ * @param {Array} values The property values.
+ * @param {Function} assignFunc The function to assign values.
+ * @returns {Object} Returns the new object.
+ */
+ function baseZipObject(props, values, assignFunc) {
+ var index = -1,
+ length = props.length,
+ valsLength = values.length,
+ result = {};
+
+ while (++index < length) {
+ var value = index < valsLength ? values[index] : undefined$1;
+ assignFunc(result, props[index], value);
+ }
+ return result;
+ }
+
+ /**
+ * Casts `value` to an empty array if it's not an array like object.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array|Object} Returns the cast array-like object.
+ */
+ function castArrayLikeObject(value) {
+ return isArrayLikeObject(value) ? value : [];
+ }
+
+ /**
+ * Casts `value` to `identity` if it's not a function.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Function} Returns cast function.
+ */
+ function castFunction(value) {
+ return typeof value == 'function' ? value : identity;
+ }
+
+ /**
+ * Casts `value` to a path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {Array} Returns the cast property path array.
+ */
+ function castPath(value, object) {
+ if (isArray(value)) {
+ return value;
+ }
+ return isKey(value, object) ? [value] : stringToPath(toString(value));
+ }
+
+ /**
+ * A `baseRest` alias which can be replaced with `identity` by module
+ * replacement plugins.
+ *
+ * @private
+ * @type {Function}
+ * @param {Function} func The function to apply a rest parameter to.
+ * @returns {Function} Returns the new function.
+ */
+ var castRest = baseRest;
+
+ /**
+ * Casts `array` to a slice if it's needed.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {number} start The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the cast slice.
+ */
+ function castSlice(array, start, end) {
+ var length = array.length;
+ end = end === undefined$1 ? length : end;
+ return (!start && end >= length) ? array : baseSlice(array, start, end);
+ }
+
+ /**
+ * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
+ *
+ * @private
+ * @param {number|Object} id The timer id or timeout object of the timer to clear.
+ */
+ var clearTimeout = ctxClearTimeout || function(id) {
+ return root.clearTimeout(id);
+ };
+
+ /**
+ * Creates a clone of `buffer`.
+ *
+ * @private
+ * @param {Buffer} buffer The buffer to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Buffer} Returns the cloned buffer.
+ */
+ function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var length = buffer.length,
+ result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
+
+ buffer.copy(result);
+ return result;
+ }
+
+ /**
+ * Creates a clone of `arrayBuffer`.
+ *
+ * @private
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+ function cloneArrayBuffer(arrayBuffer) {
+ var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
+ new Uint8Array(result).set(new Uint8Array(arrayBuffer));
+ return result;
+ }
+
+ /**
+ * Creates a clone of `dataView`.
+ *
+ * @private
+ * @param {Object} dataView The data view to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned data view.
+ */
+ function cloneDataView(dataView, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
+ return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
+ }
+
+ /**
+ * Creates a clone of `regexp`.
+ *
+ * @private
+ * @param {Object} regexp The regexp to clone.
+ * @returns {Object} Returns the cloned regexp.
+ */
+ function cloneRegExp(regexp) {
+ var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
+ result.lastIndex = regexp.lastIndex;
+ return result;
+ }
+
+ /**
+ * Creates a clone of the `symbol` object.
+ *
+ * @private
+ * @param {Object} symbol The symbol object to clone.
+ * @returns {Object} Returns the cloned symbol object.
+ */
+ function cloneSymbol(symbol) {
+ return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
+ }
+
+ /**
+ * Creates a clone of `typedArray`.
+ *
+ * @private
+ * @param {Object} typedArray The typed array to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned typed array.
+ */
+ function cloneTypedArray(typedArray, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
+ }
+
+ /**
+ * Compares values to sort them in ascending order.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {number} Returns the sort order indicator for `value`.
+ */
+ function compareAscending(value, other) {
+ if (value !== other) {
+ var valIsDefined = value !== undefined$1,
+ valIsNull = value === null,
+ valIsReflexive = value === value,
+ valIsSymbol = isSymbol(value);
+
+ var othIsDefined = other !== undefined$1,
+ othIsNull = other === null,
+ othIsReflexive = other === other,
+ othIsSymbol = isSymbol(other);
+
+ if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
+ (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
+ (valIsNull && othIsDefined && othIsReflexive) ||
+ (!valIsDefined && othIsReflexive) ||
+ !valIsReflexive) {
+ return 1;
+ }
+ if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
+ (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
+ (othIsNull && valIsDefined && valIsReflexive) ||
+ (!othIsDefined && valIsReflexive) ||
+ !othIsReflexive) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Used by `_.orderBy` to compare multiple properties of a value to another
+ * and stable sort them.
+ *
+ * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
+ * specify an order of "desc" for descending or "asc" for ascending sort order
+ * of corresponding values.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {boolean[]|string[]} orders The order to sort by for each property.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareMultiple(object, other, orders) {
+ var index = -1,
+ objCriteria = object.criteria,
+ othCriteria = other.criteria,
+ length = objCriteria.length,
+ ordersLength = orders.length;
+
+ while (++index < length) {
+ var result = compareAscending(objCriteria[index], othCriteria[index]);
+ if (result) {
+ if (index >= ordersLength) {
+ return result;
+ }
+ var order = orders[index];
+ return result * (order == 'desc' ? -1 : 1);
+ }
+ }
+ // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+ // that causes it, under certain circumstances, to provide the same value for
+ // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+ // for more details.
+ //
+ // This also ensures a stable sort in V8 and other engines.
+ // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
+ return object.index - other.index;
+ }
+
+ /**
+ * Creates an array that is the composition of partially applied arguments,
+ * placeholders, and provided arguments into a single array of arguments.
+ *
+ * @private
+ * @param {Array} args The provided arguments.
+ * @param {Array} partials The arguments to prepend to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgs(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersLength = holders.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(leftLength + rangeLength),
+ isUncurried = !isCurried;
+
+ while (++leftIndex < leftLength) {
+ result[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result[holders[argsIndex]] = args[argsIndex];
+ }
+ }
+ while (rangeLength--) {
+ result[leftIndex++] = args[argsIndex++];
+ }
+ return result;
+ }
+
+ /**
+ * This function is like `composeArgs` except that the arguments composition
+ * is tailored for `_.partialRight`.
+ *
+ * @private
+ * @param {Array} args The provided arguments.
+ * @param {Array} partials The arguments to append to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgsRight(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersIndex = -1,
+ holdersLength = holders.length,
+ rightIndex = -1,
+ rightLength = partials.length,
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(rangeLength + rightLength),
+ isUncurried = !isCurried;
+
+ while (++argsIndex < rangeLength) {
+ result[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+ function copyArray(source, array) {
+ var index = -1,
+ length = source.length;
+
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
+
+ /**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property identifiers to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @param {Function} [customizer] The function to customize copied values.
+ * @returns {Object} Returns `object`.
+ */
+ function copyObject(source, props, object, customizer) {
+ var isNew = !object;
+ object || (object = {});
+
+ var index = -1,
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+
+ var newValue = customizer
+ ? customizer(object[key], source[key], key, object, source)
+ : undefined$1;
+
+ if (newValue === undefined$1) {
+ newValue = source[key];
+ }
+ if (isNew) {
+ baseAssignValue(object, key, newValue);
+ } else {
+ assignValue(object, key, newValue);
+ }
+ }
+ return object;
+ }
+
+ /**
+ * Copies own symbols of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+ function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+ }
+
+ /**
+ * Copies own and inherited symbols of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+ function copySymbolsIn(source, object) {
+ return copyObject(source, getSymbolsIn(source), object);
+ }
+
+ /**
+ * Creates a function like `_.groupBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} [initializer] The accumulator object initializer.
+ * @returns {Function} Returns the new aggregator function.
+ */
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee) {
+ var func = isArray(collection) ? arrayAggregator : baseAggregator,
+ accumulator = initializer ? initializer() : {};
+
+ return func(collection, setter, getIteratee(iteratee, 2), accumulator);
+ };
+ }
+
+ /**
+ * Creates a function like `_.assign`.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+ function createAssigner(assigner) {
+ return baseRest(function(object, sources) {
+ var index = -1,
+ length = sources.length,
+ customizer = length > 1 ? sources[length - 1] : undefined$1,
+ guard = length > 2 ? sources[2] : undefined$1;
+
+ customizer = (assigner.length > 3 && typeof customizer == 'function')
+ ? (length--, customizer)
+ : undefined$1;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined$1 : customizer;
+ length = 1;
+ }
+ object = Object(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+ }
+
+ /**
+ * Creates a `baseEach` or `baseEachRight` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee) {
+ if (collection == null) {
+ return collection;
+ }
+ if (!isArrayLike(collection)) {
+ return eachFunc(collection, iteratee);
+ }
+ var length = collection.length,
+ index = fromRight ? length : -1,
+ iterable = Object(collection);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (iteratee(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
+
+ /**
+ * Creates a base function for methods like `_.forIn` and `_.forOwn`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseFor(fromRight) {
+ return function(object, iteratee, keysFunc) {
+ var index = -1,
+ iterable = Object(object),
+ props = keysFunc(object),
+ length = props.length;
+
+ while (length--) {
+ var key = props[fromRight ? length : ++index];
+ if (iteratee(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with the optional `this`
+ * binding of `thisArg`.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createBind(func, bitmask, thisArg) {
+ var isBind = bitmask & WRAP_BIND_FLAG,
+ Ctor = createCtor(func);
+
+ function wrapper() {
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, arguments);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a function like `_.lowerFirst`.
+ *
+ * @private
+ * @param {string} methodName The name of the `String` case method to use.
+ * @returns {Function} Returns the new case function.
+ */
+ function createCaseFirst(methodName) {
+ return function(string) {
+ string = toString(string);
+
+ var strSymbols = hasUnicode(string)
+ ? stringToArray(string)
+ : undefined$1;
+
+ var chr = strSymbols
+ ? strSymbols[0]
+ : string.charAt(0);
+
+ var trailing = strSymbols
+ ? castSlice(strSymbols, 1).join('')
+ : string.slice(1);
+
+ return chr[methodName]() + trailing;
+ };
+ }
+
+ /**
+ * Creates a function like `_.camelCase`.
+ *
+ * @private
+ * @param {Function} callback The function to combine each word.
+ * @returns {Function} Returns the new compounder function.
+ */
+ function createCompounder(callback) {
+ return function(string) {
+ return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
+ };
+ }
+
+ /**
+ * Creates a function that produces an instance of `Ctor` regardless of
+ * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+ *
+ * @private
+ * @param {Function} Ctor The constructor to wrap.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCtor(Ctor) {
+ return function() {
+ // Use a `switch` statement to work with class constructors. See
+ // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
+ // for more details.
+ var args = arguments;
+ switch (args.length) {
+ case 0: return new Ctor;
+ case 1: return new Ctor(args[0]);
+ case 2: return new Ctor(args[0], args[1]);
+ case 3: return new Ctor(args[0], args[1], args[2]);
+ case 4: return new Ctor(args[0], args[1], args[2], args[3]);
+ case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ var thisBinding = baseCreate(Ctor.prototype),
+ result = Ctor.apply(thisBinding, args);
+
+ // Mimic the constructor's `return` behavior.
+ // See https://es5.github.io/#x13.2.2 for more details.
+ return isObject(result) ? result : thisBinding;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to enable currying.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {number} arity The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCurry(func, bitmask, arity) {
+ var Ctor = createCtor(func);
+
+ function wrapper() {
+ var length = arguments.length,
+ args = Array(length),
+ index = length,
+ placeholder = getHolder(wrapper);
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
+ ? []
+ : replaceHolders(args, placeholder);
+
+ length -= holders.length;
+ if (length < arity) {
+ return createRecurry(
+ func, bitmask, createHybrid, wrapper.placeholder, undefined$1,
+ args, holders, undefined$1, undefined$1, arity - length);
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return apply(fn, this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.find` or `_.findLast` function.
+ *
+ * @private
+ * @param {Function} findIndexFunc The function to find the collection index.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFind(findIndexFunc) {
+ return function(collection, predicate, fromIndex) {
+ var iterable = Object(collection);
+ if (!isArrayLike(collection)) {
+ var iteratee = getIteratee(predicate, 3);
+ collection = keys(collection);
+ predicate = function(key) { return iteratee(iterable[key], key, iterable); };
+ }
+ var index = findIndexFunc(collection, predicate, fromIndex);
+ return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined$1;
+ };
+ }
+
+ /**
+ * Creates a `_.flow` or `_.flowRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new flow function.
+ */
+ function createFlow(fromRight) {
+ return flatRest(function(funcs) {
+ var length = funcs.length,
+ index = length,
+ prereq = LodashWrapper.prototype.thru;
+
+ if (fromRight) {
+ funcs.reverse();
+ }
+ while (index--) {
+ var func = funcs[index];
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
+ var wrapper = new LodashWrapper([], true);
+ }
+ }
+ index = wrapper ? index : length;
+ while (++index < length) {
+ func = funcs[index];
+
+ var funcName = getFuncName(func),
+ data = funcName == 'wrapper' ? getData(func) : undefined$1;
+
+ if (data && isLaziable(data[0]) &&
+ data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
+ !data[4].length && data[9] == 1
+ ) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = (func.length == 1 && isLaziable(func))
+ ? wrapper[funcName]()
+ : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments,
+ value = args[0];
+
+ if (wrapper && args.length == 1 && isArray(value)) {
+ return wrapper.plant(value).value();
+ }
+ var index = 0,
+ result = length ? funcs[index].apply(this, args) : value;
+
+ while (++index < length) {
+ result = funcs[index].call(this, result);
+ }
+ return result;
+ };
+ });
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with optional `this`
+ * binding of `thisArg`, partial application, and currying.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to
+ * the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [partialsRight] The arguments to append to those provided
+ * to the new function.
+ * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
+ var isAry = bitmask & WRAP_ARY_FLAG,
+ isBind = bitmask & WRAP_BIND_FLAG,
+ isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
+ isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
+ isFlip = bitmask & WRAP_FLIP_FLAG,
+ Ctor = isBindKey ? undefined$1 : createCtor(func);
+
+ function wrapper() {
+ var length = arguments.length,
+ args = Array(length),
+ index = length;
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (isCurried) {
+ var placeholder = getHolder(wrapper),
+ holdersCount = countHolders(args, placeholder);
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders, isCurried);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
+ }
+ length -= holdersCount;
+ if (isCurried && length < arity) {
+ var newHolders = replaceHolders(args, placeholder);
+ return createRecurry(
+ func, bitmask, createHybrid, wrapper.placeholder, thisArg,
+ args, newHolders, argPos, ary, arity - length
+ );
+ }
+ var thisBinding = isBind ? thisArg : this,
+ fn = isBindKey ? thisBinding[func] : func;
+
+ length = args.length;
+ if (argPos) {
+ args = reorder(args, argPos);
+ } else if (isFlip && length > 1) {
+ args.reverse();
+ }
+ if (isAry && ary < length) {
+ args.length = ary;
+ }
+ if (this && this !== root && this instanceof wrapper) {
+ fn = Ctor || createCtor(fn);
+ }
+ return fn.apply(thisBinding, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a function like `_.invertBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} toIteratee The function to resolve iteratees.
+ * @returns {Function} Returns the new inverter function.
+ */
+ function createInverter(setter, toIteratee) {
+ return function(object, iteratee) {
+ return baseInverter(object, setter, toIteratee(iteratee), {});
+ };
+ }
+
+ /**
+ * Creates a function that performs a mathematical operation on two values.
+ *
+ * @private
+ * @param {Function} operator The function to perform the operation.
+ * @param {number} [defaultValue] The value used for `undefined` arguments.
+ * @returns {Function} Returns the new mathematical operation function.
+ */
+ function createMathOperation(operator, defaultValue) {
+ return function(value, other) {
+ var result;
+ if (value === undefined$1 && other === undefined$1) {
+ return defaultValue;
+ }
+ if (value !== undefined$1) {
+ result = value;
+ }
+ if (other !== undefined$1) {
+ if (result === undefined$1) {
+ return other;
+ }
+ if (typeof value == 'string' || typeof other == 'string') {
+ value = baseToString(value);
+ other = baseToString(other);
+ } else {
+ value = baseToNumber(value);
+ other = baseToNumber(other);
+ }
+ result = operator(value, other);
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function like `_.over`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over iteratees.
+ * @returns {Function} Returns the new over function.
+ */
+ function createOver(arrayFunc) {
+ return flatRest(function(iteratees) {
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+ return baseRest(function(args) {
+ var thisArg = this;
+ return arrayFunc(iteratees, function(iteratee) {
+ return apply(iteratee, thisArg, args);
+ });
+ });
+ });
+ }
+
+ /**
+ * Creates the padding for `string` based on `length`. The `chars` string
+ * is truncated if the number of characters exceeds `length`.
+ *
+ * @private
+ * @param {number} length The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padding for `string`.
+ */
+ function createPadding(length, chars) {
+ chars = chars === undefined$1 ? ' ' : baseToString(chars);
+
+ var charsLength = chars.length;
+ if (charsLength < 2) {
+ return charsLength ? baseRepeat(chars, length) : chars;
+ }
+ var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
+ return hasUnicode(chars)
+ ? castSlice(stringToArray(result), 0, length).join('')
+ : result.slice(0, length);
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with the `this` binding
+ * of `thisArg` and `partials` prepended to the arguments it receives.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} partials The arguments to prepend to those provided to
+ * the new function.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createPartial(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & WRAP_BIND_FLAG,
+ Ctor = createCtor(func);
+
+ function wrapper() {
+ var argsIndex = -1,
+ argsLength = arguments.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ args = Array(leftLength + argsLength),
+ fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ return apply(fn, isBind ? thisArg : this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.range` or `_.rangeRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new range function.
+ */
+ function createRange(fromRight) {
+ return function(start, end, step) {
+ if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
+ end = step = undefined$1;
+ }
+ // Ensure the sign of `-0` is preserved.
+ start = toFinite(start);
+ if (end === undefined$1) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ step = step === undefined$1 ? (start < end ? 1 : -1) : toFinite(step);
+ return baseRange(start, end, step, fromRight);
+ };
+ }
+
+ /**
+ * Creates a function that performs a relational operation on two values.
+ *
+ * @private
+ * @param {Function} operator The function to perform the operation.
+ * @returns {Function} Returns the new relational operation function.
+ */
+ function createRelationalOperation(operator) {
+ return function(value, other) {
+ if (!(typeof value == 'string' && typeof other == 'string')) {
+ value = toNumber(value);
+ other = toNumber(other);
+ }
+ return operator(value, other);
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to continue currying.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @param {Function} wrapFunc The function to create the `func` wrapper.
+ * @param {*} placeholder The placeholder value.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to
+ * the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
+ var isCurry = bitmask & WRAP_CURRY_FLAG,
+ newHolders = isCurry ? holders : undefined$1,
+ newHoldersRight = isCurry ? undefined$1 : holders,
+ newPartials = isCurry ? partials : undefined$1,
+ newPartialsRight = isCurry ? undefined$1 : partials;
+
+ bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
+ bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
+
+ if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
+ bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
+ }
+ var newData = [
+ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
+ newHoldersRight, argPos, ary, arity
+ ];
+
+ var result = wrapFunc.apply(undefined$1, newData);
+ if (isLaziable(func)) {
+ setData(result, newData);
+ }
+ result.placeholder = placeholder;
+ return setWrapToString(result, func, bitmask);
+ }
+
+ /**
+ * Creates a function like `_.round`.
+ *
+ * @private
+ * @param {string} methodName The name of the `Math` method to use when rounding.
+ * @returns {Function} Returns the new round function.
+ */
+ function createRound(methodName) {
+ var func = Math[methodName];
+ return function(number, precision) {
+ number = toNumber(number);
+ precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
+ if (precision && nativeIsFinite(number)) {
+ // Shift with exponential notation to avoid floating-point issues.
+ // See [MDN](https://mdn.io/round#Examples) for more details.
+ var pair = (toString(number) + 'e').split('e'),
+ value = func(pair[0] + 'e' + (+pair[1] + precision));
+
+ pair = (toString(value) + 'e').split('e');
+ return +(pair[0] + 'e' + (+pair[1] - precision));
+ }
+ return func(number);
+ };
+ }
+
+ /**
+ * Creates a set object of `values`.
+ *
+ * @private
+ * @param {Array} values The values to add to the set.
+ * @returns {Object} Returns the new set.
+ */
+ var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
+ return new Set(values);
+ };
+
+ /**
+ * Creates a `_.toPairs` or `_.toPairsIn` function.
+ *
+ * @private
+ * @param {Function} keysFunc The function to get the keys of a given object.
+ * @returns {Function} Returns the new pairs function.
+ */
+ function createToPairs(keysFunc) {
+ return function(object) {
+ var tag = getTag(object);
+ if (tag == mapTag) {
+ return mapToArray(object);
+ }
+ if (tag == setTag) {
+ return setToPairs(object);
+ }
+ return baseToPairs(object, keysFunc(object));
+ };
+ }
+
+ /**
+ * Creates a function that either curries or invokes `func` with optional
+ * `this` binding and partially applied arguments.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to wrap.
+ * @param {number} bitmask The bitmask flags.
+ * 1 - `_.bind`
+ * 2 - `_.bindKey`
+ * 4 - `_.curry` or `_.curryRight` of a bound function
+ * 8 - `_.curry`
+ * 16 - `_.curryRight`
+ * 32 - `_.partial`
+ * 64 - `_.partialRight`
+ * 128 - `_.rearg`
+ * 256 - `_.ary`
+ * 512 - `_.flip`
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to be partially applied.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
+ var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
+ partials = holders = undefined$1;
+ }
+ ary = ary === undefined$1 ? ary : nativeMax(toInteger(ary), 0);
+ arity = arity === undefined$1 ? arity : toInteger(arity);
+ length -= holders ? holders.length : 0;
+
+ if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials,
+ holdersRight = holders;
+
+ partials = holders = undefined$1;
+ }
+ var data = isBindKey ? undefined$1 : getData(func);
+
+ var newData = [
+ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
+ argPos, ary, arity
+ ];
+
+ if (data) {
+ mergeData(newData, data);
+ }
+ func = newData[0];
+ bitmask = newData[1];
+ thisArg = newData[2];
+ partials = newData[3];
+ holders = newData[4];
+ arity = newData[9] = newData[9] === undefined$1
+ ? (isBindKey ? 0 : func.length)
+ : nativeMax(newData[9] - length, 0);
+
+ if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
+ bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
+ }
+ if (!bitmask || bitmask == WRAP_BIND_FLAG) {
+ var result = createBind(func, bitmask, thisArg);
+ } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
+ result = createCurry(func, bitmask, arity);
+ } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
+ result = createPartial(func, bitmask, thisArg, partials);
+ } else {
+ result = createHybrid.apply(undefined$1, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setWrapToString(setter(result, newData), func, bitmask);
+ }
+
+ /**
+ * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
+ * of source objects to the destination object for all destination properties
+ * that resolve to `undefined`.
+ *
+ * @private
+ * @param {*} objValue The destination value.
+ * @param {*} srcValue The source value.
+ * @param {string} key The key of the property to assign.
+ * @param {Object} object The parent object of `objValue`.
+ * @returns {*} Returns the value to assign.
+ */
+ function customDefaultsAssignIn(objValue, srcValue, key, object) {
+ if (objValue === undefined$1 ||
+ (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
+ return srcValue;
+ }
+ return objValue;
+ }
+
+ /**
+ * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
+ * objects into destination objects that are passed thru.
+ *
+ * @private
+ * @param {*} objValue The destination value.
+ * @param {*} srcValue The source value.
+ * @param {string} key The key of the property to merge.
+ * @param {Object} object The parent object of `objValue`.
+ * @param {Object} source The parent object of `srcValue`.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ * @returns {*} Returns the value to assign.
+ */
+ function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
+ if (isObject(objValue) && isObject(srcValue)) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ stack.set(srcValue, objValue);
+ baseMerge(objValue, srcValue, undefined$1, customDefaultsMerge, stack);
+ stack['delete'](srcValue);
+ }
+ return objValue;
+ }
+
+ /**
+ * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
+ * objects.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @param {string} key The key of the property to inspect.
+ * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
+ */
+ function customOmitClone(value) {
+ return isPlainObject(value) ? undefined$1 : value;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `array` and `other` objects.
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ */
+ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
+ arrLength = array.length,
+ othLength = other.length;
+
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+ return false;
+ }
+ // Check that cyclic values are equal.
+ var arrStacked = stack.get(array);
+ var othStacked = stack.get(other);
+ if (arrStacked && othStacked) {
+ return arrStacked == other && othStacked == array;
+ }
+ var index = -1,
+ result = true,
+ seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined$1;
+
+ stack.set(array, other);
+ stack.set(other, array);
+
+ // Ignore non-index properties.
+ while (++index < arrLength) {
+ var arrValue = array[index],
+ othValue = other[index];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, arrValue, index, other, array, stack)
+ : customizer(arrValue, othValue, index, array, other, stack);
+ }
+ if (compared !== undefined$1) {
+ if (compared) {
+ continue;
+ }
+ result = false;
+ break;
+ }
+ // Recursively compare arrays (susceptible to call stack limits).
+ if (seen) {
+ if (!arraySome(other, function(othValue, othIndex) {
+ if (!cacheHas(seen, othIndex) &&
+ (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
+ return seen.push(othIndex);
+ }
+ })) {
+ result = false;
+ break;
+ }
+ } else if (!(
+ arrValue === othValue ||
+ equalFunc(arrValue, othValue, bitmask, customizer, stack)
+ )) {
+ result = false;
+ break;
+ }
+ }
+ stack['delete'](array);
+ stack['delete'](other);
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
+ * the same `toStringTag`.
+ *
+ * **Note:** This function only supports comparing values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {string} tag The `toStringTag` of the objects to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+ switch (tag) {
+ case dataViewTag:
+ if ((object.byteLength != other.byteLength) ||
+ (object.byteOffset != other.byteOffset)) {
+ return false;
+ }
+ object = object.buffer;
+ other = other.buffer;
+
+ case arrayBufferTag:
+ if ((object.byteLength != other.byteLength) ||
+ !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
+ return false;
+ }
+ return true;
+
+ case boolTag:
+ case dateTag:
+ case numberTag:
+ // Coerce booleans to `1` or `0` and dates to milliseconds.
+ // Invalid dates are coerced to `NaN`.
+ return eq(+object, +other);
+
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+
+ case regexpTag:
+ case stringTag:
+ // Coerce regexes to strings and treat strings, primitives and objects,
+ // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
+ // for more details.
+ return object == (other + '');
+
+ case mapTag:
+ var convert = mapToArray;
+
+ case setTag:
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
+ convert || (convert = setToArray);
+
+ if (object.size != other.size && !isPartial) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(object);
+ if (stacked) {
+ return stacked == other;
+ }
+ bitmask |= COMPARE_UNORDERED_FLAG;
+
+ // Recursively compare objects (susceptible to call stack limits).
+ stack.set(object, other);
+ var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+ stack['delete'](object);
+ return result;
+
+ case symbolTag:
+ if (symbolValueOf) {
+ return symbolValueOf.call(object) == symbolValueOf.call(other);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for objects with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
+ objProps = getAllKeys(object),
+ objLength = objProps.length,
+ othProps = getAllKeys(other),
+ othLength = othProps.length;
+
+ if (objLength != othLength && !isPartial) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
+ return false;
+ }
+ }
+ // Check that cyclic values are equal.
+ var objStacked = stack.get(object);
+ var othStacked = stack.get(other);
+ if (objStacked && othStacked) {
+ return objStacked == other && othStacked == object;
+ }
+ var result = true;
+ stack.set(object, other);
+ stack.set(other, object);
+
+ var skipCtor = isPartial;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key],
+ othValue = other[key];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, objValue, key, other, object, stack)
+ : customizer(objValue, othValue, key, object, other, stack);
+ }
+ // Recursively compare objects (susceptible to call stack limits).
+ if (!(compared === undefined$1
+ ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
+ : compared
+ )) {
+ result = false;
+ break;
+ }
+ skipCtor || (skipCtor = key == 'constructor');
+ }
+ if (result && !skipCtor) {
+ var objCtor = object.constructor,
+ othCtor = other.constructor;
+
+ // Non `Object` object instances with different constructors are not equal.
+ if (objCtor != othCtor &&
+ ('constructor' in object && 'constructor' in other) &&
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+ result = false;
+ }
+ }
+ stack['delete'](object);
+ stack['delete'](other);
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseRest` which flattens the rest array.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @returns {Function} Returns the new function.
+ */
+ function flatRest(func) {
+ return setToString(overRest(func, undefined$1, flatten), func + '');
+ }
+
+ /**
+ * Creates an array of own enumerable property names and symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+ function getAllKeys(object) {
+ return baseGetAllKeys(object, keys, getSymbols);
+ }
+
+ /**
+ * Creates an array of own and inherited enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+ function getAllKeysIn(object) {
+ return baseGetAllKeys(object, keysIn, getSymbolsIn);
+ }
+
+ /**
+ * Gets metadata for `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {*} Returns the metadata for `func`.
+ */
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
+
+ /**
+ * Gets the name of `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {string} Returns the function name.
+ */
+ function getFuncName(func) {
+ var result = (func.name + ''),
+ array = realNames[result],
+ length = hasOwnProperty.call(realNames, result) ? array.length : 0;
+
+ while (length--) {
+ var data = array[length],
+ otherFunc = data.func;
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the argument placeholder value for `func`.
+ *
+ * @private
+ * @param {Function} func The function to inspect.
+ * @returns {*} Returns the placeholder value.
+ */
+ function getHolder(func) {
+ var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
+ return object.placeholder;
+ }
+
+ /**
+ * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
+ * this function returns the custom method, otherwise it returns `baseIteratee`.
+ * If arguments are provided, the chosen function is invoked with them and
+ * its result is returned.
+ *
+ * @private
+ * @param {*} [value] The value to convert to an iteratee.
+ * @param {number} [arity] The arity of the created iteratee.
+ * @returns {Function} Returns the chosen function or its result.
+ */
+ function getIteratee() {
+ var result = lodash.iteratee || iteratee;
+ result = result === iteratee ? baseIteratee : result;
+ return arguments.length ? result(arguments[0], arguments[1]) : result;
+ }
+
+ /**
+ * Gets the data for `map`.
+ *
+ * @private
+ * @param {Object} map The map to query.
+ * @param {string} key The reference key.
+ * @returns {*} Returns the map data.
+ */
+ function getMapData(map, key) {
+ var data = map.__data__;
+ return isKeyable(key)
+ ? data[typeof key == 'string' ? 'string' : 'hash']
+ : data.map;
+ }
+
+ /**
+ * Gets the property names, values, and compare flags of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the match data of `object`.
+ */
+ function getMatchData(object) {
+ var result = keys(object),
+ length = result.length;
+
+ while (length--) {
+ var key = result[length],
+ value = object[key];
+
+ result[length] = [key, value, isStrictComparable(value)];
+ }
+ return result;
+ }
+
+ /**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+ function getNative(object, key) {
+ var value = getValue(object, key);
+ return baseIsNative(value) ? value : undefined$1;
+ }
+
+ /**
+ * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the raw `toStringTag`.
+ */
+ function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag),
+ tag = value[symToStringTag];
+
+ try {
+ value[symToStringTag] = undefined$1;
+ var unmasked = true;
+ } catch (e) {}
+
+ var result = nativeObjectToString.call(value);
+ if (unmasked) {
+ if (isOwn) {
+ value[symToStringTag] = tag;
+ } else {
+ delete value[symToStringTag];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of the own enumerable symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+ var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
+ if (object == null) {
+ return [];
+ }
+ object = Object(object);
+ return arrayFilter(nativeGetSymbols(object), function(symbol) {
+ return propertyIsEnumerable.call(object, symbol);
+ });
+ };
+
+ /**
+ * Creates an array of the own and inherited enumerable symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+ var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
+ var result = [];
+ while (object) {
+ arrayPush(result, getSymbols(object));
+ object = getPrototype(object);
+ }
+ return result;
+ };
+
+ /**
+ * Gets the `toStringTag` of `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+ var getTag = baseGetTag;
+
+ // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
+ if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
+ (Map && getTag(new Map) != mapTag) ||
+ (Promise && getTag(Promise.resolve()) != promiseTag) ||
+ (Set && getTag(new Set) != setTag) ||
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
+ getTag = function(value) {
+ var result = baseGetTag(value),
+ Ctor = result == objectTag ? value.constructor : undefined$1,
+ ctorString = Ctor ? toSource(Ctor) : '';
+
+ if (ctorString) {
+ switch (ctorString) {
+ case dataViewCtorString: return dataViewTag;
+ case mapCtorString: return mapTag;
+ case promiseCtorString: return promiseTag;
+ case setCtorString: return setTag;
+ case weakMapCtorString: return weakMapTag;
+ }
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Gets the view, applying any `transforms` to the `start` and `end` positions.
+ *
+ * @private
+ * @param {number} start The start of the view.
+ * @param {number} end The end of the view.
+ * @param {Array} transforms The transformations to apply to the view.
+ * @returns {Object} Returns an object containing the `start` and `end`
+ * positions of the view.
+ */
+ function getView(start, end, transforms) {
+ var index = -1,
+ length = transforms.length;
+
+ while (++index < length) {
+ var data = transforms[index],
+ size = data.size;
+
+ switch (data.type) {
+ case 'drop': start += size; break;
+ case 'dropRight': end -= size; break;
+ case 'take': end = nativeMin(end, start + size); break;
+ case 'takeRight': start = nativeMax(start, end - size); break;
+ }
+ }
+ return { 'start': start, 'end': end };
+ }
+
+ /**
+ * Extracts wrapper details from the `source` body comment.
+ *
+ * @private
+ * @param {string} source The source to inspect.
+ * @returns {Array} Returns the wrapper details.
+ */
+ function getWrapDetails(source) {
+ var match = source.match(reWrapDetails);
+ return match ? match[1].split(reSplitDetails) : [];
+ }
+
+ /**
+ * Checks if `path` exists on `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @param {Function} hasFunc The function to check properties.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ */
+ function hasPath(object, path, hasFunc) {
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ result = false;
+
+ while (++index < length) {
+ var key = toKey(path[index]);
+ if (!(result = object != null && hasFunc(object, key))) {
+ break;
+ }
+ object = object[key];
+ }
+ if (result || ++index != length) {
+ return result;
+ }
+ length = object == null ? 0 : object.length;
+ return !!length && isLength(length) && isIndex(key, length) &&
+ (isArray(object) || isArguments(object));
+ }
+
+ /**
+ * Initializes an array clone.
+ *
+ * @private
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
+ */
+ function initCloneArray(array) {
+ var length = array.length,
+ result = new array.constructor(length);
+
+ // Add properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
+ }
+ return result;
+ }
+
+ /**
+ * Initializes an object clone.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneObject(object) {
+ return (typeof object.constructor == 'function' && !isPrototype(object))
+ ? baseCreate(getPrototype(object))
+ : {};
+ }
+
+ /**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+
+ case dataViewTag:
+ return cloneDataView(object, isDeep);
+
+ case float32Tag: case float64Tag:
+ case int8Tag: case int16Tag: case int32Tag:
+ case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+
+ case mapTag:
+ return new Ctor;
+
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ return cloneRegExp(object);
+
+ case setTag:
+ return new Ctor;
+
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+ }
+
+ /**
+ * Inserts wrapper `details` in a comment at the top of the `source` body.
+ *
+ * @private
+ * @param {string} source The source to modify.
+ * @returns {Array} details The details to insert.
+ * @returns {string} Returns the modified source.
+ */
+ function insertWrapDetails(source, details) {
+ var length = details.length;
+ if (!length) {
+ return source;
+ }
+ var lastIndex = length - 1;
+ details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
+ details = details.join(length > 2 ? ', ' : ' ');
+ return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
+ }
+
+ /**
+ * Checks if `value` is a flattenable `arguments` object or array.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
+ */
+ function isFlattenable(value) {
+ return isArray(value) || isArguments(value) ||
+ !!(spreadableSymbol && value && value[spreadableSymbol]);
+ }
+
+ /**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+ function isIndex(value, length) {
+ var type = typeof value;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+
+ return !!length &&
+ (type == 'number' ||
+ (type != 'symbol' && reIsUint.test(value))) &&
+ (value > -1 && value % 1 == 0 && value < length);
+ }
+
+ /**
+ * Checks if the given arguments are from an iteratee call.
+ *
+ * @private
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
+ * else `false`.
+ */
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)
+ ) {
+ return eq(object[index], value);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if `value` is a property name and not a property path.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+ */
+ function isKey(value, object) {
+ if (isArray(value)) {
+ return false;
+ }
+ var type = typeof value;
+ if (type == 'number' || type == 'symbol' || type == 'boolean' ||
+ value == null || isSymbol(value)) {
+ return true;
+ }
+ return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
+ (object != null && value in Object(object));
+ }
+
+ /**
+ * Checks if `value` is suitable for use as unique object key.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
+ */
+ function isKeyable(value) {
+ var type = typeof value;
+ return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
+ ? (value !== '__proto__')
+ : (value === null);
+ }
+
+ /**
+ * Checks if `func` has a lazy counterpart.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
+ * else `false`.
+ */
+ function isLaziable(func) {
+ var funcName = getFuncName(func),
+ other = lodash[funcName];
+
+ if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
+ return false;
+ }
+ if (func === other) {
+ return true;
+ }
+ var data = getData(other);
+ return !!data && func === data[0];
+ }
+
+ /**
+ * Checks if `func` has its source masked.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` is masked, else `false`.
+ */
+ function isMasked(func) {
+ return !!maskSrcKey && (maskSrcKey in func);
+ }
+
+ /**
+ * Checks if `func` is capable of being masked.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
+ */
+ var isMaskable = coreJsData ? isFunction : stubFalse;
+
+ /**
+ * Checks if `value` is likely a prototype object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
+ */
+ function isPrototype(value) {
+ var Ctor = value && value.constructor,
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+
+ return value === proto;
+ }
+
+ /**
+ * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` if suitable for strict
+ * equality comparisons, else `false`.
+ */
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
+ }
+
+ /**
+ * A specialized version of `matchesProperty` for source values suitable
+ * for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ */
+ function matchesStrictComparable(key, srcValue) {
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === srcValue &&
+ (srcValue !== undefined$1 || (key in Object(object)));
+ };
+ }
+
+ /**
+ * A specialized version of `_.memoize` which clears the memoized function's
+ * cache when it exceeds `MAX_MEMOIZE_SIZE`.
+ *
+ * @private
+ * @param {Function} func The function to have its output memoized.
+ * @returns {Function} Returns the new memoized function.
+ */
+ function memoizeCapped(func) {
+ var result = memoize(func, function(key) {
+ if (cache.size === MAX_MEMOIZE_SIZE) {
+ cache.clear();
+ }
+ return key;
+ });
+
+ var cache = result.cache;
+ return result;
+ }
+
+ /**
+ * Merges the function metadata of `source` into `data`.
+ *
+ * Merging metadata reduces the number of wrappers used to invoke a function.
+ * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
+ * may be applied regardless of execution order. Methods like `_.ary` and
+ * `_.rearg` modify function arguments, making the order in which they are
+ * executed important, preventing the merging of metadata. However, we make
+ * an exception for a safe combined case where curried functions have `_.ary`
+ * and or `_.rearg` applied.
+ *
+ * @private
+ * @param {Array} data The destination metadata.
+ * @param {Array} source The source metadata.
+ * @returns {Array} Returns `data`.
+ */
+ function mergeData(data, source) {
+ var bitmask = data[1],
+ srcBitmask = source[1],
+ newBitmask = bitmask | srcBitmask,
+ isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
+
+ var isCombo =
+ ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
+ ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
+ ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
+
+ // Exit early if metadata can't be merged.
+ if (!(isCommon || isCombo)) {
+ return data;
+ }
+ // Use source `thisArg` if available.
+ if (srcBitmask & WRAP_BIND_FLAG) {
+ data[2] = source[2];
+ // Set when currying a bound function.
+ newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
+ }
+ // Compose partial arguments.
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : value;
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
+ }
+ // Compose partial right arguments.
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
+ }
+ // Use source `argPos` if available.
+ value = source[7];
+ if (value) {
+ data[7] = value;
+ }
+ // Use source `ary` if it's smaller.
+ if (srcBitmask & WRAP_ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ // Use source `arity` if one is not provided.
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ // Use source `func` and merge bitmasks.
+ data[0] = source[0];
+ data[1] = newBitmask;
+
+ return data;
+ }
+
+ /**
+ * This function is like
+ * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * except that it includes inherited enumerable properties.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function nativeKeysIn(object) {
+ var result = [];
+ if (object != null) {
+ for (var key in Object(object)) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts `value` to a string using `Object.prototype.toString`.
+ *
+ * @private
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ */
+ function objectToString(value) {
+ return nativeObjectToString.call(value);
+ }
+
+ /**
+ * A specialized version of `baseRest` which transforms the rest array.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @param {Function} transform The rest array transform.
+ * @returns {Function} Returns the new function.
+ */
+ function overRest(func, start, transform) {
+ start = nativeMax(start === undefined$1 ? (func.length - 1) : start, 0);
+ return function() {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ array = Array(length);
+
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ index = -1;
+ var otherArgs = Array(start + 1);
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = transform(array);
+ return apply(func, this, otherArgs);
+ };
+ }
+
+ /**
+ * Gets the parent value at `path` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} path The path to get the parent value of.
+ * @returns {*} Returns the parent value.
+ */
+ function parent(object, path) {
+ return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
+ }
+
+ /**
+ * Reorder `array` according to the specified indexes where the element at
+ * the first index is assigned as the first element, the element at
+ * the second index is assigned as the second element, and so on.
+ *
+ * @private
+ * @param {Array} array The array to reorder.
+ * @param {Array} indexes The arranged array indexes.
+ * @returns {Array} Returns `array`.
+ */
+ function reorder(array, indexes) {
+ var arrLength = array.length,
+ length = nativeMin(indexes.length, arrLength),
+ oldArray = copyArray(array);
+
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined$1;
+ }
+ return array;
+ }
+
+ /**
+ * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the property to get.
+ * @returns {*} Returns the property value.
+ */
+ function safeGet(object, key) {
+ if (key === 'constructor' && typeof object[key] === 'function') {
+ return;
+ }
+
+ if (key == '__proto__') {
+ return;
+ }
+
+ return object[key];
+ }
+
+ /**
+ * Sets metadata for `func`.
+ *
+ * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
+ * period of time, it will trip its breaker and transition to an identity
+ * function to avoid garbage collection pauses in V8. See
+ * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
+ * for more details.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var setData = shortOut(baseSetData);
+
+ /**
+ * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @returns {number|Object} Returns the timer id or timeout object.
+ */
+ var setTimeout = ctxSetTimeout || function(func, wait) {
+ return root.setTimeout(func, wait);
+ };
+
+ /**
+ * Sets the `toString` method of `func` to return `string`.
+ *
+ * @private
+ * @param {Function} func The function to modify.
+ * @param {Function} string The `toString` result.
+ * @returns {Function} Returns `func`.
+ */
+ var setToString = shortOut(baseSetToString);
+
+ /**
+ * Sets the `toString` method of `wrapper` to mimic the source of `reference`
+ * with wrapper details in a comment at the top of the source body.
+ *
+ * @private
+ * @param {Function} wrapper The function to modify.
+ * @param {Function} reference The reference function.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @returns {Function} Returns `wrapper`.
+ */
+ function setWrapToString(wrapper, reference, bitmask) {
+ var source = (reference + '');
+ return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
+ }
+
+ /**
+ * Creates a function that'll short out and invoke `identity` instead
+ * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
+ * milliseconds.
+ *
+ * @private
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new shortable function.
+ */
+ function shortOut(func) {
+ var count = 0,
+ lastCalled = 0;
+
+ return function() {
+ var stamp = nativeNow(),
+ remaining = HOT_SPAN - (stamp - lastCalled);
+
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return arguments[0];
+ }
+ } else {
+ count = 0;
+ }
+ return func.apply(undefined$1, arguments);
+ };
+ }
+
+ /**
+ * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
+ *
+ * @private
+ * @param {Array} array The array to shuffle.
+ * @param {number} [size=array.length] The size of `array`.
+ * @returns {Array} Returns `array`.
+ */
+ function shuffleSelf(array, size) {
+ var index = -1,
+ length = array.length,
+ lastIndex = length - 1;
+
+ size = size === undefined$1 ? length : size;
+ while (++index < size) {
+ var rand = baseRandom(index, lastIndex),
+ value = array[rand];
+
+ array[rand] = array[index];
+ array[index] = value;
+ }
+ array.length = size;
+ return array;
+ }
+
+ /**
+ * Converts `string` to a property path array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the property path array.
+ */
+ var stringToPath = memoizeCapped(function(string) {
+ var result = [];
+ if (string.charCodeAt(0) === 46 /* . */) {
+ result.push('');
+ }
+ string.replace(rePropName, function(match, number, quote, subString) {
+ result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
+ });
+
+ /**
+ * Converts `value` to a string key if it's not a string or symbol.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {string|symbol} Returns the key.
+ */
+ function toKey(value) {
+ if (typeof value == 'string' || isSymbol(value)) {
+ return value;
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+ }
+
+ /**
+ * Converts `func` to its source code.
+ *
+ * @private
+ * @param {Function} func The function to convert.
+ * @returns {string} Returns the source code.
+ */
+ function toSource(func) {
+ if (func != null) {
+ try {
+ return funcToString.call(func);
+ } catch (e) {}
+ try {
+ return (func + '');
+ } catch (e) {}
+ }
+ return '';
+ }
+
+ /**
+ * Updates wrapper `details` based on `bitmask` flags.
+ *
+ * @private
+ * @returns {Array} details The details to modify.
+ * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
+ * @returns {Array} Returns `details`.
+ */
+ function updateWrapDetails(details, bitmask) {
+ arrayEach(wrapFlags, function(pair) {
+ var value = '_.' + pair[0];
+ if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
+ details.push(value);
+ }
+ });
+ return details.sort();
+ }
+
+ /**
+ * Creates a clone of `wrapper`.
+ *
+ * @private
+ * @param {Object} wrapper The wrapper to clone.
+ * @returns {Object} Returns the cloned wrapper.
+ */
+ function wrapperClone(wrapper) {
+ if (wrapper instanceof LazyWrapper) {
+ return wrapper.clone();
+ }
+ var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
+ result.__actions__ = copyArray(wrapper.__actions__);
+ result.__index__ = wrapper.__index__;
+ result.__values__ = wrapper.__values__;
+ return result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of elements split into groups the length of `size`.
+ * If `array` can't be split evenly, the final chunk will be the remaining
+ * elements.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to process.
+ * @param {number} [size=1] The length of each chunk
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the new array of chunks.
+ * @example
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 2);
+ * // => [['a', 'b'], ['c', 'd']]
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 3);
+ * // => [['a', 'b', 'c'], ['d']]
+ */
+ function chunk(array, size, guard) {
+ if ((guard ? isIterateeCall(array, size, guard) : size === undefined$1)) {
+ size = 1;
+ } else {
+ size = nativeMax(toInteger(size), 0);
+ }
+ var length = array == null ? 0 : array.length;
+ if (!length || size < 1) {
+ return [];
+ }
+ var index = 0,
+ resIndex = 0,
+ result = Array(nativeCeil(length / size));
+
+ while (index < length) {
+ result[resIndex++] = baseSlice(array, index, (index += size));
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array with all falsey values removed. The values `false`, `null`,
+ * `0`, `""`, `undefined`, and `NaN` are falsey.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
+ */
+ function compact(array) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates a new array concatenating `array` with any additional arrays
+ * and/or values.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to concatenate.
+ * @param {...*} [values] The values to concatenate.
+ * @returns {Array} Returns the new concatenated array.
+ * @example
+ *
+ * var array = [1];
+ * var other = _.concat(array, 2, [3], [[4]]);
+ *
+ * console.log(other);
+ * // => [1, 2, 3, [4]]
+ *
+ * console.log(array);
+ * // => [1]
+ */
+ function concat() {
+ var length = arguments.length;
+ if (!length) {
+ return [];
+ }
+ var args = Array(length - 1),
+ array = arguments[0],
+ index = length;
+
+ while (index--) {
+ args[index - 1] = arguments[index];
+ }
+ return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
+ }
+
+ /**
+ * Creates an array of `array` values not included in the other given arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons. The order and references of result values are
+ * determined by the first array.
+ *
+ * **Note:** Unlike `_.pullAll`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @see _.without, _.xor
+ * @example
+ *
+ * _.difference([2, 1], [2, 3]);
+ * // => [1]
+ */
+ var difference = baseRest(function(array, values) {
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
+ : [];
+ });
+
+ /**
+ * This method is like `_.difference` except that it accepts `iteratee` which
+ * is invoked for each element of `array` and `values` to generate the criterion
+ * by which they're compared. The order and references of result values are
+ * determined by the first array. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
+ * // => [1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
+ * // => [{ 'x': 2 }]
+ */
+ var differenceBy = baseRest(function(array, values) {
+ var iteratee = last(values);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined$1;
+ }
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
+ : [];
+ });
+
+ /**
+ * This method is like `_.difference` except that it accepts `comparator`
+ * which is invoked to compare elements of `array` to `values`. The order and
+ * references of result values are determined by the first array. The comparator
+ * is invoked with two arguments: (arrVal, othVal).
+ *
+ * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ *
+ * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
+ * // => [{ 'x': 2, 'y': 1 }]
+ */
+ var differenceWith = baseRest(function(array, values) {
+ var comparator = last(values);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined$1;
+ }
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined$1, comparator)
+ : [];
+ });
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.drop([1, 2, 3]);
+ * // => [2, 3]
+ *
+ * _.drop([1, 2, 3], 2);
+ * // => [3]
+ *
+ * _.drop([1, 2, 3], 5);
+ * // => []
+ *
+ * _.drop([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function drop(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined$1) ? 1 : toInteger(n);
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the end.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropRight([1, 2, 3]);
+ * // => [1, 2]
+ *
+ * _.dropRight([1, 2, 3], 2);
+ * // => [1]
+ *
+ * _.dropRight([1, 2, 3], 5);
+ * // => []
+ *
+ * _.dropRight([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function dropRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined$1) ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the end.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.dropRightWhile(users, function(o) { return !o.active; });
+ * // => objects for ['barney']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.dropRightWhile(users, ['active', false]);
+ * // => objects for ['barney']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.dropRightWhile(users, 'active');
+ * // => objects for ['barney', 'fred', 'pebbles']
+ */
+ function dropRightWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), true, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the beginning.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.dropWhile(users, function(o) { return !o.active; });
+ * // => objects for ['pebbles']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.dropWhile(users, { 'user': 'barney', 'active': false });
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.dropWhile(users, ['active', false]);
+ * // => objects for ['pebbles']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.dropWhile(users, 'active');
+ * // => objects for ['barney', 'fred', 'pebbles']
+ */
+ function dropWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), true)
+ : [];
+ }
+
+ /**
+ * Fills elements of `array` with `value` from `start` up to, but not
+ * including, `end`.
+ *
+ * **Note:** This method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.2.0
+ * @category Array
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.fill(array, 'a');
+ * console.log(array);
+ * // => ['a', 'a', 'a']
+ *
+ * _.fill(Array(3), 2);
+ * // => [2, 2, 2]
+ *
+ * _.fill([4, 6, 8, 10], '*', 1, 3);
+ * // => [4, '*', '*', 10]
+ */
+ function fill(array, value, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
+ }
+ return baseFill(array, value, start, end);
+ }
+
+ /**
+ * This method is like `_.find` except that it returns the index of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.findIndex(users, function(o) { return o.user == 'barney'; });
+ * // => 0
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findIndex(users, { 'user': 'fred', 'active': false });
+ * // => 1
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findIndex(users, ['active', false]);
+ * // => 0
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findIndex(users, 'active');
+ * // => 2
+ */
+ function findIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index);
+ }
+
+ /**
+ * This method is like `_.findIndex` except that it iterates over elements
+ * of `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=array.length-1] The index to search from.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
+ * // => 2
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findLastIndex(users, { 'user': 'barney', 'active': true });
+ * // => 0
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findLastIndex(users, ['active', false]);
+ * // => 2
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findLastIndex(users, 'active');
+ * // => 0
+ */
+ function findLastIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length - 1;
+ if (fromIndex !== undefined$1) {
+ index = toInteger(fromIndex);
+ index = fromIndex < 0
+ ? nativeMax(length + index, 0)
+ : nativeMin(index, length - 1);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index, true);
+ }
+
+ /**
+ * Flattens `array` a single level deep.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, [3, [4]], 5]
+ */
+ function flatten(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, 1) : [];
+ }
+
+ /**
+ * Recursively flattens `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flattenDeep([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, 3, 4, 5]
+ */
+ function flattenDeep(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, INFINITY) : [];
+ }
+
+ /**
+ * Recursively flatten `array` up to `depth` times.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.4.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @param {number} [depth=1] The maximum recursion depth.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * var array = [1, [2, [3, [4]], 5]];
+ *
+ * _.flattenDepth(array, 1);
+ * // => [1, 2, [3, [4]], 5]
+ *
+ * _.flattenDepth(array, 2);
+ * // => [1, 2, 3, [4], 5]
+ */
+ function flattenDepth(array, depth) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ depth = depth === undefined$1 ? 1 : toInteger(depth);
+ return baseFlatten(array, depth);
+ }
+
+ /**
+ * The inverse of `_.toPairs`; this method returns an object composed
+ * from key-value `pairs`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} pairs The key-value pairs.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.fromPairs([['a', 1], ['b', 2]]);
+ * // => { 'a': 1, 'b': 2 }
+ */
+ function fromPairs(pairs) {
+ var index = -1,
+ length = pairs == null ? 0 : pairs.length,
+ result = {};
+
+ while (++index < length) {
+ var pair = pairs[index];
+ result[pair[0]] = pair[1];
+ }
+ return result;
+ }
+
+ /**
+ * Gets the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @alias first
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the first element of `array`.
+ * @example
+ *
+ * _.head([1, 2, 3]);
+ * // => 1
+ *
+ * _.head([]);
+ * // => undefined
+ */
+ function head(array) {
+ return (array && array.length) ? array[0] : undefined$1;
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `value` is found in `array`
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it's used as the
+ * offset from the end of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 1, 2], 2);
+ * // => 1
+ *
+ * // Search from the `fromIndex`.
+ * _.indexOf([1, 2, 1, 2], 2, 2);
+ * // => 3
+ */
+ function indexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseIndexOf(array, value, index);
+ }
+
+ /**
+ * Gets all but the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.initial([1, 2, 3]);
+ * // => [1, 2]
+ */
+ function initial(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 0, -1) : [];
+ }
+
+ /**
+ * Creates an array of unique values that are included in all given arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons. The order and references of result values are
+ * determined by the first array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of intersecting values.
+ * @example
+ *
+ * _.intersection([2, 1], [2, 3]);
+ * // => [2]
+ */
+ var intersection = baseRest(function(arrays) {
+ var mapped = arrayMap(arrays, castArrayLikeObject);
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped)
+ : [];
+ });
+
+ /**
+ * This method is like `_.intersection` except that it accepts `iteratee`
+ * which is invoked for each element of each `arrays` to generate the criterion
+ * by which they're compared. The order and references of result values are
+ * determined by the first array. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of intersecting values.
+ * @example
+ *
+ * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
+ * // => [2.1]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }]
+ */
+ var intersectionBy = baseRest(function(arrays) {
+ var iteratee = last(arrays),
+ mapped = arrayMap(arrays, castArrayLikeObject);
+
+ if (iteratee === last(mapped)) {
+ iteratee = undefined$1;
+ } else {
+ mapped.pop();
+ }
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped, getIteratee(iteratee, 2))
+ : [];
+ });
+
+ /**
+ * This method is like `_.intersection` except that it accepts `comparator`
+ * which is invoked to compare elements of `arrays`. The order and references
+ * of result values are determined by the first array. The comparator is
+ * invoked with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of intersecting values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.intersectionWith(objects, others, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }]
+ */
+ var intersectionWith = baseRest(function(arrays) {
+ var comparator = last(arrays),
+ mapped = arrayMap(arrays, castArrayLikeObject);
+
+ comparator = typeof comparator == 'function' ? comparator : undefined$1;
+ if (comparator) {
+ mapped.pop();
+ }
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped, undefined$1, comparator)
+ : [];
+ });
+
+ /**
+ * Converts all elements in `array` into a string separated by `separator`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to convert.
+ * @param {string} [separator=','] The element separator.
+ * @returns {string} Returns the joined string.
+ * @example
+ *
+ * _.join(['a', 'b', 'c'], '~');
+ * // => 'a~b~c'
+ */
+ function join(array, separator) {
+ return array == null ? '' : nativeJoin.call(array, separator);
+ }
+
+ /**
+ * Gets the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the last element of `array`.
+ * @example
+ *
+ * _.last([1, 2, 3]);
+ * // => 3
+ */
+ function last(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? array[length - 1] : undefined$1;
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it iterates over elements of
+ * `array` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=array.length-1] The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 1, 2], 2);
+ * // => 3
+ *
+ * // Search from the `fromIndex`.
+ * _.lastIndexOf([1, 2, 1, 2], 2, 2);
+ * // => 1
+ */
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (fromIndex !== undefined$1) {
+ index = toInteger(fromIndex);
+ index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
+ }
+ return value === value
+ ? strictLastIndexOf(array, value, index)
+ : baseFindIndex(array, baseIsNaN, index, true);
+ }
+
+ /**
+ * Gets the element at index `n` of `array`. If `n` is negative, the nth
+ * element from the end is returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.11.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=0] The index of the element to return.
+ * @returns {*} Returns the nth element of `array`.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'd'];
+ *
+ * _.nth(array, 1);
+ * // => 'b'
+ *
+ * _.nth(array, -2);
+ * // => 'c';
+ */
+ function nth(array, n) {
+ return (array && array.length) ? baseNth(array, toInteger(n)) : undefined$1;
+ }
+
+ /**
+ * Removes all given values from `array` using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
+ * to remove elements from an array by predicate.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...*} [values] The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
+ *
+ * _.pull(array, 'a', 'c');
+ * console.log(array);
+ * // => ['b', 'b']
+ */
+ var pull = baseRest(pullAll);
+
+ /**
+ * This method is like `_.pull` except that it accepts an array of values to remove.
+ *
+ * **Note:** Unlike `_.difference`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
+ *
+ * _.pullAll(array, ['a', 'c']);
+ * console.log(array);
+ * // => ['b', 'b']
+ */
+ function pullAll(array, values) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values)
+ : array;
+ }
+
+ /**
+ * This method is like `_.pullAll` except that it accepts `iteratee` which is
+ * invoked for each element of `array` and `values` to generate the criterion
+ * by which they're compared. The iteratee is invoked with one argument: (value).
+ *
+ * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
+ *
+ * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
+ * console.log(array);
+ * // => [{ 'x': 2 }]
+ */
+ function pullAllBy(array, values, iteratee) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values, getIteratee(iteratee, 2))
+ : array;
+ }
+
+ /**
+ * This method is like `_.pullAll` except that it accepts `comparator` which
+ * is invoked to compare elements of `array` to `values`. The comparator is
+ * invoked with two arguments: (arrVal, othVal).
+ *
+ * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.6.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
+ *
+ * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
+ * console.log(array);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
+ */
+ function pullAllWith(array, values, comparator) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values, undefined$1, comparator)
+ : array;
+ }
+
+ /**
+ * Removes elements from `array` corresponding to `indexes` and returns an
+ * array of removed elements.
+ *
+ * **Note:** Unlike `_.at`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...(number|number[])} [indexes] The indexes of elements to remove.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = ['a', 'b', 'c', 'd'];
+ * var pulled = _.pullAt(array, [1, 3]);
+ *
+ * console.log(array);
+ * // => ['a', 'c']
+ *
+ * console.log(pulled);
+ * // => ['b', 'd']
+ */
+ var pullAt = flatRest(function(array, indexes) {
+ var length = array == null ? 0 : array.length,
+ result = baseAt(array, indexes);
+
+ basePullAt(array, arrayMap(indexes, function(index) {
+ return isIndex(index, length) ? +index : index;
+ }).sort(compareAscending));
+
+ return result;
+ });
+
+ /**
+ * Removes all elements from `array` that `predicate` returns truthy for
+ * and returns an array of the removed elements. The predicate is invoked
+ * with three arguments: (value, index, array).
+ *
+ * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
+ * to pull elements from an array by value.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [1, 2, 3, 4];
+ * var evens = _.remove(array, function(n) {
+ * return n % 2 == 0;
+ * });
+ *
+ * console.log(array);
+ * // => [1, 3]
+ *
+ * console.log(evens);
+ * // => [2, 4]
+ */
+ function remove(array, predicate) {
+ var result = [];
+ if (!(array && array.length)) {
+ return result;
+ }
+ var index = -1,
+ indexes = [],
+ length = array.length;
+
+ predicate = getIteratee(predicate, 3);
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result.push(value);
+ indexes.push(index);
+ }
+ }
+ basePullAt(array, indexes);
+ return result;
+ }
+
+ /**
+ * Reverses `array` so that the first element becomes the last, the second
+ * element becomes the second to last, and so on.
+ *
+ * **Note:** This method mutates `array` and is based on
+ * [`Array#reverse`](https://mdn.io/Array/reverse).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.reverse(array);
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function reverse(array) {
+ return array == null ? array : nativeReverse.call(array);
+ }
+
+ /**
+ * Creates a slice of `array` from `start` up to, but not including, `end`.
+ *
+ * **Note:** This method is used instead of
+ * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
+ * returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function slice(array, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
+ }
+ else {
+ start = start == null ? 0 : toInteger(start);
+ end = end === undefined$1 ? length : toInteger(end);
+ }
+ return baseSlice(array, start, end);
+ }
+
+ /**
+ * Uses a binary search to determine the lowest index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedIndex([30, 50], 40);
+ * // => 1
+ */
+ function sortedIndex(array, value) {
+ return baseSortedIndex(array, value);
+ }
+
+ /**
+ * This method is like `_.sortedIndex` except that it accepts `iteratee`
+ * which is invoked for `value` and each element of `array` to compute their
+ * sort ranking. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * var objects = [{ 'x': 4 }, { 'x': 5 }];
+ *
+ * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
+ * // => 0
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
+ * // => 0
+ */
+ function sortedIndexBy(array, value, iteratee) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it performs a binary
+ * search on a sorted `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
+ * // => 1
+ */
+ function sortedIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value);
+ if (index < length && eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * This method is like `_.sortedIndex` except that it returns the highest
+ * index at which `value` should be inserted into `array` in order to
+ * maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
+ * // => 4
+ */
+ function sortedLastIndex(array, value) {
+ return baseSortedIndex(array, value, true);
+ }
+
+ /**
+ * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
+ * which is invoked for `value` and each element of `array` to compute their
+ * sort ranking. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * var objects = [{ 'x': 4 }, { 'x': 5 }];
+ *
+ * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
+ * // => 1
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
+ * // => 1
+ */
+ function sortedLastIndexBy(array, value, iteratee) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
+ }
+
+ /**
+ * This method is like `_.lastIndexOf` except that it performs a binary
+ * search on a sorted `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
+ * // => 3
+ */
+ function sortedLastIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value, true) - 1;
+ if (eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * This method is like `_.uniq` except that it's designed and optimized
+ * for sorted arrays.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.sortedUniq([1, 1, 2]);
+ * // => [1, 2]
+ */
+ function sortedUniq(array) {
+ return (array && array.length)
+ ? baseSortedUniq(array)
+ : [];
+ }
+
+ /**
+ * This method is like `_.uniqBy` except that it's designed and optimized
+ * for sorted arrays.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
+ * // => [1.1, 2.3]
+ */
+ function sortedUniqBy(array, iteratee) {
+ return (array && array.length)
+ ? baseSortedUniq(array, getIteratee(iteratee, 2))
+ : [];
+ }
+
+ /**
+ * Gets all but the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.tail([1, 2, 3]);
+ * // => [2, 3]
+ */
+ function tail(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 1, length) : [];
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.take([1, 2, 3]);
+ * // => [1]
+ *
+ * _.take([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * _.take([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.take([1, 2, 3], 0);
+ * // => []
+ */
+ function take(array, n, guard) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ n = (guard || n === undefined$1) ? 1 : toInteger(n);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the end.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRight([1, 2, 3]);
+ * // => [3]
+ *
+ * _.takeRight([1, 2, 3], 2);
+ * // => [2, 3]
+ *
+ * _.takeRight([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.takeRight([1, 2, 3], 0);
+ * // => []
+ */
+ function takeRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined$1) ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the end. Elements are
+ * taken until `predicate` returns falsey. The predicate is invoked with
+ * three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.takeRightWhile(users, function(o) { return !o.active; });
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
+ * // => objects for ['pebbles']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.takeRightWhile(users, ['active', false]);
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.takeRightWhile(users, 'active');
+ * // => []
+ */
+ function takeRightWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), false, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the beginning. Elements
+ * are taken until `predicate` returns falsey. The predicate is invoked with
+ * three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.takeWhile(users, function(o) { return !o.active; });
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.takeWhile(users, { 'user': 'barney', 'active': false });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.takeWhile(users, ['active', false]);
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.takeWhile(users, 'active');
+ * // => []
+ */
+ function takeWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3))
+ : [];
+ }
+
+ /**
+ * Creates an array of unique values, in order, from all given arrays using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.union([2], [1, 2]);
+ * // => [2, 1]
+ */
+ var union = baseRest(function(arrays) {
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
+ });
+
+ /**
+ * This method is like `_.union` except that it accepts `iteratee` which is
+ * invoked for each element of each `arrays` to generate the criterion by
+ * which uniqueness is computed. Result values are chosen from the first
+ * array in which the value occurs. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.unionBy([2.1], [1.2, 2.3], Math.floor);
+ * // => [2.1, 1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ var unionBy = baseRest(function(arrays) {
+ var iteratee = last(arrays);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined$1;
+ }
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
+ });
+
+ /**
+ * This method is like `_.union` except that it accepts `comparator` which
+ * is invoked to compare elements of `arrays`. Result values are chosen from
+ * the first array in which the value occurs. The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.unionWith(objects, others, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
+ */
+ var unionWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == 'function' ? comparator : undefined$1;
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined$1, comparator);
+ });
+
+ /**
+ * Creates a duplicate-free version of an array, using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons, in which only the first occurrence of each element
+ * is kept. The order of result values is determined by the order they occur
+ * in the array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.uniq([2, 1, 2]);
+ * // => [2, 1]
+ */
+ function uniq(array) {
+ return (array && array.length) ? baseUniq(array) : [];
+ }
+
+ /**
+ * This method is like `_.uniq` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * uniqueness is computed. The order of result values is determined by the
+ * order they occur in the array. The iteratee is invoked with one argument:
+ * (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
+ * // => [2.1, 1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ function uniqBy(array, iteratee) {
+ return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
+ }
+
+ /**
+ * This method is like `_.uniq` except that it accepts `comparator` which
+ * is invoked to compare elements of `array`. The order of result values is
+ * determined by the order they occur in the array.The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.uniqWith(objects, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
+ */
+ function uniqWith(array, comparator) {
+ comparator = typeof comparator == 'function' ? comparator : undefined$1;
+ return (array && array.length) ? baseUniq(array, undefined$1, comparator) : [];
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts an array of grouped
+ * elements and creates an array regrouping the elements to their pre-zip
+ * configuration.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.2.0
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
+ * // => [['a', 1, true], ['b', 2, false]]
+ *
+ * _.unzip(zipped);
+ * // => [['a', 'b'], [1, 2], [true, false]]
+ */
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var length = 0;
+ array = arrayFilter(array, function(group) {
+ if (isArrayLikeObject(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ return baseTimes(length, function(index) {
+ return arrayMap(array, baseProperty(index));
+ });
+ }
+
+ /**
+ * This method is like `_.unzip` except that it accepts `iteratee` to specify
+ * how regrouped values should be combined. The iteratee is invoked with the
+ * elements of each group: (...group).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.8.0
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @param {Function} [iteratee=_.identity] The function to combine
+ * regrouped values.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
+ * // => [[1, 10, 100], [2, 20, 200]]
+ *
+ * _.unzipWith(zipped, _.add);
+ * // => [3, 30, 300]
+ */
+ function unzipWith(array, iteratee) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var result = unzip(array);
+ if (iteratee == null) {
+ return result;
+ }
+ return arrayMap(result, function(group) {
+ return apply(iteratee, undefined$1, group);
+ });
+ }
+
+ /**
+ * Creates an array excluding all given values using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * **Note:** Unlike `_.pull`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...*} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @see _.difference, _.xor
+ * @example
+ *
+ * _.without([2, 1, 2, 3], 1, 2);
+ * // => [3]
+ */
+ var without = baseRest(function(array, values) {
+ return isArrayLikeObject(array)
+ ? baseDifference(array, values)
+ : [];
+ });
+
+ /**
+ * Creates an array of unique values that is the
+ * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
+ * of the given arrays. The order of result values is determined by the order
+ * they occur in the arrays.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of filtered values.
+ * @see _.difference, _.without
+ * @example
+ *
+ * _.xor([2, 1], [2, 3]);
+ * // => [1, 3]
+ */
+ var xor = baseRest(function(arrays) {
+ return baseXor(arrayFilter(arrays, isArrayLikeObject));
+ });
+
+ /**
+ * This method is like `_.xor` except that it accepts `iteratee` which is
+ * invoked for each element of each `arrays` to generate the criterion by
+ * which by which they're compared. The order of result values is determined
+ * by the order they occur in the arrays. The iteratee is invoked with one
+ * argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
+ * // => [1.2, 3.4]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 2 }]
+ */
+ var xorBy = baseRest(function(arrays) {
+ var iteratee = last(arrays);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined$1;
+ }
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
+ });
+
+ /**
+ * This method is like `_.xor` except that it accepts `comparator` which is
+ * invoked to compare elements of `arrays`. The order of result values is
+ * determined by the order they occur in the arrays. The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.xorWith(objects, others, _.isEqual);
+ * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
+ */
+ var xorWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == 'function' ? comparator : undefined$1;
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined$1, comparator);
+ });
+
+ /**
+ * Creates an array of grouped elements, the first of which contains the
+ * first elements of the given arrays, the second of which contains the
+ * second elements of the given arrays, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zip(['a', 'b'], [1, 2], [true, false]);
+ * // => [['a', 1, true], ['b', 2, false]]
+ */
+ var zip = baseRest(unzip);
+
+ /**
+ * This method is like `_.fromPairs` except that it accepts two arrays,
+ * one of property identifiers and one of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.4.0
+ * @category Array
+ * @param {Array} [props=[]] The property identifiers.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObject(['a', 'b'], [1, 2]);
+ * // => { 'a': 1, 'b': 2 }
+ */
+ function zipObject(props, values) {
+ return baseZipObject(props || [], values || [], assignValue);
+ }
+
+ /**
+ * This method is like `_.zipObject` except that it supports property paths.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.1.0
+ * @category Array
+ * @param {Array} [props=[]] The property identifiers.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
+ * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
+ */
+ function zipObjectDeep(props, values) {
+ return baseZipObject(props || [], values || [], baseSet);
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts `iteratee` to specify
+ * how grouped values should be combined. The iteratee is invoked with the
+ * elements of each group: (...group).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.8.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @param {Function} [iteratee=_.identity] The function to combine
+ * grouped values.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
+ * return a + b + c;
+ * });
+ * // => [111, 222]
+ */
+ var zipWith = baseRest(function(arrays) {
+ var length = arrays.length,
+ iteratee = length > 1 ? arrays[length - 1] : undefined$1;
+
+ iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined$1;
+ return unzipWith(arrays, iteratee);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` wrapper instance that wraps `value` with explicit method
+ * chain sequences enabled. The result of such sequences must be unwrapped
+ * with `_#value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.3.0
+ * @category Seq
+ * @param {*} value The value to wrap.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'pebbles', 'age': 1 }
+ * ];
+ *
+ * var youngest = _
+ * .chain(users)
+ * .sortBy('age')
+ * .map(function(o) {
+ * return o.user + ' is ' + o.age;
+ * })
+ * .head()
+ * .value();
+ * // => 'pebbles is 1'
+ */
+ function chain(value) {
+ var result = lodash(value);
+ result.__chain__ = true;
+ return result;
+ }
+
+ /**
+ * This method invokes `interceptor` and returns `value`. The interceptor
+ * is invoked with one argument; (value). The purpose of this method is to
+ * "tap into" a method chain sequence in order to modify intermediate results.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Seq
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * _([1, 2, 3])
+ * .tap(function(array) {
+ * // Mutate input array.
+ * array.pop();
+ * })
+ * .reverse()
+ * .value();
+ * // => [2, 1]
+ */
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+
+ /**
+ * This method is like `_.tap` except that it returns the result of `interceptor`.
+ * The purpose of this method is to "pass thru" values replacing intermediate
+ * results in a method chain sequence.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Seq
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {*} Returns the result of `interceptor`.
+ * @example
+ *
+ * _(' abc ')
+ * .chain()
+ * .trim()
+ * .thru(function(value) {
+ * return [value];
+ * })
+ * .value();
+ * // => ['abc']
+ */
+ function thru(value, interceptor) {
+ return interceptor(value);
+ }
+
+ /**
+ * This method is the wrapper version of `_.at`.
+ *
+ * @name at
+ * @memberOf _
+ * @since 1.0.0
+ * @category Seq
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
+ *
+ * _(object).at(['a[0].b.c', 'a[1]']).value();
+ * // => [3, 4]
+ */
+ var wrapperAt = flatRest(function(paths) {
+ var length = paths.length,
+ start = length ? paths[0] : 0,
+ value = this.__wrapped__,
+ interceptor = function(object) { return baseAt(object, paths); };
+
+ if (length > 1 || this.__actions__.length ||
+ !(value instanceof LazyWrapper) || !isIndex(start)) {
+ return this.thru(interceptor);
+ }
+ value = value.slice(start, +start + (length ? 1 : 0));
+ value.__actions__.push({
+ 'func': thru,
+ 'args': [interceptor],
+ 'thisArg': undefined$1
+ });
+ return new LodashWrapper(value, this.__chain__).thru(function(array) {
+ if (length && !array.length) {
+ array.push(undefined$1);
+ }
+ return array;
+ });
+ });
+
+ /**
+ * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
+ *
+ * @name chain
+ * @memberOf _
+ * @since 0.1.0
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // A sequence without explicit chaining.
+ * _(users).head();
+ * // => { 'user': 'barney', 'age': 36 }
+ *
+ * // A sequence with explicit chaining.
+ * _(users)
+ * .chain()
+ * .head()
+ * .pick('user')
+ * .value();
+ * // => { 'user': 'barney' }
+ */
+ function wrapperChain() {
+ return chain(this);
+ }
+
+ /**
+ * Executes the chain sequence and returns the wrapped result.
+ *
+ * @name commit
+ * @memberOf _
+ * @since 3.2.0
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapped = _(array).push(3);
+ *
+ * console.log(array);
+ * // => [1, 2]
+ *
+ * wrapped = wrapped.commit();
+ * console.log(array);
+ * // => [1, 2, 3]
+ *
+ * wrapped.last();
+ * // => 3
+ *
+ * console.log(array);
+ * // => [1, 2, 3]
+ */
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
+
+ /**
+ * Gets the next value on a wrapped object following the
+ * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
+ *
+ * @name next
+ * @memberOf _
+ * @since 4.0.0
+ * @category Seq
+ * @returns {Object} Returns the next iterator value.
+ * @example
+ *
+ * var wrapped = _([1, 2]);
+ *
+ * wrapped.next();
+ * // => { 'done': false, 'value': 1 }
+ *
+ * wrapped.next();
+ * // => { 'done': false, 'value': 2 }
+ *
+ * wrapped.next();
+ * // => { 'done': true, 'value': undefined }
+ */
+ function wrapperNext() {
+ if (this.__values__ === undefined$1) {
+ this.__values__ = toArray(this.value());
+ }
+ var done = this.__index__ >= this.__values__.length,
+ value = done ? undefined$1 : this.__values__[this.__index__++];
+
+ return { 'done': done, 'value': value };
+ }
+
+ /**
+ * Enables the wrapper to be iterable.
+ *
+ * @name Symbol.iterator
+ * @memberOf _
+ * @since 4.0.0
+ * @category Seq
+ * @returns {Object} Returns the wrapper object.
+ * @example
+ *
+ * var wrapped = _([1, 2]);
+ *
+ * wrapped[Symbol.iterator]() === wrapped;
+ * // => true
+ *
+ * Array.from(wrapped);
+ * // => [1, 2]
+ */
+ function wrapperToIterator() {
+ return this;
+ }
+
+ /**
+ * Creates a clone of the chain sequence planting `value` as the wrapped value.
+ *
+ * @name plant
+ * @memberOf _
+ * @since 3.2.0
+ * @category Seq
+ * @param {*} value The value to plant.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var wrapped = _([1, 2]).map(square);
+ * var other = wrapped.plant([3, 4]);
+ *
+ * other.value();
+ * // => [9, 16]
+ *
+ * wrapped.value();
+ * // => [1, 4]
+ */
+ function wrapperPlant(value) {
+ var result,
+ parent = this;
+
+ while (parent instanceof baseLodash) {
+ var clone = wrapperClone(parent);
+ clone.__index__ = 0;
+ clone.__values__ = undefined$1;
+ if (result) {
+ previous.__wrapped__ = clone;
+ } else {
+ result = clone;
+ }
+ var previous = clone;
+ parent = parent.__wrapped__;
+ }
+ previous.__wrapped__ = value;
+ return result;
+ }
+
+ /**
+ * This method is the wrapper version of `_.reverse`.
+ *
+ * **Note:** This method mutates the wrapped array.
+ *
+ * @name reverse
+ * @memberOf _
+ * @since 0.1.0
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _(array).reverse().value()
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+ if (value instanceof LazyWrapper) {
+ var wrapped = value;
+ if (this.__actions__.length) {
+ wrapped = new LazyWrapper(this);
+ }
+ wrapped = wrapped.reverse();
+ wrapped.__actions__.push({
+ 'func': thru,
+ 'args': [reverse],
+ 'thisArg': undefined$1
+ });
+ return new LodashWrapper(wrapped, this.__chain__);
+ }
+ return this.thru(reverse);
+ }
+
+ /**
+ * Executes the chain sequence to resolve the unwrapped value.
+ *
+ * @name value
+ * @memberOf _
+ * @since 0.1.0
+ * @alias toJSON, valueOf
+ * @category Seq
+ * @returns {*} Returns the resolved unwrapped value.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
+ */
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` thru `iteratee`. The corresponding value of
+ * each key is the number of times the key was returned by `iteratee`. The
+ * iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.countBy([6.1, 4.2, 6.3], Math.floor);
+ * // => { '4': 1, '6': 2 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.countBy(['one', 'two', 'three'], 'length');
+ * // => { '3': 2, '5': 1 }
+ */
+ var countBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ ++result[key];
+ } else {
+ baseAssignValue(result, key, 1);
+ }
+ });
+
+ /**
+ * Checks if `predicate` returns truthy for **all** elements of `collection`.
+ * Iteration is stopped once `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * **Note:** This method returns `true` for
+ * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
+ * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
+ * elements of empty collections.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * // => false
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.every(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.every(users, ['active', false]);
+ * // => true
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.every(users, 'active');
+ * // => false
+ */
+ function every(collection, predicate, guard) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined$1;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning an array of all elements
+ * `predicate` returns truthy for. The predicate is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * **Note:** Unlike `_.remove`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @see _.reject
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.filter(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.filter(users, { 'age': 36, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.filter(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.filter(users, 'active');
+ * // => objects for ['barney']
+ *
+ * // Combining several predicates using `_.overEvery` or `_.overSome`.
+ * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
+ * // => objects for ['fred', 'barney']
+ */
+ function filter(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning the first element
+ * `predicate` returns truthy for. The predicate is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false },
+ * { 'user': 'pebbles', 'age': 1, 'active': true }
+ * ];
+ *
+ * _.find(users, function(o) { return o.age < 40; });
+ * // => object for 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.find(users, { 'age': 1, 'active': true });
+ * // => object for 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.find(users, ['active', false]);
+ * // => object for 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.find(users, 'active');
+ * // => object for 'barney'
+ */
+ var find = createFind(findIndex);
+
+ /**
+ * This method is like `_.find` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=collection.length-1] The index to search from.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * _.findLast([1, 2, 3, 4], function(n) {
+ * return n % 2 == 1;
+ * });
+ * // => 3
+ */
+ var findLast = createFind(findLastIndex);
+
+ /**
+ * Creates a flattened array of values by running each element in `collection`
+ * thru `iteratee` and flattening the mapped results. The iteratee is invoked
+ * with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [n, n];
+ * }
+ *
+ * _.flatMap([1, 2], duplicate);
+ * // => [1, 1, 2, 2]
+ */
+ function flatMap(collection, iteratee) {
+ return baseFlatten(map(collection, iteratee), 1);
+ }
+
+ /**
+ * This method is like `_.flatMap` except that it recursively flattens the
+ * mapped results.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [[[n, n]]];
+ * }
+ *
+ * _.flatMapDeep([1, 2], duplicate);
+ * // => [1, 1, 2, 2]
+ */
+ function flatMapDeep(collection, iteratee) {
+ return baseFlatten(map(collection, iteratee), INFINITY);
+ }
+
+ /**
+ * This method is like `_.flatMap` except that it recursively flattens the
+ * mapped results up to `depth` times.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.7.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {number} [depth=1] The maximum recursion depth.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [[[n, n]]];
+ * }
+ *
+ * _.flatMapDepth([1, 2], duplicate, 2);
+ * // => [[1, 1], [2, 2]]
+ */
+ function flatMapDepth(collection, iteratee, depth) {
+ depth = depth === undefined$1 ? 1 : toInteger(depth);
+ return baseFlatten(map(collection, iteratee), depth);
+ }
+
+ /**
+ * Iterates over elements of `collection` and invokes `iteratee` for each element.
+ * The iteratee is invoked with three arguments: (value, index|key, collection).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * **Note:** As with other "Collections" methods, objects with a "length"
+ * property are iterated like arrays. To avoid this behavior use `_.forIn`
+ * or `_.forOwn` for object iteration.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @alias each
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @see _.forEachRight
+ * @example
+ *
+ * _.forEach([1, 2], function(value) {
+ * console.log(value);
+ * });
+ * // => Logs `1` then `2`.
+ *
+ * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a' then 'b' (iteration order is not guaranteed).
+ */
+ function forEach(collection, iteratee) {
+ var func = isArray(collection) ? arrayEach : baseEach;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.forEach` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @alias eachRight
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @see _.forEach
+ * @example
+ *
+ * _.forEachRight([1, 2], function(value) {
+ * console.log(value);
+ * });
+ * // => Logs `2` then `1`.
+ */
+ function forEachRight(collection, iteratee) {
+ var func = isArray(collection) ? arrayEachRight : baseEachRight;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` thru `iteratee`. The order of grouped values
+ * is determined by the order they occur in `collection`. The corresponding
+ * value of each key is an array of elements responsible for generating the
+ * key. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.groupBy([6.1, 4.2, 6.3], Math.floor);
+ * // => { '4': [4.2], '6': [6.1, 6.3] }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
+ */
+ var groupBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ result[key].push(value);
+ } else {
+ baseAssignValue(result, key, [value]);
+ }
+ });
+
+ /**
+ * Checks if `value` is in `collection`. If `collection` is a string, it's
+ * checked for a substring of `value`, otherwise
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * is used for equality comparisons. If `fromIndex` is negative, it's used as
+ * the offset from the end of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
+ * @returns {boolean} Returns `true` if `value` is found, else `false`.
+ * @example
+ *
+ * _.includes([1, 2, 3], 1);
+ * // => true
+ *
+ * _.includes([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.includes({ 'a': 1, 'b': 2 }, 1);
+ * // => true
+ *
+ * _.includes('abcd', 'bc');
+ * // => true
+ */
+ function includes(collection, value, fromIndex, guard) {
+ collection = isArrayLike(collection) ? collection : values(collection);
+ fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
+
+ var length = collection.length;
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return isString(collection)
+ ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
+ : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
+ }
+
+ /**
+ * Invokes the method at `path` of each element in `collection`, returning
+ * an array of the results of each invoked method. Any additional arguments
+ * are provided to each invoked method. If `path` is a function, it's invoked
+ * for, and `this` bound to, each element in `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Array|Function|string} path The path of the method to invoke or
+ * the function invoked per iteration.
+ * @param {...*} [args] The arguments to invoke each method with.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ *
+ * _.invokeMap([123, 456], String.prototype.split, '');
+ * // => [['1', '2', '3'], ['4', '5', '6']]
+ */
+ var invokeMap = baseRest(function(collection, path, args) {
+ var index = -1,
+ isFunc = typeof path == 'function',
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value) {
+ result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
+ });
+ return result;
+ });
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` thru `iteratee`. The corresponding value of
+ * each key is the last element responsible for generating the key. The
+ * iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * var array = [
+ * { 'dir': 'left', 'code': 97 },
+ * { 'dir': 'right', 'code': 100 }
+ * ];
+ *
+ * _.keyBy(array, function(o) {
+ * return String.fromCharCode(o.code);
+ * });
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.keyBy(array, 'dir');
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+ */
+ var keyBy = createAggregator(function(result, value, key) {
+ baseAssignValue(result, key, value);
+ });
+
+ /**
+ * Creates an array of values by running each element in `collection` thru
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+ *
+ * The guarded methods are:
+ * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
+ * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
+ * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
+ * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * _.map([4, 8], square);
+ * // => [16, 64]
+ *
+ * _.map({ 'a': 4, 'b': 8 }, square);
+ * // => [16, 64] (iteration order is not guaranteed)
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
+ */
+ function map(collection, iteratee) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.sortBy` except that it allows specifying the sort
+ * orders of the iteratees to sort by. If `orders` is unspecified, all values
+ * are sorted in ascending order. Otherwise, specify an order of "desc" for
+ * descending or "asc" for ascending sort order of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
+ * The iteratees to sort by.
+ * @param {string[]} [orders] The sort orders of `iteratees`.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 34 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'barney', 'age': 36 }
+ * ];
+ *
+ * // Sort by `user` in ascending order and by `age` in descending order.
+ * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
+ */
+ function orderBy(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
+ }
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
+ }
+ orders = guard ? undefined$1 : orders;
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseOrderBy(collection, iteratees, orders);
+ }
+
+ /**
+ * Creates an array of elements split into two groups, the first of which
+ * contains elements `predicate` returns truthy for, the second of which
+ * contains elements `predicate` returns falsey for. The predicate is
+ * invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the array of grouped elements.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true },
+ * { 'user': 'pebbles', 'age': 1, 'active': false }
+ * ];
+ *
+ * _.partition(users, function(o) { return o.active; });
+ * // => objects for [['fred'], ['barney', 'pebbles']]
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.partition(users, { 'age': 1, 'active': false });
+ * // => objects for [['pebbles'], ['barney', 'fred']]
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.partition(users, ['active', false]);
+ * // => objects for [['barney', 'pebbles'], ['fred']]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.partition(users, 'active');
+ * // => objects for [['fred'], ['barney', 'pebbles']]
+ */
+ var partition = createAggregator(function(result, value, key) {
+ result[key ? 0 : 1].push(value);
+ }, function() { return [[], []]; });
+
+ /**
+ * Reduces `collection` to a value which is the accumulated result of running
+ * each element in `collection` thru `iteratee`, where each successive
+ * invocation is supplied the return value of the previous. If `accumulator`
+ * is not given, the first element of `collection` is used as the initial
+ * value. The iteratee is invoked with four arguments:
+ * (accumulator, value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.reduce`, `_.reduceRight`, and `_.transform`.
+ *
+ * The guarded methods are:
+ * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
+ * and `sortBy`
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @see _.reduceRight
+ * @example
+ *
+ * _.reduce([1, 2], function(sum, n) {
+ * return sum + n;
+ * }, 0);
+ * // => 3
+ *
+ * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * return result;
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
+ */
+ function reduce(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduce : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
+ }
+
+ /**
+ * This method is like `_.reduce` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @see _.reduce
+ * @example
+ *
+ * var array = [[0, 1], [2, 3], [4, 5]];
+ *
+ * _.reduceRight(array, function(flattened, other) {
+ * return flattened.concat(other);
+ * }, []);
+ * // => [4, 5, 2, 3, 0, 1]
+ */
+ function reduceRight(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduceRight : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
+ }
+
+ /**
+ * The opposite of `_.filter`; this method returns the elements of `collection`
+ * that `predicate` does **not** return truthy for.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @see _.filter
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true }
+ * ];
+ *
+ * _.reject(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.reject(users, { 'age': 40, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.reject(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.reject(users, 'active');
+ * // => objects for ['barney']
+ */
+ function reject(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, negate(getIteratee(predicate, 3)));
+ }
+
+ /**
+ * Gets a random element from `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to sample.
+ * @returns {*} Returns the random element.
+ * @example
+ *
+ * _.sample([1, 2, 3, 4]);
+ * // => 2
+ */
+ function sample(collection) {
+ var func = isArray(collection) ? arraySample : baseSample;
+ return func(collection);
+ }
+
+ /**
+ * Gets `n` random elements at unique keys from `collection` up to the
+ * size of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to sample.
+ * @param {number} [n=1] The number of elements to sample.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Array} Returns the random elements.
+ * @example
+ *
+ * _.sampleSize([1, 2, 3], 2);
+ * // => [3, 1]
+ *
+ * _.sampleSize([1, 2, 3], 4);
+ * // => [2, 3, 1]
+ */
+ function sampleSize(collection, n, guard) {
+ if ((guard ? isIterateeCall(collection, n, guard) : n === undefined$1)) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ var func = isArray(collection) ? arraySampleSize : baseSampleSize;
+ return func(collection, n);
+ }
+
+ /**
+ * Creates an array of shuffled values, using a version of the
+ * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4]);
+ * // => [4, 1, 3, 2]
+ */
+ function shuffle(collection) {
+ var func = isArray(collection) ? arrayShuffle : baseShuffle;
+ return func(collection);
+ }
+
+ /**
+ * Gets the size of `collection` by returning its length for array-like
+ * values or the number of own enumerable string keyed properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @returns {number} Returns the collection size.
+ * @example
+ *
+ * _.size([1, 2, 3]);
+ * // => 3
+ *
+ * _.size({ 'a': 1, 'b': 2 });
+ * // => 2
+ *
+ * _.size('pebbles');
+ * // => 7
+ */
+ function size(collection) {
+ if (collection == null) {
+ return 0;
+ }
+ if (isArrayLike(collection)) {
+ return isString(collection) ? stringSize(collection) : collection.length;
+ }
+ var tag = getTag(collection);
+ if (tag == mapTag || tag == setTag) {
+ return collection.size;
+ }
+ return baseKeys(collection).length;
+ }
+
+ /**
+ * Checks if `predicate` returns truthy for **any** element of `collection`.
+ * Iteration is stopped once `predicate` returns truthy. The predicate is
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.some([null, 0, 'yes', false], Boolean);
+ * // => true
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.some(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.some(users, ['active', false]);
+ * // => true
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.some(users, 'active');
+ * // => true
+ */
+ function some(collection, predicate, guard) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined$1;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Creates an array of elements, sorted in ascending order by the results of
+ * running each element in a collection thru each iteratee. This method
+ * performs a stable sort, that is, it preserves the original sort order of
+ * equal elements. The iteratees are invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {...(Function|Function[])} [iteratees=[_.identity]]
+ * The iteratees to sort by.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 30 },
+ * { 'user': 'barney', 'age': 34 }
+ * ];
+ *
+ * _.sortBy(users, [function(o) { return o.user; }]);
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
+ *
+ * _.sortBy(users, ['user', 'age']);
+ * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
+ */
+ var sortBy = baseRest(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var length = iteratees.length;
+ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
+ iteratees = [];
+ } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
+ iteratees = [iteratees[0]];
+ }
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Gets the timestamp of the number of milliseconds that have elapsed since
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Date
+ * @returns {number} Returns the timestamp.
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => Logs the number of milliseconds it took for the deferred invocation.
+ */
+ var now = ctxNow || function() {
+ return root.Date.now();
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The opposite of `_.before`; this method creates a function that invokes
+ * `func` once it's called `n` or more times.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {number} n The number of calls before `func` is invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var saves = ['profile', 'settings'];
+ *
+ * var done = _.after(saves.length, function() {
+ * console.log('done saving!');
+ * });
+ *
+ * _.forEach(saves, function(type) {
+ * asyncSave({ 'type': type, 'complete': done });
+ * });
+ * // => Logs 'done saving!' after the two async saves have completed.
+ */
+ function after(n, func) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func`, with up to `n` arguments,
+ * ignoring any additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @param {number} [n=func.length] The arity cap.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the new capped function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.ary(parseInt, 1));
+ * // => [6, 8, 10]
+ */
+ function ary(func, n, guard) {
+ n = guard ? undefined$1 : n;
+ n = (func && n == null) ? func.length : n;
+ return createWrap(func, WRAP_ARY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, n);
+ }
+
+ /**
+ * Creates a function that invokes `func`, with the `this` binding and arguments
+ * of the created function, while it's called less than `n` times. Subsequent
+ * calls to the created function return the result of the last `func` invocation.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {number} n The number of calls at which `func` is no longer invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * jQuery(element).on('click', _.before(5, addContactToList));
+ * // => Allows adding up to 4 contacts to the list.
+ */
+ function before(n, func) {
+ var result;
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n > 0) {
+ result = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined$1;
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of `thisArg`
+ * and `partials` prepended to the arguments it receives.
+ *
+ * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
+ * property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * function greet(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * var bound = _.bind(greet, object, 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * // Bound with placeholders.
+ * var bound = _.bind(greet, object, _, '!');
+ * bound('hi');
+ * // => 'hi fred!'
+ */
+ var bind = baseRest(function(func, thisArg, partials) {
+ var bitmask = WRAP_BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bind));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(func, bitmask, thisArg, partials, holders);
+ });
+
+ /**
+ * Creates a function that invokes the method at `object[key]` with `partials`
+ * prepended to the arguments it receives.
+ *
+ * This method differs from `_.bind` by allowing bound functions to reference
+ * methods that may be redefined or don't yet exist. See
+ * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
+ * for more details.
+ *
+ * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.10.0
+ * @category Function
+ * @param {Object} object The object to invoke the method on.
+ * @param {string} key The key of the method.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var object = {
+ * 'user': 'fred',
+ * 'greet': function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ * };
+ *
+ * var bound = _.bindKey(object, 'greet', 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * object.greet = function(greeting, punctuation) {
+ * return greeting + 'ya ' + this.user + punctuation;
+ * };
+ *
+ * bound('!');
+ * // => 'hiya fred!'
+ *
+ * // Bound with placeholders.
+ * var bound = _.bindKey(object, 'greet', _, '!');
+ * bound('hi');
+ * // => 'hiya fred!'
+ */
+ var bindKey = baseRest(function(object, key, partials) {
+ var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bindKey));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(key, bitmask, object, partials, holders);
+ });
+
+ /**
+ * Creates a function that accepts arguments of `func` and either invokes
+ * `func` returning its result, if at least `arity` number of arguments have
+ * been provided, or returns a function that accepts the remaining `func`
+ * arguments, and so on. The arity of `func` may be specified if `func.length`
+ * is not sufficient.
+ *
+ * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curry(abc);
+ *
+ * curried(1)(2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // Curried with placeholders.
+ * curried(1)(_, 3)(2);
+ * // => [1, 2, 3]
+ */
+ function curry(func, arity, guard) {
+ arity = guard ? undefined$1 : arity;
+ var result = createWrap(func, WRAP_CURRY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
+ result.placeholder = curry.placeholder;
+ return result;
+ }
+
+ /**
+ * This method is like `_.curry` except that arguments are applied to `func`
+ * in the manner of `_.partialRight` instead of `_.partial`.
+ *
+ * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curryRight(abc);
+ *
+ * curried(3)(2)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(2, 3)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // Curried with placeholders.
+ * curried(3)(1, _)(2);
+ * // => [1, 2, 3]
+ */
+ function curryRight(func, arity, guard) {
+ arity = guard ? undefined$1 : arity;
+ var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
+ result.placeholder = curryRight.placeholder;
+ return result;
+ }
+
+ /**
+ * Creates a debounced function that delays invoking `func` until after `wait`
+ * milliseconds have elapsed since the last time the debounced function was
+ * invoked. The debounced function comes with a `cancel` method to cancel
+ * delayed `func` invocations and a `flush` method to immediately invoke them.
+ * Provide `options` to indicate whether `func` should be invoked on the
+ * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
+ * with the last arguments provided to the debounced function. Subsequent
+ * calls to the debounced function return the result of the last `func`
+ * invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the debounced function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
+ * for details over the differences between `_.debounce` and `_.throttle`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to debounce.
+ * @param {number} [wait=0] The number of milliseconds to delay.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.leading=false]
+ * Specify invoking on the leading edge of the timeout.
+ * @param {number} [options.maxWait]
+ * The maximum time `func` is allowed to be delayed before it's invoked.
+ * @param {boolean} [options.trailing=true]
+ * Specify invoking on the trailing edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * // Avoid costly calculations while the window size is in flux.
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
+ *
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
+ * jQuery(element).on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * }));
+ *
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
+ * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
+ * var source = new EventSource('/stream');
+ * jQuery(source).on('message', debounced);
+ *
+ * // Cancel the trailing debounced invocation.
+ * jQuery(window).on('popstate', debounced.cancel);
+ */
+ function debounce(func, wait, options) {
+ var lastArgs,
+ lastThis,
+ maxWait,
+ result,
+ timerId,
+ lastCallTime,
+ lastInvokeTime = 0,
+ leading = false,
+ maxing = false,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ wait = toNumber(wait) || 0;
+ if (isObject(options)) {
+ leading = !!options.leading;
+ maxing = 'maxWait' in options;
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+
+ function invokeFunc(time) {
+ var args = lastArgs,
+ thisArg = lastThis;
+
+ lastArgs = lastThis = undefined$1;
+ lastInvokeTime = time;
+ result = func.apply(thisArg, args);
+ return result;
+ }
+
+ function leadingEdge(time) {
+ // Reset any `maxWait` timer.
+ lastInvokeTime = time;
+ // Start the timer for the trailing edge.
+ timerId = setTimeout(timerExpired, wait);
+ // Invoke the leading edge.
+ return leading ? invokeFunc(time) : result;
+ }
+
+ function remainingWait(time) {
+ var timeSinceLastCall = time - lastCallTime,
+ timeSinceLastInvoke = time - lastInvokeTime,
+ timeWaiting = wait - timeSinceLastCall;
+
+ return maxing
+ ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
+ : timeWaiting;
+ }
+
+ function shouldInvoke(time) {
+ var timeSinceLastCall = time - lastCallTime,
+ timeSinceLastInvoke = time - lastInvokeTime;
+
+ // Either this is the first call, activity has stopped and we're at the
+ // trailing edge, the system time has gone backwards and we're treating
+ // it as the trailing edge, or we've hit the `maxWait` limit.
+ return (lastCallTime === undefined$1 || (timeSinceLastCall >= wait) ||
+ (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
+ }
+
+ function timerExpired() {
+ var time = now();
+ if (shouldInvoke(time)) {
+ return trailingEdge(time);
+ }
+ // Restart the timer.
+ timerId = setTimeout(timerExpired, remainingWait(time));
+ }
+
+ function trailingEdge(time) {
+ timerId = undefined$1;
+
+ // Only invoke if we have `lastArgs` which means `func` has been
+ // debounced at least once.
+ if (trailing && lastArgs) {
+ return invokeFunc(time);
+ }
+ lastArgs = lastThis = undefined$1;
+ return result;
+ }
+
+ function cancel() {
+ if (timerId !== undefined$1) {
+ clearTimeout(timerId);
+ }
+ lastInvokeTime = 0;
+ lastArgs = lastCallTime = lastThis = timerId = undefined$1;
+ }
+
+ function flush() {
+ return timerId === undefined$1 ? result : trailingEdge(now());
+ }
+
+ function debounced() {
+ var time = now(),
+ isInvoking = shouldInvoke(time);
+
+ lastArgs = arguments;
+ lastThis = this;
+ lastCallTime = time;
+
+ if (isInvoking) {
+ if (timerId === undefined$1) {
+ return leadingEdge(lastCallTime);
+ }
+ if (maxing) {
+ // Handle invocations in a tight loop.
+ clearTimeout(timerId);
+ timerId = setTimeout(timerExpired, wait);
+ return invokeFunc(lastCallTime);
+ }
+ }
+ if (timerId === undefined$1) {
+ timerId = setTimeout(timerExpired, wait);
+ }
+ return result;
+ }
+ debounced.cancel = cancel;
+ debounced.flush = flush;
+ return debounced;
+ }
+
+ /**
+ * Defers invoking the `func` until the current call stack has cleared. Any
+ * additional arguments are provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to defer.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.defer(function(text) {
+ * console.log(text);
+ * }, 'deferred');
+ * // => Logs 'deferred' after one millisecond.
+ */
+ var defer = baseRest(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
+
+ /**
+ * Invokes `func` after `wait` milliseconds. Any additional arguments are
+ * provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.delay(function(text) {
+ * console.log(text);
+ * }, 1000, 'later');
+ * // => Logs 'later' after one second.
+ */
+ var delay = baseRest(function(func, wait, args) {
+ return baseDelay(func, toNumber(wait) || 0, args);
+ });
+
+ /**
+ * Creates a function that invokes `func` with arguments reversed.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Function
+ * @param {Function} func The function to flip arguments for.
+ * @returns {Function} Returns the new flipped function.
+ * @example
+ *
+ * var flipped = _.flip(function() {
+ * return _.toArray(arguments);
+ * });
+ *
+ * flipped('a', 'b', 'c', 'd');
+ * // => ['d', 'c', 'b', 'a']
+ */
+ function flip(func) {
+ return createWrap(func, WRAP_FLIP_FLAG);
+ }
+
+ /**
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * provided, it determines the cache key for storing the result based on the
+ * arguments provided to the memoized function. By default, the first argument
+ * provided to the memoized function is used as the map cache key. The `func`
+ * is invoked with the `this` binding of the memoized function.
+ *
+ * **Note:** The cache is exposed as the `cache` property on the memoized
+ * function. Its creation may be customized by replacing the `_.memoize.Cache`
+ * constructor with one whose instances implement the
+ * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
+ * method interface of `clear`, `delete`, `get`, `has`, and `set`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the cache key.
+ * @returns {Function} Returns the new memoized function.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ * var other = { 'c': 3, 'd': 4 };
+ *
+ * var values = _.memoize(_.values);
+ * values(object);
+ * // => [1, 2]
+ *
+ * values(other);
+ * // => [3, 4]
+ *
+ * object.a = 2;
+ * values(object);
+ * // => [1, 2]
+ *
+ * // Modify the result cache.
+ * values.cache.set(object, ['a', 'b']);
+ * values(object);
+ * // => ['a', 'b']
+ *
+ * // Replace `_.memoize.Cache`.
+ * _.memoize.Cache = WeakMap;
+ */
+ function memoize(func, resolver) {
+ if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments,
+ key = resolver ? resolver.apply(this, args) : args[0],
+ cache = memoized.cache;
+
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
+ var result = func.apply(this, args);
+ memoized.cache = cache.set(key, result) || cache;
+ return result;
+ };
+ memoized.cache = new (memoize.Cache || MapCache);
+ return memoized;
+ }
+
+ // Expose `MapCache`.
+ memoize.Cache = MapCache;
+
+ /**
+ * Creates a function that negates the result of the predicate `func`. The
+ * `func` predicate is invoked with the `this` binding and arguments of the
+ * created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} predicate The predicate to negate.
+ * @returns {Function} Returns the new negated function.
+ * @example
+ *
+ * function isEven(n) {
+ * return n % 2 == 0;
+ * }
+ *
+ * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
+ * // => [1, 3, 5]
+ */
+ function negate(predicate) {
+ if (typeof predicate != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ var args = arguments;
+ switch (args.length) {
+ case 0: return !predicate.call(this);
+ case 1: return !predicate.call(this, args[0]);
+ case 2: return !predicate.call(this, args[0], args[1]);
+ case 3: return !predicate.call(this, args[0], args[1], args[2]);
+ }
+ return !predicate.apply(this, args);
+ };
+ }
+
+ /**
+ * Creates a function that is restricted to invoking `func` once. Repeat calls
+ * to the function return the value of the first invocation. The `func` is
+ * invoked with the `this` binding and arguments of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // => `createApplication` is invoked once
+ */
+ function once(func) {
+ return before(2, func);
+ }
+
+ /**
+ * Creates a function that invokes `func` with its arguments transformed.
+ *
+ * @static
+ * @since 4.0.0
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to wrap.
+ * @param {...(Function|Function[])} [transforms=[_.identity]]
+ * The argument transforms.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function doubled(n) {
+ * return n * 2;
+ * }
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var func = _.overArgs(function(x, y) {
+ * return [x, y];
+ * }, [square, doubled]);
+ *
+ * func(9, 3);
+ * // => [81, 6]
+ *
+ * func(10, 5);
+ * // => [100, 10]
+ */
+ var overArgs = castRest(function(func, transforms) {
+ transforms = (transforms.length == 1 && isArray(transforms[0]))
+ ? arrayMap(transforms[0], baseUnary(getIteratee()))
+ : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
+
+ var funcsLength = transforms.length;
+ return baseRest(function(args) {
+ var index = -1,
+ length = nativeMin(args.length, funcsLength);
+
+ while (++index < length) {
+ args[index] = transforms[index].call(this, args[index]);
+ }
+ return apply(func, this, args);
+ });
+ });
+
+ /**
+ * Creates a function that invokes `func` with `partials` prepended to the
+ * arguments it receives. This method is like `_.bind` except it does **not**
+ * alter the `this` binding.
+ *
+ * The `_.partial.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.2.0
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * function greet(greeting, name) {
+ * return greeting + ' ' + name;
+ * }
+ *
+ * var sayHelloTo = _.partial(greet, 'hello');
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ *
+ * // Partially applied with placeholders.
+ * var greetFred = _.partial(greet, _, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ */
+ var partial = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partial));
+ return createWrap(func, WRAP_PARTIAL_FLAG, undefined$1, partials, holders);
+ });
+
+ /**
+ * This method is like `_.partial` except that partially applied arguments
+ * are appended to the arguments it receives.
+ *
+ * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * function greet(greeting, name) {
+ * return greeting + ' ' + name;
+ * }
+ *
+ * var greetFred = _.partialRight(greet, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ *
+ * // Partially applied with placeholders.
+ * var sayHelloTo = _.partialRight(greet, 'hello', _);
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ */
+ var partialRight = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partialRight));
+ return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined$1, partials, holders);
+ });
+
+ /**
+ * Creates a function that invokes `func` with arguments arranged according
+ * to the specified `indexes` where the argument value at the first index is
+ * provided as the first argument, the argument value at the second index is
+ * provided as the second argument, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {Function} func The function to rearrange arguments for.
+ * @param {...(number|number[])} indexes The arranged argument indexes.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var rearged = _.rearg(function(a, b, c) {
+ * return [a, b, c];
+ * }, [2, 0, 1]);
+ *
+ * rearged('b', 'c', 'a')
+ * // => ['a', 'b', 'c']
+ */
+ var rearg = flatRest(function(func, indexes) {
+ return createWrap(func, WRAP_REARG_FLAG, undefined$1, undefined$1, undefined$1, indexes);
+ });
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the
+ * created function and arguments from `start` and beyond provided as
+ * an array.
+ *
+ * **Note:** This method is based on the
+ * [rest parameter](https://mdn.io/rest_parameters).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Function
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.rest(function(what, names) {
+ * return what + ' ' + _.initial(names).join(', ') +
+ * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
+ * });
+ *
+ * say('hello', 'fred', 'barney', 'pebbles');
+ * // => 'hello fred, barney, & pebbles'
+ */
+ function rest(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = start === undefined$1 ? start : toInteger(start);
+ return baseRest(func, start);
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the
+ * create function and an array of arguments much like
+ * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
+ *
+ * **Note:** This method is based on the
+ * [spread operator](https://mdn.io/spread_operator).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.2.0
+ * @category Function
+ * @param {Function} func The function to spread arguments over.
+ * @param {number} [start=0] The start position of the spread.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.spread(function(who, what) {
+ * return who + ' says ' + what;
+ * });
+ *
+ * say(['fred', 'hello']);
+ * // => 'fred says hello'
+ *
+ * var numbers = Promise.all([
+ * Promise.resolve(40),
+ * Promise.resolve(36)
+ * ]);
+ *
+ * numbers.then(_.spread(function(x, y) {
+ * return x + y;
+ * }));
+ * // => a Promise of 76
+ */
+ function spread(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = start == null ? 0 : nativeMax(toInteger(start), 0);
+ return baseRest(function(args) {
+ var array = args[start],
+ otherArgs = castSlice(args, 0, start);
+
+ if (array) {
+ arrayPush(otherArgs, array);
+ }
+ return apply(func, this, otherArgs);
+ });
+ }
+
+ /**
+ * Creates a throttled function that only invokes `func` at most once per
+ * every `wait` milliseconds. The throttled function comes with a `cancel`
+ * method to cancel delayed `func` invocations and a `flush` method to
+ * immediately invoke them. Provide `options` to indicate whether `func`
+ * should be invoked on the leading and/or trailing edge of the `wait`
+ * timeout. The `func` is invoked with the last arguments provided to the
+ * throttled function. Subsequent calls to the throttled function return the
+ * result of the last `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the throttled function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
+ * for details over the differences between `_.throttle` and `_.debounce`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to throttle.
+ * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.leading=true]
+ * Specify invoking on the leading edge of the timeout.
+ * @param {boolean} [options.trailing=true]
+ * Specify invoking on the trailing edge of the timeout.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * // Avoid excessively updating the position while scrolling.
+ * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+ *
+ * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
+ * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
+ * jQuery(element).on('click', throttled);
+ *
+ * // Cancel the trailing throttled invocation.
+ * jQuery(window).on('popstate', throttled.cancel);
+ */
+ function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (isObject(options)) {
+ leading = 'leading' in options ? !!options.leading : leading;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, {
+ 'leading': leading,
+ 'maxWait': wait,
+ 'trailing': trailing
+ });
+ }
+
+ /**
+ * Creates a function that accepts up to one argument, ignoring any
+ * additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new capped function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.unary(parseInt));
+ * // => [6, 8, 10]
+ */
+ function unary(func) {
+ return ary(func, 1);
+ }
+
+ /**
+ * Creates a function that provides `value` to `wrapper` as its first
+ * argument. Any additional arguments provided to the function are appended
+ * to those provided to the `wrapper`. The wrapper is invoked with the `this`
+ * binding of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {*} value The value to wrap.
+ * @param {Function} [wrapper=identity] The wrapper function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var p = _.wrap(_.escape, function(func, text) {
+ * return '' + func(text) + '
';
+ * });
+ *
+ * p('fred, barney, & pebbles');
+ * // => 'fred, barney, & pebbles
'
+ */
+ function wrap(value, wrapper) {
+ return partial(castFunction(wrapper), value);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Casts `value` as an array if it's not one.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.4.0
+ * @category Lang
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the cast array.
+ * @example
+ *
+ * _.castArray(1);
+ * // => [1]
+ *
+ * _.castArray({ 'a': 1 });
+ * // => [{ 'a': 1 }]
+ *
+ * _.castArray('abc');
+ * // => ['abc']
+ *
+ * _.castArray(null);
+ * // => [null]
+ *
+ * _.castArray(undefined);
+ * // => [undefined]
+ *
+ * _.castArray();
+ * // => []
+ *
+ * var array = [1, 2, 3];
+ * console.log(_.castArray(array) === array);
+ * // => true
+ */
+ function castArray() {
+ if (!arguments.length) {
+ return [];
+ }
+ var value = arguments[0];
+ return isArray(value) ? value : [value];
+ }
+
+ /**
+ * Creates a shallow clone of `value`.
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
+ * and supports cloning arrays, array buffers, booleans, date objects, maps,
+ * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
+ * arrays. The own enumerable properties of `arguments` objects are cloned
+ * as plain objects. An empty object is returned for uncloneable values such
+ * as error objects, functions, DOM nodes, and WeakMaps.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @returns {*} Returns the cloned value.
+ * @see _.cloneDeep
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var shallow = _.clone(objects);
+ * console.log(shallow[0] === objects[0]);
+ * // => true
+ */
+ function clone(value) {
+ return baseClone(value, CLONE_SYMBOLS_FLAG);
+ }
+
+ /**
+ * This method is like `_.clone` except that it accepts `customizer` which
+ * is invoked to produce the cloned value. If `customizer` returns `undefined`,
+ * cloning is handled by the method instead. The `customizer` is invoked with
+ * up to four arguments; (value [, index|key, object, stack]).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @returns {*} Returns the cloned value.
+ * @see _.cloneDeepWith
+ * @example
+ *
+ * function customizer(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(false);
+ * }
+ * }
+ *
+ * var el = _.cloneWith(document.body, customizer);
+ *
+ * console.log(el === document.body);
+ * // => false
+ * console.log(el.nodeName);
+ * // => 'BODY'
+ * console.log(el.childNodes.length);
+ * // => 0
+ */
+ function cloneWith(value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined$1;
+ return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
+ }
+
+ /**
+ * This method is like `_.clone` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @returns {*} Returns the deep cloned value.
+ * @see _.clone
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var deep = _.cloneDeep(objects);
+ * console.log(deep[0] === objects[0]);
+ * // => false
+ */
+ function cloneDeep(value) {
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
+ }
+
+ /**
+ * This method is like `_.cloneWith` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @returns {*} Returns the deep cloned value.
+ * @see _.cloneWith
+ * @example
+ *
+ * function customizer(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(true);
+ * }
+ * }
+ *
+ * var el = _.cloneDeepWith(document.body, customizer);
+ *
+ * console.log(el === document.body);
+ * // => false
+ * console.log(el.nodeName);
+ * // => 'BODY'
+ * console.log(el.childNodes.length);
+ * // => 20
+ */
+ function cloneDeepWith(value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined$1;
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
+ }
+
+ /**
+ * Checks if `object` conforms to `source` by invoking the predicate
+ * properties of `source` with the corresponding property values of `object`.
+ *
+ * **Note:** This method is equivalent to `_.conforms` when `source` is
+ * partially applied.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.14.0
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {boolean} Returns `true` if `object` conforms, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ *
+ * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
+ * // => true
+ *
+ * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
+ * // => false
+ */
+ function conformsTo(object, source) {
+ return source == null || baseConformsTo(object, source, keys(source));
+ }
+
+ /**
+ * Performs a
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * comparison between two values to determine if they are equivalent.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ * var other = { 'a': 1 };
+ *
+ * _.eq(object, object);
+ * // => true
+ *
+ * _.eq(object, other);
+ * // => false
+ *
+ * _.eq('a', 'a');
+ * // => true
+ *
+ * _.eq('a', Object('a'));
+ * // => false
+ *
+ * _.eq(NaN, NaN);
+ * // => true
+ */
+ function eq(value, other) {
+ return value === other || (value !== value && other !== other);
+ }
+
+ /**
+ * Checks if `value` is greater than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`,
+ * else `false`.
+ * @see _.lt
+ * @example
+ *
+ * _.gt(3, 1);
+ * // => true
+ *
+ * _.gt(3, 3);
+ * // => false
+ *
+ * _.gt(1, 3);
+ * // => false
+ */
+ var gt = createRelationalOperation(baseGt);
+
+ /**
+ * Checks if `value` is greater than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than or equal to
+ * `other`, else `false`.
+ * @see _.lte
+ * @example
+ *
+ * _.gte(3, 1);
+ * // => true
+ *
+ * _.gte(3, 3);
+ * // => true
+ *
+ * _.gte(1, 3);
+ * // => false
+ */
+ var gte = createRelationalOperation(function(value, other) {
+ return value >= other;
+ });
+
+ /**
+ * Checks if `value` is likely an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ * else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
+ return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
+ !propertyIsEnumerable.call(value, 'callee');
+ };
+
+ /**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+ var isArray = Array.isArray;
+
+ /**
+ * Checks if `value` is classified as an `ArrayBuffer` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
+ * @example
+ *
+ * _.isArrayBuffer(new ArrayBuffer(2));
+ * // => true
+ *
+ * _.isArrayBuffer(new Array(2));
+ * // => false
+ */
+ var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
+
+ /**
+ * Checks if `value` is array-like. A value is considered array-like if it's
+ * not a function and has a `value.length` that's an integer greater than or
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * @example
+ *
+ * _.isArrayLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLike(document.body.children);
+ * // => true
+ *
+ * _.isArrayLike('abc');
+ * // => true
+ *
+ * _.isArrayLike(_.noop);
+ * // => false
+ */
+ function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+ }
+
+ /**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
+ * else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+ function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a boolean primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
+ * @example
+ *
+ * _.isBoolean(false);
+ * // => true
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+ function isBoolean(value) {
+ return value === true || value === false ||
+ (isObjectLike(value) && baseGetTag(value) == boolTag);
+ }
+
+ /**
+ * Checks if `value` is a buffer.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
+ * @example
+ *
+ * _.isBuffer(new Buffer(2));
+ * // => true
+ *
+ * _.isBuffer(new Uint8Array(2));
+ * // => false
+ */
+ var isBuffer = nativeIsBuffer || stubFalse;
+
+ /**
+ * Checks if `value` is classified as a `Date` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
+ * @example
+ *
+ * _.isDate(new Date);
+ * // => true
+ *
+ * _.isDate('Mon April 23 2012');
+ * // => false
+ */
+ var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
+
+ /**
+ * Checks if `value` is likely a DOM element.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
+ * @example
+ *
+ * _.isElement(document.body);
+ * // => true
+ *
+ * _.isElement('');
+ * // => false
+ */
+ function isElement(value) {
+ return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
+ }
+
+ /**
+ * Checks if `value` is an empty object, collection, map, or set.
+ *
+ * Objects are considered empty if they have no own enumerable string keyed
+ * properties.
+ *
+ * Array-like values such as `arguments` objects, arrays, buffers, strings, or
+ * jQuery-like collections are considered empty if they have a `length` of `0`.
+ * Similarly, maps and sets are considered empty if they have a `size` of `0`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty(null);
+ * // => true
+ *
+ * _.isEmpty(true);
+ * // => true
+ *
+ * _.isEmpty(1);
+ * // => true
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({ 'a': 1 });
+ * // => false
+ */
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArrayLike(value) &&
+ (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
+ isBuffer(value) || isTypedArray(value) || isArguments(value))) {
+ return !value.length;
+ }
+ var tag = getTag(value);
+ if (tag == mapTag || tag == setTag) {
+ return !value.size;
+ }
+ if (isPrototype(value)) {
+ return !baseKeys(value).length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent.
+ *
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
+ * date objects, error objects, maps, numbers, `Object` objects, regexes,
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
+ * by their own, not inherited, enumerable properties. Functions and DOM
+ * nodes are compared by strict equality, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ * var other = { 'a': 1 };
+ *
+ * _.isEqual(object, other);
+ * // => true
+ *
+ * object === other;
+ * // => false
+ */
+ function isEqual(value, other) {
+ return baseIsEqual(value, other);
+ }
+
+ /**
+ * This method is like `_.isEqual` except that it accepts `customizer` which
+ * is invoked to compare values. If `customizer` returns `undefined`, comparisons
+ * are handled by the method instead. The `customizer` is invoked with up to
+ * six arguments: (objValue, othValue [, index|key, object, other, stack]).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * function isGreeting(value) {
+ * return /^h(?:i|ello)$/.test(value);
+ * }
+ *
+ * function customizer(objValue, othValue) {
+ * if (isGreeting(objValue) && isGreeting(othValue)) {
+ * return true;
+ * }
+ * }
+ *
+ * var array = ['hello', 'goodbye'];
+ * var other = ['hi', 'goodbye'];
+ *
+ * _.isEqualWith(array, other, customizer);
+ * // => true
+ */
+ function isEqualWith(value, other, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined$1;
+ var result = customizer ? customizer(value, other) : undefined$1;
+ return result === undefined$1 ? baseIsEqual(value, other, undefined$1, customizer) : !!result;
+ }
+
+ /**
+ * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
+ * `SyntaxError`, `TypeError`, or `URIError` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
+ * @example
+ *
+ * _.isError(new Error);
+ * // => true
+ *
+ * _.isError(Error);
+ * // => false
+ */
+ function isError(value) {
+ if (!isObjectLike(value)) {
+ return false;
+ }
+ var tag = baseGetTag(value);
+ return tag == errorTag || tag == domExcTag ||
+ (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
+ }
+
+ /**
+ * Checks if `value` is a finite primitive number.
+ *
+ * **Note:** This method is based on
+ * [`Number.isFinite`](https://mdn.io/Number/isFinite).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
+ * @example
+ *
+ * _.isFinite(3);
+ * // => true
+ *
+ * _.isFinite(Number.MIN_VALUE);
+ * // => true
+ *
+ * _.isFinite(Infinity);
+ * // => false
+ *
+ * _.isFinite('3');
+ * // => false
+ */
+ function isFinite(value) {
+ return typeof value == 'number' && nativeIsFinite(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+ function isFunction(value) {
+ if (!isObject(value)) {
+ return false;
+ }
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in Safari 9 which returns 'object' for typed arrays and other constructors.
+ var tag = baseGetTag(value);
+ return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+ }
+
+ /**
+ * Checks if `value` is an integer.
+ *
+ * **Note:** This method is based on
+ * [`Number.isInteger`](https://mdn.io/Number/isInteger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
+ * @example
+ *
+ * _.isInteger(3);
+ * // => true
+ *
+ * _.isInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isInteger(Infinity);
+ * // => false
+ *
+ * _.isInteger('3');
+ * // => false
+ */
+ function isInteger(value) {
+ return typeof value == 'number' && value == toInteger(value);
+ }
+
+ /**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @example
+ *
+ * _.isLength(3);
+ * // => true
+ *
+ * _.isLength(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isLength(Infinity);
+ * // => false
+ *
+ * _.isLength('3');
+ * // => false
+ */
+ function isLength(value) {
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+ function isObject(value) {
+ var type = typeof value;
+ return value != null && (type == 'object' || type == 'function');
+ }
+
+ /**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+ function isObjectLike(value) {
+ return value != null && typeof value == 'object';
+ }
+
+ /**
+ * Checks if `value` is classified as a `Map` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a map, else `false`.
+ * @example
+ *
+ * _.isMap(new Map);
+ * // => true
+ *
+ * _.isMap(new WeakMap);
+ * // => false
+ */
+ var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
+
+ /**
+ * Performs a partial deep comparison between `object` and `source` to
+ * determine if `object` contains equivalent property values.
+ *
+ * **Note:** This method is equivalent to `_.matches` when `source` is
+ * partially applied.
+ *
+ * Partial comparisons will match empty array and empty object `source`
+ * values against any array or object value, respectively. See `_.isEqual`
+ * for a list of supported value comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ *
+ * _.isMatch(object, { 'b': 2 });
+ * // => true
+ *
+ * _.isMatch(object, { 'b': 1 });
+ * // => false
+ */
+ function isMatch(object, source) {
+ return object === source || baseIsMatch(object, source, getMatchData(source));
+ }
+
+ /**
+ * This method is like `_.isMatch` except that it accepts `customizer` which
+ * is invoked to compare values. If `customizer` returns `undefined`, comparisons
+ * are handled by the method instead. The `customizer` is invoked with five
+ * arguments: (objValue, srcValue, index|key, object, source).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * function isGreeting(value) {
+ * return /^h(?:i|ello)$/.test(value);
+ * }
+ *
+ * function customizer(objValue, srcValue) {
+ * if (isGreeting(objValue) && isGreeting(srcValue)) {
+ * return true;
+ * }
+ * }
+ *
+ * var object = { 'greeting': 'hello' };
+ * var source = { 'greeting': 'hi' };
+ *
+ * _.isMatchWith(object, source, customizer);
+ * // => true
+ */
+ function isMatchWith(object, source, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined$1;
+ return baseIsMatch(object, source, getMatchData(source), customizer);
+ }
+
+ /**
+ * Checks if `value` is `NaN`.
+ *
+ * **Note:** This method is based on
+ * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
+ * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
+ * `undefined` and other non-number values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ * @example
+ *
+ * _.isNaN(NaN);
+ * // => true
+ *
+ * _.isNaN(new Number(NaN));
+ * // => true
+ *
+ * isNaN(undefined);
+ * // => true
+ *
+ * _.isNaN(undefined);
+ * // => false
+ */
+ function isNaN(value) {
+ // An `NaN` primitive is the only value that is not equal to itself.
+ // Perform the `toStringTag` check first to avoid errors with some
+ // ActiveX objects in IE.
+ return isNumber(value) && value != +value;
+ }
+
+ /**
+ * Checks if `value` is a pristine native function.
+ *
+ * **Note:** This method can't reliably detect native functions in the presence
+ * of the core-js package because core-js circumvents this kind of detection.
+ * Despite multiple requests, the core-js maintainer has made it clear: any
+ * attempt to fix the detection will be obstructed. As a result, we're left
+ * with little choice but to throw an error. Unfortunately, this also affects
+ * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
+ * which rely on core-js.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function,
+ * else `false`.
+ * @example
+ *
+ * _.isNative(Array.prototype.push);
+ * // => true
+ *
+ * _.isNative(_);
+ * // => false
+ */
+ function isNative(value) {
+ if (isMaskable(value)) {
+ throw new Error(CORE_ERROR_TEXT);
+ }
+ return baseIsNative(value);
+ }
+
+ /**
+ * Checks if `value` is `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
+ * @example
+ *
+ * _.isNull(null);
+ * // => true
+ *
+ * _.isNull(void 0);
+ * // => false
+ */
+ function isNull(value) {
+ return value === null;
+ }
+
+ /**
+ * Checks if `value` is `null` or `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
+ * @example
+ *
+ * _.isNil(null);
+ * // => true
+ *
+ * _.isNil(void 0);
+ * // => true
+ *
+ * _.isNil(NaN);
+ * // => false
+ */
+ function isNil(value) {
+ return value == null;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Number` primitive or object.
+ *
+ * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
+ * classified as numbers, use the `_.isFinite` method.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a number, else `false`.
+ * @example
+ *
+ * _.isNumber(3);
+ * // => true
+ *
+ * _.isNumber(Number.MIN_VALUE);
+ * // => true
+ *
+ * _.isNumber(Infinity);
+ * // => true
+ *
+ * _.isNumber('3');
+ * // => false
+ */
+ function isNumber(value) {
+ return typeof value == 'number' ||
+ (isObjectLike(value) && baseGetTag(value) == numberTag);
+ }
+
+ /**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.8.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+ function isPlainObject(value) {
+ if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
+ return typeof Ctor == 'function' && Ctor instanceof Ctor &&
+ funcToString.call(Ctor) == objectCtorString;
+ }
+
+ /**
+ * Checks if `value` is classified as a `RegExp` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
+ * @example
+ *
+ * _.isRegExp(/abc/);
+ * // => true
+ *
+ * _.isRegExp('/abc/');
+ * // => false
+ */
+ var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
+
+ /**
+ * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
+ * double precision number which isn't the result of a rounded unsafe integer.
+ *
+ * **Note:** This method is based on
+ * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
+ * @example
+ *
+ * _.isSafeInteger(3);
+ * // => true
+ *
+ * _.isSafeInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isSafeInteger(Infinity);
+ * // => false
+ *
+ * _.isSafeInteger('3');
+ * // => false
+ */
+ function isSafeInteger(value) {
+ return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Set` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a set, else `false`.
+ * @example
+ *
+ * _.isSet(new Set);
+ * // => true
+ *
+ * _.isSet(new WeakSet);
+ * // => false
+ */
+ var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+ function isString(value) {
+ return typeof value == 'string' ||
+ (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+ function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && baseGetTag(value) == symbolTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a typed array.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ * @example
+ *
+ * _.isTypedArray(new Uint8Array);
+ * // => true
+ *
+ * _.isTypedArray([]);
+ * // => false
+ */
+ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+
+ /**
+ * Checks if `value` is `undefined`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ *
+ * _.isUndefined(null);
+ * // => false
+ */
+ function isUndefined(value) {
+ return value === undefined$1;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakMap` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
+ * @example
+ *
+ * _.isWeakMap(new WeakMap);
+ * // => true
+ *
+ * _.isWeakMap(new Map);
+ * // => false
+ */
+ function isWeakMap(value) {
+ return isObjectLike(value) && getTag(value) == weakMapTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakSet` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
+ * @example
+ *
+ * _.isWeakSet(new WeakSet);
+ * // => true
+ *
+ * _.isWeakSet(new Set);
+ * // => false
+ */
+ function isWeakSet(value) {
+ return isObjectLike(value) && baseGetTag(value) == weakSetTag;
+ }
+
+ /**
+ * Checks if `value` is less than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`,
+ * else `false`.
+ * @see _.gt
+ * @example
+ *
+ * _.lt(1, 3);
+ * // => true
+ *
+ * _.lt(3, 3);
+ * // => false
+ *
+ * _.lt(3, 1);
+ * // => false
+ */
+ var lt = createRelationalOperation(baseLt);
+
+ /**
+ * Checks if `value` is less than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.9.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than or equal to
+ * `other`, else `false`.
+ * @see _.gte
+ * @example
+ *
+ * _.lte(1, 3);
+ * // => true
+ *
+ * _.lte(3, 3);
+ * // => true
+ *
+ * _.lte(3, 1);
+ * // => false
+ */
+ var lte = createRelationalOperation(function(value, other) {
+ return value <= other;
+ });
+
+ /**
+ * Converts `value` to an array.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the converted array.
+ * @example
+ *
+ * _.toArray({ 'a': 1, 'b': 2 });
+ * // => [1, 2]
+ *
+ * _.toArray('abc');
+ * // => ['a', 'b', 'c']
+ *
+ * _.toArray(1);
+ * // => []
+ *
+ * _.toArray(null);
+ * // => []
+ */
+ function toArray(value) {
+ if (!value) {
+ return [];
+ }
+ if (isArrayLike(value)) {
+ return isString(value) ? stringToArray(value) : copyArray(value);
+ }
+ if (symIterator && value[symIterator]) {
+ return iteratorToArray(value[symIterator]());
+ }
+ var tag = getTag(value),
+ func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
+
+ return func(value);
+ }
+
+ /**
+ * Converts `value` to a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.12.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted number.
+ * @example
+ *
+ * _.toFinite(3.2);
+ * // => 3.2
+ *
+ * _.toFinite(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toFinite(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toFinite('3.2');
+ * // => 3.2
+ */
+ function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+ }
+
+ /**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3.2);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3.2');
+ * // => 3
+ */
+ function toInteger(value) {
+ var result = toFinite(value),
+ remainder = result % 1;
+
+ return result === result ? (remainder ? result - remainder : result) : 0;
+ }
+
+ /**
+ * Converts `value` to an integer suitable for use as the length of an
+ * array-like object.
+ *
+ * **Note:** This method is based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toLength(3.2);
+ * // => 3
+ *
+ * _.toLength(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toLength(Infinity);
+ * // => 4294967295
+ *
+ * _.toLength('3.2');
+ * // => 3
+ */
+ function toLength(value) {
+ return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
+ }
+
+ /**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+ function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+ }
+
+ /**
+ * Converts `value` to a plain object flattening inherited enumerable string
+ * keyed properties of `value` to own properties of the plain object.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
+ *
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
+ */
+ function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+ }
+
+ /**
+ * Converts `value` to a safe integer. A safe integer can be compared and
+ * represented correctly.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toSafeInteger(3.2);
+ * // => 3
+ *
+ * _.toSafeInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toSafeInteger(Infinity);
+ * // => 9007199254740991
+ *
+ * _.toSafeInteger('3.2');
+ * // => 3
+ */
+ function toSafeInteger(value) {
+ return value
+ ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
+ : (value === 0 ? value : 0);
+ }
+
+ /**
+ * Converts `value` to a string. An empty string is returned for `null`
+ * and `undefined` values. The sign of `-0` is preserved.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.toString(null);
+ * // => ''
+ *
+ * _.toString(-0);
+ * // => '-0'
+ *
+ * _.toString([1, 2, 3]);
+ * // => '1,2,3'
+ */
+ function toString(value) {
+ return value == null ? '' : baseToString(value);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Assigns own enumerable string keyed properties of source objects to the
+ * destination object. Source objects are applied from left to right.
+ * Subsequent sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object` and is loosely based on
+ * [`Object.assign`](https://mdn.io/Object/assign).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.10.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.assignIn
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * function Bar() {
+ * this.c = 3;
+ * }
+ *
+ * Foo.prototype.b = 2;
+ * Bar.prototype.d = 4;
+ *
+ * _.assign({ 'a': 0 }, new Foo, new Bar);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ var assign = createAssigner(function(object, source) {
+ if (isPrototype(source) || isArrayLike(source)) {
+ copyObject(source, keys(source), object);
+ return;
+ }
+ for (var key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ assignValue(object, key, source[key]);
+ }
+ }
+ });
+
+ /**
+ * This method is like `_.assign` except that it iterates over own and
+ * inherited source properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias extend
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.assign
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * function Bar() {
+ * this.c = 3;
+ * }
+ *
+ * Foo.prototype.b = 2;
+ * Bar.prototype.d = 4;
+ *
+ * _.assignIn({ 'a': 0 }, new Foo, new Bar);
+ * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
+ */
+ var assignIn = createAssigner(function(object, source) {
+ copyObject(source, keysIn(source), object);
+ });
+
+ /**
+ * This method is like `_.assignIn` except that it accepts `customizer`
+ * which is invoked to produce the assigned values. If `customizer` returns
+ * `undefined`, assignment is handled by the method instead. The `customizer`
+ * is invoked with five arguments: (objValue, srcValue, key, object, source).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias extendWith
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @see _.assignWith
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * return _.isUndefined(objValue) ? srcValue : objValue;
+ * }
+ *
+ * var defaults = _.partialRight(_.assignInWith, customizer);
+ *
+ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keysIn(source), object, customizer);
+ });
+
+ /**
+ * This method is like `_.assign` except that it accepts `customizer`
+ * which is invoked to produce the assigned values. If `customizer` returns
+ * `undefined`, assignment is handled by the method instead. The `customizer`
+ * is invoked with five arguments: (objValue, srcValue, key, object, source).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @see _.assignInWith
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * return _.isUndefined(objValue) ? srcValue : objValue;
+ * }
+ *
+ * var defaults = _.partialRight(_.assignWith, customizer);
+ *
+ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keys(source), object, customizer);
+ });
+
+ /**
+ * Creates an array of values corresponding to `paths` of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Array} Returns the picked values.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
+ *
+ * _.at(object, ['a[0].b.c', 'a[1]']);
+ * // => [3, 4]
+ */
+ var at = flatRest(baseAt);
+
+ /**
+ * Creates an object that inherits from the `prototype` object. If a
+ * `properties` object is given, its own enumerable string keyed properties
+ * are assigned to the created object.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.3.0
+ * @category Object
+ * @param {Object} prototype The object to inherit from.
+ * @param {Object} [properties] The properties to assign to the object.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
+ * }
+ *
+ * function Circle() {
+ * Shape.call(this);
+ * }
+ *
+ * Circle.prototype = _.create(Shape.prototype, {
+ * 'constructor': Circle
+ * });
+ *
+ * var circle = new Circle;
+ * circle instanceof Circle;
+ * // => true
+ *
+ * circle instanceof Shape;
+ * // => true
+ */
+ function create(prototype, properties) {
+ var result = baseCreate(prototype);
+ return properties == null ? result : baseAssign(result, properties);
+ }
+
+ /**
+ * Assigns own and inherited enumerable string keyed properties of source
+ * objects to the destination object for all destination properties that
+ * resolve to `undefined`. Source objects are applied from left to right.
+ * Once a property is set, additional values of the same property are ignored.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.defaultsDeep
+ * @example
+ *
+ * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var defaults = baseRest(function(object, sources) {
+ object = Object(object);
+
+ var index = -1;
+ var length = sources.length;
+ var guard = length > 2 ? sources[2] : undefined$1;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ length = 1;
+ }
+
+ while (++index < length) {
+ var source = sources[index];
+ var props = keysIn(source);
+ var propsIndex = -1;
+ var propsLength = props.length;
+
+ while (++propsIndex < propsLength) {
+ var key = props[propsIndex];
+ var value = object[key];
+
+ if (value === undefined$1 ||
+ (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
+ object[key] = source[key];
+ }
+ }
+ }
+
+ return object;
+ });
+
+ /**
+ * This method is like `_.defaults` except that it recursively assigns
+ * default properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.10.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.defaults
+ * @example
+ *
+ * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
+ * // => { 'a': { 'b': 2, 'c': 3 } }
+ */
+ var defaultsDeep = baseRest(function(args) {
+ args.push(undefined$1, customDefaultsMerge);
+ return apply(mergeWith, undefined$1, args);
+ });
+
+ /**
+ * This method is like `_.find` except that it returns the key of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {string|undefined} Returns the key of the matched element,
+ * else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findKey(users, function(o) { return o.age < 40; });
+ * // => 'barney' (iteration order is not guaranteed)
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findKey(users, { 'age': 1, 'active': true });
+ * // => 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findKey(users, ['active', false]);
+ * // => 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findKey(users, 'active');
+ * // => 'barney'
+ */
+ function findKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
+ }
+
+ /**
+ * This method is like `_.findKey` except that it iterates over elements of
+ * a collection in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {string|undefined} Returns the key of the matched element,
+ * else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findLastKey(users, function(o) { return o.age < 40; });
+ * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findLastKey(users, { 'age': 36, 'active': true });
+ * // => 'barney'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findLastKey(users, ['active', false]);
+ * // => 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findLastKey(users, 'active');
+ * // => 'pebbles'
+ */
+ function findLastKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
+ }
+
+ /**
+ * Iterates over own and inherited enumerable string keyed properties of an
+ * object and invokes `iteratee` for each property. The iteratee is invoked
+ * with three arguments: (value, key, object). Iteratee functions may exit
+ * iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forInRight
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forIn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
+ */
+ function forIn(object, iteratee) {
+ return object == null
+ ? object
+ : baseFor(object, getIteratee(iteratee, 3), keysIn);
+ }
+
+ /**
+ * This method is like `_.forIn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forIn
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forInRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
+ */
+ function forInRight(object, iteratee) {
+ return object == null
+ ? object
+ : baseForRight(object, getIteratee(iteratee, 3), keysIn);
+ }
+
+ /**
+ * Iterates over own enumerable string keyed properties of an object and
+ * invokes `iteratee` for each property. The iteratee is invoked with three
+ * arguments: (value, key, object). Iteratee functions may exit iteration
+ * early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forOwnRight
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a' then 'b' (iteration order is not guaranteed).
+ */
+ function forOwn(object, iteratee) {
+ return object && baseForOwn(object, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.forOwn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.0.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forOwn
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwnRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
+ */
+ function forOwnRight(object, iteratee) {
+ return object && baseForOwnRight(object, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * Creates an array of function property names from own enumerable properties
+ * of `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the function names.
+ * @see _.functionsIn
+ * @example
+ *
+ * function Foo() {
+ * this.a = _.constant('a');
+ * this.b = _.constant('b');
+ * }
+ *
+ * Foo.prototype.c = _.constant('c');
+ *
+ * _.functions(new Foo);
+ * // => ['a', 'b']
+ */
+ function functions(object) {
+ return object == null ? [] : baseFunctions(object, keys(object));
+ }
+
+ /**
+ * Creates an array of function property names from own and inherited
+ * enumerable properties of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the function names.
+ * @see _.functions
+ * @example
+ *
+ * function Foo() {
+ * this.a = _.constant('a');
+ * this.b = _.constant('b');
+ * }
+ *
+ * Foo.prototype.c = _.constant('c');
+ *
+ * _.functionsIn(new Foo);
+ * // => ['a', 'b', 'c']
+ */
+ function functionsIn(object) {
+ return object == null ? [] : baseFunctions(object, keysIn(object));
+ }
+
+ /**
+ * Gets the value at `path` of `object`. If the resolved value is
+ * `undefined`, the `defaultValue` is returned in its place.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.get(object, 'a[0].b.c');
+ * // => 3
+ *
+ * _.get(object, ['a', '0', 'b', 'c']);
+ * // => 3
+ *
+ * _.get(object, 'a.b.c', 'default');
+ * // => 'default'
+ */
+ function get(object, path, defaultValue) {
+ var result = object == null ? undefined$1 : baseGet(object, path);
+ return result === undefined$1 ? defaultValue : result;
+ }
+
+ /**
+ * Checks if `path` is a direct property of `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = { 'a': { 'b': 2 } };
+ * var other = _.create({ 'a': _.create({ 'b': 2 }) });
+ *
+ * _.has(object, 'a');
+ * // => true
+ *
+ * _.has(object, 'a.b');
+ * // => true
+ *
+ * _.has(object, ['a', 'b']);
+ * // => true
+ *
+ * _.has(other, 'a');
+ * // => false
+ */
+ function has(object, path) {
+ return object != null && hasPath(object, path, baseHas);
+ }
+
+ /**
+ * Checks if `path` is a direct or inherited property of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = _.create({ 'a': _.create({ 'b': 2 }) });
+ *
+ * _.hasIn(object, 'a');
+ * // => true
+ *
+ * _.hasIn(object, 'a.b');
+ * // => true
+ *
+ * _.hasIn(object, ['a', 'b']);
+ * // => true
+ *
+ * _.hasIn(object, 'b');
+ * // => false
+ */
+ function hasIn(object, path) {
+ return object != null && hasPath(object, path, baseHasIn);
+ }
+
+ /**
+ * Creates an object composed of the inverted keys and values of `object`.
+ * If `object` contains duplicate values, subsequent values overwrite
+ * property assignments of previous values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.7.0
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invert(object);
+ * // => { '1': 'c', '2': 'b' }
+ */
+ var invert = createInverter(function(result, value, key) {
+ if (value != null &&
+ typeof value.toString != 'function') {
+ value = nativeObjectToString.call(value);
+ }
+
+ result[value] = key;
+ }, constant(identity));
+
+ /**
+ * This method is like `_.invert` except that the inverted object is generated
+ * from the results of running each element of `object` thru `iteratee`. The
+ * corresponding inverted value of each inverted key is an array of keys
+ * responsible for generating the inverted value. The iteratee is invoked
+ * with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.1.0
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invertBy(object);
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ *
+ * _.invertBy(object, function(value) {
+ * return 'group' + value;
+ * });
+ * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
+ */
+ var invertBy = createInverter(function(result, value, key) {
+ if (value != null &&
+ typeof value.toString != 'function') {
+ value = nativeObjectToString.call(value);
+ }
+
+ if (hasOwnProperty.call(result, value)) {
+ result[value].push(key);
+ } else {
+ result[value] = [key];
+ }
+ }, getIteratee);
+
+ /**
+ * Invokes the method at `path` of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
+ *
+ * _.invoke(object, 'a[0].b.c.slice', 1, 3);
+ * // => [2, 3]
+ */
+ var invoke = baseRest(baseInvoke);
+
+ /**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+ function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+ */
+ function keysIn(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+ }
+
+ /**
+ * The opposite of `_.mapValues`; this method creates an object with the
+ * same values as `object` and keys generated by running each own enumerable
+ * string keyed property of `object` thru `iteratee`. The iteratee is invoked
+ * with three arguments: (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.8.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @see _.mapValues
+ * @example
+ *
+ * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
+ * return key + value;
+ * });
+ * // => { 'a1': 1, 'b2': 2 }
+ */
+ function mapKeys(object, iteratee) {
+ var result = {};
+ iteratee = getIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ baseAssignValue(result, iteratee(value, key, object), value);
+ });
+ return result;
+ }
+
+ /**
+ * Creates an object with the same keys as `object` and values generated
+ * by running each own enumerable string keyed property of `object` thru
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @see _.mapKeys
+ * @example
+ *
+ * var users = {
+ * 'fred': { 'user': 'fred', 'age': 40 },
+ * 'pebbles': { 'user': 'pebbles', 'age': 1 }
+ * };
+ *
+ * _.mapValues(users, function(o) { return o.age; });
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.mapValues(users, 'age');
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ */
+ function mapValues(object, iteratee) {
+ var result = {};
+ iteratee = getIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ baseAssignValue(result, key, iteratee(value, key, object));
+ });
+ return result;
+ }
+
+ /**
+ * This method is like `_.assign` except that it recursively merges own and
+ * inherited enumerable string keyed properties of source objects into the
+ * destination object. Source properties that resolve to `undefined` are
+ * skipped if a destination value exists. Array and plain object properties
+ * are merged recursively. Other objects and value types are overridden by
+ * assignment. Source objects are applied from left to right. Subsequent
+ * sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {
+ * 'a': [{ 'b': 2 }, { 'd': 4 }]
+ * };
+ *
+ * var other = {
+ * 'a': [{ 'c': 3 }, { 'e': 5 }]
+ * };
+ *
+ * _.merge(object, other);
+ * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
+ */
+ var merge = createAssigner(function(object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+ });
+
+ /**
+ * This method is like `_.merge` except that it accepts `customizer` which
+ * is invoked to produce the merged values of the destination and source
+ * properties. If `customizer` returns `undefined`, merging is handled by the
+ * method instead. The `customizer` is invoked with six arguments:
+ * (objValue, srcValue, key, object, source, stack).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} customizer The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * if (_.isArray(objValue)) {
+ * return objValue.concat(srcValue);
+ * }
+ * }
+ *
+ * var object = { 'a': [1], 'b': [2] };
+ * var other = { 'a': [3], 'b': [4] };
+ *
+ * _.mergeWith(object, other, customizer);
+ * // => { 'a': [1, 3], 'b': [2, 4] }
+ */
+ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
+ baseMerge(object, source, srcIndex, customizer);
+ });
+
+ /**
+ * The opposite of `_.pick`; this method creates an object composed of the
+ * own and inherited enumerable property paths of `object` that are not omitted.
+ *
+ * **Note:** This method is considerably slower than `_.pick`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [paths] The property paths to omit.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.omit(object, ['a', 'c']);
+ * // => { 'b': '2' }
+ */
+ var omit = flatRest(function(object, paths) {
+ var result = {};
+ if (object == null) {
+ return result;
+ }
+ var isDeep = false;
+ paths = arrayMap(paths, function(path) {
+ path = castPath(path, object);
+ isDeep || (isDeep = path.length > 1);
+ return path;
+ });
+ copyObject(object, getAllKeysIn(object), result);
+ if (isDeep) {
+ result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
+ }
+ var length = paths.length;
+ while (length--) {
+ baseUnset(result, paths[length]);
+ }
+ return result;
+ });
+
+ /**
+ * The opposite of `_.pickBy`; this method creates an object composed of
+ * the own and inherited enumerable string keyed properties of `object` that
+ * `predicate` doesn't return truthy for. The predicate is invoked with two
+ * arguments: (value, key).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function} [predicate=_.identity] The function invoked per property.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.omitBy(object, _.isNumber);
+ * // => { 'b': '2' }
+ */
+ function omitBy(object, predicate) {
+ return pickBy(object, negate(getIteratee(predicate)));
+ }
+
+ /**
+ * Creates an object composed of the picked `object` properties.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pick(object, ['a', 'c']);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ var pick = flatRest(function(object, paths) {
+ return object == null ? {} : basePick(object, paths);
+ });
+
+ /**
+ * Creates an object composed of the `object` properties `predicate` returns
+ * truthy for. The predicate is invoked with two arguments: (value, key).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function} [predicate=_.identity] The function invoked per property.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pickBy(object, _.isNumber);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ function pickBy(object, predicate) {
+ if (object == null) {
+ return {};
+ }
+ var props = arrayMap(getAllKeysIn(object), function(prop) {
+ return [prop];
+ });
+ predicate = getIteratee(predicate);
+ return basePickBy(object, props, function(value, path) {
+ return predicate(value, path[0]);
+ });
+ }
+
+ /**
+ * This method is like `_.get` except that if the resolved value is a
+ * function it's invoked with the `this` binding of its parent object and
+ * its result is returned.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to resolve.
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
+ *
+ * _.result(object, 'a[0].b.c1');
+ * // => 3
+ *
+ * _.result(object, 'a[0].b.c2');
+ * // => 4
+ *
+ * _.result(object, 'a[0].b.c3', 'default');
+ * // => 'default'
+ *
+ * _.result(object, 'a[0].b.c3', _.constant('default'));
+ * // => 'default'
+ */
+ function result(object, path, defaultValue) {
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length;
+
+ // Ensure the loop is entered when path is empty.
+ if (!length) {
+ length = 1;
+ object = undefined$1;
+ }
+ while (++index < length) {
+ var value = object == null ? undefined$1 : object[toKey(path[index])];
+ if (value === undefined$1) {
+ index = length;
+ value = defaultValue;
+ }
+ object = isFunction(value) ? value.call(object) : value;
+ }
+ return object;
+ }
+
+ /**
+ * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
+ * it's created. Arrays are created for missing index properties while objects
+ * are created for all other missing properties. Use `_.setWith` to customize
+ * `path` creation.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.set(object, 'a[0].b.c', 4);
+ * console.log(object.a[0].b.c);
+ * // => 4
+ *
+ * _.set(object, ['x', '0', 'y', 'z'], 5);
+ * console.log(object.x[0].y.z);
+ * // => 5
+ */
+ function set(object, path, value) {
+ return object == null ? object : baseSet(object, path, value);
+ }
+
+ /**
+ * This method is like `_.set` except that it accepts `customizer` which is
+ * invoked to produce the objects of `path`. If `customizer` returns `undefined`
+ * path creation is handled by the method instead. The `customizer` is invoked
+ * with three arguments: (nsValue, key, nsObject).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {};
+ *
+ * _.setWith(object, '[0][1]', 'a', Object);
+ * // => { '0': { '1': 'a' } }
+ */
+ function setWith(object, path, value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined$1;
+ return object == null ? object : baseSet(object, path, value, customizer);
+ }
+
+ /**
+ * Creates an array of own enumerable string keyed-value pairs for `object`
+ * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
+ * entries are returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias entries
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the key-value pairs.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.toPairs(new Foo);
+ * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
+ */
+ var toPairs = createToPairs(keys);
+
+ /**
+ * Creates an array of own and inherited enumerable string keyed-value pairs
+ * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
+ * or set, its entries are returned.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @alias entriesIn
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the key-value pairs.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.toPairsIn(new Foo);
+ * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
+ */
+ var toPairsIn = createToPairs(keysIn);
+
+ /**
+ * An alternative to `_.reduce`; this method transforms `object` to a new
+ * `accumulator` object which is the result of running each of its own
+ * enumerable string keyed properties thru `iteratee`, with each invocation
+ * potentially mutating the `accumulator` object. If `accumulator` is not
+ * provided, a new object with the same `[[Prototype]]` will be used. The
+ * iteratee is invoked with four arguments: (accumulator, value, key, object).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The custom accumulator value.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.transform([2, 3, 4], function(result, n) {
+ * result.push(n *= n);
+ * return n % 2 == 0;
+ * }, []);
+ * // => [4, 9]
+ *
+ * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ */
+ function transform(object, iteratee, accumulator) {
+ var isArr = isArray(object),
+ isArrLike = isArr || isBuffer(object) || isTypedArray(object);
+
+ iteratee = getIteratee(iteratee, 4);
+ if (accumulator == null) {
+ var Ctor = object && object.constructor;
+ if (isArrLike) {
+ accumulator = isArr ? new Ctor : [];
+ }
+ else if (isObject(object)) {
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
+ }
+ else {
+ accumulator = {};
+ }
+ }
+ (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
+ return iteratee(accumulator, value, index, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes the property at `path` of `object`.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to unset.
+ * @returns {boolean} Returns `true` if the property is deleted, else `false`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 7 } }] };
+ * _.unset(object, 'a[0].b.c');
+ * // => true
+ *
+ * console.log(object);
+ * // => { 'a': [{ 'b': {} }] };
+ *
+ * _.unset(object, ['a', '0', 'b', 'c']);
+ * // => true
+ *
+ * console.log(object);
+ * // => { 'a': [{ 'b': {} }] };
+ */
+ function unset(object, path) {
+ return object == null ? true : baseUnset(object, path);
+ }
+
+ /**
+ * This method is like `_.set` except that accepts `updater` to produce the
+ * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
+ * is invoked with one argument: (value).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.6.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {Function} updater The function to produce the updated value.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.update(object, 'a[0].b.c', function(n) { return n * n; });
+ * console.log(object.a[0].b.c);
+ * // => 9
+ *
+ * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
+ * console.log(object.x[0].y.z);
+ * // => 0
+ */
+ function update(object, path, updater) {
+ return object == null ? object : baseUpdate(object, path, castFunction(updater));
+ }
+
+ /**
+ * This method is like `_.update` except that it accepts `customizer` which is
+ * invoked to produce the objects of `path`. If `customizer` returns `undefined`
+ * path creation is handled by the method instead. The `customizer` is invoked
+ * with three arguments: (nsValue, key, nsObject).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.6.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {Function} updater The function to produce the updated value.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {};
+ *
+ * _.updateWith(object, '[0][1]', _.constant('a'), Object);
+ * // => { '0': { '1': 'a' } }
+ */
+ function updateWith(object, path, updater, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined$1;
+ return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
+ }
+
+ /**
+ * Creates an array of the own enumerable string keyed property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.values(new Foo);
+ * // => [1, 2] (iteration order is not guaranteed)
+ *
+ * _.values('hi');
+ * // => ['h', 'i']
+ */
+ function values(object) {
+ return object == null ? [] : baseValues(object, keys(object));
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable string keyed property
+ * values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.valuesIn(new Foo);
+ * // => [1, 2, 3] (iteration order is not guaranteed)
+ */
+ function valuesIn(object) {
+ return object == null ? [] : baseValues(object, keysIn(object));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Clamps `number` within the inclusive `lower` and `upper` bounds.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Number
+ * @param {number} number The number to clamp.
+ * @param {number} [lower] The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the clamped number.
+ * @example
+ *
+ * _.clamp(-10, -5, 5);
+ * // => -5
+ *
+ * _.clamp(10, -5, 5);
+ * // => 5
+ */
+ function clamp(number, lower, upper) {
+ if (upper === undefined$1) {
+ upper = lower;
+ lower = undefined$1;
+ }
+ if (upper !== undefined$1) {
+ upper = toNumber(upper);
+ upper = upper === upper ? upper : 0;
+ }
+ if (lower !== undefined$1) {
+ lower = toNumber(lower);
+ lower = lower === lower ? lower : 0;
+ }
+ return baseClamp(toNumber(number), lower, upper);
+ }
+
+ /**
+ * Checks if `n` is between `start` and up to, but not including, `end`. If
+ * `end` is not specified, it's set to `start` with `start` then set to `0`.
+ * If `start` is greater than `end` the params are swapped to support
+ * negative ranges.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.3.0
+ * @category Number
+ * @param {number} number The number to check.
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
+ * @see _.range, _.rangeRight
+ * @example
+ *
+ * _.inRange(3, 2, 4);
+ * // => true
+ *
+ * _.inRange(4, 8);
+ * // => true
+ *
+ * _.inRange(4, 2);
+ * // => false
+ *
+ * _.inRange(2, 2);
+ * // => false
+ *
+ * _.inRange(1.2, 2);
+ * // => true
+ *
+ * _.inRange(5.2, 4);
+ * // => false
+ *
+ * _.inRange(-3, -2, -6);
+ * // => true
+ */
+ function inRange(number, start, end) {
+ start = toFinite(start);
+ if (end === undefined$1) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ number = toNumber(number);
+ return baseInRange(number, start, end);
+ }
+
+ /**
+ * Produces a random number between the inclusive `lower` and `upper` bounds.
+ * If only one argument is provided a number between `0` and the given number
+ * is returned. If `floating` is `true`, or either `lower` or `upper` are
+ * floats, a floating-point number is returned instead of an integer.
+ *
+ * **Note:** JavaScript follows the IEEE-754 standard for resolving
+ * floating-point values which can produce unexpected results.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.7.0
+ * @category Number
+ * @param {number} [lower=0] The lower bound.
+ * @param {number} [upper=1] The upper bound.
+ * @param {boolean} [floating] Specify returning a floating-point number.
+ * @returns {number} Returns the random number.
+ * @example
+ *
+ * _.random(0, 5);
+ * // => an integer between 0 and 5
+ *
+ * _.random(5);
+ * // => also an integer between 0 and 5
+ *
+ * _.random(5, true);
+ * // => a floating-point number between 0 and 5
+ *
+ * _.random(1.2, 5.2);
+ * // => a floating-point number between 1.2 and 5.2
+ */
+ function random(lower, upper, floating) {
+ if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
+ upper = floating = undefined$1;
+ }
+ if (floating === undefined$1) {
+ if (typeof upper == 'boolean') {
+ floating = upper;
+ upper = undefined$1;
+ }
+ else if (typeof lower == 'boolean') {
+ floating = lower;
+ lower = undefined$1;
+ }
+ }
+ if (lower === undefined$1 && upper === undefined$1) {
+ lower = 0;
+ upper = 1;
+ }
+ else {
+ lower = toFinite(lower);
+ if (upper === undefined$1) {
+ upper = lower;
+ lower = 0;
+ } else {
+ upper = toFinite(upper);
+ }
+ }
+ if (lower > upper) {
+ var temp = lower;
+ lower = upper;
+ upper = temp;
+ }
+ if (floating || lower % 1 || upper % 1) {
+ var rand = nativeRandom();
+ return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
+ }
+ return baseRandom(lower, upper);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the camel cased string.
+ * @example
+ *
+ * _.camelCase('Foo Bar');
+ * // => 'fooBar'
+ *
+ * _.camelCase('--foo-bar--');
+ * // => 'fooBar'
+ *
+ * _.camelCase('__FOO_BAR__');
+ * // => 'fooBar'
+ */
+ var camelCase = createCompounder(function(result, word, index) {
+ word = word.toLowerCase();
+ return result + (index ? capitalize(word) : word);
+ });
+
+ /**
+ * Converts the first character of `string` to upper case and the remaining
+ * to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to capitalize.
+ * @returns {string} Returns the capitalized string.
+ * @example
+ *
+ * _.capitalize('FRED');
+ * // => 'Fred'
+ */
+ function capitalize(string) {
+ return upperFirst(toString(string).toLowerCase());
+ }
+
+ /**
+ * Deburrs `string` by converting
+ * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
+ * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
+ * letters to basic Latin letters and removing
+ * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to deburr.
+ * @returns {string} Returns the deburred string.
+ * @example
+ *
+ * _.deburr('déjà vu');
+ * // => 'deja vu'
+ */
+ function deburr(string) {
+ string = toString(string);
+ return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
+ }
+
+ /**
+ * Checks if `string` ends with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=string.length] The position to search up to.
+ * @returns {boolean} Returns `true` if `string` ends with `target`,
+ * else `false`.
+ * @example
+ *
+ * _.endsWith('abc', 'c');
+ * // => true
+ *
+ * _.endsWith('abc', 'b');
+ * // => false
+ *
+ * _.endsWith('abc', 'b', 2);
+ * // => true
+ */
+ function endsWith(string, target, position) {
+ string = toString(string);
+ target = baseToString(target);
+
+ var length = string.length;
+ position = position === undefined$1
+ ? length
+ : baseClamp(toInteger(position), 0, length);
+
+ var end = position;
+ position -= target.length;
+ return position >= 0 && string.slice(position, end) == target;
+ }
+
+ /**
+ * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
+ * corresponding HTML entities.
+ *
+ * **Note:** No other characters are escaped. To escape additional
+ * characters use a third-party library like [_he_](https://mths.be/he).
+ *
+ * Though the ">" character is escaped for symmetry, characters like
+ * ">" and "/" don't need escaping in HTML and have no special meaning
+ * unless they're part of a tag or unquoted attribute value. See
+ * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
+ * (under "semi-related fun fact") for more details.
+ *
+ * When working with HTML you should always
+ * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
+ * XSS vectors.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escape('fred, barney, & pebbles');
+ * // => 'fred, barney, & pebbles'
+ */
+ function escape(string) {
+ string = toString(string);
+ return (string && reHasUnescapedHtml.test(string))
+ ? string.replace(reUnescapedHtml, escapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
+ * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escapeRegExp('[lodash](https://lodash.com/)');
+ * // => '\[lodash\]\(https://lodash\.com/\)'
+ */
+ function escapeRegExp(string) {
+ string = toString(string);
+ return (string && reHasRegExpChar.test(string))
+ ? string.replace(reRegExpChar, '\\$&')
+ : string;
+ }
+
+ /**
+ * Converts `string` to
+ * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the kebab cased string.
+ * @example
+ *
+ * _.kebabCase('Foo Bar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('fooBar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('__FOO_BAR__');
+ * // => 'foo-bar'
+ */
+ var kebabCase = createCompounder(function(result, word, index) {
+ return result + (index ? '-' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts `string`, as space separated words, to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the lower cased string.
+ * @example
+ *
+ * _.lowerCase('--Foo-Bar--');
+ * // => 'foo bar'
+ *
+ * _.lowerCase('fooBar');
+ * // => 'foo bar'
+ *
+ * _.lowerCase('__FOO_BAR__');
+ * // => 'foo bar'
+ */
+ var lowerCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts the first character of `string` to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.lowerFirst('Fred');
+ * // => 'fred'
+ *
+ * _.lowerFirst('FRED');
+ * // => 'fRED'
+ */
+ var lowerFirst = createCaseFirst('toLowerCase');
+
+ /**
+ * Pads `string` on the left and right sides if it's shorter than `length`.
+ * Padding characters are truncated if they can't be evenly divided by `length`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.pad('abc', 8);
+ * // => ' abc '
+ *
+ * _.pad('abc', 8, '_-');
+ * // => '_-abc_-_'
+ *
+ * _.pad('abc', 3);
+ * // => 'abc'
+ */
+ function pad(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = length ? stringSize(string) : 0;
+ if (!length || strLength >= length) {
+ return string;
+ }
+ var mid = (length - strLength) / 2;
+ return (
+ createPadding(nativeFloor(mid), chars) +
+ string +
+ createPadding(nativeCeil(mid), chars)
+ );
+ }
+
+ /**
+ * Pads `string` on the right side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padEnd('abc', 6);
+ * // => 'abc '
+ *
+ * _.padEnd('abc', 6, '_-');
+ * // => 'abc_-_'
+ *
+ * _.padEnd('abc', 3);
+ * // => 'abc'
+ */
+ function padEnd(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = length ? stringSize(string) : 0;
+ return (length && strLength < length)
+ ? (string + createPadding(length - strLength, chars))
+ : string;
+ }
+
+ /**
+ * Pads `string` on the left side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padStart('abc', 6);
+ * // => ' abc'
+ *
+ * _.padStart('abc', 6, '_-');
+ * // => '_-_abc'
+ *
+ * _.padStart('abc', 3);
+ * // => 'abc'
+ */
+ function padStart(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = length ? stringSize(string) : 0;
+ return (length && strLength < length)
+ ? (createPadding(length - strLength, chars) + string)
+ : string;
+ }
+
+ /**
+ * Converts `string` to an integer of the specified radix. If `radix` is
+ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
+ * hexadecimal, in which case a `radix` of `16` is used.
+ *
+ * **Note:** This method aligns with the
+ * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category String
+ * @param {string} string The string to convert.
+ * @param {number} [radix=10] The radix to interpret `value` by.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.parseInt('08');
+ * // => 8
+ *
+ * _.map(['6', '08', '10'], _.parseInt);
+ * // => [6, 8, 10]
+ */
+ function parseInt(string, radix, guard) {
+ if (guard || radix == null) {
+ radix = 0;
+ } else if (radix) {
+ radix = +radix;
+ }
+ return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
+ }
+
+ /**
+ * Repeats the given string `n` times.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to repeat.
+ * @param {number} [n=1] The number of times to repeat the string.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {string} Returns the repeated string.
+ * @example
+ *
+ * _.repeat('*', 3);
+ * // => '***'
+ *
+ * _.repeat('abc', 2);
+ * // => 'abcabc'
+ *
+ * _.repeat('abc', 0);
+ * // => ''
+ */
+ function repeat(string, n, guard) {
+ if ((guard ? isIterateeCall(string, n, guard) : n === undefined$1)) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ return baseRepeat(toString(string), n);
+ }
+
+ /**
+ * Replaces matches for `pattern` in `string` with `replacement`.
+ *
+ * **Note:** This method is based on
+ * [`String#replace`](https://mdn.io/String/replace).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to modify.
+ * @param {RegExp|string} pattern The pattern to replace.
+ * @param {Function|string} replacement The match replacement.
+ * @returns {string} Returns the modified string.
+ * @example
+ *
+ * _.replace('Hi Fred', 'Fred', 'Barney');
+ * // => 'Hi Barney'
+ */
+ function replace() {
+ var args = arguments,
+ string = toString(args[0]);
+
+ return args.length < 3 ? string : string.replace(args[1], args[2]);
+ }
+
+ /**
+ * Converts `string` to
+ * [snake case](https://en.wikipedia.org/wiki/Snake_case).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the snake cased string.
+ * @example
+ *
+ * _.snakeCase('Foo Bar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('fooBar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('--FOO-BAR--');
+ * // => 'foo_bar'
+ */
+ var snakeCase = createCompounder(function(result, word, index) {
+ return result + (index ? '_' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Splits `string` by `separator`.
+ *
+ * **Note:** This method is based on
+ * [`String#split`](https://mdn.io/String/split).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category String
+ * @param {string} [string=''] The string to split.
+ * @param {RegExp|string} separator The separator pattern to split by.
+ * @param {number} [limit] The length to truncate results to.
+ * @returns {Array} Returns the string segments.
+ * @example
+ *
+ * _.split('a-b-c', '-', 2);
+ * // => ['a', 'b']
+ */
+ function split(string, separator, limit) {
+ if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
+ separator = limit = undefined$1;
+ }
+ limit = limit === undefined$1 ? MAX_ARRAY_LENGTH : limit >>> 0;
+ if (!limit) {
+ return [];
+ }
+ string = toString(string);
+ if (string && (
+ typeof separator == 'string' ||
+ (separator != null && !isRegExp(separator))
+ )) {
+ separator = baseToString(separator);
+ if (!separator && hasUnicode(string)) {
+ return castSlice(stringToArray(string), 0, limit);
+ }
+ }
+ return string.split(separator, limit);
+ }
+
+ /**
+ * Converts `string` to
+ * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
+ *
+ * @static
+ * @memberOf _
+ * @since 3.1.0
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the start cased string.
+ * @example
+ *
+ * _.startCase('--foo-bar--');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('fooBar');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('__FOO_BAR__');
+ * // => 'FOO BAR'
+ */
+ var startCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + upperFirst(word);
+ });
+
+ /**
+ * Checks if `string` starts with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=0] The position to search from.
+ * @returns {boolean} Returns `true` if `string` starts with `target`,
+ * else `false`.
+ * @example
+ *
+ * _.startsWith('abc', 'a');
+ * // => true
+ *
+ * _.startsWith('abc', 'b');
+ * // => false
+ *
+ * _.startsWith('abc', 'b', 1);
+ * // => true
+ */
+ function startsWith(string, target, position) {
+ string = toString(string);
+ position = position == null
+ ? 0
+ : baseClamp(toInteger(position), 0, string.length);
+
+ target = baseToString(target);
+ return string.slice(position, position + target.length) == target;
+ }
+
+ /**
+ * Creates a compiled template function that can interpolate data properties
+ * in "interpolate" delimiters, HTML-escape interpolated data properties in
+ * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
+ * properties may be accessed as free variables in the template. If a setting
+ * object is given, it takes precedence over `_.templateSettings` values.
+ *
+ * **Note:** In the development build `_.template` utilizes
+ * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+ * for easier debugging.
+ *
+ * For more information on precompiling templates see
+ * [lodash's custom builds documentation](https://lodash.com/custom-builds).
+ *
+ * For more information on Chrome extension sandboxes see
+ * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The template string.
+ * @param {Object} [options={}] The options object.
+ * @param {RegExp} [options.escape=_.templateSettings.escape]
+ * The HTML "escape" delimiter.
+ * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
+ * The "evaluate" delimiter.
+ * @param {Object} [options.imports=_.templateSettings.imports]
+ * An object to import into the template as free variables.
+ * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
+ * The "interpolate" delimiter.
+ * @param {string} [options.sourceURL='lodash.templateSources[n]']
+ * The sourceURL of the compiled template.
+ * @param {string} [options.variable='obj']
+ * The data object variable name.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
+ * @returns {Function} Returns the compiled template function.
+ * @example
+ *
+ * // Use the "interpolate" delimiter to create a compiled template.
+ * var compiled = _.template('hello <%= user %>!');
+ * compiled({ 'user': 'fred' });
+ * // => 'hello fred!'
+ *
+ * // Use the HTML "escape" delimiter to escape data property values.
+ * var compiled = _.template('<%- value %>');
+ * compiled({ 'value': '