From 4576a31dd3d5f964123de916edd624dbbb24792e Mon Sep 17 00:00:00 2001 From: Jesse James Isler Date: Mon, 27 Jun 2022 10:33:08 +0200 Subject: [PATCH] added encrypt/decrpyt workflow --- .obsidian/community-plugins.json | 4 +- .obsidian/core-plugins.json | 1 + .obsidian/plugins/calendar/data.json | 10 + .obsidian/plugins/calendar/main.js | 4457 ++++++++++++++++++ .obsidian/plugins/calendar/manifest.json | 10 + .obsidian/plugins/meld-encrypt/data.json | 7 + .obsidian/plugins/meld-encrypt/main.js | 764 +++ .obsidian/plugins/meld-encrypt/manifest.json | 10 + .obsidian/plugins/meld-encrypt/styles.css | 42 + .obsidian/workspace | 38 +- 10 files changed, 5331 insertions(+), 12 deletions(-) create mode 100644 .obsidian/plugins/calendar/data.json create mode 100644 .obsidian/plugins/calendar/main.js create mode 100644 .obsidian/plugins/calendar/manifest.json create mode 100644 .obsidian/plugins/meld-encrypt/data.json create mode 100644 .obsidian/plugins/meld-encrypt/main.js create mode 100644 .obsidian/plugins/meld-encrypt/manifest.json create mode 100644 .obsidian/plugins/meld-encrypt/styles.css diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json index 431e842..31902b1 100644 --- a/.obsidian/community-plugins.json +++ b/.obsidian/community-plugins.json @@ -1,5 +1,7 @@ [ "obsidian-git", "table-editor-obsidian", - "obsidian-image-toolkit" + "obsidian-image-toolkit", + "calendar", + "meld-encrypt" ] \ No newline at end of file diff --git a/.obsidian/core-plugins.json b/.obsidian/core-plugins.json index d331556..1f21bdc 100644 --- a/.obsidian/core-plugins.json +++ b/.obsidian/core-plugins.json @@ -7,6 +7,7 @@ "outgoing-link", "tag-pane", "page-preview", + "daily-notes", "note-composer", "command-palette", "slash-command", diff --git a/.obsidian/plugins/calendar/data.json b/.obsidian/plugins/calendar/data.json new file mode 100644 index 0000000..b03e21d --- /dev/null +++ b/.obsidian/plugins/calendar/data.json @@ -0,0 +1,10 @@ +{ + "shouldConfirmBeforeCreate": true, + "weekStart": "locale", + "wordsPerDot": 250, + "showWeeklyNote": false, + "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 0000000..eb2951b --- /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 0000000..028bfa5 --- /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/meld-encrypt/data.json b/.obsidian/plugins/meld-encrypt/data.json new file mode 100644 index 0000000..3a06bb5 --- /dev/null +++ b/.obsidian/plugins/meld-encrypt/data.json @@ -0,0 +1,7 @@ +{ + "expandToWholeLines": true, + "confirmPassword": true, + "showButton": true, + "rememberPassword": true, + "rememberPasswordTimeout": 120 +} \ No newline at end of file diff --git a/.obsidian/plugins/meld-encrypt/main.js b/.obsidian/plugins/meld-encrypt/main.js new file mode 100644 index 0000000..6f57c62 --- /dev/null +++ b/.obsidian/plugins/meld-encrypt/main.js @@ -0,0 +1,764 @@ +'use strict'; + +var obsidian = require('obsidian'); + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +class DecryptModal extends obsidian.Modal { + constructor(app, title, text = '', showButton) { + super(app); + this.decryptInPlace = false; + this.text = text; + this.titleEl.innerText = title; + this.showButton = showButton; + } + onOpen() { + let { contentEl } = this; + const textEl = contentEl.createDiv().createEl('textarea', { text: this.text }); + textEl.style.width = '100%'; + textEl.style.height = '100%'; + textEl.rows = 10; + textEl.readOnly = true; + //textEl.focus(); // Doesn't seem to work here... + setTimeout(() => { textEl.focus(); }, 100); //... but this does + const btnContainerEl = contentEl.createDiv(''); + if (this.showButton) { + const copyBtnEl = btnContainerEl.createEl('button', { text: 'Copy' }); + copyBtnEl.addEventListener('click', () => { + navigator.clipboard.writeText(textEl.value); + }); + } + const decryptInPlaceBtnEl = btnContainerEl.createEl('button', { text: 'Decrypt in-place' }); + decryptInPlaceBtnEl.addEventListener('click', () => { + this.decryptInPlace = true; + this.close(); + }); + const cancelBtnEl = btnContainerEl.createEl('button', { text: 'Close' }); + cancelBtnEl.addEventListener('click', () => { + this.close(); + }); + } +} + +class PasswordModal extends obsidian.Modal { + constructor(app, isEncrypting, confirmPassword, defaultPassword = null, hint) { + super(app); + this.password = null; + this.hint = null; + this.defaultPassword = null; + this.defaultPassword = defaultPassword; + this.confirmPassword = confirmPassword; + this.isEncrypting = isEncrypting; + this.hint = hint; + } + onOpen() { + var _a, _b, _c; + let { contentEl } = this; + contentEl.empty(); + contentEl.addClass('meld-e-password'); + if (obsidian.Platform.isMobile) { + contentEl.addClass('meld-e-platform-mobile'); + } + else if (obsidian.Platform.isDesktop) { + contentEl.addClass('meld-e-platform-desktop'); + } + /* Main password input row */ + const inputPwContainerEl = contentEl.createDiv({ cls: 'meld-e-row' }); + inputPwContainerEl.createSpan({ cls: 'meld-e-icon', text: '🔑' }); + const pwInputEl = inputPwContainerEl.createEl('input', { type: 'password', value: (_a = this.defaultPassword) !== null && _a !== void 0 ? _a : '' }); + pwInputEl.placeholder = 'Enter your password'; + pwInputEl.focus(); + if (obsidian.Platform.isMobile) { + // Add 'Next' button for mobile + const inputInputNextBtnEl = inputPwContainerEl.createEl('button', { + text: '→', + cls: 'meld-e-button-next' + }); + inputInputNextBtnEl.addEventListener('click', (ev) => { + inputPasswordHandler(); + }); + } + /* End Main password input row */ + /* Confirm password input row */ + const confirmPwShown = this.confirmPassword; + const confirmPwContainerEl = contentEl.createDiv({ cls: 'meld-e-row' }); + confirmPwContainerEl.createSpan({ cls: 'meld-e-icon', text: '🔑' }); + const pwConfirmInputEl = confirmPwContainerEl.createEl('input', { + type: 'password', + value: (_b = this.defaultPassword) !== null && _b !== void 0 ? _b : '' + }); + pwConfirmInputEl.placeholder = 'Confirm your password'; + const messageEl = contentEl.createDiv({ cls: 'meld-e-message' }); + messageEl.hide(); + if (obsidian.Platform.isMobile) { + // Add 'Next' button for mobile + const confirmInputNextBtnEl = confirmPwContainerEl.createEl('button', { + text: '→', + cls: 'meld-e-button-next' + }); + confirmInputNextBtnEl.addEventListener('click', (ev) => { + confirmPasswordHandler(); + }); + } + if (!confirmPwShown) { + confirmPwContainerEl.hide(); + } + /* End Confirm password input row */ + /* Hint input row */ + const hintInputShown = this.isEncrypting; + const inputHintContainerEl = contentEl.createDiv({ cls: 'meld-e-row' }); + inputHintContainerEl.createSpan({ cls: 'meld-e-icon', text: '💡' }); + const hintInputEl = inputHintContainerEl.createEl('input', { type: 'text', value: this.hint }); + hintInputEl.placeholder = 'Enter an optional password hint'; + if (obsidian.Platform.isMobile) { + // Add 'Next' button for mobile + const hintInputNextBtnEl = inputHintContainerEl.createEl('button', { + text: '→', + cls: 'meld-e-button-next' + }); + hintInputNextBtnEl.addEventListener('click', (ev) => { + hintPasswordHandler(); + }); + } + if (!hintInputShown) { + inputHintContainerEl.hide(); + } + /* End Hint input row */ + /* Hint text row */ + const spanHintContainerEl = contentEl.createDiv({ cls: 'meld-e-row' }); + spanHintContainerEl.createSpan({ cls: 'meld-e-icon', text: '💡' }); + spanHintContainerEl.createSpan({ cls: 'meld-e-hint', text: `Hint: '${this.hint}'` }); + if (hintInputShown || ((_c = this.hint) !== null && _c !== void 0 ? _c : '').length == 0) { + spanHintContainerEl.hide(); + } + /* END Hint text row */ + const confirmPwButtonEl = contentEl.createEl('button', { + text: 'Confirm', + cls: 'meld-e-button-confirm' + }); + confirmPwButtonEl.addEventListener('click', (ev) => { + if (validate()) { + this.close(); + } + else { + pwInputEl.focus(); + } + }); + const validate = () => { + if (confirmPwShown) { + if (pwInputEl.value != pwConfirmInputEl.value) { + // passwords don't match + messageEl.setText('Passwords don\'t match'); + messageEl.show(); + return false; + } + } + this.password = pwInputEl.value; + this.hint = hintInputEl.value; + return true; + }; + const inputPasswordHandler = () => { + if (confirmPwShown) { + pwConfirmInputEl.focus(); + return; + } + if (hintInputShown) { + hintInputEl.focus(); + return; + } + if (validate()) { + this.close(); + } + }; + const confirmPasswordHandler = () => { + if (validate()) { + if (hintInputShown) { + hintInputEl.focus(); + } + else { + this.close(); + } + } + }; + const hintPasswordHandler = () => { + if (validate()) { + this.close(); + } + else { + pwInputEl.focus(); + } + }; + hintInputEl.addEventListener('keypress', (ev) => { + if ((ev.code === 'Enter' || ev.code === 'NumpadEnter') + && pwInputEl.value.length > 0) { + ev.preventDefault(); + hintPasswordHandler(); + } + }); + pwConfirmInputEl.addEventListener('keypress', (ev) => { + if ((ev.code === 'Enter' || ev.code === 'NumpadEnter') + && pwConfirmInputEl.value.length > 0) { + ev.preventDefault(); + confirmPasswordHandler(); + } + }); + pwInputEl.addEventListener('keypress', (ev) => { + if ((ev.code === 'Enter' || ev.code === 'NumpadEnter') + && pwInputEl.value.length > 0) { + ev.preventDefault(); + inputPasswordHandler(); + } + }); + } +} + +const vectorSize = 16; +const utf8Encoder = new TextEncoder(); +const utf8Decoder = new TextDecoder(); +const iterations = 1000; +const salt = utf8Encoder.encode('XHWnDAT6ehMVY2zD'); +class CryptoHelperV2 { + deriveKey(password) { + return __awaiter(this, void 0, void 0, function* () { + const buffer = utf8Encoder.encode(password); + const key = yield crypto.subtle.importKey('raw', buffer, { name: 'PBKDF2' }, false, ['deriveKey']); + const privateKey = crypto.subtle.deriveKey({ + name: 'PBKDF2', + hash: { name: 'SHA-256' }, + iterations, + salt + }, key, { + name: 'AES-GCM', + length: 256 + }, false, ['encrypt', 'decrypt']); + return privateKey; + }); + } + encryptToBase64(text, password) { + return __awaiter(this, void 0, void 0, function* () { + const key = yield this.deriveKey(password); + const textBytesToEncrypt = utf8Encoder.encode(text); + const vector = crypto.getRandomValues(new Uint8Array(vectorSize)); + // encrypt into bytes + const encryptedBytes = new Uint8Array(yield crypto.subtle.encrypt({ name: 'AES-GCM', iv: vector }, key, textBytesToEncrypt)); + const finalBytes = new Uint8Array(vector.byteLength + encryptedBytes.byteLength); + finalBytes.set(vector, 0); + finalBytes.set(encryptedBytes, vector.byteLength); + //convert array to base64 + const base64Text = btoa(String.fromCharCode(...finalBytes)); + return base64Text; + }); + } + stringToArray(str) { + var result = []; + for (var i = 0; i < str.length; i++) { + result.push(str.charCodeAt(i)); + } + return new Uint8Array(result); + } + decryptFromBase64(base64Encoded, password) { + return __awaiter(this, void 0, void 0, function* () { + try { + let bytesToDecode = this.stringToArray(atob(base64Encoded)); + // extract iv + const vector = bytesToDecode.slice(0, vectorSize); + // extract encrypted text + const encryptedTextBytes = bytesToDecode.slice(vectorSize); + const key = yield this.deriveKey(password); + // decrypt into bytes + let decryptedBytes = yield crypto.subtle.decrypt({ name: 'AES-GCM', iv: vector }, key, encryptedTextBytes); + // convert bytes to text + let decryptedText = utf8Decoder.decode(decryptedBytes); + return decryptedText; + } + catch (e) { + //console.error(e); + return null; + } + }); + } +} +const algorithmObsolete = { + name: 'AES-GCM', + iv: new Uint8Array([196, 190, 240, 190, 188, 78, 41, 132, 15, 220, 84, 211]), + tagLength: 128 +}; +class CryptoHelperObsolete { + buildKey(password) { + return __awaiter(this, void 0, void 0, function* () { + let utf8Encode = new TextEncoder(); + let passwordBytes = utf8Encode.encode(password); + let passwordDigest = yield crypto.subtle.digest({ name: 'SHA-256' }, passwordBytes); + let key = yield crypto.subtle.importKey('raw', passwordDigest, algorithmObsolete, false, ['encrypt', 'decrypt']); + return key; + }); + } + encryptToBase64(text, password) { + return __awaiter(this, void 0, void 0, function* () { + let key = yield this.buildKey(password); + let utf8Encode = new TextEncoder(); + let bytesToEncrypt = utf8Encode.encode(text); + // encrypt into bytes + let encryptedBytes = new Uint8Array(yield crypto.subtle.encrypt(algorithmObsolete, key, bytesToEncrypt)); + //convert array to base64 + let base64Text = btoa(String.fromCharCode(...encryptedBytes)); + return base64Text; + }); + } + stringToArray(str) { + var result = []; + for (var i = 0; i < str.length; i++) { + result.push(str.charCodeAt(i)); + } + return new Uint8Array(result); + } + decryptFromBase64(base64Encoded, password) { + return __awaiter(this, void 0, void 0, function* () { + try { + // convert base 64 to array + let bytesToDecrypt = this.stringToArray(atob(base64Encoded)); + let key = yield this.buildKey(password); + // decrypt into bytes + let decryptedBytes = yield crypto.subtle.decrypt(algorithmObsolete, key, bytesToDecrypt); + // convert bytes to text + let utf8Decode = new TextDecoder(); + let decryptedText = utf8Decode.decode(decryptedBytes); + return decryptedText; + } + catch (e) { + return null; + } + }); + } +} + +class MeldEncryptSettingsTab extends obsidian.PluginSettingTab { + constructor(app, plugin) { + super(app, plugin); + this.plugin = plugin; + } + display() { + let { containerEl } = this; + containerEl.empty(); + containerEl.createEl('h2', { text: 'Settings for Meld Encrypt' }); + new obsidian.Setting(containerEl) + .setName('Expand selection to whole line?') + .setDesc('Partial selections will get expanded to the whole line.') + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.expandToWholeLines) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.expandToWholeLines = value; + yield this.plugin.saveSettings(); + //this.updateSettingsUi(); + })); + }); + new obsidian.Setting(containerEl) + .setName('Confirm password?') + .setDesc('Confirm password when encrypting.') + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.confirmPassword) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.confirmPassword = value; + yield this.plugin.saveSettings(); + this.updateSettingsUi(); + })); + }); + new obsidian.Setting(containerEl) + .setName('Copy button?') + .setDesc('Show a button to copy decrypted text.') + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.showButton) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.showButton = value; + yield this.plugin.saveSettings(); + this.updateSettingsUi(); + })); + }); + new obsidian.Setting(containerEl) + .setName('Remember password?') + .setDesc('Remember the last used password for this session.') + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.rememberPassword) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.rememberPassword = value; + yield this.plugin.saveSettings(); + this.updateSettingsUi(); + })); + }); + this.pwTimeoutSetting = new obsidian.Setting(containerEl) + .setName(this.buildPasswordTimeoutSettingName()) + .setDesc('The number of minutes to remember the last used password.') + .addSlider(slider => { + slider + .setLimits(0, 120, 5) + .setValue(this.plugin.settings.rememberPasswordTimeout) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.rememberPasswordTimeout = value; + yield this.plugin.saveSettings(); + this.updateSettingsUi(); + })); + }); + this.updateSettingsUi(); + } + updateSettingsUi() { + this.pwTimeoutSetting.setName(this.buildPasswordTimeoutSettingName()); + if (this.plugin.settings.rememberPassword) { + this.pwTimeoutSetting.settingEl.show(); + } + else { + this.pwTimeoutSetting.settingEl.hide(); + } + } + buildPasswordTimeoutSettingName() { + const value = this.plugin.settings.rememberPasswordTimeout; + let timeoutString = `${value} minutes`; + if (value == 0) { + timeoutString = 'Never forget'; + } + return `Remember Password Timeout (${timeoutString})`; + } +} + +const _PREFIX = '%%🔐'; +const _PREFIX_OBSOLETE = _PREFIX + ' '; +const _PREFIX_A = _PREFIX + 'α '; +const _SUFFIX = ' 🔐%%'; +const _HINT = '💡'; +const DEFAULT_SETTINGS = { + expandToWholeLines: true, + confirmPassword: true, + showButton: false, + rememberPassword: true, + rememberPasswordTimeout: 30 +}; +class MeldEncrypt extends obsidian.Plugin { + onload() { + return __awaiter(this, void 0, void 0, function* () { + yield this.loadSettings(); + this.addSettingTab(new MeldEncryptSettingsTab(this.app, this)); + this.addCommand({ + id: 'meld-encrypt', + name: 'Encrypt/Decrypt', + editorCheckCallback: (checking, editor, view) => this.processEncryptDecryptCommand(checking, editor, view, false) + }); + this.addCommand({ + id: 'meld-encrypt-in-place', + name: 'Encrypt/Decrypt In-place', + editorCheckCallback: (checking, editor, view) => this.processEncryptDecryptCommand(checking, editor, view, true) + }); + this.addCommand({ + id: 'meld-encrypt-note', + name: 'Encrypt/Decrypt Whole Note', + editorCheckCallback: (checking, editor, view) => this.processEncryptDecryptWholeNoteCommand(checking, editor, view) + }); + }); + } + loadSettings() { + return __awaiter(this, void 0, void 0, function* () { + this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData()); + }); + } + saveSettings() { + return __awaiter(this, void 0, void 0, function* () { + yield this.saveData(this.settings); + }); + } + isSettingsModalOpen() { + return document.querySelector('.mod-settings') !== null; + } + processEncryptDecryptWholeNoteCommand(checking, editor, view) { + if (checking && this.isSettingsModalOpen()) { + // Settings is open, ensures this command can show up in other + // plugins which list commands e.g. customizable-sidebar + return true; + } + const startPos = editor.offsetToPos(0); + const endPos = { line: editor.lastLine(), ch: editor.getLine(editor.lastLine()).length }; + const selectionText = editor.getRange(startPos, endPos).trim(); + return this.processSelection(checking, editor, selectionText, startPos, endPos, true); + } + processEncryptDecryptCommand(checking, editor, view, decryptInPlace) { + if (checking && this.isSettingsModalOpen()) { + // Settings is open, ensures this command can show up in other + // plugins which list commands e.g. customizable-sidebar + return true; + } + let startPos = editor.getCursor('from'); + let endPos = editor.getCursor('to'); + if (this.settings.expandToWholeLines) { + const startLine = startPos.line; + startPos = { line: startLine, ch: 0 }; // want the start of the first line + const endLine = endPos.line; + const endLineText = editor.getLine(endLine); + endPos = { line: endLine, ch: endLineText.length }; // want the end of last line + } + else { + if (!editor.somethingSelected()) { + // nothing selected, assume user wants to decrypt, expand to start and end markers + startPos = this.getClosestPrevTextCursorPos(editor, _PREFIX, startPos); + endPos = this.getClosestNextTextCursorPos(editor, _SUFFIX, endPos); + } + } + const selectionText = editor.getRange(startPos, endPos); + return this.processSelection(checking, editor, selectionText, startPos, endPos, decryptInPlace); + } + getClosestPrevTextCursorPos(editor, text, defaultValue) { + const initOffset = editor.posToOffset(editor.getCursor("from")); + for (let offset = initOffset; offset >= 0; offset--) { + const offsetPos = editor.offsetToPos(offset); + const textEndOffset = offset + text.length; + const prefixEndPos = editor.offsetToPos(textEndOffset); + const testText = editor.getRange(offsetPos, prefixEndPos); + if (testText == text) { + return offsetPos; + } + } + return defaultValue; + } + getClosestNextTextCursorPos(editor, text, defaultValue) { + const initOffset = editor.posToOffset(editor.getCursor("from")); + const lastLineNum = editor.lastLine(); + let maxOffset = editor.posToOffset({ line: lastLineNum, ch: editor.getLine(lastLineNum).length }); + for (let offset = initOffset; offset <= maxOffset - text.length; offset++) { + const offsetPos = editor.offsetToPos(offset); + const textEndOffset = offset + text.length; + const prefixEndPos = editor.offsetToPos(textEndOffset); + const testText = editor.getRange(offsetPos, prefixEndPos); + if (testText == text) { + return prefixEndPos; + } + } + return defaultValue; + } + analyseSelection(selectionText) { + const result = new SelectionAnalysis(); + result.isEmpty = selectionText.length === 0; + result.hasObsoleteEncryptedPrefix = selectionText.startsWith(_PREFIX_OBSOLETE); + result.hasEncryptedPrefix = result.hasObsoleteEncryptedPrefix || selectionText.startsWith(_PREFIX_A); + result.hasDecryptSuffix = selectionText.endsWith(_SUFFIX); + result.containsEncryptedMarkers = + selectionText.contains(_PREFIX_OBSOLETE) + || selectionText.contains(_PREFIX_A) + || selectionText.contains(_SUFFIX); + result.canDecrypt = result.hasEncryptedPrefix && result.hasDecryptSuffix; + result.canEncrypt = !result.hasEncryptedPrefix && !result.containsEncryptedMarkers; + if (result.canDecrypt) { + result.decryptable = this.parseDecryptableContent(selectionText); + if (result.decryptable == null) { + result.canDecrypt = false; + } + } + return result; + } + processSelection(checking, editor, selectionText, finalSelectionStart, finalSelectionEnd, decryptInPlace) { + var _a; + const selectionAnalysis = this.analyseSelection(selectionText); + if (selectionAnalysis.isEmpty) { + if (!checking) { + new obsidian.Notice('Nothing to Encrypt.'); + } + return false; + } + if (!selectionAnalysis.canDecrypt && !selectionAnalysis.canEncrypt) { + if (!checking) { + new obsidian.Notice('Unable to Encrypt or Decrypt that.'); + } + return false; + } + if (checking) { + return true; + } + // Fetch password from user + // determine default password + const isRememberPasswordExpired = !this.settings.rememberPassword + || (this.passwordLastUsedExpiry != null + && Date.now() > this.passwordLastUsedExpiry); + const confirmPassword = selectionAnalysis.canEncrypt && this.settings.confirmPassword; + if (isRememberPasswordExpired || confirmPassword) { + // forget password + this.passwordLastUsed = ''; + } + const pwModal = new PasswordModal(this.app, selectionAnalysis.canEncrypt, confirmPassword, this.passwordLastUsed, (_a = selectionAnalysis.decryptable) === null || _a === void 0 ? void 0 : _a.hint); + pwModal.onClose = () => { + var _a; + const pw = (_a = pwModal.password) !== null && _a !== void 0 ? _a : ''; + if (pw.length == 0) { + return; + } + const hint = pwModal.hint; + // remember password? + if (this.settings.rememberPassword) { + this.passwordLastUsed = pw; + this.passwordLastUsedExpiry = + this.settings.rememberPasswordTimeout == 0 + ? null + : Date.now() + this.settings.rememberPasswordTimeout * 1000 * 60 // new expiry + ; + } + if (selectionAnalysis.canEncrypt) { + const encryptable = new Encryptable(); + encryptable.text = selectionText; + encryptable.hint = hint; + this.encryptSelection(editor, encryptable, pw, finalSelectionStart, finalSelectionEnd); + } + else { + if (selectionAnalysis.decryptable.version == 1) { + this.decryptSelection_a(editor, selectionAnalysis.decryptable, pw, finalSelectionStart, finalSelectionEnd, decryptInPlace); + } + else { + this.decryptSelectionObsolete(editor, selectionAnalysis.decryptable, pw, finalSelectionStart, finalSelectionEnd, decryptInPlace); + } + } + }; + pwModal.open(); + return true; + } + encryptSelection(editor, encryptable, password, finalSelectionStart, finalSelectionEnd) { + return __awaiter(this, void 0, void 0, function* () { + //encrypt + const crypto = new CryptoHelperV2(); + const encodedText = this.encodeEncryption(yield crypto.encryptToBase64(encryptable.text, password), encryptable.hint); + editor.setSelection(finalSelectionStart, finalSelectionEnd); + editor.replaceSelection(encodedText); + }); + } + decryptSelection_a(editor, decryptable, password, selectionStart, selectionEnd, decryptInPlace) { + return __awaiter(this, void 0, void 0, function* () { + // decrypt + const crypto = new CryptoHelperV2(); + const decryptedText = yield crypto.decryptFromBase64(decryptable.base64CipherText, password); + if (decryptedText === null) { + new obsidian.Notice('❌ Decryption failed!'); + } + else { + if (decryptInPlace) { + editor.setSelection(selectionStart, selectionEnd); + editor.replaceSelection(decryptedText); + } + else { + const decryptModal = new DecryptModal(this.app, '🔓', decryptedText, this.settings.showButton); + decryptModal.onClose = () => { + editor.focus(); + if (decryptModal.decryptInPlace) { + editor.setSelection(selectionStart, selectionEnd); + editor.replaceSelection(decryptedText); + } + }; + decryptModal.open(); + } + } + }); + } + decryptSelectionObsolete(editor, decryptable, password, selectionStart, selectionEnd, decryptInPlace) { + return __awaiter(this, void 0, void 0, function* () { + // decrypt + const base64CipherText = this.removeMarkers(decryptable.base64CipherText); + const crypto = new CryptoHelperObsolete(); + const decryptedText = yield crypto.decryptFromBase64(base64CipherText, password); + if (decryptedText === null) { + new obsidian.Notice('❌ Decryption failed!'); + } + else { + if (decryptInPlace) { + editor.setSelection(selectionStart, selectionEnd); + editor.replaceSelection(decryptedText); + } + else { + const decryptModal = new DecryptModal(this.app, '🔓', decryptedText, this.settings.showButton); + decryptModal.onClose = () => { + editor.focus(); + if (decryptModal.decryptInPlace) { + editor.setSelection(selectionStart, selectionEnd); + editor.replaceSelection(decryptedText); + } + }; + decryptModal.open(); + } + } + }); + } + parseDecryptableContent(text) { + const result = new Decryptable(); + let content = text; + if (content.startsWith(_PREFIX_A) && content.endsWith(_SUFFIX)) { + result.version = 1; + content = content.replace(_PREFIX_A, '').replace(_SUFFIX, ''); + } + else if (content.startsWith(_PREFIX_OBSOLETE) && content.endsWith(_SUFFIX)) { + result.version = 0; + content = content.replace(_PREFIX_OBSOLETE, '').replace(_SUFFIX, ''); + } + else { + return null; // invalid format + } + // check if there is a hint + //console.table(content); + if (content.substr(0, _HINT.length) == _HINT) { + const endHintMarker = content.indexOf(_HINT, _HINT.length); + if (endHintMarker < 0) { + return null; // invalid format + } + result.hint = content.substring(_HINT.length, endHintMarker); + result.base64CipherText = content.substring(endHintMarker + _HINT.length); + } + else { + result.base64CipherText = content; + } + //console.table(result); + return result; + } + removeMarkers(text) { + if (text.startsWith(_PREFIX_A) && text.endsWith(_SUFFIX)) { + return text.replace(_PREFIX_A, '').replace(_SUFFIX, ''); + } + if (text.startsWith(_PREFIX_OBSOLETE) && text.endsWith(_SUFFIX)) { + return text.replace(_PREFIX_OBSOLETE, '').replace(_SUFFIX, ''); + } + return text; + } + encodeEncryption(encryptedText, hint) { + if (!encryptedText.contains(_PREFIX_OBSOLETE) && !encryptedText.contains(_PREFIX_A) && !encryptedText.contains(_SUFFIX)) { + if (hint) { + return _PREFIX_A.concat(_HINT, hint, _HINT, encryptedText, _SUFFIX); + } + return _PREFIX_A.concat(encryptedText, _SUFFIX); + } + return encryptedText; + } +} +class SelectionAnalysis { +} +class Encryptable { +} +class Decryptable { +} + +module.exports = MeldEncrypt; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsiLi4vbm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIi4uL3NyYy9EZWNyeXB0TW9kYWwudHMiLCIuLi9zcmMvUGFzc3dvcmRNb2RhbC50cyIsIi4uL3NyYy9DcnlwdG9IZWxwZXIudHMiLCIuLi9zcmMvTWVsZEVuY3J5cHRTZXR0aW5nc1RhYi50cyIsIi4uL3NyYy9tYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfSk7XHJcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgb1trMl0gPSBtW2tdO1xyXG59KTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgbykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvLCBwKSkgX19jcmVhdGVCaW5kaW5nKG8sIG0sIHApO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgaWYgKG8gJiYgdHlwZW9mIG8ubGVuZ3RoID09PSBcIm51bWJlclwiKSByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHMgPyBcIk9iamVjdCBpcyBub3QgaXRlcmFibGUuXCIgOiBcIlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXlzKCkge1xyXG4gICAgZm9yICh2YXIgcyA9IDAsIGkgPSAwLCBpbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBpbDsgaSsrKSBzICs9IGFyZ3VtZW50c1tpXS5sZW5ndGg7XHJcbiAgICBmb3IgKHZhciByID0gQXJyYXkocyksIGsgPSAwLCBpID0gMDsgaSA8IGlsOyBpKyspXHJcbiAgICAgICAgZm9yICh2YXIgYSA9IGFyZ3VtZW50c1tpXSwgaiA9IDAsIGpsID0gYS5sZW5ndGg7IGogPCBqbDsgaisrLCBrKyspXHJcbiAgICAgICAgICAgIHJba10gPSBhW2pdO1xyXG4gICAgcmV0dXJuIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5KHRvLCBmcm9tLCBwYWNrKSB7XHJcbiAgICBpZiAocGFjayB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSBmb3IgKHZhciBpID0gMCwgbCA9IGZyb20ubGVuZ3RoLCBhcjsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgIGlmIChhciB8fCAhKGkgaW4gZnJvbSkpIHtcclxuICAgICAgICAgICAgaWYgKCFhcikgYXIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tLCAwLCBpKTtcclxuICAgICAgICAgICAgYXJbaV0gPSBmcm9tW2ldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0by5jb25jYXQoYXIgfHwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSkpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG52YXIgX19zZXRNb2R1bGVEZWZhdWx0ID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCB2KSB7XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgXCJkZWZhdWx0XCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgdmFsdWU6IHYgfSk7XHJcbn0pIDogZnVuY3Rpb24obywgdikge1xyXG4gICAgb1tcImRlZmF1bHRcIl0gPSB2O1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0U3Rhcihtb2QpIHtcclxuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XHJcbiAgICB2YXIgcmVzdWx0ID0ge307XHJcbiAgICBpZiAobW9kICE9IG51bGwpIGZvciAodmFyIGsgaW4gbW9kKSBpZiAoayAhPT0gXCJkZWZhdWx0XCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwgayk7XHJcbiAgICBfX3NldE1vZHVsZURlZmF1bHQocmVzdWx0LCBtb2QpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XHJcbn1cclxuIiwiaW1wb3J0IHsgQXBwLCBNb2RhbCB9IGZyb20gJ29ic2lkaWFuJztcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERlY3J5cHRNb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHR0ZXh0OiBzdHJpbmc7XHJcblx0ZGVjcnlwdEluUGxhY2U6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHRzaG93QnV0dG9uOiBib29sZWFuXHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCB0aXRsZTogc3RyaW5nLCB0ZXh0OiBzdHJpbmcgPSAnJywgc2hvd0J1dHRvbjpib29sZWFuKSB7XHJcblx0XHRzdXBlcihhcHApO1xyXG5cdFx0dGhpcy50ZXh0ID0gdGV4dDtcclxuXHRcdHRoaXMudGl0bGVFbC5pbm5lclRleHQgPSB0aXRsZTtcclxuXHRcdHRoaXMuc2hvd0J1dHRvbiA9IHNob3dCdXR0b247XHJcblx0fVxyXG5cclxuXHRvbk9wZW4oKSB7XHJcblx0XHRsZXQgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblxyXG5cdFx0Y29uc3QgdGV4dEVsID0gY29udGVudEVsLmNyZWF0ZURpdigpLmNyZWF0ZUVsKCd0ZXh0YXJlYScsIHsgdGV4dDogdGhpcy50ZXh0IH0pO1xyXG5cdFx0dGV4dEVsLnN0eWxlLndpZHRoID0gJzEwMCUnO1xyXG5cdFx0dGV4dEVsLnN0eWxlLmhlaWdodCA9ICcxMDAlJztcclxuXHRcdHRleHRFbC5yb3dzID0gMTA7XHJcblx0XHR0ZXh0RWwucmVhZE9ubHkgPSB0cnVlO1xyXG5cdFx0Ly90ZXh0RWwuZm9jdXMoKTsgLy8gRG9lc24ndCBzZWVtIHRvIHdvcmsgaGVyZS4uLlxyXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7IHRleHRFbC5mb2N1cygpIH0sMTAwKTsgLy8uLi4gYnV0IHRoaXMgZG9lc1xyXG5cclxuXHJcblx0XHRjb25zdCBidG5Db250YWluZXJFbCA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoJycpO1xyXG5cclxuXHRcdGlmICh0aGlzLnNob3dCdXR0b24pe1xyXG5cdFx0Y29uc3QgY29weUJ0bkVsID0gYnRuQ29udGFpbmVyRWwuY3JlYXRlRWwoJ2J1dHRvbicsIHsgdGV4dDogJ0NvcHknIH0pO1xyXG5cdFx0Y29weUJ0bkVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xyXG5cdFx0XHRuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0ZXh0RWwudmFsdWUpO1xyXG5cdFx0fSk7IH1cclxuXHJcblx0XHRjb25zdCBkZWNyeXB0SW5QbGFjZUJ0bkVsID0gYnRuQ29udGFpbmVyRWwuY3JlYXRlRWwoJ2J1dHRvbicsIHsgdGV4dDogJ0RlY3J5cHQgaW4tcGxhY2UnIH0pO1xyXG5cdFx0ZGVjcnlwdEluUGxhY2VCdG5FbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcclxuXHRcdFx0dGhpcy5kZWNyeXB0SW5QbGFjZSA9IHRydWU7XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGNvbnN0IGNhbmNlbEJ0bkVsID0gYnRuQ29udGFpbmVyRWwuY3JlYXRlRWwoJ2J1dHRvbicsIHsgdGV4dDogJ0Nsb3NlJyB9KTtcclxuXHRcdGNhbmNlbEJ0bkVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xyXG5cdFx0XHR0aGlzLmNsb3NlKCk7XHJcblx0XHR9KTtcclxuXHJcblx0fVxyXG5cclxufSIsImltcG9ydCB7IEFwcCwgTW9kYWwsIFBsYXRmb3JtIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGFzc3dvcmRNb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHRwYXNzd29yZDogc3RyaW5nID0gbnVsbDtcclxuXHRoaW50OiBzdHJpbmcgPSBudWxsO1xyXG5cdGRlZmF1bHRQYXNzd29yZDogc3RyaW5nID0gbnVsbDtcclxuXHRjb25maXJtUGFzc3dvcmQ6IGJvb2xlYW47XHJcblx0aXNFbmNyeXB0aW5nOiBib29sZWFuO1xyXG5cclxuXHRjb25zdHJ1Y3RvcihhcHA6IEFwcCwgaXNFbmNyeXB0aW5nOmJvb2xlYW4sIGNvbmZpcm1QYXNzd29yZDogYm9vbGVhbiwgZGVmYXVsdFBhc3N3b3JkOiBzdHJpbmcgPSBudWxsLCBoaW50OnN0cmluZyApIHtcclxuXHRcdHN1cGVyKGFwcCk7XHJcblx0XHR0aGlzLmRlZmF1bHRQYXNzd29yZCA9IGRlZmF1bHRQYXNzd29yZDtcclxuXHRcdHRoaXMuY29uZmlybVBhc3N3b3JkID0gY29uZmlybVBhc3N3b3JkO1xyXG5cdFx0dGhpcy5pc0VuY3J5cHRpbmcgPSBpc0VuY3J5cHRpbmc7XHJcblx0XHR0aGlzLmhpbnQgPSBoaW50O1xyXG5cdH1cclxuXHJcblx0b25PcGVuKCkge1xyXG5cdFx0bGV0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG5cclxuXHRcdGNvbnRlbnRFbC5lbXB0eSgpO1xyXG5cclxuXHRcdGNvbnRlbnRFbC5hZGRDbGFzcyggJ21lbGQtZS1wYXNzd29yZCcgKTtcclxuXHRcdGlmIChQbGF0Zm9ybS5pc01vYmlsZSl7XHJcblx0XHRcdGNvbnRlbnRFbC5hZGRDbGFzcyggJ21lbGQtZS1wbGF0Zm9ybS1tb2JpbGUnICk7XHJcblx0XHR9ZWxzZSBpZiAoUGxhdGZvcm0uaXNEZXNrdG9wKXtcclxuXHRcdFx0Y29udGVudEVsLmFkZENsYXNzKCAnbWVsZC1lLXBsYXRmb3JtLWRlc2t0b3AnICk7XHJcblx0XHR9XHJcblxyXG5cdFx0LyogTWFpbiBwYXNzd29yZCBpbnB1dCByb3cgKi9cclxuXHRcdGNvbnN0IGlucHV0UHdDb250YWluZXJFbCA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoIHsgY2xzOidtZWxkLWUtcm93JyB9ICk7XHJcblx0XHRpbnB1dFB3Q29udGFpbmVyRWwuY3JlYXRlU3Bhbih7IGNsczonbWVsZC1lLWljb24nLCB0ZXh0OiAn8J+UkScgfSk7XHJcblx0XHRcclxuXHRcdGNvbnN0IHB3SW5wdXRFbCA9IGlucHV0UHdDb250YWluZXJFbC5jcmVhdGVFbCgnaW5wdXQnLCB7IHR5cGU6ICdwYXNzd29yZCcsIHZhbHVlOiB0aGlzLmRlZmF1bHRQYXNzd29yZCA/PyAnJyB9KTtcclxuXHJcblx0XHRwd0lucHV0RWwucGxhY2Vob2xkZXIgPSAnRW50ZXIgeW91ciBwYXNzd29yZCc7XHJcblx0XHRwd0lucHV0RWwuZm9jdXMoKTtcclxuXHJcblx0XHRpZiAoUGxhdGZvcm0uaXNNb2JpbGUpe1xyXG5cdFx0XHQvLyBBZGQgJ05leHQnIGJ1dHRvbiBmb3IgbW9iaWxlXHJcblx0XHRcdGNvbnN0IGlucHV0SW5wdXROZXh0QnRuRWwgPSBpbnB1dFB3Q29udGFpbmVyRWwuY3JlYXRlRWwoJ2J1dHRvbicsIHtcclxuXHRcdFx0XHR0ZXh0OiAn4oaSJyxcclxuXHRcdFx0XHRjbHM6J21lbGQtZS1idXR0b24tbmV4dCdcclxuXHRcdFx0fSk7XHJcblx0XHRcdGlucHV0SW5wdXROZXh0QnRuRWwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZXYpID0+IHtcclxuXHRcdFx0XHRpbnB1dFBhc3N3b3JkSGFuZGxlcigpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHQvKiBFbmQgTWFpbiBwYXNzd29yZCBpbnB1dCByb3cgKi9cclxuXHJcblx0XHQvKiBDb25maXJtIHBhc3N3b3JkIGlucHV0IHJvdyAqL1xyXG5cdFx0Y29uc3QgY29uZmlybVB3U2hvd24gPSB0aGlzLmNvbmZpcm1QYXNzd29yZDtcclxuXHRcdGNvbnN0IGNvbmZpcm1Qd0NvbnRhaW5lckVsID0gY29udGVudEVsLmNyZWF0ZURpdiggeyBjbHM6J21lbGQtZS1yb3cnIH0gKTtcclxuXHRcdGNvbmZpcm1Qd0NvbnRhaW5lckVsLmNyZWF0ZVNwYW4oIHsgY2xzOidtZWxkLWUtaWNvbicsIHRleHQ6ICfwn5SRJyB9ICk7XHJcblx0XHRcclxuXHRcdGNvbnN0IHB3Q29uZmlybUlucHV0RWwgPSBjb25maXJtUHdDb250YWluZXJFbC5jcmVhdGVFbCggJ2lucHV0Jywge1xyXG5cdFx0XHR0eXBlOiAncGFzc3dvcmQnLFxyXG5cdFx0XHR2YWx1ZTogdGhpcy5kZWZhdWx0UGFzc3dvcmQgPz8gJydcclxuXHRcdH0pO1xyXG5cdFx0cHdDb25maXJtSW5wdXRFbC5wbGFjZWhvbGRlciA9ICdDb25maXJtIHlvdXIgcGFzc3dvcmQnO1xyXG5cclxuXHRcdGNvbnN0IG1lc3NhZ2VFbCA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoeyBjbHM6J21lbGQtZS1tZXNzYWdlJyB9KTtcclxuXHRcdG1lc3NhZ2VFbC5oaWRlKCk7XHJcblx0XHRcclxuXHRcdFxyXG5cdFx0aWYgKFBsYXRmb3JtLmlzTW9iaWxlKXtcclxuXHRcdFx0Ly8gQWRkICdOZXh0JyBidXR0b24gZm9yIG1vYmlsZVxyXG5cdFx0XHRjb25zdCBjb25maXJtSW5wdXROZXh0QnRuRWwgPSBjb25maXJtUHdDb250YWluZXJFbC5jcmVhdGVFbCgnYnV0dG9uJywge1xyXG5cdFx0XHRcdHRleHQ6ICfihpInLFxyXG5cdFx0XHRcdGNsczonbWVsZC1lLWJ1dHRvbi1uZXh0J1xyXG5cdFx0XHR9KTtcclxuXHRcdFx0Y29uZmlybUlucHV0TmV4dEJ0bkVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGV2KSA9PiB7XHJcblx0XHRcdFx0Y29uZmlybVBhc3N3b3JkSGFuZGxlcigpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHRcdFxyXG5cdFx0aWYgKCFjb25maXJtUHdTaG93bikge1xyXG5cdFx0XHRjb25maXJtUHdDb250YWluZXJFbC5oaWRlKCk7XHJcblx0XHR9XHJcblx0XHQvKiBFbmQgQ29uZmlybSBwYXNzd29yZCBpbnB1dCByb3cgKi9cclxuXHJcblx0XHQvKiBIaW50IGlucHV0IHJvdyAqL1xyXG5cdFx0Y29uc3QgaGludElucHV0U2hvd24gPSB0aGlzLmlzRW5jcnlwdGluZztcclxuXHRcdGNvbnN0IGlucHV0SGludENvbnRhaW5lckVsID0gY29udGVudEVsLmNyZWF0ZURpdiggeyBjbHM6J21lbGQtZS1yb3cnIH0gKTtcclxuXHRcdGlucHV0SGludENvbnRhaW5lckVsLmNyZWF0ZVNwYW4oeyBjbHM6J21lbGQtZS1pY29uJywgdGV4dDogJ/CfkqEnIH0pO1xyXG5cdFx0Y29uc3QgaGludElucHV0RWwgPSBpbnB1dEhpbnRDb250YWluZXJFbC5jcmVhdGVFbCgnaW5wdXQnLCB7IHR5cGU6ICd0ZXh0JywgdmFsdWU6IHRoaXMuaGludCB9KTtcclxuXHRcdGhpbnRJbnB1dEVsLnBsYWNlaG9sZGVyID0gJ0VudGVyIGFuIG9wdGlvbmFsIHBhc3N3b3JkIGhpbnQnO1xyXG5cdFx0aWYgKFBsYXRmb3JtLmlzTW9iaWxlKXtcclxuXHRcdFx0Ly8gQWRkICdOZXh0JyBidXR0b24gZm9yIG1vYmlsZVxyXG5cdFx0XHRjb25zdCBoaW50SW5wdXROZXh0QnRuRWwgPSBpbnB1dEhpbnRDb250YWluZXJFbC5jcmVhdGVFbCgnYnV0dG9uJywge1xyXG5cdFx0XHRcdHRleHQ6ICfihpInLFxyXG5cdFx0XHRcdGNsczonbWVsZC1lLWJ1dHRvbi1uZXh0J1xyXG5cdFx0XHR9KTtcclxuXHRcdFx0aGludElucHV0TmV4dEJ0bkVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGV2KSA9PiB7XHJcblx0XHRcdFx0aGludFBhc3N3b3JkSGFuZGxlcigpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHRcdGlmICghaGludElucHV0U2hvd24pe1xyXG5cdFx0XHRpbnB1dEhpbnRDb250YWluZXJFbC5oaWRlKCk7XHJcblx0XHR9XHJcblx0XHQvKiBFbmQgSGludCBpbnB1dCByb3cgKi9cclxuXHJcblx0XHQvKiBIaW50IHRleHQgcm93ICovXHJcblx0XHRjb25zdCBzcGFuSGludENvbnRhaW5lckVsID0gY29udGVudEVsLmNyZWF0ZURpdiggeyBjbHM6J21lbGQtZS1yb3cnIH0gKTtcclxuXHRcdHNwYW5IaW50Q29udGFpbmVyRWwuY3JlYXRlU3Bhbih7IGNsczonbWVsZC1lLWljb24nLCB0ZXh0OiAn8J+SoScgfSk7XHJcblx0XHRzcGFuSGludENvbnRhaW5lckVsLmNyZWF0ZVNwYW4oIHtjbHM6ICdtZWxkLWUtaGludCcsIHRleHQ6YEhpbnQ6ICcke3RoaXMuaGludH0nYH0pO1xyXG5cclxuXHRcdGlmIChoaW50SW5wdXRTaG93biB8fCAodGhpcy5oaW50ID8/ICcnKS5sZW5ndGg9PTApe1xyXG5cdFx0XHRzcGFuSGludENvbnRhaW5lckVsLmhpZGUoKTtcclxuXHRcdH1cclxuXHJcblx0XHQvKiBFTkQgSGludCB0ZXh0IHJvdyAqL1xyXG5cclxuXHRcdGNvbnN0IGNvbmZpcm1Qd0J1dHRvbkVsID0gY29udGVudEVsLmNyZWF0ZUVsKCAnYnV0dG9uJywge1xyXG5cdFx0XHR0ZXh0OidDb25maXJtJyxcclxuXHRcdFx0Y2xzOidtZWxkLWUtYnV0dG9uLWNvbmZpcm0nXHJcblx0XHR9KTtcclxuXHRcdGNvbmZpcm1Qd0J1dHRvbkVsLmFkZEV2ZW50TGlzdGVuZXIoICdjbGljaycsIChldikgPT57XHJcblx0XHRcdGlmICh2YWxpZGF0ZSgpKXtcclxuXHRcdFx0XHR0aGlzLmNsb3NlKCk7XHJcblx0XHRcdH1lbHNle1xyXG5cdFx0XHRcdHB3SW5wdXRFbC5mb2N1cygpO1xyXG5cdFx0XHR9XHJcblx0XHR9KVxyXG5cclxuXHRcdGNvbnN0IHZhbGlkYXRlID0gKCkgOiBib29sZWFuID0+IHtcclxuXHRcdFx0aWYgKGNvbmZpcm1Qd1Nob3duKXtcclxuXHRcdFx0XHRpZiAocHdJbnB1dEVsLnZhbHVlICE9IHB3Q29uZmlybUlucHV0RWwudmFsdWUpe1xyXG5cdFx0XHRcdFx0Ly8gcGFzc3dvcmRzIGRvbid0IG1hdGNoXHJcblx0XHRcdFx0XHRtZXNzYWdlRWwuc2V0VGV4dCgnUGFzc3dvcmRzIGRvblxcJ3QgbWF0Y2gnKTtcclxuXHRcdFx0XHRcdG1lc3NhZ2VFbC5zaG93KCk7XHJcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLnBhc3N3b3JkID0gcHdJbnB1dEVsLnZhbHVlO1xyXG5cdFx0XHRcclxuXHRcdFx0dGhpcy5oaW50ID0gaGludElucHV0RWwudmFsdWU7XHJcblxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBpbnB1dFBhc3N3b3JkSGFuZGxlciA9ICgpID0+e1xyXG5cdFx0XHRpZiAoY29uZmlybVB3U2hvd24pe1xyXG5cdFx0XHRcdHB3Q29uZmlybUlucHV0RWwuZm9jdXMoKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmIChoaW50SW5wdXRTaG93bil7XHJcblx0XHRcdFx0aGludElucHV0RWwuZm9jdXMoKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmICggdmFsaWRhdGUoKSApe1xyXG5cdFx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGNvbmZpcm1QYXNzd29yZEhhbmRsZXIgPSAoKSA9PiB7XHJcblx0XHRcdGlmICggdmFsaWRhdGUoKSApe1xyXG5cdFx0XHRcdGlmIChoaW50SW5wdXRTaG93bil7XHJcblx0XHRcdFx0XHRoaW50SW5wdXRFbC5mb2N1cygpO1xyXG5cdFx0XHRcdH1lbHNle1xyXG5cdFx0XHRcdFx0dGhpcy5jbG9zZSgpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGhpbnRQYXNzd29yZEhhbmRsZXIgPSAoKSA9PiB7XHJcblx0XHRcdGlmICh2YWxpZGF0ZSgpKXtcclxuXHRcdFx0XHR0aGlzLmNsb3NlKCk7XHJcblx0XHRcdH1lbHNle1xyXG5cdFx0XHRcdHB3SW5wdXRFbC5mb2N1cygpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRcclxuXHRcdGhpbnRJbnB1dEVsLmFkZEV2ZW50TGlzdGVuZXIoJ2tleXByZXNzJywgKGV2KSA9PiB7XHJcblx0XHRcdGlmIChcclxuXHRcdFx0XHQoIGV2LmNvZGUgPT09ICdFbnRlcicgfHwgZXYuY29kZSA9PT0gJ051bXBhZEVudGVyJyApXHJcblx0XHRcdFx0JiYgcHdJbnB1dEVsLnZhbHVlLmxlbmd0aCA+IDBcclxuXHRcdFx0KSB7XHJcblx0XHRcdFx0ZXYucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRoaW50UGFzc3dvcmRIYW5kbGVyKCk7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHRcdHB3Q29uZmlybUlucHV0RWwuYWRkRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCAoZXYpID0+IHtcclxuXHRcdFx0aWYgKFxyXG5cdFx0XHRcdCggZXYuY29kZSA9PT0gJ0VudGVyJyB8fCBldi5jb2RlID09PSAnTnVtcGFkRW50ZXInIClcclxuXHRcdFx0XHQmJiBwd0NvbmZpcm1JbnB1dEVsLnZhbHVlLmxlbmd0aCA+IDBcclxuXHRcdFx0KSB7XHJcblx0XHRcdFx0ZXYucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRjb25maXJtUGFzc3dvcmRIYW5kbGVyKCk7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHJcblx0XHRwd0lucHV0RWwuYWRkRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCAoZXYpID0+IHtcclxuXHRcdFx0aWYgKFxyXG5cdFx0XHRcdCggZXYuY29kZSA9PT0gJ0VudGVyJyB8fCBldi5jb2RlID09PSAnTnVtcGFkRW50ZXInIClcclxuXHRcdFx0XHQmJiBwd0lucHV0RWwudmFsdWUubGVuZ3RoID4gMFxyXG5cdFx0XHQpIHtcclxuXHRcdFx0XHRldi5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdGlucHV0UGFzc3dvcmRIYW5kbGVyKCk7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHR9XHJcblxyXG59IiwiY29uc3QgdmVjdG9yU2l6ZVx0PSAxNjtcclxuY29uc3QgdXRmOEVuY29kZXJcdD0gbmV3IFRleHRFbmNvZGVyKCk7XHJcbmNvbnN0IHV0ZjhEZWNvZGVyXHQ9IG5ldyBUZXh0RGVjb2RlcigpO1xyXG5jb25zdCBpdGVyYXRpb25zXHQ9IDEwMDA7XHJcbmNvbnN0IHNhbHRcdFx0XHQ9IHV0ZjhFbmNvZGVyLmVuY29kZSgnWEhXbkRBVDZlaE1WWTJ6RCcpO1xyXG5cclxuZXhwb3J0IGNsYXNzIENyeXB0b0hlbHBlclYyIHtcclxuXHJcblx0cHJpdmF0ZSBhc3luYyBkZXJpdmVLZXkocGFzc3dvcmQ6c3RyaW5nKSA6UHJvbWlzZTxDcnlwdG9LZXk+IHtcclxuXHRcdGNvbnN0IGJ1ZmZlciAgICAgPSB1dGY4RW5jb2Rlci5lbmNvZGUocGFzc3dvcmQpO1xyXG5cdFx0Y29uc3Qga2V5ICAgICAgICA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuaW1wb3J0S2V5KCdyYXcnLCBidWZmZXIsIHtuYW1lOiAnUEJLREYyJ30sIGZhbHNlLCBbJ2Rlcml2ZUtleSddKTtcclxuXHRcdGNvbnN0IHByaXZhdGVLZXkgPSBjcnlwdG8uc3VidGxlLmRlcml2ZUtleShcclxuXHRcdFx0e1xyXG5cdFx0XHRcdG5hbWU6ICdQQktERjInLFxyXG5cdFx0XHRcdGhhc2g6IHtuYW1lOiAnU0hBLTI1Nid9LFxyXG5cdFx0XHRcdGl0ZXJhdGlvbnMsXHJcblx0XHRcdFx0c2FsdFxyXG5cdFx0XHR9LFxyXG5cdFx0XHRrZXksXHJcblx0XHRcdHtcclxuXHRcdFx0XHRuYW1lOiAnQUVTLUdDTScsXHJcblx0XHRcdFx0bGVuZ3RoOiAyNTZcclxuXHRcdFx0fSxcclxuXHRcdFx0ZmFsc2UsXHJcblx0XHRcdFsnZW5jcnlwdCcsICdkZWNyeXB0J11cclxuXHRcdCk7XHJcblx0XHRcclxuXHRcdHJldHVybiBwcml2YXRlS2V5O1xyXG5cdH1cclxuXHJcblx0cHVibGljIGFzeW5jIGVuY3J5cHRUb0Jhc2U2NCh0ZXh0OiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuXHRcdGNvbnN0IGtleSA9IGF3YWl0IHRoaXMuZGVyaXZlS2V5KHBhc3N3b3JkKTtcclxuXHRcdFxyXG5cdFx0Y29uc3QgdGV4dEJ5dGVzVG9FbmNyeXB0ID0gdXRmOEVuY29kZXIuZW5jb2RlKHRleHQpO1xyXG5cdFx0Y29uc3QgdmVjdG9yID0gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheSh2ZWN0b3JTaXplKSk7XHJcblx0XHRcclxuXHRcdC8vIGVuY3J5cHQgaW50byBieXRlc1xyXG5cdFx0Y29uc3QgZW5jcnlwdGVkQnl0ZXMgPSBuZXcgVWludDhBcnJheShcclxuXHRcdFx0YXdhaXQgY3J5cHRvLnN1YnRsZS5lbmNyeXB0KFxyXG5cdFx0XHRcdHtuYW1lOiAnQUVTLUdDTScsIGl2OiB2ZWN0b3J9LFxyXG5cdFx0XHRcdGtleSxcclxuXHRcdFx0XHR0ZXh0Qnl0ZXNUb0VuY3J5cHRcclxuXHRcdFx0KVxyXG5cdFx0KTtcclxuXHRcdFxyXG5cdFx0Y29uc3QgZmluYWxCeXRlcyA9IG5ldyBVaW50OEFycmF5KCB2ZWN0b3IuYnl0ZUxlbmd0aCArIGVuY3J5cHRlZEJ5dGVzLmJ5dGVMZW5ndGggKTtcclxuXHRcdGZpbmFsQnl0ZXMuc2V0KCB2ZWN0b3IsIDAgKTtcclxuXHRcdGZpbmFsQnl0ZXMuc2V0KCBlbmNyeXB0ZWRCeXRlcywgdmVjdG9yLmJ5dGVMZW5ndGggKTtcclxuXHJcblx0XHQvL2NvbnZlcnQgYXJyYXkgdG8gYmFzZTY0XHJcblx0XHRjb25zdCBiYXNlNjRUZXh0ID0gYnRvYSggU3RyaW5nLmZyb21DaGFyQ29kZSguLi5maW5hbEJ5dGVzKSApO1xyXG5cclxuXHRcdHJldHVybiBiYXNlNjRUZXh0O1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBzdHJpbmdUb0FycmF5KHN0cjogc3RyaW5nKTogVWludDhBcnJheSB7XHJcblx0XHR2YXIgcmVzdWx0ID0gW107XHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRyZXN1bHQucHVzaChzdHIuY2hhckNvZGVBdChpKSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbmV3IFVpbnQ4QXJyYXkocmVzdWx0KTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyBhc3luYyBkZWNyeXB0RnJvbUJhc2U2NChiYXNlNjRFbmNvZGVkOiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cdFx0dHJ5IHtcclxuXHJcblx0XHRcdGxldCBieXRlc1RvRGVjb2RlID0gdGhpcy5zdHJpbmdUb0FycmF5KGF0b2IoYmFzZTY0RW5jb2RlZCkpO1xyXG5cdFx0XHRcclxuXHRcdFx0Ly8gZXh0cmFjdCBpdlxyXG5cdFx0XHRjb25zdCB2ZWN0b3IgPSBieXRlc1RvRGVjb2RlLnNsaWNlKDAsdmVjdG9yU2l6ZSk7XHJcblxyXG5cdFx0XHQvLyBleHRyYWN0IGVuY3J5cHRlZCB0ZXh0XHJcblx0XHRcdGNvbnN0IGVuY3J5cHRlZFRleHRCeXRlcyA9IGJ5dGVzVG9EZWNvZGUuc2xpY2UodmVjdG9yU2l6ZSk7XHJcblxyXG5cdFx0XHRjb25zdCBrZXkgPSBhd2FpdCB0aGlzLmRlcml2ZUtleShwYXNzd29yZCk7XHJcblxyXG5cdFx0XHQvLyBkZWNyeXB0IGludG8gYnl0ZXNcclxuXHRcdFx0bGV0IGRlY3J5cHRlZEJ5dGVzID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5kZWNyeXB0KFxyXG5cdFx0XHRcdHtuYW1lOiAnQUVTLUdDTScsIGl2OiB2ZWN0b3J9LFxyXG5cdFx0XHRcdGtleSxcclxuXHRcdFx0XHRlbmNyeXB0ZWRUZXh0Qnl0ZXNcclxuXHRcdFx0KTtcclxuXHJcblx0XHRcdC8vIGNvbnZlcnQgYnl0ZXMgdG8gdGV4dFxyXG5cdFx0XHRsZXQgZGVjcnlwdGVkVGV4dCA9IHV0ZjhEZWNvZGVyLmRlY29kZShkZWNyeXB0ZWRCeXRlcyk7XHJcblx0XHRcdHJldHVybiBkZWNyeXB0ZWRUZXh0O1xyXG5cdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHQvL2NvbnNvbGUuZXJyb3IoZSk7XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcbn1cclxuXHJcbmNvbnN0IGFsZ29yaXRobU9ic29sZXRlID0ge1xyXG5cdG5hbWU6ICdBRVMtR0NNJyxcclxuXHRpdjogbmV3IFVpbnQ4QXJyYXkoWzE5NiwgMTkwLCAyNDAsIDE5MCwgMTg4LCA3OCwgNDEsIDEzMiwgMTUsIDIyMCwgODQsIDIxMV0pLFxyXG5cdHRhZ0xlbmd0aDogMTI4XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBDcnlwdG9IZWxwZXJPYnNvbGV0ZSB7XHJcblxyXG5cdHByaXZhdGUgYXN5bmMgYnVpbGRLZXkocGFzc3dvcmQ6IHN0cmluZykge1xyXG5cdFx0bGV0IHV0ZjhFbmNvZGUgPSBuZXcgVGV4dEVuY29kZXIoKTtcclxuXHRcdGxldCBwYXNzd29yZEJ5dGVzID0gdXRmOEVuY29kZS5lbmNvZGUocGFzc3dvcmQpO1xyXG5cclxuXHRcdGxldCBwYXNzd29yZERpZ2VzdCA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuZGlnZXN0KHsgbmFtZTogJ1NIQS0yNTYnIH0sIHBhc3N3b3JkQnl0ZXMpO1xyXG5cclxuXHRcdGxldCBrZXkgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmltcG9ydEtleShcclxuXHRcdFx0J3JhdycsXHJcblx0XHRcdHBhc3N3b3JkRGlnZXN0LFxyXG5cdFx0XHRhbGdvcml0aG1PYnNvbGV0ZSxcclxuXHRcdFx0ZmFsc2UsXHJcblx0XHRcdFsnZW5jcnlwdCcsICdkZWNyeXB0J11cclxuXHRcdCk7XHJcblxyXG5cdFx0cmV0dXJuIGtleTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyBhc3luYyBlbmNyeXB0VG9CYXNlNjQodGV4dDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHRcdGxldCBrZXkgPSBhd2FpdCB0aGlzLmJ1aWxkS2V5KHBhc3N3b3JkKTtcclxuXHJcblx0XHRsZXQgdXRmOEVuY29kZSA9IG5ldyBUZXh0RW5jb2RlcigpO1xyXG5cdFx0bGV0IGJ5dGVzVG9FbmNyeXB0ID0gdXRmOEVuY29kZS5lbmNvZGUodGV4dCk7XHJcblxyXG5cdFx0Ly8gZW5jcnlwdCBpbnRvIGJ5dGVzXHJcblx0XHRsZXQgZW5jcnlwdGVkQnl0ZXMgPSBuZXcgVWludDhBcnJheShhd2FpdCBjcnlwdG8uc3VidGxlLmVuY3J5cHQoXHJcblx0XHRcdGFsZ29yaXRobU9ic29sZXRlLCBrZXksIGJ5dGVzVG9FbmNyeXB0XHJcblx0XHQpKTtcclxuXHJcblx0XHQvL2NvbnZlcnQgYXJyYXkgdG8gYmFzZTY0XHJcblx0XHRsZXQgYmFzZTY0VGV4dCA9IGJ0b2EoU3RyaW5nLmZyb21DaGFyQ29kZSguLi5lbmNyeXB0ZWRCeXRlcykpO1xyXG5cclxuXHRcdHJldHVybiBiYXNlNjRUZXh0O1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBzdHJpbmdUb0FycmF5KHN0cjogc3RyaW5nKTogVWludDhBcnJheSB7XHJcblx0XHR2YXIgcmVzdWx0ID0gW107XHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRyZXN1bHQucHVzaChzdHIuY2hhckNvZGVBdChpKSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbmV3IFVpbnQ4QXJyYXkocmVzdWx0KTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyBhc3luYyBkZWNyeXB0RnJvbUJhc2U2NChiYXNlNjRFbmNvZGVkOiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Ly8gY29udmVydCBiYXNlIDY0IHRvIGFycmF5XHJcblx0XHRcdGxldCBieXRlc1RvRGVjcnlwdCA9IHRoaXMuc3RyaW5nVG9BcnJheShhdG9iKGJhc2U2NEVuY29kZWQpKTtcclxuXHJcblx0XHRcdGxldCBrZXkgPSBhd2FpdCB0aGlzLmJ1aWxkS2V5KHBhc3N3b3JkKTtcclxuXHJcblx0XHRcdC8vIGRlY3J5cHQgaW50byBieXRlc1xyXG5cdFx0XHRsZXQgZGVjcnlwdGVkQnl0ZXMgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmRlY3J5cHQoYWxnb3JpdGhtT2Jzb2xldGUsIGtleSwgYnl0ZXNUb0RlY3J5cHQpO1xyXG5cclxuXHRcdFx0Ly8gY29udmVydCBieXRlcyB0byB0ZXh0XHJcblx0XHRcdGxldCB1dGY4RGVjb2RlID0gbmV3IFRleHREZWNvZGVyKCk7XHJcblx0XHRcdGxldCBkZWNyeXB0ZWRUZXh0ID0gdXRmOERlY29kZS5kZWNvZGUoZGVjcnlwdGVkQnl0ZXMpO1xyXG5cdFx0XHRyZXR1cm4gZGVjcnlwdGVkVGV4dDtcclxuXHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0cmV0dXJuIG51bGw7XHJcblx0XHR9XHJcblx0fVxyXG5cclxufVxyXG4iLCJpbXBvcnQgeyBBcHAsIFBsdWdpblNldHRpbmdUYWIsIFNldHRpbmcgfSBmcm9tIFwib2JzaWRpYW5cIjtcclxuaW1wb3J0IE1lbGRFbmNyeXB0IGZyb20gXCIuL21haW5cIjtcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1lbGRFbmNyeXB0U2V0dGluZ3NUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcclxuXHRwbHVnaW46IE1lbGRFbmNyeXB0O1xyXG5cclxuXHRwd1RpbWVvdXRTZXR0aW5nOlNldHRpbmc7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwbHVnaW46IE1lbGRFbmNyeXB0KSB7XHJcblx0XHRzdXBlcihhcHAsIHBsdWdpbik7XHJcblx0XHR0aGlzLnBsdWdpbiA9IHBsdWdpbjtcclxuXHR9XHJcblxyXG5cdGRpc3BsYXkoKTogdm9pZCB7XHJcblx0XHRsZXQgeyBjb250YWluZXJFbCB9ID0gdGhpcztcclxuXHJcblx0XHRjb250YWluZXJFbC5lbXB0eSgpO1xyXG5cdFx0XHJcblx0XHRjb250YWluZXJFbC5jcmVhdGVFbCgnaDInLCB7dGV4dDogJ1NldHRpbmdzIGZvciBNZWxkIEVuY3J5cHQnfSk7XHJcblxyXG5cclxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG5cdFx0XHQuc2V0TmFtZSgnRXhwYW5kIHNlbGVjdGlvbiB0byB3aG9sZSBsaW5lPycpXHJcblx0XHRcdC5zZXREZXNjKCdQYXJ0aWFsIHNlbGVjdGlvbnMgd2lsbCBnZXQgZXhwYW5kZWQgdG8gdGhlIHdob2xlIGxpbmUuJylcclxuXHRcdFx0LmFkZFRvZ2dsZSggdG9nZ2xlID0+e1xyXG5cdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmV4cGFuZFRvV2hvbGVMaW5lcylcclxuXHRcdFx0XHRcdC5vbkNoYW5nZSggYXN5bmMgdmFsdWUgPT57XHJcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmV4cGFuZFRvV2hvbGVMaW5lcyA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0Ly90aGlzLnVwZGF0ZVNldHRpbmdzVWkoKTtcclxuXHRcdFx0XHRcdH0pXHJcblx0XHRcdH0pXHJcblx0XHQ7XHJcblxyXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcblx0XHRcdC5zZXROYW1lKCdDb25maXJtIHBhc3N3b3JkPycpXHJcblx0XHRcdC5zZXREZXNjKCdDb25maXJtIHBhc3N3b3JkIHdoZW4gZW5jcnlwdGluZy4nKVxyXG5cdFx0XHQuYWRkVG9nZ2xlKCB0b2dnbGUgPT57XHJcblx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuY29uZmlybVBhc3N3b3JkKVxyXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKCBhc3luYyB2YWx1ZSA9PntcclxuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuY29uZmlybVBhc3N3b3JkID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZVNldHRpbmdzVWkoKTtcclxuXHRcdFx0XHRcdH0pXHJcblx0XHRcdH0pXHJcblx0XHQ7XHJcblxyXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcblx0XHRcdC5zZXROYW1lKCdDb3B5IGJ1dHRvbj8nKVxyXG5cdFx0XHQuc2V0RGVzYygnU2hvdyBhIGJ1dHRvbiB0byBjb3B5IGRlY3J5cHRlZCB0ZXh0LicpXHJcblx0XHRcdC5hZGRUb2dnbGUoIHRvZ2dsZSA9PntcclxuXHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5zaG93QnV0dG9uKVxyXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKCBhc3luYyB2YWx1ZSA9PntcclxuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd0J1dHRvbiA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0dGhpcy51cGRhdGVTZXR0aW5nc1VpKCk7XHJcblx0XHRcdFx0XHR9KVxyXG5cdFx0XHR9KVxyXG5cdFx0O1xyXG5cclxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG5cdFx0XHQuc2V0TmFtZSgnUmVtZW1iZXIgcGFzc3dvcmQ/JylcclxuXHRcdFx0LnNldERlc2MoJ1JlbWVtYmVyIHRoZSBsYXN0IHVzZWQgcGFzc3dvcmQgZm9yIHRoaXMgc2Vzc2lvbi4nKVxyXG5cdFx0XHQuYWRkVG9nZ2xlKCB0b2dnbGUgPT57XHJcblx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MucmVtZW1iZXJQYXNzd29yZClcclxuXHRcdFx0XHRcdC5vbkNoYW5nZSggYXN5bmMgdmFsdWUgPT57XHJcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnJlbWVtYmVyUGFzc3dvcmQgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdHRoaXMudXBkYXRlU2V0dGluZ3NVaSgpO1xyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0fSlcclxuXHRcdDtcclxuXHJcblx0XHR0aGlzLnB3VGltZW91dFNldHRpbmcgPSBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuXHRcdFx0LnNldE5hbWUoIHRoaXMuYnVpbGRQYXNzd29yZFRpbWVvdXRTZXR0aW5nTmFtZSgpIClcclxuXHRcdFx0LnNldERlc2MoJ1RoZSBudW1iZXIgb2YgbWludXRlcyB0byByZW1lbWJlciB0aGUgbGFzdCB1c2VkIHBhc3N3b3JkLicpXHJcblx0XHRcdC5hZGRTbGlkZXIoIHNsaWRlciA9PiB7XHJcblx0XHRcdFx0c2xpZGVyXHJcblx0XHRcdFx0XHQuc2V0TGltaXRzKDAsIDEyMCwgNSlcclxuXHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5yZW1lbWJlclBhc3N3b3JkVGltZW91dClcclxuXHRcdFx0XHRcdC5vbkNoYW5nZSggYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5yZW1lbWJlclBhc3N3b3JkVGltZW91dCA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0dGhpcy51cGRhdGVTZXR0aW5nc1VpKCk7XHJcblx0XHRcdFx0XHR9KVxyXG5cdFx0XHRcdDtcclxuXHRcdFx0XHRcclxuXHRcdFx0fSlcclxuXHRcdDtcclxuXHJcblx0XHR0aGlzLnVwZGF0ZVNldHRpbmdzVWkoKTtcclxuXHR9XHJcblxyXG5cdHVwZGF0ZVNldHRpbmdzVWkoKTp2b2lke1xyXG5cdFx0dGhpcy5wd1RpbWVvdXRTZXR0aW5nLnNldE5hbWUodGhpcy5idWlsZFBhc3N3b3JkVGltZW91dFNldHRpbmdOYW1lKCkpO1xyXG5cclxuXHJcblx0XHRpZiAoIHRoaXMucGx1Z2luLnNldHRpbmdzLnJlbWVtYmVyUGFzc3dvcmQgKXtcclxuXHRcdFx0dGhpcy5wd1RpbWVvdXRTZXR0aW5nLnNldHRpbmdFbC5zaG93KCk7XHJcblx0XHR9ZWxzZXtcclxuXHRcdFx0dGhpcy5wd1RpbWVvdXRTZXR0aW5nLnNldHRpbmdFbC5oaWRlKCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRidWlsZFBhc3N3b3JkVGltZW91dFNldHRpbmdOYW1lKCk6c3RyaW5ne1xyXG5cdFx0Y29uc3QgdmFsdWUgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5yZW1lbWJlclBhc3N3b3JkVGltZW91dDtcclxuXHRcdGxldCB0aW1lb3V0U3RyaW5nID0gYCR7dmFsdWV9IG1pbnV0ZXNgO1xyXG5cdFx0aWYodmFsdWUgPT0gMCl7XHJcblx0XHRcdHRpbWVvdXRTdHJpbmcgPSAnTmV2ZXIgZm9yZ2V0JztcclxuXHRcdH1cclxuXHRcdHJldHVybiBgUmVtZW1iZXIgUGFzc3dvcmQgVGltZW91dCAoJHt0aW1lb3V0U3RyaW5nfSlgO1xyXG5cdH1cclxufSIsImltcG9ydCB7IE5vdGljZSwgUGx1Z2luLCBNYXJrZG93blZpZXcsIEVkaXRvciwgRWRpdG9yUG9zaXRpb24gfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCBEZWNyeXB0TW9kYWwgZnJvbSAnLi9EZWNyeXB0TW9kYWwnO1xyXG5pbXBvcnQgUGFzc3dvcmRNb2RhbCBmcm9tICcuL1Bhc3N3b3JkTW9kYWwnO1xyXG5pbXBvcnQgeyBDcnlwdG9IZWxwZXJWMiwgQ3J5cHRvSGVscGVyT2Jzb2xldGV9IGZyb20gJy4vQ3J5cHRvSGVscGVyJztcclxuaW1wb3J0IE1lbGRFbmNyeXB0U2V0dGluZ3NUYWIgZnJvbSAnLi9NZWxkRW5jcnlwdFNldHRpbmdzVGFiJztcclxuXHJcbmNvbnN0IF9QUkVGSVg6IHN0cmluZyA9ICclJfCflJAnO1xyXG5jb25zdCBfUFJFRklYX09CU09MRVRFOiBzdHJpbmcgPSBfUFJFRklYICsgJyAnO1xyXG5jb25zdCBfUFJFRklYX0E6IHN0cmluZyA9IF9QUkVGSVggKyAnzrEgJztcclxuY29uc3QgX1NVRkZJWDogc3RyaW5nID0gJyDwn5SQJSUnO1xyXG5cclxuY29uc3QgX0hJTlQ6IHN0cmluZyA9ICfwn5KhJztcclxuXHJcbmludGVyZmFjZSBNZWxkRW5jcnlwdFBsdWdpblNldHRpbmdzIHtcclxuXHRleHBhbmRUb1dob2xlTGluZXM6IGJvb2xlYW4sXHJcblx0Y29uZmlybVBhc3N3b3JkOiBib29sZWFuO1xyXG5cdHNob3dCdXR0b246IGJvb2xlYW47XHJcblx0cmVtZW1iZXJQYXNzd29yZDogYm9vbGVhbjtcclxuXHRyZW1lbWJlclBhc3N3b3JkVGltZW91dDogbnVtYmVyO1xyXG59XHJcblxyXG5jb25zdCBERUZBVUxUX1NFVFRJTkdTOiBNZWxkRW5jcnlwdFBsdWdpblNldHRpbmdzID0ge1xyXG5cdGV4cGFuZFRvV2hvbGVMaW5lczogdHJ1ZSxcclxuXHRjb25maXJtUGFzc3dvcmQ6IHRydWUsXHJcblx0c2hvd0J1dHRvbjogZmFsc2UsXHJcblx0cmVtZW1iZXJQYXNzd29yZDogdHJ1ZSxcclxuXHRyZW1lbWJlclBhc3N3b3JkVGltZW91dDogMzBcclxufVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWVsZEVuY3J5cHQgZXh0ZW5kcyBQbHVnaW4ge1xyXG5cclxuXHRzZXR0aW5nczogTWVsZEVuY3J5cHRQbHVnaW5TZXR0aW5ncztcclxuXHRwYXNzd29yZExhc3RVc2VkRXhwaXJ5OiBudW1iZXJcclxuXHRwYXNzd29yZExhc3RVc2VkOiBzdHJpbmc7XHJcblxyXG5cdGFzeW5jIG9ubG9hZCgpIHtcclxuXHJcblx0XHRhd2FpdCB0aGlzLmxvYWRTZXR0aW5ncygpO1xyXG5cclxuXHRcdHRoaXMuYWRkU2V0dGluZ1RhYihuZXcgTWVsZEVuY3J5cHRTZXR0aW5nc1RhYih0aGlzLmFwcCwgdGhpcykpO1xyXG5cclxuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XHJcblx0XHRcdGlkOiAnbWVsZC1lbmNyeXB0JyxcclxuXHRcdFx0bmFtZTogJ0VuY3J5cHQvRGVjcnlwdCcsXHJcblx0XHRcdGVkaXRvckNoZWNrQ2FsbGJhY2s6IChjaGVja2luZywgZWRpdG9yLCB2aWV3KSA9PiB0aGlzLnByb2Nlc3NFbmNyeXB0RGVjcnlwdENvbW1hbmQoY2hlY2tpbmcsIGVkaXRvciwgdmlldywgZmFsc2UpXHJcblx0XHR9KTtcclxuXHJcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xyXG5cdFx0XHRpZDogJ21lbGQtZW5jcnlwdC1pbi1wbGFjZScsXHJcblx0XHRcdG5hbWU6ICdFbmNyeXB0L0RlY3J5cHQgSW4tcGxhY2UnLFxyXG5cdFx0XHRlZGl0b3JDaGVja0NhbGxiYWNrOiAoY2hlY2tpbmcsIGVkaXRvciwgdmlldykgPT4gdGhpcy5wcm9jZXNzRW5jcnlwdERlY3J5cHRDb21tYW5kKGNoZWNraW5nLCBlZGl0b3IsIHZpZXcsIHRydWUpXHJcblx0XHR9KTtcclxuXHJcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xyXG5cdFx0XHRpZDogJ21lbGQtZW5jcnlwdC1ub3RlJyxcclxuXHRcdFx0bmFtZTogJ0VuY3J5cHQvRGVjcnlwdCBXaG9sZSBOb3RlJyxcclxuXHRcdFx0ZWRpdG9yQ2hlY2tDYWxsYmFjazogKGNoZWNraW5nLCBlZGl0b3IsIHZpZXcpID0+IHRoaXMucHJvY2Vzc0VuY3J5cHREZWNyeXB0V2hvbGVOb3RlQ29tbWFuZChjaGVja2luZywgZWRpdG9yLCB2aWV3KVxyXG5cdFx0fSk7XHJcblxyXG5cdH1cclxuXHJcblx0YXN5bmMgbG9hZFNldHRpbmdzKCkge1xyXG5cdFx0dGhpcy5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oe30sIERFRkFVTFRfU0VUVElOR1MsIGF3YWl0IHRoaXMubG9hZERhdGEoKSk7XHJcblx0fVxyXG5cclxuXHRhc3luYyBzYXZlU2V0dGluZ3MoKSB7XHJcblx0XHRhd2FpdCB0aGlzLnNhdmVEYXRhKHRoaXMuc2V0dGluZ3MpO1xyXG5cdH1cclxuXHJcblx0aXNTZXR0aW5nc01vZGFsT3BlbigpIDogYm9vbGVhbntcclxuXHRcdHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcubW9kLXNldHRpbmdzJykgIT09IG51bGw7XHJcblx0fSBcclxuXHJcblx0cHJvY2Vzc0VuY3J5cHREZWNyeXB0V2hvbGVOb3RlQ29tbWFuZChjaGVja2luZzogYm9vbGVhbiwgZWRpdG9yOiBFZGl0b3IsIHZpZXc6IE1hcmtkb3duVmlldyk6IGJvb2xlYW4ge1xyXG5cclxuXHRcdGlmICggY2hlY2tpbmcgJiYgdGhpcy5pc1NldHRpbmdzTW9kYWxPcGVuKCkgKXtcclxuXHRcdFx0Ly8gU2V0dGluZ3MgaXMgb3BlbiwgZW5zdXJlcyB0aGlzIGNvbW1hbmQgY2FuIHNob3cgdXAgaW4gb3RoZXJcclxuXHRcdFx0Ly8gcGx1Z2lucyB3aGljaCBsaXN0IGNvbW1hbmRzIGUuZy4gY3VzdG9taXphYmxlLXNpZGViYXJcclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3Qgc3RhcnRQb3MgPSBlZGl0b3Iub2Zmc2V0VG9Qb3MoMCk7XHJcblx0XHRjb25zdCBlbmRQb3MgPSB7IGxpbmU6IGVkaXRvci5sYXN0TGluZSgpLCBjaDogZWRpdG9yLmdldExpbmUoZWRpdG9yLmxhc3RMaW5lKCkpLmxlbmd0aCB9O1xyXG5cclxuXHRcdGNvbnN0IHNlbGVjdGlvblRleHQgPSBlZGl0b3IuZ2V0UmFuZ2Uoc3RhcnRQb3MsIGVuZFBvcykudHJpbSgpO1xyXG5cclxuXHRcdHJldHVybiB0aGlzLnByb2Nlc3NTZWxlY3Rpb24oXHJcblx0XHRcdGNoZWNraW5nLFxyXG5cdFx0XHRlZGl0b3IsXHJcblx0XHRcdHNlbGVjdGlvblRleHQsXHJcblx0XHRcdHN0YXJ0UG9zLFxyXG5cdFx0XHRlbmRQb3MsXHJcblx0XHRcdHRydWVcclxuXHRcdCk7XHJcblx0fVxyXG5cclxuXHRwcm9jZXNzRW5jcnlwdERlY3J5cHRDb21tYW5kKGNoZWNraW5nOiBib29sZWFuLCBlZGl0b3I6IEVkaXRvciwgdmlldzogTWFya2Rvd25WaWV3LCBkZWNyeXB0SW5QbGFjZTogYm9vbGVhbik6IGJvb2xlYW4ge1xyXG5cdFx0aWYgKCBjaGVja2luZyAmJiB0aGlzLmlzU2V0dGluZ3NNb2RhbE9wZW4oKSApe1xyXG5cdFx0XHQvLyBTZXR0aW5ncyBpcyBvcGVuLCBlbnN1cmVzIHRoaXMgY29tbWFuZCBjYW4gc2hvdyB1cCBpbiBvdGhlclxyXG5cdFx0XHQvLyBwbHVnaW5zIHdoaWNoIGxpc3QgY29tbWFuZHMgZS5nLiBjdXN0b21pemFibGUtc2lkZWJhclxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHRsZXQgc3RhcnRQb3MgPSBlZGl0b3IuZ2V0Q3Vyc29yKCdmcm9tJyk7XHJcblx0XHRsZXQgZW5kUG9zID0gZWRpdG9yLmdldEN1cnNvcigndG8nKTtcclxuXHJcblx0XHRpZiAodGhpcy5zZXR0aW5ncy5leHBhbmRUb1dob2xlTGluZXMpe1xyXG5cdFx0XHRjb25zdCBzdGFydExpbmUgPSBzdGFydFBvcy5saW5lO1xyXG5cdFx0XHRzdGFydFBvcyA9IHsgbGluZTogc3RhcnRMaW5lLCBjaDogMCB9OyAvLyB3YW50IHRoZSBzdGFydCBvZiB0aGUgZmlyc3QgbGluZVxyXG5cclxuXHRcdFx0Y29uc3QgZW5kTGluZSA9IGVuZFBvcy5saW5lO1xyXG5cdFx0XHRjb25zdCBlbmRMaW5lVGV4dCA9IGVkaXRvci5nZXRMaW5lKGVuZExpbmUpO1xyXG5cdFx0XHRlbmRQb3MgPSB7IGxpbmU6IGVuZExpbmUsIGNoOiBlbmRMaW5lVGV4dC5sZW5ndGggfTsgLy8gd2FudCB0aGUgZW5kIG9mIGxhc3QgbGluZVxyXG5cdFx0fWVsc2V7XHJcblx0XHRcdGlmICggIWVkaXRvci5zb21ldGhpbmdTZWxlY3RlZCgpICl7XHJcblx0XHRcdFx0Ly8gbm90aGluZyBzZWxlY3RlZCwgYXNzdW1lIHVzZXIgd2FudHMgdG8gZGVjcnlwdCwgZXhwYW5kIHRvIHN0YXJ0IGFuZCBlbmQgbWFya2Vyc1xyXG5cdFx0XHRcdHN0YXJ0UG9zID0gdGhpcy5nZXRDbG9zZXN0UHJldlRleHRDdXJzb3JQb3MoZWRpdG9yLCBfUFJFRklYLCBzdGFydFBvcyApO1xyXG5cdFx0XHRcdGVuZFBvcyA9IHRoaXMuZ2V0Q2xvc2VzdE5leHRUZXh0Q3Vyc29yUG9zKGVkaXRvciwgX1NVRkZJWCwgZW5kUG9zICk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBzZWxlY3Rpb25UZXh0ID0gZWRpdG9yLmdldFJhbmdlKHN0YXJ0UG9zLCBlbmRQb3MpO1xyXG5cclxuXHRcdHJldHVybiB0aGlzLnByb2Nlc3NTZWxlY3Rpb24oXHJcblx0XHRcdGNoZWNraW5nLFxyXG5cdFx0XHRlZGl0b3IsXHJcblx0XHRcdHNlbGVjdGlvblRleHQsXHJcblx0XHRcdHN0YXJ0UG9zLFxyXG5cdFx0XHRlbmRQb3MsXHJcblx0XHRcdGRlY3J5cHRJblBsYWNlXHJcblx0XHQpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBnZXRDbG9zZXN0UHJldlRleHRDdXJzb3JQb3MoZWRpdG9yOiBFZGl0b3IsIHRleHQ6IHN0cmluZywgZGVmYXVsdFZhbHVlOkVkaXRvclBvc2l0aW9uICk6IEVkaXRvclBvc2l0aW9ue1xyXG5cdFx0Y29uc3QgaW5pdE9mZnNldCA9IGVkaXRvci5wb3NUb09mZnNldCggZWRpdG9yLmdldEN1cnNvcihcImZyb21cIikgKTtcclxuXHJcblx0XHRmb3IgKGxldCBvZmZzZXQgPSBpbml0T2Zmc2V0OyBvZmZzZXQgPj0gMDsgb2Zmc2V0LS0pIHtcclxuXHRcdFx0Y29uc3Qgb2Zmc2V0UG9zID0gZWRpdG9yLm9mZnNldFRvUG9zKG9mZnNldCk7XHJcblx0XHRcdGNvbnN0IHRleHRFbmRPZmZzZXQgPSBvZmZzZXQgKyB0ZXh0Lmxlbmd0aDtcclxuXHRcdFx0Y29uc3QgcHJlZml4RW5kUG9zID0gZWRpdG9yLm9mZnNldFRvUG9zKHRleHRFbmRPZmZzZXQpO1xyXG5cdFx0XHRcclxuXHRcdFx0Y29uc3QgdGVzdFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoIG9mZnNldFBvcywgcHJlZml4RW5kUG9zICk7XHJcblx0XHRcdGlmICh0ZXN0VGV4dCA9PSB0ZXh0KXtcclxuXHRcdFx0XHRyZXR1cm4gb2Zmc2V0UG9zO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGRlZmF1bHRWYWx1ZTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgZ2V0Q2xvc2VzdE5leHRUZXh0Q3Vyc29yUG9zKGVkaXRvcjogRWRpdG9yLCB0ZXh0OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZTpFZGl0b3JQb3NpdGlvbiApOiBFZGl0b3JQb3NpdGlvbntcclxuXHRcdGNvbnN0IGluaXRPZmZzZXQgPSBlZGl0b3IucG9zVG9PZmZzZXQoIGVkaXRvci5nZXRDdXJzb3IoXCJmcm9tXCIpICk7XHJcblx0XHRjb25zdCBsYXN0TGluZU51bSA9IGVkaXRvci5sYXN0TGluZSgpO1xyXG5cclxuXHRcdGxldCBtYXhPZmZzZXQgPSBlZGl0b3IucG9zVG9PZmZzZXQoIHtsaW5lOmxhc3RMaW5lTnVtLCBjaDplZGl0b3IuZ2V0TGluZShsYXN0TGluZU51bSkubGVuZ3RofSApO1xyXG5cclxuXHRcdGZvciAobGV0IG9mZnNldCA9IGluaXRPZmZzZXQ7IG9mZnNldCA8PSBtYXhPZmZzZXQgLSB0ZXh0Lmxlbmd0aDsgb2Zmc2V0KyspIHtcclxuXHRcdFx0Y29uc3Qgb2Zmc2V0UG9zID0gZWRpdG9yLm9mZnNldFRvUG9zKG9mZnNldCk7XHJcblx0XHRcdGNvbnN0IHRleHRFbmRPZmZzZXQgPSBvZmZzZXQgKyB0ZXh0Lmxlbmd0aDtcclxuXHRcdFx0Y29uc3QgcHJlZml4RW5kUG9zID0gZWRpdG9yLm9mZnNldFRvUG9zKHRleHRFbmRPZmZzZXQpO1xyXG5cdFx0XHRcclxuXHRcdFx0Y29uc3QgdGVzdFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoIG9mZnNldFBvcywgcHJlZml4RW5kUG9zICk7XHJcblx0XHRcdFxyXG5cdFx0XHRpZiAodGVzdFRleHQgPT0gdGV4dCl7XHJcblx0XHRcdFx0cmV0dXJuIHByZWZpeEVuZFBvcztcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0XHJcblx0XHRyZXR1cm4gZGVmYXVsdFZhbHVlO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBhbmFseXNlU2VsZWN0aW9uKCBzZWxlY3Rpb25UZXh0OiBzdHJpbmcgKTpTZWxlY3Rpb25BbmFseXNpc3tcclxuXHRcdFxyXG5cdFx0Y29uc3QgcmVzdWx0ID0gbmV3IFNlbGVjdGlvbkFuYWx5c2lzKCk7XHJcblxyXG5cdFx0cmVzdWx0LmlzRW1wdHkgPSBzZWxlY3Rpb25UZXh0Lmxlbmd0aCA9PT0gMDtcclxuXHJcblx0XHRyZXN1bHQuaGFzT2Jzb2xldGVFbmNyeXB0ZWRQcmVmaXggPSBzZWxlY3Rpb25UZXh0LnN0YXJ0c1dpdGgoX1BSRUZJWF9PQlNPTEVURSk7XHJcblx0XHRyZXN1bHQuaGFzRW5jcnlwdGVkUHJlZml4ID0gcmVzdWx0Lmhhc09ic29sZXRlRW5jcnlwdGVkUHJlZml4IHx8IHNlbGVjdGlvblRleHQuc3RhcnRzV2l0aChfUFJFRklYX0EpO1xyXG5cclxuXHRcdHJlc3VsdC5oYXNEZWNyeXB0U3VmZml4ID0gc2VsZWN0aW9uVGV4dC5lbmRzV2l0aChfU1VGRklYKTtcclxuXHJcblx0XHRyZXN1bHQuY29udGFpbnNFbmNyeXB0ZWRNYXJrZXJzID1cclxuXHRcdFx0c2VsZWN0aW9uVGV4dC5jb250YWlucyhfUFJFRklYX09CU09MRVRFKVxyXG5cdFx0XHR8fCBzZWxlY3Rpb25UZXh0LmNvbnRhaW5zKF9QUkVGSVhfQSlcclxuXHRcdFx0fHwgc2VsZWN0aW9uVGV4dC5jb250YWlucyhfU1VGRklYKVxyXG5cdFx0O1xyXG5cclxuXHRcdHJlc3VsdC5jYW5EZWNyeXB0ID0gcmVzdWx0Lmhhc0VuY3J5cHRlZFByZWZpeCAmJiByZXN1bHQuaGFzRGVjcnlwdFN1ZmZpeDtcclxuXHRcdHJlc3VsdC5jYW5FbmNyeXB0ID0gIXJlc3VsdC5oYXNFbmNyeXB0ZWRQcmVmaXggJiYgIXJlc3VsdC5jb250YWluc0VuY3J5cHRlZE1hcmtlcnM7XHJcblx0XHRcclxuXHRcdGlmIChyZXN1bHQuY2FuRGVjcnlwdCl7XHJcblx0XHRcdHJlc3VsdC5kZWNyeXB0YWJsZSA9IHRoaXMucGFyc2VEZWNyeXB0YWJsZUNvbnRlbnQoc2VsZWN0aW9uVGV4dCk7XHJcblx0XHRcdGlmIChyZXN1bHQuZGVjcnlwdGFibGUgPT0gbnVsbCl7XHJcblx0XHRcdFx0cmVzdWx0LmNhbkRlY3J5cHQgPSBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiByZXN1bHQ7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHByb2Nlc3NTZWxlY3Rpb24oXHJcblx0XHRjaGVja2luZzogYm9vbGVhbixcclxuXHRcdGVkaXRvcjogRWRpdG9yLFxyXG5cdFx0c2VsZWN0aW9uVGV4dDogc3RyaW5nLFxyXG5cdFx0ZmluYWxTZWxlY3Rpb25TdGFydDogQ29kZU1pcnJvci5Qb3NpdGlvbixcclxuXHRcdGZpbmFsU2VsZWN0aW9uRW5kOiBDb2RlTWlycm9yLlBvc2l0aW9uLFxyXG5cdFx0ZGVjcnlwdEluUGxhY2U6IGJvb2xlYW5cclxuXHQpe1xyXG5cclxuXHRcdGNvbnN0IHNlbGVjdGlvbkFuYWx5c2lzID0gdGhpcy5hbmFseXNlU2VsZWN0aW9uKHNlbGVjdGlvblRleHQpO1xyXG5cclxuXHRcdGlmIChzZWxlY3Rpb25BbmFseXNpcy5pc0VtcHR5KSB7XHJcblx0XHRcdGlmICghY2hlY2tpbmcpe1xyXG5cdFx0XHRcdG5ldyBOb3RpY2UoJ05vdGhpbmcgdG8gRW5jcnlwdC4nKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCFzZWxlY3Rpb25BbmFseXNpcy5jYW5EZWNyeXB0ICYmICFzZWxlY3Rpb25BbmFseXNpcy5jYW5FbmNyeXB0KSB7XHJcblx0XHRcdGlmICghY2hlY2tpbmcpe1xyXG5cdFx0XHRcdG5ldyBOb3RpY2UoJ1VuYWJsZSB0byBFbmNyeXB0IG9yIERlY3J5cHQgdGhhdC4nKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGNoZWNraW5nKSB7XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEZldGNoIHBhc3N3b3JkIGZyb20gdXNlclxyXG5cclxuXHRcdC8vIGRldGVybWluZSBkZWZhdWx0IHBhc3N3b3JkXHJcblx0XHRjb25zdCBpc1JlbWVtYmVyUGFzc3dvcmRFeHBpcmVkID1cclxuXHRcdFx0IXRoaXMuc2V0dGluZ3MucmVtZW1iZXJQYXNzd29yZFxyXG5cdFx0XHR8fCAoXHJcblx0XHRcdFx0dGhpcy5wYXNzd29yZExhc3RVc2VkRXhwaXJ5ICE9IG51bGxcclxuXHRcdFx0XHQmJiBEYXRlLm5vdygpID4gdGhpcy5wYXNzd29yZExhc3RVc2VkRXhwaXJ5XHJcblx0XHRcdClcclxuXHRcdDtcclxuXHJcblx0XHRjb25zdCBjb25maXJtUGFzc3dvcmQgPSBzZWxlY3Rpb25BbmFseXNpcy5jYW5FbmNyeXB0ICYmIHRoaXMuc2V0dGluZ3MuY29uZmlybVBhc3N3b3JkO1xyXG5cclxuXHRcdGlmICggaXNSZW1lbWJlclBhc3N3b3JkRXhwaXJlZCB8fCBjb25maXJtUGFzc3dvcmQgKSB7XHJcblx0XHRcdC8vIGZvcmdldCBwYXNzd29yZFxyXG5cdFx0XHR0aGlzLnBhc3N3b3JkTGFzdFVzZWQgPSAnJztcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBwd01vZGFsID0gbmV3IFBhc3N3b3JkTW9kYWwoXHJcblx0XHRcdHRoaXMuYXBwLFxyXG5cdFx0XHRzZWxlY3Rpb25BbmFseXNpcy5jYW5FbmNyeXB0LFxyXG5cdFx0XHRjb25maXJtUGFzc3dvcmQsXHJcblx0XHRcdHRoaXMucGFzc3dvcmRMYXN0VXNlZCxcclxuXHRcdFx0c2VsZWN0aW9uQW5hbHlzaXMuZGVjcnlwdGFibGU/LmhpbnRcclxuXHRcdCk7XHJcblx0XHRwd01vZGFsLm9uQ2xvc2UgPSAoKSA9PiB7XHJcblx0XHRcdGNvbnN0IHB3ID0gcHdNb2RhbC5wYXNzd29yZCA/PyAnJ1xyXG5cdFx0XHRpZiAocHcubGVuZ3RoID09IDApIHtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHRcdFx0Y29uc3QgaGludCA9IHB3TW9kYWwuaGludDtcclxuXHJcblx0XHRcdC8vIHJlbWVtYmVyIHBhc3N3b3JkP1xyXG5cdFx0XHRpZiAodGhpcy5zZXR0aW5ncy5yZW1lbWJlclBhc3N3b3JkKSB7XHJcblx0XHRcdFx0dGhpcy5wYXNzd29yZExhc3RVc2VkID0gcHc7XHJcblx0XHRcdFx0dGhpcy5wYXNzd29yZExhc3RVc2VkRXhwaXJ5ID1cclxuXHRcdFx0XHRcdHRoaXMuc2V0dGluZ3MucmVtZW1iZXJQYXNzd29yZFRpbWVvdXQgPT0gMFxyXG5cdFx0XHRcdFx0XHQ/IG51bGxcclxuXHRcdFx0XHRcdFx0OiBEYXRlLm5vdygpICsgdGhpcy5zZXR0aW5ncy5yZW1lbWJlclBhc3N3b3JkVGltZW91dCAqIDEwMDAgKiA2MC8vIG5ldyBleHBpcnlcclxuXHRcdFx0XHRcdDtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKHNlbGVjdGlvbkFuYWx5c2lzLmNhbkVuY3J5cHQpIHtcclxuXHRcdFx0XHRjb25zdCBlbmNyeXB0YWJsZSA9IG5ldyBFbmNyeXB0YWJsZSgpO1xyXG5cdFx0XHRcdGVuY3J5cHRhYmxlLnRleHQgPSBzZWxlY3Rpb25UZXh0O1xyXG5cdFx0XHRcdGVuY3J5cHRhYmxlLmhpbnQgPSBoaW50O1xyXG5cclxuXHRcdFx0XHR0aGlzLmVuY3J5cHRTZWxlY3Rpb24oXHJcblx0XHRcdFx0XHRlZGl0b3IsXHJcblx0XHRcdFx0XHRlbmNyeXB0YWJsZSxcclxuXHRcdFx0XHRcdHB3LFxyXG5cdFx0XHRcdFx0ZmluYWxTZWxlY3Rpb25TdGFydCxcclxuXHRcdFx0XHRcdGZpbmFsU2VsZWN0aW9uRW5kXHJcblx0XHRcdFx0KTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0aWYgKHNlbGVjdGlvbkFuYWx5c2lzLmRlY3J5cHRhYmxlLnZlcnNpb24gPT0gMSl7XHJcblx0XHRcdFx0XHR0aGlzLmRlY3J5cHRTZWxlY3Rpb25fYShcclxuXHRcdFx0XHRcdFx0ZWRpdG9yLFxyXG5cdFx0XHRcdFx0XHRzZWxlY3Rpb25BbmFseXNpcy5kZWNyeXB0YWJsZSxcclxuXHRcdFx0XHRcdFx0cHcsXHJcblx0XHRcdFx0XHRcdGZpbmFsU2VsZWN0aW9uU3RhcnQsXHJcblx0XHRcdFx0XHRcdGZpbmFsU2VsZWN0aW9uRW5kLFxyXG5cdFx0XHRcdFx0XHRkZWNyeXB0SW5QbGFjZVxyXG5cdFx0XHRcdFx0KTtcclxuXHRcdFx0XHR9ZWxzZXtcclxuXHRcdFx0XHRcdHRoaXMuZGVjcnlwdFNlbGVjdGlvbk9ic29sZXRlKFxyXG5cdFx0XHRcdFx0XHRlZGl0b3IsXHJcblx0XHRcdFx0XHRcdHNlbGVjdGlvbkFuYWx5c2lzLmRlY3J5cHRhYmxlLFxyXG5cdFx0XHRcdFx0XHRwdyxcclxuXHRcdFx0XHRcdFx0ZmluYWxTZWxlY3Rpb25TdGFydCxcclxuXHRcdFx0XHRcdFx0ZmluYWxTZWxlY3Rpb25FbmQsXHJcblx0XHRcdFx0XHRcdGRlY3J5cHRJblBsYWNlXHJcblx0XHRcdFx0XHQpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0cHdNb2RhbC5vcGVuKCk7XHJcblxyXG5cdFx0cmV0dXJuIHRydWU7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFzeW5jIGVuY3J5cHRTZWxlY3Rpb24oXHJcblx0XHRlZGl0b3I6IEVkaXRvcixcclxuXHRcdGVuY3J5cHRhYmxlOiBFbmNyeXB0YWJsZSxcclxuXHRcdHBhc3N3b3JkOiBzdHJpbmcsXHJcblx0XHRmaW5hbFNlbGVjdGlvblN0YXJ0OiBDb2RlTWlycm9yLlBvc2l0aW9uLFxyXG5cdFx0ZmluYWxTZWxlY3Rpb25FbmQ6IENvZGVNaXJyb3IuUG9zaXRpb24sXHJcblx0KSB7XHJcblx0XHQvL2VuY3J5cHRcclxuXHRcdGNvbnN0IGNyeXB0byA9IG5ldyBDcnlwdG9IZWxwZXJWMigpO1xyXG5cdFx0Y29uc3QgZW5jb2RlZFRleHQgPSB0aGlzLmVuY29kZUVuY3J5cHRpb24oXHJcblx0XHRcdGF3YWl0IGNyeXB0by5lbmNyeXB0VG9CYXNlNjQoZW5jcnlwdGFibGUudGV4dCwgcGFzc3dvcmQpLFxyXG5cdFx0XHRlbmNyeXB0YWJsZS5oaW50XHJcblx0XHQpO1xyXG5cdFx0ZWRpdG9yLnNldFNlbGVjdGlvbihmaW5hbFNlbGVjdGlvblN0YXJ0LCBmaW5hbFNlbGVjdGlvbkVuZCk7XHJcblx0XHRlZGl0b3IucmVwbGFjZVNlbGVjdGlvbihlbmNvZGVkVGV4dCk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFzeW5jIGRlY3J5cHRTZWxlY3Rpb25fYShcclxuXHRcdGVkaXRvcjogRWRpdG9yLFxyXG5cdFx0ZGVjcnlwdGFibGU6IERlY3J5cHRhYmxlLFxyXG5cdFx0cGFzc3dvcmQ6IHN0cmluZyxcclxuXHRcdHNlbGVjdGlvblN0YXJ0OiBDb2RlTWlycm9yLlBvc2l0aW9uLFxyXG5cdFx0c2VsZWN0aW9uRW5kOiBDb2RlTWlycm9yLlBvc2l0aW9uLFxyXG5cdFx0ZGVjcnlwdEluUGxhY2U6IGJvb2xlYW5cclxuXHQpIHtcclxuXHRcdC8vIGRlY3J5cHRcclxuXHJcblx0XHRjb25zdCBjcnlwdG8gPSBuZXcgQ3J5cHRvSGVscGVyVjIoKTtcclxuXHRcdGNvbnN0IGRlY3J5cHRlZFRleHQgPSBhd2FpdCBjcnlwdG8uZGVjcnlwdEZyb21CYXNlNjQoZGVjcnlwdGFibGUuYmFzZTY0Q2lwaGVyVGV4dCwgcGFzc3dvcmQpO1xyXG5cdFx0aWYgKGRlY3J5cHRlZFRleHQgPT09IG51bGwpIHtcclxuXHRcdFx0bmV3IE5vdGljZSgn4p2MIERlY3J5cHRpb24gZmFpbGVkIScpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdGlmIChkZWNyeXB0SW5QbGFjZSkge1xyXG5cdFx0XHRcdGVkaXRvci5zZXRTZWxlY3Rpb24oc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XHJcblx0XHRcdFx0ZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24oZGVjcnlwdGVkVGV4dCk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Y29uc3QgZGVjcnlwdE1vZGFsID0gbmV3IERlY3J5cHRNb2RhbCh0aGlzLmFwcCwgJ/CflJMnLCBkZWNyeXB0ZWRUZXh0LCB0aGlzLnNldHRpbmdzLnNob3dCdXR0b24pO1xyXG5cdFx0XHRcdGRlY3J5cHRNb2RhbC5vbkNsb3NlID0gKCkgPT4ge1xyXG5cdFx0XHRcdFx0ZWRpdG9yLmZvY3VzKCk7XHJcblx0XHRcdFx0XHRpZiAoZGVjcnlwdE1vZGFsLmRlY3J5cHRJblBsYWNlKSB7XHJcblx0XHRcdFx0XHRcdGVkaXRvci5zZXRTZWxlY3Rpb24oc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XHJcblx0XHRcdFx0XHRcdGVkaXRvci5yZXBsYWNlU2VsZWN0aW9uKGRlY3J5cHRlZFRleHQpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRkZWNyeXB0TW9kYWwub3BlbigpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFzeW5jIGRlY3J5cHRTZWxlY3Rpb25PYnNvbGV0ZShcclxuXHRcdGVkaXRvcjogRWRpdG9yLFxyXG5cdFx0ZGVjcnlwdGFibGU6IERlY3J5cHRhYmxlLFxyXG5cdFx0cGFzc3dvcmQ6IHN0cmluZyxcclxuXHRcdHNlbGVjdGlvblN0YXJ0OiBDb2RlTWlycm9yLlBvc2l0aW9uLFxyXG5cdFx0c2VsZWN0aW9uRW5kOiBDb2RlTWlycm9yLlBvc2l0aW9uLFxyXG5cdFx0ZGVjcnlwdEluUGxhY2U6IGJvb2xlYW5cclxuXHQpIHtcclxuXHRcdC8vIGRlY3J5cHRcclxuXHRcdGNvbnN0IGJhc2U2NENpcGhlclRleHQgPSB0aGlzLnJlbW92ZU1hcmtlcnMoZGVjcnlwdGFibGUuYmFzZTY0Q2lwaGVyVGV4dCk7XHJcblx0XHRjb25zdCBjcnlwdG8gPSBuZXcgQ3J5cHRvSGVscGVyT2Jzb2xldGUoKTtcclxuXHRcdGNvbnN0IGRlY3J5cHRlZFRleHQgPSBhd2FpdCBjcnlwdG8uZGVjcnlwdEZyb21CYXNlNjQoYmFzZTY0Q2lwaGVyVGV4dCwgcGFzc3dvcmQpO1xyXG5cdFx0aWYgKGRlY3J5cHRlZFRleHQgPT09IG51bGwpIHtcclxuXHRcdFx0bmV3IE5vdGljZSgn4p2MIERlY3J5cHRpb24gZmFpbGVkIScpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdGlmIChkZWNyeXB0SW5QbGFjZSkge1xyXG5cdFx0XHRcdGVkaXRvci5zZXRTZWxlY3Rpb24oc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XHJcblx0XHRcdFx0ZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24oZGVjcnlwdGVkVGV4dCk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Y29uc3QgZGVjcnlwdE1vZGFsID0gbmV3IERlY3J5cHRNb2RhbCh0aGlzLmFwcCwgJ/CflJMnLCBkZWNyeXB0ZWRUZXh0LCB0aGlzLnNldHRpbmdzLnNob3dCdXR0b24pO1xyXG5cdFx0XHRcdGRlY3J5cHRNb2RhbC5vbkNsb3NlID0gKCkgPT4ge1xyXG5cdFx0XHRcdFx0ZWRpdG9yLmZvY3VzKCk7XHJcblx0XHRcdFx0XHRpZiAoZGVjcnlwdE1vZGFsLmRlY3J5cHRJblBsYWNlKSB7XHJcblx0XHRcdFx0XHRcdGVkaXRvci5zZXRTZWxlY3Rpb24oc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XHJcblx0XHRcdFx0XHRcdGVkaXRvci5yZXBsYWNlU2VsZWN0aW9uKGRlY3J5cHRlZFRleHQpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRkZWNyeXB0TW9kYWwub3BlbigpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHBhcnNlRGVjcnlwdGFibGVDb250ZW50KHRleHQ6IHN0cmluZykgOiBEZWNyeXB0YWJsZXtcclxuXHRcdGNvbnN0IHJlc3VsdCA9IG5ldyBEZWNyeXB0YWJsZSgpO1xyXG5cclxuXHRcdGxldCBjb250ZW50ID0gdGV4dDtcclxuXHRcdGlmIChjb250ZW50LnN0YXJ0c1dpdGgoX1BSRUZJWF9BKSAmJiBjb250ZW50LmVuZHNXaXRoKF9TVUZGSVgpKSB7XHJcblx0XHRcdHJlc3VsdC52ZXJzaW9uPTE7XHJcblx0XHRcdGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoX1BSRUZJWF9BLCAnJykucmVwbGFjZShfU1VGRklYLCAnJyk7XHJcblx0XHR9ZWxzZSBpZiAoY29udGVudC5zdGFydHNXaXRoKF9QUkVGSVhfT0JTT0xFVEUpICYmIGNvbnRlbnQuZW5kc1dpdGgoX1NVRkZJWCkpIHtcclxuXHRcdFx0cmVzdWx0LnZlcnNpb249MDtcclxuXHRcdFx0Y29udGVudCA9IGNvbnRlbnQucmVwbGFjZShfUFJFRklYX09CU09MRVRFLCAnJykucmVwbGFjZShfU1VGRklYLCAnJyk7XHJcblx0XHR9ZWxzZSB7XHJcblx0XHRcdHJldHVybiBudWxsOyAvLyBpbnZhbGlkIGZvcm1hdFxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIGNoZWNrIGlmIHRoZXJlIGlzIGEgaGludFxyXG5cdFx0Ly9jb25zb2xlLnRhYmxlKGNvbnRlbnQpO1xyXG5cdFx0aWYgKGNvbnRlbnQuc3Vic3RyKDAsX0hJTlQubGVuZ3RoKSA9PSBfSElOVCl7XHJcblx0XHRcdGNvbnN0IGVuZEhpbnRNYXJrZXIgPSBjb250ZW50LmluZGV4T2YoX0hJTlQsX0hJTlQubGVuZ3RoKTtcclxuXHRcdFx0aWYgKGVuZEhpbnRNYXJrZXI8MCl7XHJcblx0XHRcdFx0cmV0dXJuIG51bGw7IC8vIGludmFsaWQgZm9ybWF0XHJcblx0XHRcdH1cclxuXHRcdFx0cmVzdWx0LmhpbnQgPSBjb250ZW50LnN1YnN0cmluZyhfSElOVC5sZW5ndGgsZW5kSGludE1hcmtlcilcclxuXHRcdFx0cmVzdWx0LmJhc2U2NENpcGhlclRleHQgPSBjb250ZW50LnN1YnN0cmluZyhlbmRIaW50TWFya2VyK19ISU5ULmxlbmd0aCk7XHJcblx0XHR9ZWxzZXtcclxuXHRcdFx0cmVzdWx0LmJhc2U2NENpcGhlclRleHQgPSBjb250ZW50O1xyXG5cdFx0fVxyXG5cdFx0XHJcblx0XHQvL2NvbnNvbGUudGFibGUocmVzdWx0KTtcclxuXHJcblx0XHRyZXR1cm4gcmVzdWx0O1xyXG5cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVtb3ZlTWFya2Vycyh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdFx0aWYgKHRleHQuc3RhcnRzV2l0aChfUFJFRklYX0EpICYmIHRleHQuZW5kc1dpdGgoX1NVRkZJWCkpIHtcclxuXHRcdFx0cmV0dXJuIHRleHQucmVwbGFjZShfUFJFRklYX0EsICcnKS5yZXBsYWNlKF9TVUZGSVgsICcnKTtcclxuXHRcdH1cclxuXHRcdGlmICh0ZXh0LnN0YXJ0c1dpdGgoX1BSRUZJWF9PQlNPTEVURSkgJiYgdGV4dC5lbmRzV2l0aChfU1VGRklYKSkge1xyXG5cdFx0XHRyZXR1cm4gdGV4dC5yZXBsYWNlKF9QUkVGSVhfT0JTT0xFVEUsICcnKS5yZXBsYWNlKF9TVUZGSVgsICcnKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0ZXh0O1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBlbmNvZGVFbmNyeXB0aW9uKCBlbmNyeXB0ZWRUZXh0OiBzdHJpbmcsIGhpbnQ6IHN0cmluZyApOiBzdHJpbmcge1xyXG5cdFx0aWYgKCFlbmNyeXB0ZWRUZXh0LmNvbnRhaW5zKF9QUkVGSVhfT0JTT0xFVEUpICYmICFlbmNyeXB0ZWRUZXh0LmNvbnRhaW5zKF9QUkVGSVhfQSkgJiYgIWVuY3J5cHRlZFRleHQuY29udGFpbnMoX1NVRkZJWCkpIHtcclxuXHRcdFx0aWYgKGhpbnQpe1xyXG5cdFx0XHRcdHJldHVybiBfUFJFRklYX0EuY29uY2F0KF9ISU5ULCBoaW50LCBfSElOVCwgZW5jcnlwdGVkVGV4dCwgX1NVRkZJWCk7XHRcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gX1BSRUZJWF9BLmNvbmNhdChlbmNyeXB0ZWRUZXh0LCBfU1VGRklYKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiBlbmNyeXB0ZWRUZXh0O1xyXG5cdH1cclxuXHJcbn1cclxuXHJcbmNsYXNzIFNlbGVjdGlvbkFuYWx5c2lze1xyXG5cdGlzRW1wdHk6IGJvb2xlYW47XHJcblx0aGFzT2Jzb2xldGVFbmNyeXB0ZWRQcmVmaXg6IGJvb2xlYW47XHJcblx0aGFzRW5jcnlwdGVkUHJlZml4OiBib29sZWFuO1xyXG5cdGhhc0RlY3J5cHRTdWZmaXg6IGJvb2xlYW47XHJcblx0Y2FuRGVjcnlwdDogYm9vbGVhbjtcclxuXHRjYW5FbmNyeXB0OiBib29sZWFuO1xyXG5cdGNvbnRhaW5zRW5jcnlwdGVkTWFya2VyczogYm9vbGVhbjtcclxuXHRkZWNyeXB0YWJsZSA6IERlY3J5cHRhYmxlO1xyXG59XHJcblxyXG5jbGFzcyBFbmNyeXB0YWJsZXtcclxuXHR0ZXh0OnN0cmluZztcclxuXHRoaW50OnN0cmluZztcclxufVxyXG5cclxuY2xhc3MgRGVjcnlwdGFibGV7XHJcblx0dmVyc2lvbjogbnVtYmVyO1xyXG5cdGJhc2U2NENpcGhlclRleHQ6c3RyaW5nO1xyXG5cdGhpbnQ6c3RyaW5nO1xyXG59Il0sIm5hbWVzIjpbIk1vZGFsIiwiUGxhdGZvcm0iLCJQbHVnaW5TZXR0aW5nVGFiIiwiU2V0dGluZyIsIlBsdWdpbiIsIk5vdGljZSJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF1REE7QUFDTyxTQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUU7QUFDN0QsSUFBSSxTQUFTLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxPQUFPLEtBQUssWUFBWSxDQUFDLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLFVBQVUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUU7QUFDaEgsSUFBSSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUU7QUFDL0QsUUFBUSxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ25HLFFBQVEsU0FBUyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ3RHLFFBQVEsU0FBUyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFO0FBQ3RILFFBQVEsSUFBSSxDQUFDLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFVBQVUsSUFBSSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQzlFLEtBQUssQ0FBQyxDQUFDO0FBQ1A7O0FDM0VxQixNQUFBLFlBQWEsU0FBUUEsY0FBSyxDQUFBO0FBSzlDLElBQUEsV0FBQSxDQUFZLEdBQVEsRUFBRSxLQUFhLEVBQUUsSUFBZSxHQUFBLEVBQUUsRUFBRSxVQUFrQixFQUFBO1FBQ3pFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUpaLElBQWMsQ0FBQSxjQUFBLEdBQVksS0FBSyxDQUFDO0FBSy9CLFFBQUEsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7QUFDakIsUUFBQSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7QUFDL0IsUUFBQSxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztLQUM3QjtJQUVELE1BQU0sR0FBQTtBQUNMLFFBQUEsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQztBQUV6QixRQUFBLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQy9FLFFBQUEsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO0FBQzVCLFFBQUEsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQzdCLFFBQUEsTUFBTSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7QUFDakIsUUFBQSxNQUFNLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQzs7QUFFdkIsUUFBQSxVQUFVLENBQUMsTUFBUSxFQUFBLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQSxFQUFFLEVBQUMsR0FBRyxDQUFDLENBQUM7UUFHekMsTUFBTSxjQUFjLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUUvQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUM7QUFDcEIsWUFBQSxNQUFNLFNBQVMsR0FBRyxjQUFjLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBQ3RFLFlBQUEsU0FBUyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxNQUFLO2dCQUN4QyxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDN0MsYUFBQyxDQUFDLENBQUM7QUFBRSxTQUFBO0FBRUwsUUFBQSxNQUFNLG1CQUFtQixHQUFHLGNBQWMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztBQUM1RixRQUFBLG1CQUFtQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxNQUFLO0FBQ2xELFlBQUEsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7WUFDM0IsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2QsU0FBQyxDQUFDLENBQUM7QUFFSCxRQUFBLE1BQU0sV0FBVyxHQUFHLGNBQWMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7QUFDekUsUUFBQSxXQUFXLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE1BQUs7WUFDMUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2QsU0FBQyxDQUFDLENBQUM7S0FFSDtBQUVEOztBQzdDb0IsTUFBQSxhQUFjLFNBQVFBLGNBQUssQ0FBQTtJQU8vQyxXQUFZLENBQUEsR0FBUSxFQUFFLFlBQW9CLEVBQUUsZUFBd0IsRUFBRSxlQUFBLEdBQTBCLElBQUksRUFBRSxJQUFXLEVBQUE7UUFDaEgsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBUFosSUFBUSxDQUFBLFFBQUEsR0FBVyxJQUFJLENBQUM7UUFDeEIsSUFBSSxDQUFBLElBQUEsR0FBVyxJQUFJLENBQUM7UUFDcEIsSUFBZSxDQUFBLGVBQUEsR0FBVyxJQUFJLENBQUM7QUFNOUIsUUFBQSxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztBQUN2QyxRQUFBLElBQUksQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO0FBQ3ZDLFFBQUEsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7QUFDakMsUUFBQSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztLQUNqQjtJQUVELE1BQU0sR0FBQTs7QUFDTCxRQUFBLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFFekIsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO0FBRWxCLFFBQUEsU0FBUyxDQUFDLFFBQVEsQ0FBRSxpQkFBaUIsQ0FBRSxDQUFDO1FBQ3hDLElBQUlDLGlCQUFRLENBQUMsUUFBUSxFQUFDO0FBQ3JCLFlBQUEsU0FBUyxDQUFDLFFBQVEsQ0FBRSx3QkFBd0IsQ0FBRSxDQUFDO0FBQy9DLFNBQUE7YUFBSyxJQUFJQSxpQkFBUSxDQUFDLFNBQVMsRUFBQztBQUM1QixZQUFBLFNBQVMsQ0FBQyxRQUFRLENBQUUseUJBQXlCLENBQUUsQ0FBQztBQUNoRCxTQUFBOztBQUdELFFBQUEsTUFBTSxrQkFBa0IsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFFLEVBQUUsR0FBRyxFQUFDLFlBQVksRUFBRSxDQUFFLENBQUM7QUFDdkUsUUFBQSxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsRUFBRSxHQUFHLEVBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRWpFLE1BQU0sU0FBUyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFBLEVBQUEsR0FBQSxJQUFJLENBQUMsZUFBZSxNQUFJLElBQUEsSUFBQSxFQUFBLEtBQUEsS0FBQSxDQUFBLEdBQUEsRUFBQSxHQUFBLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFFaEgsUUFBQSxTQUFTLENBQUMsV0FBVyxHQUFHLHFCQUFxQixDQUFDO1FBQzlDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVsQixJQUFJQSxpQkFBUSxDQUFDLFFBQVEsRUFBQzs7QUFFckIsWUFBQSxNQUFNLG1CQUFtQixHQUFHLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUU7QUFDakUsZ0JBQUEsSUFBSSxFQUFFLEdBQUc7QUFDVCxnQkFBQSxHQUFHLEVBQUMsb0JBQW9CO0FBQ3hCLGFBQUEsQ0FBQyxDQUFDO1lBQ0gsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxLQUFJO0FBQ3BELGdCQUFBLG9CQUFvQixFQUFFLENBQUM7QUFDeEIsYUFBQyxDQUFDLENBQUM7QUFDSCxTQUFBOzs7QUFLRCxRQUFBLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7QUFDNUMsUUFBQSxNQUFNLG9CQUFvQixHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUUsRUFBRSxHQUFHLEVBQUMsWUFBWSxFQUFFLENBQUUsQ0FBQztBQUN6RSxRQUFBLG9CQUFvQixDQUFDLFVBQVUsQ0FBRSxFQUFFLEdBQUcsRUFBQyxhQUFhLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFFLENBQUM7QUFFckUsUUFBQSxNQUFNLGdCQUFnQixHQUFHLG9CQUFvQixDQUFDLFFBQVEsQ0FBRSxPQUFPLEVBQUU7QUFDaEUsWUFBQSxJQUFJLEVBQUUsVUFBVTtBQUNoQixZQUFBLEtBQUssRUFBRSxDQUFBLEVBQUEsR0FBQSxJQUFJLENBQUMsZUFBZSxtQ0FBSSxFQUFFO0FBQ2pDLFNBQUEsQ0FBQyxDQUFDO0FBQ0gsUUFBQSxnQkFBZ0IsQ0FBQyxXQUFXLEdBQUcsdUJBQXVCLENBQUM7QUFFdkQsUUFBQSxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxFQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztRQUNoRSxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFHakIsSUFBSUEsaUJBQVEsQ0FBQyxRQUFRLEVBQUM7O0FBRXJCLFlBQUEsTUFBTSxxQkFBcUIsR0FBRyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFO0FBQ3JFLGdCQUFBLElBQUksRUFBRSxHQUFHO0FBQ1QsZ0JBQUEsR0FBRyxFQUFDLG9CQUFvQjtBQUN4QixhQUFBLENBQUMsQ0FBQztZQUNILHFCQUFxQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsS0FBSTtBQUN0RCxnQkFBQSxzQkFBc0IsRUFBRSxDQUFDO0FBQzFCLGFBQUMsQ0FBQyxDQUFDO0FBQ0gsU0FBQTtRQUVELElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDcEIsb0JBQW9CLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDNUIsU0FBQTs7O0FBSUQsUUFBQSxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO0FBQ3pDLFFBQUEsTUFBTSxvQkFBb0IsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFFLEVBQUUsR0FBRyxFQUFDLFlBQVksRUFBRSxDQUFFLENBQUM7QUFDekUsUUFBQSxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsRUFBRSxHQUFHLEVBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ25FLE1BQU0sV0FBVyxHQUFHLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUMvRixRQUFBLFdBQVcsQ0FBQyxXQUFXLEdBQUcsaUNBQWlDLENBQUM7UUFDNUQsSUFBSUEsaUJBQVEsQ0FBQyxRQUFRLEVBQUM7O0FBRXJCLFlBQUEsTUFBTSxrQkFBa0IsR0FBRyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFO0FBQ2xFLGdCQUFBLElBQUksRUFBRSxHQUFHO0FBQ1QsZ0JBQUEsR0FBRyxFQUFDLG9CQUFvQjtBQUN4QixhQUFBLENBQUMsQ0FBQztZQUNILGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsS0FBSTtBQUNuRCxnQkFBQSxtQkFBbUIsRUFBRSxDQUFDO0FBQ3ZCLGFBQUMsQ0FBQyxDQUFDO0FBQ0gsU0FBQTtRQUNELElBQUksQ0FBQyxjQUFjLEVBQUM7WUFDbkIsb0JBQW9CLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDNUIsU0FBQTs7O0FBSUQsUUFBQSxNQUFNLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUUsRUFBRSxHQUFHLEVBQUMsWUFBWSxFQUFFLENBQUUsQ0FBQztBQUN4RSxRQUFBLG1CQUFtQixDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsRUFBQyxhQUFhLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDbEUsUUFBQSxtQkFBbUIsQ0FBQyxVQUFVLENBQUUsRUFBQyxHQUFHLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBQyxVQUFVLElBQUksQ0FBQyxJQUFJLENBQUcsQ0FBQSxDQUFBLEVBQUMsQ0FBQyxDQUFDO0FBRW5GLFFBQUEsSUFBSSxjQUFjLElBQUksQ0FBQyxDQUFBLEVBQUEsR0FBQSxJQUFJLENBQUMsSUFBSSxNQUFJLElBQUEsSUFBQSxFQUFBLEtBQUEsS0FBQSxDQUFBLEdBQUEsRUFBQSxHQUFBLEVBQUUsRUFBRSxNQUFNLElBQUUsQ0FBQyxFQUFDO1lBQ2pELG1CQUFtQixDQUFDLElBQUksRUFBRSxDQUFDO0FBQzNCLFNBQUE7O0FBSUQsUUFBQSxNQUFNLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUUsUUFBUSxFQUFFO0FBQ3ZELFlBQUEsSUFBSSxFQUFDLFNBQVM7QUFDZCxZQUFBLEdBQUcsRUFBQyx1QkFBdUI7QUFDM0IsU0FBQSxDQUFDLENBQUM7UUFDSCxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLEtBQUk7WUFDbkQsSUFBSSxRQUFRLEVBQUUsRUFBQztnQkFDZCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDYixhQUFBO0FBQUksaUJBQUE7Z0JBQ0osU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2xCLGFBQUE7QUFDRixTQUFDLENBQUMsQ0FBQTtRQUVGLE1BQU0sUUFBUSxHQUFHLE1BQWU7QUFDL0IsWUFBQSxJQUFJLGNBQWMsRUFBQztBQUNsQixnQkFBQSxJQUFJLFNBQVMsQ0FBQyxLQUFLLElBQUksZ0JBQWdCLENBQUMsS0FBSyxFQUFDOztBQUU3QyxvQkFBQSxTQUFTLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUM7b0JBQzVDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNqQixvQkFBQSxPQUFPLEtBQUssQ0FBQztBQUNiLGlCQUFBO0FBQ0QsYUFBQTtBQUVELFlBQUEsSUFBSSxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO0FBRWhDLFlBQUEsSUFBSSxDQUFDLElBQUksR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDO0FBRTlCLFlBQUEsT0FBTyxJQUFJLENBQUM7QUFDYixTQUFDLENBQUE7UUFFRCxNQUFNLG9CQUFvQixHQUFHLE1BQUs7QUFDakMsWUFBQSxJQUFJLGNBQWMsRUFBQztnQkFDbEIsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3pCLE9BQU87QUFDUCxhQUFBO0FBRUQsWUFBQSxJQUFJLGNBQWMsRUFBQztnQkFDbEIsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNwQixPQUFPO0FBQ1AsYUFBQTtZQUVELElBQUssUUFBUSxFQUFFLEVBQUU7Z0JBQ2hCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUNiLGFBQUE7QUFDRixTQUFDLENBQUE7UUFFRCxNQUFNLHNCQUFzQixHQUFHLE1BQUs7WUFDbkMsSUFBSyxRQUFRLEVBQUUsRUFBRTtBQUNoQixnQkFBQSxJQUFJLGNBQWMsRUFBQztvQkFDbEIsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ3BCLGlCQUFBO0FBQUkscUJBQUE7b0JBQ0osSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2IsaUJBQUE7QUFDRCxhQUFBO0FBQ0YsU0FBQyxDQUFBO1FBRUQsTUFBTSxtQkFBbUIsR0FBRyxNQUFLO1lBQ2hDLElBQUksUUFBUSxFQUFFLEVBQUM7Z0JBQ2QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2IsYUFBQTtBQUFJLGlCQUFBO2dCQUNKLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUNsQixhQUFBO0FBQ0YsU0FBQyxDQUFBO1FBRUQsV0FBVyxDQUFDLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsS0FBSTtBQUMvQyxZQUFBLElBQ0MsQ0FBRSxFQUFFLENBQUMsSUFBSSxLQUFLLE9BQU8sSUFBSSxFQUFFLENBQUMsSUFBSSxLQUFLLGFBQWE7QUFDL0MsbUJBQUEsU0FBUyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUM1QjtnQkFDRCxFQUFFLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDcEIsZ0JBQUEsbUJBQW1CLEVBQUUsQ0FBQztBQUN0QixhQUFBO0FBQ0YsU0FBQyxDQUFDLENBQUM7UUFFSCxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEtBQUk7QUFDcEQsWUFBQSxJQUNDLENBQUUsRUFBRSxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksRUFBRSxDQUFDLElBQUksS0FBSyxhQUFhO0FBQy9DLG1CQUFBLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUNuQztnQkFDRCxFQUFFLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDcEIsZ0JBQUEsc0JBQXNCLEVBQUUsQ0FBQztBQUN6QixhQUFBO0FBQ0YsU0FBQyxDQUFDLENBQUM7UUFHSCxTQUFTLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLENBQUMsRUFBRSxLQUFJO0FBQzdDLFlBQUEsSUFDQyxDQUFFLEVBQUUsQ0FBQyxJQUFJLEtBQUssT0FBTyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEtBQUssYUFBYTtBQUMvQyxtQkFBQSxTQUFTLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQzVCO2dCQUNELEVBQUUsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNwQixnQkFBQSxvQkFBb0IsRUFBRSxDQUFDO0FBQ3ZCLGFBQUE7QUFDRixTQUFDLENBQUMsQ0FBQztLQUVIO0FBRUQ7O0FDbE5ELE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztBQUN0QixNQUFNLFdBQVcsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBQ3RDLE1BQU0sV0FBVyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7QUFDdEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE1BQU0sSUFBSSxHQUFLLFdBQVcsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztNQUV6QyxjQUFjLENBQUE7QUFFWixJQUFBLFNBQVMsQ0FBQyxRQUFlLEVBQUE7O1lBQ3RDLE1BQU0sTUFBTSxHQUFPLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDaEQsTUFBTSxHQUFHLEdBQVUsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUMsSUFBSSxFQUFFLFFBQVEsRUFBQyxFQUFFLEtBQUssRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFDeEcsWUFBQSxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FDekM7QUFDQyxnQkFBQSxJQUFJLEVBQUUsUUFBUTtBQUNkLGdCQUFBLElBQUksRUFBRSxFQUFDLElBQUksRUFBRSxTQUFTLEVBQUM7Z0JBQ3ZCLFVBQVU7Z0JBQ1YsSUFBSTtBQUNKLGFBQUEsRUFDRCxHQUFHLEVBQ0g7QUFDQyxnQkFBQSxJQUFJLEVBQUUsU0FBUztBQUNmLGdCQUFBLE1BQU0sRUFBRSxHQUFHO2FBQ1gsRUFDRCxLQUFLLEVBQ0wsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQ3RCLENBQUM7QUFFRixZQUFBLE9BQU8sVUFBVSxDQUFDO1NBQ2xCLENBQUEsQ0FBQTtBQUFBLEtBQUE7SUFFWSxlQUFlLENBQUMsSUFBWSxFQUFFLFFBQWdCLEVBQUE7O1lBRTFELE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzQyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDcEQsWUFBQSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7O1lBR2xFLE1BQU0sY0FBYyxHQUFHLElBQUksVUFBVSxDQUNwQyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUMxQixFQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBQyxFQUM3QixHQUFHLEVBQ0gsa0JBQWtCLENBQ2xCLENBQ0QsQ0FBQztBQUVGLFlBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxVQUFVLENBQUUsTUFBTSxDQUFDLFVBQVUsR0FBRyxjQUFjLENBQUMsVUFBVSxDQUFFLENBQUM7QUFDbkYsWUFBQSxVQUFVLENBQUMsR0FBRyxDQUFFLE1BQU0sRUFBRSxDQUFDLENBQUUsQ0FBQztZQUM1QixVQUFVLENBQUMsR0FBRyxDQUFFLGNBQWMsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFFLENBQUM7O0FBR3BELFlBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBRSxDQUFDO0FBRTlELFlBQUEsT0FBTyxVQUFVLENBQUM7U0FDbEIsQ0FBQSxDQUFBO0FBQUEsS0FBQTtBQUVPLElBQUEsYUFBYSxDQUFDLEdBQVcsRUFBQTtRQUNoQyxJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDaEIsUUFBQSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMvQixTQUFBO0FBQ0QsUUFBQSxPQUFPLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzlCO0lBRVksaUJBQWlCLENBQUMsYUFBcUIsRUFBRSxRQUFnQixFQUFBOztZQUNyRSxJQUFJO2dCQUVILElBQUksYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7O2dCQUc1RCxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBQyxVQUFVLENBQUMsQ0FBQzs7Z0JBR2pELE1BQU0sa0JBQWtCLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFFM0QsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDOztnQkFHM0MsSUFBSSxjQUFjLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FDL0MsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUMsRUFDN0IsR0FBRyxFQUNILGtCQUFrQixDQUNsQixDQUFDOztnQkFHRixJQUFJLGFBQWEsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3ZELGdCQUFBLE9BQU8sYUFBYSxDQUFDO0FBQ3JCLGFBQUE7QUFBQyxZQUFBLE9BQU8sQ0FBQyxFQUFFOztBQUVYLGdCQUFBLE9BQU8sSUFBSSxDQUFDO0FBQ1osYUFBQTtTQUNELENBQUEsQ0FBQTtBQUFBLEtBQUE7QUFFRCxDQUFBO0FBRUQsTUFBTSxpQkFBaUIsR0FBRztBQUN6QixJQUFBLElBQUksRUFBRSxTQUFTO0FBQ2YsSUFBQSxFQUFFLEVBQUUsSUFBSSxVQUFVLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzVFLElBQUEsU0FBUyxFQUFFLEdBQUc7Q0FDZCxDQUFBO01BRVksb0JBQW9CLENBQUE7QUFFbEIsSUFBQSxRQUFRLENBQUMsUUFBZ0IsRUFBQTs7QUFDdEMsWUFBQSxJQUFJLFVBQVUsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ25DLElBQUksYUFBYSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFaEQsWUFBQSxJQUFJLGNBQWMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBRXBGLElBQUksR0FBRyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQ3RDLEtBQUssRUFDTCxjQUFjLEVBQ2QsaUJBQWlCLEVBQ2pCLEtBQUssRUFDTCxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FDdEIsQ0FBQztBQUVGLFlBQUEsT0FBTyxHQUFHLENBQUM7U0FDWCxDQUFBLENBQUE7QUFBQSxLQUFBO0lBRVksZUFBZSxDQUFDLElBQVksRUFBRSxRQUFnQixFQUFBOztZQUMxRCxJQUFJLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFeEMsWUFBQSxJQUFJLFVBQVUsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ25DLElBQUksY0FBYyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7O0FBRzdDLFlBQUEsSUFBSSxjQUFjLEdBQUcsSUFBSSxVQUFVLENBQUMsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FDOUQsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLGNBQWMsQ0FDdEMsQ0FBQyxDQUFDOztBQUdILFlBQUEsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxjQUFjLENBQUMsQ0FBQyxDQUFDO0FBRTlELFlBQUEsT0FBTyxVQUFVLENBQUM7U0FDbEIsQ0FBQSxDQUFBO0FBQUEsS0FBQTtBQUVPLElBQUEsYUFBYSxDQUFDLEdBQVcsRUFBQTtRQUNoQyxJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDaEIsUUFBQSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMvQixTQUFBO0FBQ0QsUUFBQSxPQUFPLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzlCO0lBRVksaUJBQWlCLENBQUMsYUFBcUIsRUFBRSxRQUFnQixFQUFBOztZQUNyRSxJQUFJOztnQkFFSCxJQUFJLGNBQWMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO2dCQUU3RCxJQUFJLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7O0FBR3hDLGdCQUFBLElBQUksY0FBYyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLGNBQWMsQ0FBQyxDQUFDOztBQUd6RixnQkFBQSxJQUFJLFVBQVUsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNuQyxJQUFJLGFBQWEsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3RELGdCQUFBLE9BQU8sYUFBYSxDQUFDO0FBQ3JCLGFBQUE7QUFBQyxZQUFBLE9BQU8sQ0FBQyxFQUFFO0FBQ1gsZ0JBQUEsT0FBTyxJQUFJLENBQUM7QUFDWixhQUFBO1NBQ0QsQ0FBQSxDQUFBO0FBQUEsS0FBQTtBQUVEOztBQ2pLb0IsTUFBQSxzQkFBdUIsU0FBUUMseUJBQWdCLENBQUE7SUFLbkUsV0FBWSxDQUFBLEdBQVEsRUFBRSxNQUFtQixFQUFBO0FBQ3hDLFFBQUEsS0FBSyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUNuQixRQUFBLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0tBQ3JCO0lBRUQsT0FBTyxHQUFBO0FBQ04sUUFBQSxJQUFJLEVBQUUsV0FBVyxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBRTNCLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVwQixXQUFXLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFDLElBQUksRUFBRSwyQkFBMkIsRUFBQyxDQUFDLENBQUM7UUFHaEUsSUFBSUMsZ0JBQU8sQ0FBQyxXQUFXLENBQUM7YUFDdEIsT0FBTyxDQUFDLGlDQUFpQyxDQUFDO2FBQzFDLE9BQU8sQ0FBQyx5REFBeUQsQ0FBQzthQUNsRSxTQUFTLENBQUUsTUFBTSxJQUFHO1lBQ3BCLE1BQU07aUJBQ0osUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDO0FBQ2pELGlCQUFBLFFBQVEsQ0FBRSxDQUFNLEtBQUssS0FBRyxTQUFBLENBQUEsSUFBQSxFQUFBLEtBQUEsQ0FBQSxFQUFBLEtBQUEsQ0FBQSxFQUFBLGFBQUE7Z0JBQ3hCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLGtCQUFrQixHQUFHLEtBQUssQ0FBQztBQUNoRCxnQkFBQSxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7O2FBRWpDLENBQUEsQ0FBQyxDQUFBO0FBQ0osU0FBQyxDQUFDLENBQ0Y7UUFFRCxJQUFJQSxnQkFBTyxDQUFDLFdBQVcsQ0FBQzthQUN0QixPQUFPLENBQUMsbUJBQW1CLENBQUM7YUFDNUIsT0FBTyxDQUFDLG1DQUFtQyxDQUFDO2FBQzVDLFNBQVMsQ0FBRSxNQUFNLElBQUc7WUFDcEIsTUFBTTtpQkFDSixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDO0FBQzlDLGlCQUFBLFFBQVEsQ0FBRSxDQUFNLEtBQUssS0FBRyxTQUFBLENBQUEsSUFBQSxFQUFBLEtBQUEsQ0FBQSxFQUFBLEtBQUEsQ0FBQSxFQUFBLGFBQUE7Z0JBQ3hCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUM7QUFDN0MsZ0JBQUEsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNqQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQzthQUN4QixDQUFBLENBQUMsQ0FBQTtBQUNKLFNBQUMsQ0FBQyxDQUNGO1FBRUQsSUFBSUEsZ0JBQU8sQ0FBQyxXQUFXLENBQUM7YUFDdEIsT0FBTyxDQUFDLGNBQWMsQ0FBQzthQUN2QixPQUFPLENBQUMsdUNBQXVDLENBQUM7YUFDaEQsU0FBUyxDQUFFLE1BQU0sSUFBRztZQUNwQixNQUFNO2lCQUNKLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7QUFDekMsaUJBQUEsUUFBUSxDQUFFLENBQU0sS0FBSyxLQUFHLFNBQUEsQ0FBQSxJQUFBLEVBQUEsS0FBQSxDQUFBLEVBQUEsS0FBQSxDQUFBLEVBQUEsYUFBQTtnQkFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztBQUN4QyxnQkFBQSxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2FBQ3hCLENBQUEsQ0FBQyxDQUFBO0FBQ0osU0FBQyxDQUFDLENBQ0Y7UUFFRCxJQUFJQSxnQkFBTyxDQUFDLFdBQVcsQ0FBQzthQUN0QixPQUFPLENBQUMsb0JBQW9CLENBQUM7YUFDN0IsT0FBTyxDQUFDLG1EQUFtRCxDQUFDO2FBQzVELFNBQVMsQ0FBRSxNQUFNLElBQUc7WUFDcEIsTUFBTTtpQkFDSixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUM7QUFDL0MsaUJBQUEsUUFBUSxDQUFFLENBQU0sS0FBSyxLQUFHLFNBQUEsQ0FBQSxJQUFBLEVBQUEsS0FBQSxDQUFBLEVBQUEsS0FBQSxDQUFBLEVBQUEsYUFBQTtnQkFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0FBQzlDLGdCQUFBLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDakMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7YUFDeEIsQ0FBQSxDQUFDLENBQUE7QUFDSixTQUFDLENBQUMsQ0FDRjtBQUVELFFBQUEsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUlBLGdCQUFPLENBQUMsV0FBVyxDQUFDO0FBQzlDLGFBQUEsT0FBTyxDQUFFLElBQUksQ0FBQywrQkFBK0IsRUFBRSxDQUFFO2FBQ2pELE9BQU8sQ0FBQywyREFBMkQsQ0FBQzthQUNwRSxTQUFTLENBQUUsTUFBTSxJQUFHO1lBQ3BCLE1BQU07QUFDSixpQkFBQSxTQUFTLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7aUJBQ3BCLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQztBQUN0RCxpQkFBQSxRQUFRLENBQUUsQ0FBTSxLQUFLLEtBQUcsU0FBQSxDQUFBLElBQUEsRUFBQSxLQUFBLENBQUEsRUFBQSxLQUFBLENBQUEsRUFBQSxhQUFBO2dCQUN4QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsR0FBRyxLQUFLLENBQUM7QUFDckQsZ0JBQUEsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNqQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQzthQUN4QixDQUFBLENBQUMsQ0FDRjtBQUVGLFNBQUMsQ0FBQyxDQUNGO1FBRUQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7S0FDeEI7SUFFRCxnQkFBZ0IsR0FBQTtRQUNmLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLCtCQUErQixFQUFFLENBQUMsQ0FBQztBQUd0RSxRQUFBLElBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7QUFDM0MsWUFBQSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ3ZDLFNBQUE7QUFBSSxhQUFBO0FBQ0osWUFBQSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ3ZDLFNBQUE7S0FDRDtJQUVELCtCQUErQixHQUFBO1FBQzlCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLHVCQUF1QixDQUFDO0FBQzNELFFBQUEsSUFBSSxhQUFhLEdBQUcsQ0FBRyxFQUFBLEtBQUssVUFBVSxDQUFDO1FBQ3ZDLElBQUcsS0FBSyxJQUFJLENBQUMsRUFBQztZQUNiLGFBQWEsR0FBRyxjQUFjLENBQUM7QUFDL0IsU0FBQTtRQUNELE9BQU8sQ0FBQSwyQkFBQSxFQUE4QixhQUFhLENBQUEsQ0FBQSxDQUFHLENBQUM7S0FDdEQ7QUFDRDs7QUM5R0QsTUFBTSxPQUFPLEdBQVcsTUFBTSxDQUFDO0FBQy9CLE1BQU0sZ0JBQWdCLEdBQVcsT0FBTyxHQUFHLEdBQUcsQ0FBQztBQUMvQyxNQUFNLFNBQVMsR0FBVyxPQUFPLEdBQUcsSUFBSSxDQUFDO0FBQ3pDLE1BQU0sT0FBTyxHQUFXLE9BQU8sQ0FBQztBQUVoQyxNQUFNLEtBQUssR0FBVyxJQUFJLENBQUM7QUFVM0IsTUFBTSxnQkFBZ0IsR0FBOEI7QUFDbkQsSUFBQSxrQkFBa0IsRUFBRSxJQUFJO0FBQ3hCLElBQUEsZUFBZSxFQUFFLElBQUk7QUFDckIsSUFBQSxVQUFVLEVBQUUsS0FBSztBQUNqQixJQUFBLGdCQUFnQixFQUFFLElBQUk7QUFDdEIsSUFBQSx1QkFBdUIsRUFBRSxFQUFFO0NBQzNCLENBQUE7QUFFb0IsTUFBQSxXQUFZLFNBQVFDLGVBQU0sQ0FBQTtJQU14QyxNQUFNLEdBQUE7O0FBRVgsWUFBQSxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztBQUUxQixZQUFBLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7WUFFL0QsSUFBSSxDQUFDLFVBQVUsQ0FBQztBQUNmLGdCQUFBLEVBQUUsRUFBRSxjQUFjO0FBQ2xCLGdCQUFBLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLG1CQUFtQixFQUFFLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEtBQUssSUFBSSxDQUFDLDRCQUE0QixDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQztBQUNqSCxhQUFBLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxVQUFVLENBQUM7QUFDZixnQkFBQSxFQUFFLEVBQUUsdUJBQXVCO0FBQzNCLGdCQUFBLElBQUksRUFBRSwwQkFBMEI7Z0JBQ2hDLG1CQUFtQixFQUFFLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEtBQUssSUFBSSxDQUFDLDRCQUE0QixDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQztBQUNoSCxhQUFBLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxVQUFVLENBQUM7QUFDZixnQkFBQSxFQUFFLEVBQUUsbUJBQW1CO0FBQ3ZCLGdCQUFBLElBQUksRUFBRSw0QkFBNEI7QUFDbEMsZ0JBQUEsbUJBQW1CLEVBQUUsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksS0FBSyxJQUFJLENBQUMscUNBQXFDLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUM7QUFDbkgsYUFBQSxDQUFDLENBQUM7U0FFSCxDQUFBLENBQUE7QUFBQSxLQUFBO0lBRUssWUFBWSxHQUFBOztBQUNqQixZQUFBLElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztTQUMzRSxDQUFBLENBQUE7QUFBQSxLQUFBO0lBRUssWUFBWSxHQUFBOztZQUNqQixNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ25DLENBQUEsQ0FBQTtBQUFBLEtBQUE7SUFFRCxtQkFBbUIsR0FBQTtRQUNsQixPQUFPLFFBQVEsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLEtBQUssSUFBSSxDQUFDO0tBQ3hEO0FBRUQsSUFBQSxxQ0FBcUMsQ0FBQyxRQUFpQixFQUFFLE1BQWMsRUFBRSxJQUFrQixFQUFBO0FBRTFGLFFBQUEsSUFBSyxRQUFRLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLEVBQUU7OztBQUc1QyxZQUFBLE9BQU8sSUFBSSxDQUFDO0FBQ1osU0FBQTtRQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkMsTUFBTSxNQUFNLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBRXpGLFFBQUEsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7QUFFL0QsUUFBQSxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FDM0IsUUFBUSxFQUNSLE1BQU0sRUFDTixhQUFhLEVBQ2IsUUFBUSxFQUNSLE1BQU0sRUFDTixJQUFJLENBQ0osQ0FBQztLQUNGO0FBRUQsSUFBQSw0QkFBNEIsQ0FBQyxRQUFpQixFQUFFLE1BQWMsRUFBRSxJQUFrQixFQUFFLGNBQXVCLEVBQUE7QUFDMUcsUUFBQSxJQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsRUFBRTs7O0FBRzVDLFlBQUEsT0FBTyxJQUFJLENBQUM7QUFDWixTQUFBO1FBRUQsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBRXBDLFFBQUEsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixFQUFDO0FBQ3BDLFlBQUEsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQztBQUNoQyxZQUFBLFFBQVEsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO0FBRXRDLFlBQUEsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztZQUM1QixNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzVDLFlBQUEsTUFBTSxHQUFHLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQ25ELFNBQUE7QUFBSSxhQUFBO0FBQ0osWUFBQSxJQUFLLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLEVBQUU7O2dCQUVqQyxRQUFRLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFFLENBQUM7Z0JBQ3hFLE1BQU0sR0FBRyxJQUFJLENBQUMsMkJBQTJCLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUUsQ0FBQztBQUNwRSxhQUFBO0FBQ0QsU0FBQTtRQUVELE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBRXhELFFBQUEsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQzNCLFFBQVEsRUFDUixNQUFNLEVBQ04sYUFBYSxFQUNiLFFBQVEsRUFDUixNQUFNLEVBQ04sY0FBYyxDQUNkLENBQUM7S0FDRjtBQUVPLElBQUEsMkJBQTJCLENBQUMsTUFBYyxFQUFFLElBQVksRUFBRSxZQUEyQixFQUFBO0FBQzVGLFFBQUEsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBRSxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFFLENBQUM7UUFFbEUsS0FBSyxJQUFJLE1BQU0sR0FBRyxVQUFVLEVBQUUsTUFBTSxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNwRCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzdDLFlBQUEsTUFBTSxhQUFhLEdBQUcsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDM0MsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUV2RCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFFLFNBQVMsRUFBRSxZQUFZLENBQUUsQ0FBQztZQUM1RCxJQUFJLFFBQVEsSUFBSSxJQUFJLEVBQUM7QUFDcEIsZ0JBQUEsT0FBTyxTQUFTLENBQUM7QUFDakIsYUFBQTtBQUNELFNBQUE7QUFFRCxRQUFBLE9BQU8sWUFBWSxDQUFDO0tBQ3BCO0FBRU8sSUFBQSwyQkFBMkIsQ0FBQyxNQUFjLEVBQUUsSUFBWSxFQUFFLFlBQTJCLEVBQUE7QUFDNUYsUUFBQSxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUUsQ0FBQztBQUNsRSxRQUFBLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUV0QyxJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFFLEVBQUMsSUFBSSxFQUFDLFdBQVcsRUFBRSxFQUFFLEVBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxNQUFNLEVBQUMsQ0FBRSxDQUFDO0FBRWhHLFFBQUEsS0FBSyxJQUFJLE1BQU0sR0FBRyxVQUFVLEVBQUUsTUFBTSxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzFFLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDN0MsWUFBQSxNQUFNLGFBQWEsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztZQUMzQyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRXZELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUUsU0FBUyxFQUFFLFlBQVksQ0FBRSxDQUFDO1lBRTVELElBQUksUUFBUSxJQUFJLElBQUksRUFBQztBQUNwQixnQkFBQSxPQUFPLFlBQVksQ0FBQztBQUNwQixhQUFBO0FBQ0QsU0FBQTtBQUVELFFBQUEsT0FBTyxZQUFZLENBQUM7S0FDcEI7QUFFTyxJQUFBLGdCQUFnQixDQUFFLGFBQXFCLEVBQUE7QUFFOUMsUUFBQSxNQUFNLE1BQU0sR0FBRyxJQUFJLGlCQUFpQixFQUFFLENBQUM7UUFFdkMsTUFBTSxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztRQUU1QyxNQUFNLENBQUMsMEJBQTBCLEdBQUcsYUFBYSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBQy9FLFFBQUEsTUFBTSxDQUFDLGtCQUFrQixHQUFHLE1BQU0sQ0FBQywwQkFBMEIsSUFBSSxhQUFhLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRXJHLE1BQU0sQ0FBQyxnQkFBZ0IsR0FBRyxhQUFhLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBRTFELFFBQUEsTUFBTSxDQUFDLHdCQUF3QjtBQUM5QixZQUFBLGFBQWEsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUM7QUFDckMsbUJBQUEsYUFBYSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7QUFDakMsbUJBQUEsYUFBYSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FDbEM7UUFFRCxNQUFNLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsSUFBSSxNQUFNLENBQUMsZ0JBQWdCLENBQUM7QUFDekUsUUFBQSxNQUFNLENBQUMsVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLGtCQUFrQixJQUFJLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDO1FBRW5GLElBQUksTUFBTSxDQUFDLFVBQVUsRUFBQztZQUNyQixNQUFNLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUNqRSxZQUFBLElBQUksTUFBTSxDQUFDLFdBQVcsSUFBSSxJQUFJLEVBQUM7QUFDOUIsZ0JBQUEsTUFBTSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7QUFDMUIsYUFBQTtBQUNELFNBQUE7QUFFRCxRQUFBLE9BQU8sTUFBTSxDQUFDO0tBQ2Q7SUFFTyxnQkFBZ0IsQ0FDdkIsUUFBaUIsRUFDakIsTUFBYyxFQUNkLGFBQXFCLEVBQ3JCLG1CQUF3QyxFQUN4QyxpQkFBc0MsRUFDdEMsY0FBdUIsRUFBQTs7UUFHdkIsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFL0QsSUFBSSxpQkFBaUIsQ0FBQyxPQUFPLEVBQUU7WUFDOUIsSUFBSSxDQUFDLFFBQVEsRUFBQztBQUNiLGdCQUFBLElBQUlDLGVBQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0FBQ2xDLGFBQUE7QUFDRCxZQUFBLE9BQU8sS0FBSyxDQUFDO0FBQ2IsU0FBQTtRQUVELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLEVBQUU7WUFDbkUsSUFBSSxDQUFDLFFBQVEsRUFBQztBQUNiLGdCQUFBLElBQUlBLGVBQU0sQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO0FBQ2pELGFBQUE7QUFDRCxZQUFBLE9BQU8sS0FBSyxDQUFDO0FBQ2IsU0FBQTtBQUVELFFBQUEsSUFBSSxRQUFRLEVBQUU7QUFDYixZQUFBLE9BQU8sSUFBSSxDQUFDO0FBQ1osU0FBQTs7O0FBS0QsUUFBQSxNQUFNLHlCQUF5QixHQUM5QixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCO0FBQzVCLGdCQUNGLElBQUksQ0FBQyxzQkFBc0IsSUFBSSxJQUFJO21CQUNoQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUMzQyxDQUNEO1FBRUQsTUFBTSxlQUFlLEdBQUcsaUJBQWlCLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDO1FBRXRGLElBQUsseUJBQXlCLElBQUksZUFBZSxFQUFHOztBQUVuRCxZQUFBLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7QUFDM0IsU0FBQTtRQUVELE1BQU0sT0FBTyxHQUFHLElBQUksYUFBYSxDQUNoQyxJQUFJLENBQUMsR0FBRyxFQUNSLGlCQUFpQixDQUFDLFVBQVUsRUFDNUIsZUFBZSxFQUNmLElBQUksQ0FBQyxnQkFBZ0IsRUFDckIsQ0FBQSxFQUFBLEdBQUEsaUJBQWlCLENBQUMsV0FBVyxNQUFBLElBQUEsSUFBQSxFQUFBLEtBQUEsS0FBQSxDQUFBLEdBQUEsS0FBQSxDQUFBLEdBQUEsRUFBQSxDQUFFLElBQUksQ0FDbkMsQ0FBQztBQUNGLFFBQUEsT0FBTyxDQUFDLE9BQU8sR0FBRyxNQUFLOztZQUN0QixNQUFNLEVBQUUsR0FBRyxDQUFBLEVBQUEsR0FBQSxPQUFPLENBQUMsUUFBUSxNQUFBLElBQUEsSUFBQSxFQUFBLEtBQUEsS0FBQSxDQUFBLEdBQUEsRUFBQSxHQUFJLEVBQUUsQ0FBQTtBQUNqQyxZQUFBLElBQUksRUFBRSxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUU7Z0JBQ25CLE9BQU87QUFDUCxhQUFBO0FBQ0QsWUFBQSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDOztBQUcxQixZQUFBLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRTtBQUNuQyxnQkFBQSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0FBQzNCLGdCQUFBLElBQUksQ0FBQyxzQkFBc0I7QUFDMUIsb0JBQUEsSUFBSSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsSUFBSSxDQUFDO0FBQ3pDLDBCQUFFLElBQUk7QUFDTiwwQkFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLEdBQUcsRUFBRTtBQUNoRSxpQkFBQTtBQUNGLGFBQUE7WUFFRCxJQUFJLGlCQUFpQixDQUFDLFVBQVUsRUFBRTtBQUNqQyxnQkFBQSxNQUFNLFdBQVcsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBQ3RDLGdCQUFBLFdBQVcsQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDO0FBQ2pDLGdCQUFBLFdBQVcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBRXhCLGdCQUFBLElBQUksQ0FBQyxnQkFBZ0IsQ0FDcEIsTUFBTSxFQUNOLFdBQVcsRUFDWCxFQUFFLEVBQ0YsbUJBQW1CLEVBQ25CLGlCQUFpQixDQUNqQixDQUFDO0FBQ0YsYUFBQTtBQUFNLGlCQUFBO0FBRU4sZ0JBQUEsSUFBSSxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsT0FBTyxJQUFJLENBQUMsRUFBQztBQUM5QyxvQkFBQSxJQUFJLENBQUMsa0JBQWtCLENBQ3RCLE1BQU0sRUFDTixpQkFBaUIsQ0FBQyxXQUFXLEVBQzdCLEVBQUUsRUFDRixtQkFBbUIsRUFDbkIsaUJBQWlCLEVBQ2pCLGNBQWMsQ0FDZCxDQUFDO0FBQ0YsaUJBQUE7QUFBSSxxQkFBQTtBQUNKLG9CQUFBLElBQUksQ0FBQyx3QkFBd0IsQ0FDNUIsTUFBTSxFQUNOLGlCQUFpQixDQUFDLFdBQVcsRUFDN0IsRUFBRSxFQUNGLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsY0FBYyxDQUNkLENBQUM7QUFDRixpQkFBQTtBQUNELGFBQUE7QUFDRixTQUFDLENBQUE7UUFDRCxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7QUFFZixRQUFBLE9BQU8sSUFBSSxDQUFDO0tBQ1o7SUFFYSxnQkFBZ0IsQ0FDN0IsTUFBYyxFQUNkLFdBQXdCLEVBQ3hCLFFBQWdCLEVBQ2hCLG1CQUF3QyxFQUN4QyxpQkFBc0MsRUFBQTs7O0FBR3RDLFlBQUEsTUFBTSxNQUFNLEdBQUcsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNwQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQ3hDLE1BQU0sTUFBTSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxFQUN4RCxXQUFXLENBQUMsSUFBSSxDQUNoQixDQUFDO0FBQ0YsWUFBQSxNQUFNLENBQUMsWUFBWSxDQUFDLG1CQUFtQixFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFDNUQsWUFBQSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDckMsQ0FBQSxDQUFBO0FBQUEsS0FBQTtJQUVhLGtCQUFrQixDQUMvQixNQUFjLEVBQ2QsV0FBd0IsRUFDeEIsUUFBZ0IsRUFDaEIsY0FBbUMsRUFDbkMsWUFBaUMsRUFDakMsY0FBdUIsRUFBQTs7O0FBSXZCLFlBQUEsTUFBTSxNQUFNLEdBQUcsSUFBSSxjQUFjLEVBQUUsQ0FBQztBQUNwQyxZQUFBLE1BQU0sYUFBYSxHQUFHLE1BQU0sTUFBTSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM3RixJQUFJLGFBQWEsS0FBSyxJQUFJLEVBQUU7QUFDM0IsZ0JBQUEsSUFBSUEsZUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUM7QUFDbkMsYUFBQTtBQUFNLGlCQUFBO0FBRU4sZ0JBQUEsSUFBSSxjQUFjLEVBQUU7QUFDbkIsb0JBQUEsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDbEQsb0JBQUEsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBQ3ZDLGlCQUFBO0FBQU0scUJBQUE7QUFDTixvQkFBQSxNQUFNLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUMvRixvQkFBQSxZQUFZLENBQUMsT0FBTyxHQUFHLE1BQUs7d0JBQzNCLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQzt3QkFDZixJQUFJLFlBQVksQ0FBQyxjQUFjLEVBQUU7QUFDaEMsNEJBQUEsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDbEQsNEJBQUEsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBQ3ZDLHlCQUFBO0FBQ0YscUJBQUMsQ0FBQTtvQkFDRCxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDcEIsaUJBQUE7QUFDRCxhQUFBO1NBQ0QsQ0FBQSxDQUFBO0FBQUEsS0FBQTtJQUVhLHdCQUF3QixDQUNyQyxNQUFjLEVBQ2QsV0FBd0IsRUFDeEIsUUFBZ0IsRUFDaEIsY0FBbUMsRUFDbkMsWUFBaUMsRUFDakMsY0FBdUIsRUFBQTs7O1lBR3ZCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUMxRSxZQUFBLE1BQU0sTUFBTSxHQUFHLElBQUksb0JBQW9CLEVBQUUsQ0FBQztZQUMxQyxNQUFNLGFBQWEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNqRixJQUFJLGFBQWEsS0FBSyxJQUFJLEVBQUU7QUFDM0IsZ0JBQUEsSUFBSUEsZUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUM7QUFDbkMsYUFBQTtBQUFNLGlCQUFBO0FBRU4sZ0JBQUEsSUFBSSxjQUFjLEVBQUU7QUFDbkIsb0JBQUEsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDbEQsb0JBQUEsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBQ3ZDLGlCQUFBO0FBQU0scUJBQUE7QUFDTixvQkFBQSxNQUFNLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUMvRixvQkFBQSxZQUFZLENBQUMsT0FBTyxHQUFHLE1BQUs7d0JBQzNCLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQzt3QkFDZixJQUFJLFlBQVksQ0FBQyxjQUFjLEVBQUU7QUFDaEMsNEJBQUEsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDbEQsNEJBQUEsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBQ3ZDLHlCQUFBO0FBQ0YscUJBQUMsQ0FBQTtvQkFDRCxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDcEIsaUJBQUE7QUFDRCxhQUFBO1NBQ0QsQ0FBQSxDQUFBO0FBQUEsS0FBQTtBQUVPLElBQUEsdUJBQXVCLENBQUMsSUFBWSxFQUFBO0FBQzNDLFFBQUEsTUFBTSxNQUFNLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUVqQyxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUM7QUFDbkIsUUFBQSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtBQUMvRCxZQUFBLE1BQU0sQ0FBQyxPQUFPLEdBQUMsQ0FBQyxDQUFDO0FBQ2pCLFlBQUEsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDOUQsU0FBQTtBQUFLLGFBQUEsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtBQUM1RSxZQUFBLE1BQU0sQ0FBQyxPQUFPLEdBQUMsQ0FBQyxDQUFDO0FBQ2pCLFlBQUEsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNyRSxTQUFBO0FBQUssYUFBQTtZQUNMLE9BQU8sSUFBSSxDQUFDO0FBQ1osU0FBQTs7O0FBSUQsUUFBQSxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLEVBQUM7QUFDM0MsWUFBQSxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDMUQsSUFBSSxhQUFhLEdBQUMsQ0FBQyxFQUFDO2dCQUNuQixPQUFPLElBQUksQ0FBQztBQUNaLGFBQUE7QUFDRCxZQUFBLE1BQU0sQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFDLGFBQWEsQ0FBQyxDQUFBO0FBQzNELFlBQUEsTUFBTSxDQUFDLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsYUFBYSxHQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN4RSxTQUFBO0FBQUksYUFBQTtBQUNKLFlBQUEsTUFBTSxDQUFDLGdCQUFnQixHQUFHLE9BQU8sQ0FBQztBQUNsQyxTQUFBOztBQUlELFFBQUEsT0FBTyxNQUFNLENBQUM7S0FFZDtBQUVPLElBQUEsYUFBYSxDQUFDLElBQVksRUFBQTtBQUNqQyxRQUFBLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0FBQ3pELFlBQUEsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3hELFNBQUE7QUFDRCxRQUFBLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUU7QUFDaEUsWUFBQSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztBQUMvRCxTQUFBO0FBQ0QsUUFBQSxPQUFPLElBQUksQ0FBQztLQUNaO0lBRU8sZ0JBQWdCLENBQUUsYUFBcUIsRUFBRSxJQUFZLEVBQUE7UUFDNUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0FBQ3hILFlBQUEsSUFBSSxJQUFJLEVBQUM7QUFDUixnQkFBQSxPQUFPLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQ3BFLGFBQUE7WUFDRCxPQUFPLFNBQVMsQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQ2hELFNBQUE7QUFDRCxRQUFBLE9BQU8sYUFBYSxDQUFDO0tBQ3JCO0FBRUQsQ0FBQTtBQUVELE1BQU0saUJBQWlCLENBQUE7QUFTdEIsQ0FBQTtBQUVELE1BQU0sV0FBVyxDQUFBO0FBR2hCLENBQUE7QUFFRCxNQUFNLFdBQVcsQ0FBQTtBQUloQjs7OzsifQ== diff --git a/.obsidian/plugins/meld-encrypt/manifest.json b/.obsidian/plugins/meld-encrypt/manifest.json new file mode 100644 index 0000000..ee1a6db --- /dev/null +++ b/.obsidian/plugins/meld-encrypt/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "meld-encrypt", + "name": "Meld Encrypt", + "version": "1.6.2", + "minAppVersion": "0.12.15", + "description": "Hide secrets in your notes", + "author": "meld-cp", + "authorUrl": "https://github.com/meld-cp/obsidian-encrypt", + "isDesktopOnly": false +} diff --git a/.obsidian/plugins/meld-encrypt/styles.css b/.obsidian/plugins/meld-encrypt/styles.css new file mode 100644 index 0000000..5273f02 --- /dev/null +++ b/.obsidian/plugins/meld-encrypt/styles.css @@ -0,0 +1,42 @@ +.meld-e-row{ + display: flex; + margin-bottom: 1em; +} + +.meld-e-icon{ + flex: 1; + display: inline-block; + margin-right: 1em; +} + +.meld-e-row input{ + flex: 20; +} + +.meld-e-platform-desktop .meld-e-button-confirm { + margin-left: 2.8em; + padding: 1em 2em; +} +.meld-e-platform-desktop .meld-e-button-confirm:focus{ + font-weight: bold; +} + +.meld-e-message{ + margin-left: 2.8em; + margin-bottom: 1em; +} + +.meld-e-button-next{ + margin-left: 1em; + flex: 3; +} + +.meld-e-platform-mobile .meld-e-button-next{ + display: inline-block; + margin: 0 0 0 1em; + width: auto; +} + +.meld-e-hint{ + flex: 20; +} \ No newline at end of file diff --git a/.obsidian/workspace b/.obsidian/workspace index 7411495..1ee0e95 100644 --- a/.obsidian/workspace +++ b/.obsidian/workspace @@ -4,12 +4,14 @@ "type": "split", "children": [ { - "id": "6b97c5c8667e492b", + "id": "0d2c7508a23f0a87", "type": "leaf", "state": { - "type": "image", + "type": "markdown", "state": { - "file": "attachment/Steinemann Technology/mails/spammails/fakeinvite.png" + "file": "2022-06-27.md", + "mode": "source", + "source": false } } } @@ -65,6 +67,20 @@ "id": "a54ca124d2689b37", "type": "split", "children": [ + { + "id": "36d1b5112e960052", + "type": "tabs", + "children": [ + { + "id": "39650d5b939ff18b", + "type": "leaf", + "state": { + "type": "calendar", + "state": {} + } + } + ] + }, { "id": "156a5a111c133560", "type": "tabs", @@ -75,7 +91,7 @@ "state": { "type": "backlink", "state": { - "file": "attachment/Steinemann Technology/mails/spammails/fakeinvite.png", + "file": "2022-06-27.md", "collapseAll": false, "extraContext": false, "sortOrder": "alphabetical", @@ -103,7 +119,7 @@ "state": { "type": "outgoing-link", "state": { - "file": "attachment/Steinemann Technology/mails/spammails/fakeinvite.png", + "file": "2022-06-27.md", "linksCollapsed": false, "unlinkedCollapsed": false } @@ -115,28 +131,28 @@ "state": { "type": "outline", "state": { - "file": "attachment/Steinemann Technology/mails/spammails/fakeinvite.png" + "file": "2022-06-27.md" } } } ], - "currentTab": 2 + "currentTab": 3 } ], "direction": "horizontal", "width": 300 }, - "active": "6b97c5c8667e492b", + "active": "0d2c7508a23f0a87", "lastOpenFiles": [ + "2022-06-27.md", + "steinemann technology/Ky2Help.md", "attachment/Steinemann Technology/mails/spammails/fakeinvite.png", "attachment/Steinemann Technology/mails/spammails/fake.png", "Firmen/steinemann technology/infomails/Achtung Phish!.md", - "steinemann technology/Ky2Help.md", "attachment/Steinemann Technology/penta/error23.jpg", "attachment/Steinemann Technology/keeper/sso.jpg", "attachment/Steinemann Technology/monitre.jpg", "attachment/Steinemann Technology/keeper/keeper_konto.jpg", - "attachment/Steinemann Technology/penta/läuft.jpg", - "attachment/attachment.md" + "attachment/Steinemann Technology/penta/läuft.jpg" ] } \ No newline at end of file