├── .DS_Store ├── .gitignore ├── FinderMirror.jpg ├── ObsidianMirror.gif ├── README.md ├── data.json ├── main.js ├── main.ts ├── manifest.json ├── package-lock.json ├── package.json ├── rollup.config.js ├── styles.css ├── tsconfig.json └── versions.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildspecial/obsidian-mirror/c32614d4b893578bb4bfd7ca05326f7c649c904e/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | *.iml 3 | .idea 4 | 5 | # npm 6 | node_modules 7 | package-lock.json 8 | 9 | # build 10 | main.js 11 | *.js.map 12 | 13 | # obsidian 14 | data.json 15 | -------------------------------------------------------------------------------- /FinderMirror.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildspecial/obsidian-mirror/c32614d4b893578bb4bfd7ca05326f7c649c904e/FinderMirror.jpg -------------------------------------------------------------------------------- /ObsidianMirror.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildspecial/obsidian-mirror/c32614d4b893578bb4bfd7ca05326f7c649c904e/ObsidianMirror.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Obsidian Mirror Plugin 2 | 3 | Here we are, you have multiple monitors (sometimes I have up to 6 monitors) and you want to be 200% productive with Obsidian. 4 | 5 | On one monitor you have a file opened and on another monitor you want to have a **full screen** `local graph` that helps you to connect the dots (in your mind) 6 | 7 | Why? simply because the local graph in the same Obsidian instance is too small! 8 | 9 | I was desperate and fortunately I found a workaround to run multiple instances of Obsidian in the forum using *symlink* [here](https://forum.obsidian.md/t/floating-pop-out-multiple-windows-of-the-same-vault/837/58) 10 | NB: *symlink* to create virtual links. 11 | 12 | After successfully created symlinks `ln -s` you should be able to have a "mirror" Vault which will contain the symlink of the main Vault you want to use. 13 | 14 | Here is an example: 15 | 16 | ![FinderMirror](FinderMirror.jpg) 17 | 18 | Unfortunatelly this solution partially works cause when I switch context from the main Obsidian's instance, there is no way to propagate this to a second obsidian's instance. 19 | 20 | So I created (in several hours) this plugin that syncs the active file among different Obsidian's instances. 21 | 22 | Here's a quick gif that shows how it works (right side the main Obsidian'instance, left side the secondary *mirror* obsidian's instance) 23 | 24 | ![Gif](ObsidianMirror.gif) 25 | 26 | This plugin is far from being perfect. I rely on the community to enhance it and make it more rubust. 27 | 28 | In the meantime, if you are not a developer, you can FINALLY use the precious **local graph** on a different monitor. 29 | 30 | 31 | ## Installation Info 32 | 33 | This plugin is not (yet) available in the official plugin lists. I created a pull request and waiting for a confirmation. 34 | 35 | ### Manual 36 | 1) Download/clone this repo 37 | 2) Copy the folder `obsidian-mirror` to the `plugin` folder of the main Obsidian's instance 38 | 3) Copy the same folder `obsidian-mirror` to the `plugin` folder of the second Obsidian's instance 39 | 4) Activate the plugin in both obsidian's instances 40 | 5) Go to the settings of both Obsidian's instances 41 | 6) Make sure you configure exactly the same info in both instances 42 | 7) Put the **main** vault's name (Voult's name of the main Obsidian's instance) 43 | 8) Chose a name for the file that the plugin will use to sync the workspaces 44 | 45 | 46 | ### Official 47 | *pending approval* 48 | 49 | 50 | ## Additional Info 51 | The fastes way that came in my mind in order to sync the opened file among different instances was to use a *temporary* file in the main Vault. 52 | 53 | The main instance of Obsidina will write the active file path in the temporary file and the secondary instance will read that content and open the active file. 54 | 55 | No timer/setinterval mechanisms are used. Everything is *event based*. Obsidian writes/reads the file content only when it changes. 56 | 57 | 58 | Enjoy! -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "isMirror": false, 3 | "vault": "TechKnowledge", 4 | "fileName": "ObsidianMirror.md", 5 | "fileNameGraph": "ObsidianMirror._graph.md" 6 | } -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* 2 | THIS IS A GENERATED/BUNDLED FILE BY ROLLUP 3 | if you want to view the source visit the plugins github repository 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var obsidian = require('obsidian'); 9 | 10 | /*! ***************************************************************************** 11 | Copyright (c) Microsoft Corporation. 12 | 13 | Permission to use, copy, modify, and/or distribute this software for any 14 | purpose with or without fee is hereby granted. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | PERFORMANCE OF THIS SOFTWARE. 23 | ***************************************************************************** */ 24 | 25 | function __awaiter(thisArg, _arguments, P, generator) { 26 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 27 | return new (P || (P = Promise))(function (resolve, reject) { 28 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 29 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 30 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 31 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 32 | }); 33 | } 34 | 35 | const DEFAULT_SETTINGS = { 36 | isMirror: false, 37 | vault: "", 38 | fileName: "ObsidianMirror.md", 39 | fileNameGraph: "ObsidianMirror_graph.md" 40 | }; 41 | class ObidianMirrorPlugin extends obsidian.Plugin { 42 | constructor() { 43 | super(...arguments); 44 | this.openedByThisPlugin = false; 45 | this.wroteByThisPlugin = false; 46 | this.activeFile = this.app.workspace.getActiveFile(); 47 | } 48 | onload() { 49 | return __awaiter(this, void 0, void 0, function* () { 50 | console.log('loading plugin'); 51 | yield this.loadSettings(); 52 | this.addRibbonIcon('dice', 'Obsidian Mirror', () => { 53 | new obsidian.Notice('This is a notice!'); 54 | }); 55 | this.addStatusBarItem().setText('Obsidian Mirror'); 56 | this.addCommand({ 57 | id: 'open-sample-modal', 58 | name: 'Open Sample Modal', 59 | // callback: () => { 60 | // console.log('Simple Callback'); 61 | // }, 62 | checkCallback: (checking) => { 63 | let leaf = this.app.workspace.activeLeaf; 64 | if (leaf) { 65 | if (!checking) { 66 | new SampleModal(this.app).open(); 67 | } 68 | return true; 69 | } 70 | return false; 71 | } 72 | }); 73 | this.addSettingTab(new ObsidianMirrorSettingTab(this.app, this)); 74 | this.registerCodeMirror((cm) => { 75 | console.log('codemirror', cm); 76 | }); 77 | this.registerDomEvent(document, 'click', (evt) => { 78 | console.log('click', evt); 79 | }); 80 | this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); 81 | this.app.workspace.on('file-open', () => __awaiter(this, void 0, void 0, function* () { 82 | const activeLeaf = this.app.workspace.activeLeaf; 83 | if (!activeLeaf) { 84 | return; 85 | } 86 | this.lastFile(); 87 | })); 88 | this.registerEvent(this.app.vault.on('modify', (file) => this.onChangeFile(file))); 89 | }); 90 | } 91 | onChangeFile(file) { 92 | return __awaiter(this, void 0, void 0, function* () { 93 | console.log("this.settings.isMirror:" + this.settings.isMirror); 94 | console.log("vault this.settings.fileName:" + this.settings.vault + "/" + this.settings.fileName); 95 | console.log("vault + filnemagraph:" + this.settings.vault + "/" + this.settings.fileNameGraph); 96 | console.log("active file:" + this.app.workspace.getActiveFile().path); 97 | console.log("file.path:" + file.path); 98 | if (!this.openedByThisPlugin) { 99 | if (this.settings.isMirror && file.path == this.settings.vault + "/" + this.settings.fileName || !this.settings.isMirror && file.path == this.settings.fileNameGraph) { 100 | console.log("passed"); 101 | this.readActiveOpenedFile(); 102 | } 103 | } 104 | else { 105 | this.openedByThisPlugin = false; 106 | } 107 | }); 108 | } 109 | lastFile() { 110 | return __awaiter(this, void 0, void 0, function* () { 111 | this.activeFile = this.app.workspace.getActiveFile(); 112 | console.log("lastFile"); 113 | setTimeout(() => { 114 | this.watchFileAndWrite(); 115 | }, 800); 116 | }); 117 | } 118 | watchFileAndWrite() { 119 | return __awaiter(this, void 0, void 0, function* () { 120 | var activeFile = this.activeFile; 121 | var sideCarFile = !this.settings.isMirror ? this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileName; })[0] : this.app.vault.getFiles().filter(f => { return f.path == this.settings.vault + "/" + this.settings.fileNameGraph; })[0]; 122 | console.log("sideCarFile:"); 123 | console.log(sideCarFile); 124 | if (!sideCarFile) { 125 | this.app.vault.create(!this.settings.isMirror ? this.settings.fileName : this.settings.vault + "/" + this.settings.fileNameGraph, ""); 126 | console.log("passato"); 127 | sideCarFile = this.settings.isMirror ? this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileName; })[0] : this.app.vault.getFiles().filter(f => { return f.path == this.settings.vault + "/" + this.settings.fileNameGraph; })[0]; 128 | } 129 | if (activeFile != null && activeFile != undefined) { 130 | console.log(`this is active file ${activeFile.name}`); 131 | yield this.app.vault.modify(sideCarFile, activeFile.name); 132 | } 133 | }); 134 | } 135 | readActiveOpenedFile() { 136 | return __awaiter(this, void 0, void 0, function* () { 137 | var sideCarFile = this.settings.isMirror ? this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileName; })[0] : this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileNameGraph; })[0]; 138 | console.log("sideCar:" + sideCarFile.name); 139 | var fileNameToOpen = yield (yield this.app.vault.read(sideCarFile)).trim(); 140 | var fileToOpen = this.app.vault.getFiles().filter(f => { return f.name == fileNameToOpen; })[0]; 141 | if (fileToOpen) { 142 | if ((fileToOpen === null || fileToOpen === void 0 ? void 0 : fileToOpen.name) != this.app.workspace.getActiveFile().name) { 143 | this.openedByThisPlugin = true; 144 | this.app.workspace.activeLeaf.openFile(fileToOpen); 145 | new obsidian.Notice(`ObsidianMirror: ${fileToOpen.basename} file opened`, 5000); 146 | } 147 | else { 148 | console.log("invalid file found or already opened"); 149 | } 150 | } 151 | }); 152 | } 153 | onunload() { 154 | console.log('unloading plugin'); 155 | } 156 | loadSettings() { 157 | return __awaiter(this, void 0, void 0, function* () { 158 | this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData()); 159 | }); 160 | } 161 | saveSettings() { 162 | return __awaiter(this, void 0, void 0, function* () { 163 | yield this.saveData(this.settings); 164 | }); 165 | } 166 | } 167 | class SampleModal extends obsidian.Modal { 168 | constructor(app) { 169 | super(app); 170 | } 171 | onOpen() { 172 | let { contentEl } = this; 173 | contentEl.setText('Woah!'); 174 | } 175 | onClose() { 176 | let { contentEl } = this; 177 | contentEl.empty(); 178 | } 179 | } 180 | class ObsidianMirrorSettingTab extends obsidian.PluginSettingTab { 181 | constructor(app, plugin) { 182 | super(app, plugin); 183 | this.plugin = plugin; 184 | } 185 | display() { 186 | const { containerEl } = this; 187 | containerEl.empty(); 188 | containerEl.createEl('h2', { text: 'Obsidian Mirror - Settings' }); 189 | new obsidian.Setting(containerEl) 190 | .setName('Is this Obsidian instance a Mirror?') 191 | .setDesc('If enabled, this instance will "follow" whatever the main Obsidian instance has opened' + 192 | 'PS: In order to launch multiple Obsidian instances you have to follow a workaround suggested in this community Forum') 193 | .addToggle((toggle) => toggle.setValue(this.plugin.settings.isMirror).onChange((value) => { 194 | this.plugin.settings.isMirror = value; 195 | this.plugin.saveData(this.plugin.settings); 196 | this.display(); 197 | })); 198 | new obsidian.Setting(containerEl) 199 | .setName('Vault Name') 200 | .setDesc('Please enter the Vault name your are using in the main instance of Obsidian') 201 | .addText((text) => text 202 | .setPlaceholder('MyVaultName') 203 | .setValue(this.plugin.settings.vault) 204 | .onChange((value) => __awaiter(this, void 0, void 0, function* () { 205 | this.plugin.settings.vault = value; 206 | yield this.plugin.saveSettings(); 207 | }))); 208 | new obsidian.Setting(containerEl) 209 | .setName('Mirror File') 210 | .setDesc('Please enter the file name you want to use. This plugin will use it in order to watch the active file opned. PS: You can use a name of your choice') 211 | .addText((text) => text 212 | .setPlaceholder('ObsidianMirror.md') 213 | .setValue(this.plugin.settings.fileName) 214 | .onChange((value) => __awaiter(this, void 0, void 0, function* () { 215 | this.plugin.settings.fileName = value; 216 | this.plugin.settings.fileNameGraph = value.substring(0, value.length - 2) + "_graph.md"; 217 | yield this.plugin.saveSettings(); 218 | }))); 219 | } 220 | } 221 | 222 | module.exports = ObidianMirrorPlugin; 223 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm1haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19jcmVhdGVCaW5kaW5nID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9KTtcclxufSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICBvW2syXSA9IG1ba107XHJcbn0pO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBvKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIHApKSBfX2NyZWF0ZUJpbmRpbmcobywgbSwgcCk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7XHJcbiAgICB2YXIgcyA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wuaXRlcmF0b3IsIG0gPSBzICYmIG9bc10sIGkgPSAwO1xyXG4gICAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XHJcbiAgICBpZiAobyAmJiB0eXBlb2Ygby5sZW5ndGggPT09IFwibnVtYmVyXCIpIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IocyA/IFwiT2JqZWN0IGlzIG5vdCBpdGVyYWJsZS5cIiA6IFwiU3ltYm9sLml0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbi8qKiBAZGVwcmVjYXRlZCAqL1xyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWQoKSB7XHJcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcclxuICAgICAgICBhciA9IGFyLmNvbmNhdChfX3JlYWQoYXJndW1lbnRzW2ldKSk7XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbi8qKiBAZGVwcmVjYXRlZCAqL1xyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheXMoKSB7XHJcbiAgICBmb3IgKHZhciBzID0gMCwgaSA9IDAsIGlsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGlsOyBpKyspIHMgKz0gYXJndW1lbnRzW2ldLmxlbmd0aDtcclxuICAgIGZvciAodmFyIHIgPSBBcnJheShzKSwgayA9IDAsIGkgPSAwOyBpIDwgaWw7IGkrKylcclxuICAgICAgICBmb3IgKHZhciBhID0gYXJndW1lbnRzW2ldLCBqID0gMCwgamwgPSBhLmxlbmd0aDsgaiA8IGpsOyBqKyssIGsrKylcclxuICAgICAgICAgICAgcltrXSA9IGFbal07XHJcbiAgICByZXR1cm4gcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXkodG8sIGZyb20sIHBhY2spIHtcclxuICAgIGlmIChwYWNrIHx8IGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIGZvciAodmFyIGkgPSAwLCBsID0gZnJvbS5sZW5ndGgsIGFyOyBpIDwgbDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKGFyIHx8ICEoaSBpbiBmcm9tKSkge1xyXG4gICAgICAgICAgICBpZiAoIWFyKSBhciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20sIDAsIGkpO1xyXG4gICAgICAgICAgICBhcltpXSA9IGZyb21baV07XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRvLmNvbmNhdChhciB8fCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tKSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0KHYpIHtcclxuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgX19hd2FpdCA/ICh0aGlzLnYgPSB2LCB0aGlzKSA6IG5ldyBfX2F3YWl0KHYpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0dlbmVyYXRvcih0aGlzQXJnLCBfYXJndW1lbnRzLCBnZW5lcmF0b3IpIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgZyA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSwgaSwgcSA9IFtdO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlmIChnW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKHIpIHsgci52YWx1ZSBpbnN0YW5jZW9mIF9fYXdhaXQgPyBQcm9taXNlLnJlc29sdmUoci52YWx1ZS52KS50aGVuKGZ1bGZpbGwsIHJlamVjdCkgOiBzZXR0bGUocVswXVsyXSwgcik7IH1cclxuICAgIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShmLCB2KSB7IGlmIChmKHYpLCBxLnNoaWZ0KCksIHEubGVuZ3RoKSByZXN1bWUocVswXVswXSwgcVswXVsxXSk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNEZWxlZ2F0b3Iobykge1xyXG4gICAgdmFyIGksIHA7XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIsIGZ1bmN0aW9uIChlKSB7IHRocm93IGU7IH0pLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlbbl0gPSBvW25dID8gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIChwID0gIXApID8geyB2YWx1ZTogX19hd2FpdChvW25dKHYpKSwgZG9uZTogbiA9PT0gXCJyZXR1cm5cIiB9IDogZiA/IGYodikgOiB2OyB9IDogZjsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY1ZhbHVlcyhvKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSwgaTtcclxuICAgIHJldHVybiBtID8gbS5jYWxsKG8pIDogKG8gPSB0eXBlb2YgX192YWx1ZXMgPT09IFwiZnVuY3Rpb25cIiA/IF9fdmFsdWVzKG8pIDogb1tTeW1ib2wuaXRlcmF0b3JdKCksIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpKTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpW25dID0gb1tuXSAmJiBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyB2ID0gb1tuXSh2KSwgc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgdi5kb25lLCB2LnZhbHVlKTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIGQsIHYpIHsgUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZnVuY3Rpb24odikgeyByZXNvbHZlKHsgdmFsdWU6IHYsIGRvbmU6IGQgfSk7IH0sIHJlamVjdCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWFrZVRlbXBsYXRlT2JqZWN0KGNvb2tlZCwgcmF3KSB7XHJcbiAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb29rZWQsIFwicmF3XCIsIHsgdmFsdWU6IHJhdyB9KTsgfSBlbHNlIHsgY29va2VkLnJhdyA9IHJhdzsgfVxyXG4gICAgcmV0dXJuIGNvb2tlZDtcclxufTtcclxuXHJcbnZhciBfX3NldE1vZHVsZURlZmF1bHQgPSBPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBcImRlZmF1bHRcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdiB9KTtcclxufSkgOiBmdW5jdGlvbihvLCB2KSB7XHJcbiAgICBvW1wiZGVmYXVsdFwiXSA9IHY7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgX19jcmVhdGVCaW5kaW5nKHJlc3VsdCwgbW9kLCBrKTtcclxuICAgIF9fc2V0TW9kdWxlRGVmYXVsdChyZXN1bHQsIG1vZCk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcclxufVxyXG4iLCJpbXBvcnQgeyBBcHAsIE1vZGFsLCBOb3RpY2UsIFBsdWdpbiwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZywgVEFic3RyYWN0RmlsZSwgVEZpbGUsIFZhdWx0IH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAndXJsJztcclxuXHJcbmludGVyZmFjZSBPYnNpZGlhbk1pcnJvclNldHRpbmdzIHtcclxuXHRpc01pcnJvcjogYm9vbGVhbjtcclxuXHR2YXVsdDogc3RyaW5nXHJcblx0ZmlsZU5hbWU6IHN0cmluZztcclxuXHRmaWxlTmFtZUdyYXBoOiBzdHJpbmc7XHJcbn1cclxuXHJcbmNvbnN0IERFRkFVTFRfU0VUVElOR1M6IE9ic2lkaWFuTWlycm9yU2V0dGluZ3MgPSB7XHJcblx0aXNNaXJyb3I6IGZhbHNlLFxyXG5cdHZhdWx0OiBcIlwiLFxyXG5cdGZpbGVOYW1lOiBcIk9ic2lkaWFuTWlycm9yLm1kXCIsXHJcblx0ZmlsZU5hbWVHcmFwaDogXCJPYnNpZGlhbk1pcnJvcl9ncmFwaC5tZFwiXHJcbn1cclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE9iaWRpYW5NaXJyb3JQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xyXG5cdHNldHRpbmdzOiBPYnNpZGlhbk1pcnJvclNldHRpbmdzO1xyXG5cclxuXHRvcGVuZWRCeVRoaXNQbHVnaW46IGJvb2xlYW4gPSBmYWxzZTtcclxuXHR3cm90ZUJ5VGhpc1BsdWdpbjogYm9vbGVhbiA9IGZhbHNlO1xyXG5cdGFjdGl2ZUZpbGU6IFRGaWxlID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKTtcclxuXHJcblx0YXN5bmMgb25sb2FkKCkge1xyXG5cdFx0Y29uc29sZS5sb2coJ2xvYWRpbmcgcGx1Z2luJyk7XHJcblxyXG5cdFx0YXdhaXQgdGhpcy5sb2FkU2V0dGluZ3MoKTtcclxuXHJcblx0XHR0aGlzLmFkZFJpYmJvbkljb24oJ2RpY2UnLCAnT2JzaWRpYW4gTWlycm9yJywgKCkgPT4ge1xyXG5cdFx0XHRuZXcgTm90aWNlKCdUaGlzIGlzIGEgbm90aWNlIScpO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0dGhpcy5hZGRTdGF0dXNCYXJJdGVtKCkuc2V0VGV4dCgnT2JzaWRpYW4gTWlycm9yJyk7XHJcblxyXG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcclxuXHRcdFx0aWQ6ICdvcGVuLXNhbXBsZS1tb2RhbCcsXHJcblx0XHRcdG5hbWU6ICdPcGVuIFNhbXBsZSBNb2RhbCcsXHJcblx0XHRcdC8vIGNhbGxiYWNrOiAoKSA9PiB7XHJcblx0XHRcdC8vIFx0Y29uc29sZS5sb2coJ1NpbXBsZSBDYWxsYmFjaycpO1xyXG5cdFx0XHQvLyB9LFxyXG5cdFx0XHRjaGVja0NhbGxiYWNrOiAoY2hlY2tpbmc6IGJvb2xlYW4pID0+IHtcclxuXHRcdFx0XHRsZXQgbGVhZiA9IHRoaXMuYXBwLndvcmtzcGFjZS5hY3RpdmVMZWFmO1xyXG5cdFx0XHRcdGlmIChsZWFmKSB7XHJcblx0XHRcdFx0XHRpZiAoIWNoZWNraW5nKSB7XHJcblx0XHRcdFx0XHRcdG5ldyBTYW1wbGVNb2RhbCh0aGlzLmFwcCkub3BlbigpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0dGhpcy5hZGRTZXR0aW5nVGFiKG5ldyBPYnNpZGlhbk1pcnJvclNldHRpbmdUYWIodGhpcy5hcHAsIHRoaXMpKTtcclxuXHJcblx0XHR0aGlzLnJlZ2lzdGVyQ29kZU1pcnJvcigoY206IENvZGVNaXJyb3IuRWRpdG9yKSA9PiB7XHJcblx0XHRcdGNvbnNvbGUubG9nKCdjb2RlbWlycm9yJywgY20pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0dGhpcy5yZWdpc3RlckRvbUV2ZW50KGRvY3VtZW50LCAnY2xpY2snLCAoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XHJcblx0XHRcdGNvbnNvbGUubG9nKCdjbGljaycsIGV2dCk7XHJcblx0XHR9KTtcclxuXHJcblx0XHR0aGlzLnJlZ2lzdGVySW50ZXJ2YWwod2luZG93LnNldEludGVydmFsKCgpID0+IGNvbnNvbGUubG9nKCdzZXRJbnRlcnZhbCcpLCA1ICogNjAgKiAxMDAwKSk7XHJcblxyXG5cdFx0dGhpcy5hcHAud29ya3NwYWNlLm9uKCdmaWxlLW9wZW4nLCBhc3luYyAoKSA9PiB7XHJcblxyXG5cdFx0XHRjb25zdCBhY3RpdmVMZWFmID0gdGhpcy5hcHAud29ya3NwYWNlLmFjdGl2ZUxlYWZcclxuXHRcdFx0aWYgKCFhY3RpdmVMZWFmKSB7XHJcblx0XHRcdFx0cmV0dXJuXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHRoaXMubGFzdEZpbGUoKTtcclxuXHJcblxyXG5cdFx0fSlcclxuXHJcblxyXG5cdFx0dGhpcy5yZWdpc3RlckV2ZW50KFxyXG5cdFx0XHR0aGlzLmFwcC52YXVsdC5vbignbW9kaWZ5JywgKGZpbGUpID0+IHRoaXMub25DaGFuZ2VGaWxlKGZpbGUpKVxyXG5cdFx0KTtcclxuXHJcblxyXG5cdH1cclxuXHJcblx0YXN5bmMgb25DaGFuZ2VGaWxlKGZpbGU6IFRBYnN0cmFjdEZpbGUpIHtcclxuXHJcblx0XHRjb25zb2xlLmxvZyhcInRoaXMuc2V0dGluZ3MuaXNNaXJyb3I6XCIgKyB0aGlzLnNldHRpbmdzLmlzTWlycm9yKTtcclxuXHRcdGNvbnNvbGUubG9nKFwidmF1bHQgdGhpcy5zZXR0aW5ncy5maWxlTmFtZTpcIiArIHRoaXMuc2V0dGluZ3MudmF1bHQgKyBcIi9cIiArIHRoaXMuc2V0dGluZ3MuZmlsZU5hbWUpO1xyXG5cdFx0Y29uc29sZS5sb2coXCJ2YXVsdCArIGZpbG5lbWFncmFwaDpcIiArIHRoaXMuc2V0dGluZ3MudmF1bHQgKyBcIi9cIiArIHRoaXMuc2V0dGluZ3MuZmlsZU5hbWVHcmFwaClcclxuXHRcdGNvbnNvbGUubG9nKFwiYWN0aXZlIGZpbGU6XCIgKyB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpLnBhdGgpXHJcblx0XHRjb25zb2xlLmxvZyhcImZpbGUucGF0aDpcIiArIGZpbGUucGF0aCk7XHJcblxyXG5cdFx0aWYgKCF0aGlzLm9wZW5lZEJ5VGhpc1BsdWdpbikge1xyXG5cdFx0XHRpZiAodGhpcy5zZXR0aW5ncy5pc01pcnJvciAmJiBmaWxlLnBhdGggPT0gdGhpcy5zZXR0aW5ncy52YXVsdCArIFwiL1wiICsgdGhpcy5zZXR0aW5ncy5maWxlTmFtZSB8fCAhdGhpcy5zZXR0aW5ncy5pc01pcnJvciAmJiBmaWxlLnBhdGggPT0gdGhpcy5zZXR0aW5ncy5maWxlTmFtZUdyYXBoKSB7XHJcblx0XHRcdFx0Y29uc29sZS5sb2coXCJwYXNzZWRcIik7XHJcblx0XHRcdFx0dGhpcy5yZWFkQWN0aXZlT3BlbmVkRmlsZSgpO1xyXG5cdFx0XHR9XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0aGlzLm9wZW5lZEJ5VGhpc1BsdWdpbiA9IGZhbHNlO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblxyXG5cdGFzeW5jIGxhc3RGaWxlKCkge1xyXG5cclxuXHRcdHRoaXMuYWN0aXZlRmlsZSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XHJcblxyXG5cdFx0Y29uc29sZS5sb2coXCJsYXN0RmlsZVwiKTtcclxuXHJcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcclxuXHRcdFx0dGhpcy53YXRjaEZpbGVBbmRXcml0ZSgpO1xyXG5cdFx0fSwgODAwKTtcclxuXHJcblx0fSBcclxuXHJcblxyXG5cclxuXHRhc3luYyB3YXRjaEZpbGVBbmRXcml0ZSgpIHtcclxuXHJcblxyXG5cdFx0dmFyIGFjdGl2ZUZpbGU6IFRGaWxlID0gdGhpcy5hY3RpdmVGaWxlO1xyXG5cdFx0dmFyIHNpZGVDYXJGaWxlID0gIXRoaXMuc2V0dGluZ3MuaXNNaXJyb3IgPyB0aGlzLmFwcC52YXVsdC5nZXRGaWxlcygpLmZpbHRlcihmID0+IHsgcmV0dXJuIGYubmFtZSA9PSB0aGlzLnNldHRpbmdzLmZpbGVOYW1lIH0pWzBdIDogdGhpcy5hcHAudmF1bHQuZ2V0RmlsZXMoKS5maWx0ZXIoZiA9PiB7IHJldHVybiBmLnBhdGggPT0gdGhpcy5zZXR0aW5ncy52YXVsdCArIFwiL1wiICsgdGhpcy5zZXR0aW5ncy5maWxlTmFtZUdyYXBoIH0pWzBdO1xyXG5cdFx0Y29uc29sZS5sb2coXCJzaWRlQ2FyRmlsZTpcIilcclxuXHRcdGNvbnNvbGUubG9nKHNpZGVDYXJGaWxlKVxyXG5cdFx0aWYgKCFzaWRlQ2FyRmlsZSkge1xyXG5cdFx0XHR0aGlzLmFwcC52YXVsdC5jcmVhdGUoIXRoaXMuc2V0dGluZ3MuaXNNaXJyb3IgPyB0aGlzLnNldHRpbmdzLmZpbGVOYW1lIDogdGhpcy5zZXR0aW5ncy52YXVsdCArIFwiL1wiICsgdGhpcy5zZXR0aW5ncy5maWxlTmFtZUdyYXBoLCBcIlwiKTtcclxuXHRcdFx0Y29uc29sZS5sb2coXCJwYXNzYXRvXCIpXHJcblx0XHRcdHNpZGVDYXJGaWxlID0gdGhpcy5zZXR0aW5ncy5pc01pcnJvciA/IHRoaXMuYXBwLnZhdWx0LmdldEZpbGVzKCkuZmlsdGVyKGYgPT4geyByZXR1cm4gZi5uYW1lID09IHRoaXMuc2V0dGluZ3MuZmlsZU5hbWUgfSlbMF0gOiB0aGlzLmFwcC52YXVsdC5nZXRGaWxlcygpLmZpbHRlcihmID0+IHsgcmV0dXJuIGYucGF0aCA9PSB0aGlzLnNldHRpbmdzLnZhdWx0ICsgXCIvXCIgKyB0aGlzLnNldHRpbmdzLmZpbGVOYW1lR3JhcGggfSlbMF07XHJcblx0XHR9XHJcblx0XHRpZiAoYWN0aXZlRmlsZSAhPSBudWxsICYmIGFjdGl2ZUZpbGUgIT0gdW5kZWZpbmVkKSB7XHJcblx0XHRcdGNvbnNvbGUubG9nKGB0aGlzIGlzIGFjdGl2ZSBmaWxlICR7YWN0aXZlRmlsZS5uYW1lfWApO1xyXG5cclxuXHRcdFx0YXdhaXQgdGhpcy5hcHAudmF1bHQubW9kaWZ5KHNpZGVDYXJGaWxlLCBhY3RpdmVGaWxlLm5hbWUpO1xyXG5cclxuXHRcdH1cclxuXHJcblxyXG5cdH1cclxuXHJcblxyXG5cdGFzeW5jIHJlYWRBY3RpdmVPcGVuZWRGaWxlKCkge1xyXG5cdFx0dmFyIHNpZGVDYXJGaWxlID0gdGhpcy5zZXR0aW5ncy5pc01pcnJvciA/IHRoaXMuYXBwLnZhdWx0LmdldEZpbGVzKCkuZmlsdGVyKGYgPT4geyByZXR1cm4gZi5uYW1lID09IHRoaXMuc2V0dGluZ3MuZmlsZU5hbWUgfSlbMF0gOiB0aGlzLmFwcC52YXVsdC5nZXRGaWxlcygpLmZpbHRlcihmID0+IHsgcmV0dXJuIGYubmFtZSA9PSB0aGlzLnNldHRpbmdzLmZpbGVOYW1lR3JhcGggfSlbMF07XHJcblxyXG5cdFx0Y29uc29sZS5sb2coXCJzaWRlQ2FyOlwiICsgc2lkZUNhckZpbGUubmFtZSk7XHJcblxyXG5cclxuXHRcdHZhciBmaWxlTmFtZVRvT3BlbiA9IGF3YWl0IChhd2FpdCB0aGlzLmFwcC52YXVsdC5yZWFkKHNpZGVDYXJGaWxlKSkudHJpbSgpO1xyXG5cdFx0dmFyIGZpbGVUb09wZW46IFRGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0RmlsZXMoKS5maWx0ZXIoZiA9PiB7IHJldHVybiBmLm5hbWUgPT0gZmlsZU5hbWVUb09wZW4gfSlbMF07XHJcblxyXG5cclxuXHRcdGlmIChmaWxlVG9PcGVuKSB7XHJcblx0XHRcdGlmIChmaWxlVG9PcGVuPy5uYW1lICE9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCkubmFtZSkge1xyXG5cdFx0XHRcdHRoaXMub3BlbmVkQnlUaGlzUGx1Z2luID0gdHJ1ZTtcclxuXHRcdFx0XHR0aGlzLmFwcC53b3Jrc3BhY2UuYWN0aXZlTGVhZi5vcGVuRmlsZShmaWxlVG9PcGVuKTtcclxuXHRcdFx0XHRuZXcgTm90aWNlKGBPYnNpZGlhbk1pcnJvcjogJHtmaWxlVG9PcGVuLmJhc2VuYW1lfSBmaWxlIG9wZW5lZGAsIDUwMDApO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdGNvbnNvbGUubG9nKFwiaW52YWxpZCBmaWxlIGZvdW5kIG9yIGFscmVhZHkgb3BlbmVkXCIpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRvbnVubG9hZCgpIHtcclxuXHRcdGNvbnNvbGUubG9nKCd1bmxvYWRpbmcgcGx1Z2luJyk7XHJcblx0fVxyXG5cclxuXHRhc3luYyBsb2FkU2V0dGluZ3MoKSB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKTtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHNhdmVTZXR0aW5ncygpIHtcclxuXHRcdGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7XHJcblx0fVxyXG59XHJcblxyXG5jbGFzcyBTYW1wbGVNb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHRjb25zdHJ1Y3RvcihhcHA6IEFwcCkge1xyXG5cdFx0c3VwZXIoYXBwKTtcclxuXHR9XHJcblxyXG5cdG9uT3BlbigpIHtcclxuXHRcdGxldCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcclxuXHRcdGNvbnRlbnRFbC5zZXRUZXh0KCdXb2FoIScpO1xyXG5cdH1cclxuXHJcblx0b25DbG9zZSgpIHtcclxuXHRcdGxldCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcclxuXHRcdGNvbnRlbnRFbC5lbXB0eSgpO1xyXG5cdH1cclxufVxyXG5cclxuY2xhc3MgT2JzaWRpYW5NaXJyb3JTZXR0aW5nVGFiIGV4dGVuZHMgUGx1Z2luU2V0dGluZ1RhYiB7XHJcblx0cGx1Z2luOiBPYmlkaWFuTWlycm9yUGx1Z2luO1xyXG5cclxuXHRjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBPYmlkaWFuTWlycm9yUGx1Z2luKSB7XHJcblx0XHRzdXBlcihhcHAsIHBsdWdpbik7XHJcblx0XHR0aGlzLnBsdWdpbiA9IHBsdWdpbjtcclxuXHR9XHJcblxyXG5cdGRpc3BsYXkoKTogdm9pZCB7XHJcblxyXG5cdFx0Y29uc3QgeyBjb250YWluZXJFbCB9ID0gdGhpcztcclxuXHRcdGNvbnRhaW5lckVsLmVtcHR5KCk7XHJcblxyXG5cdFx0Y29udGFpbmVyRWwuY3JlYXRlRWwoJ2gyJywgeyB0ZXh0OiAnT2JzaWRpYW4gTWlycm9yIC0gU2V0dGluZ3MnIH0pO1xyXG5cclxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG5cdFx0XHQuc2V0TmFtZSgnSXMgdGhpcyBPYnNpZGlhbiBpbnN0YW5jZSBhIE1pcnJvcj8nKVxyXG5cdFx0XHQuc2V0RGVzYyhcclxuXHRcdFx0XHQnSWYgZW5hYmxlZCwgdGhpcyBpbnN0YW5jZSB3aWxsIFwiZm9sbG93XCIgd2hhdGV2ZXIgdGhlIG1haW4gT2JzaWRpYW4gaW5zdGFuY2UgaGFzIG9wZW5lZCcgK1xyXG5cdFx0XHRcdCdQUzogSW4gb3JkZXIgdG8gbGF1bmNoIG11bHRpcGxlIE9ic2lkaWFuIGluc3RhbmNlcyB5b3UgaGF2ZSB0byBmb2xsb3cgYSB3b3JrYXJvdW5kIHN1Z2dlc3RlZCBpbiB0aGlzIGNvbW11bml0eSBGb3J1bSdcclxuXHRcdFx0KVxyXG5cdFx0XHQuYWRkVG9nZ2xlKCh0b2dnbGUpID0+XHJcblx0XHRcdFx0dG9nZ2xlLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmlzTWlycm9yKS5vbkNoYW5nZSgodmFsdWUpID0+IHtcclxuXHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmlzTWlycm9yID0gdmFsdWU7XHJcblx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zYXZlRGF0YSh0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XHJcblx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTtcclxuXHRcdFx0XHR9KSxcclxuXHRcdFx0KTtcclxuXHJcblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuXHRcdFx0LnNldE5hbWUoJ1ZhdWx0IE5hbWUnKVxyXG5cdFx0XHQuc2V0RGVzYyhcclxuXHRcdFx0XHQnUGxlYXNlIGVudGVyIHRoZSBWYXVsdCBuYW1lIHlvdXIgYXJlIHVzaW5nIGluIHRoZSBtYWluIGluc3RhbmNlIG9mIE9ic2lkaWFuJyxcclxuXHRcdFx0KVxyXG5cdFx0XHQuYWRkVGV4dCgodGV4dCkgPT5cclxuXHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoJ015VmF1bHROYW1lJylcclxuXHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy52YXVsdClcclxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudmF1bHQgPSB2YWx1ZVxyXG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdH0pLFxyXG5cdFx0XHQpO1xyXG5cclxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG5cdFx0XHQuc2V0TmFtZSgnTWlycm9yIEZpbGUnKVxyXG5cdFx0XHQuc2V0RGVzYyhcclxuXHRcdFx0XHQnUGxlYXNlIGVudGVyIHRoZSBmaWxlIG5hbWUgeW91IHdhbnQgdG8gdXNlLiBUaGlzIHBsdWdpbiB3aWxsIHVzZSBpdCBpbiBvcmRlciB0byB3YXRjaCB0aGUgYWN0aXZlIGZpbGUgb3BuZWQuIFBTOiBZb3UgY2FuIHVzZSBhIG5hbWUgb2YgeW91ciBjaG9pY2UnLFxyXG5cdFx0XHQpXHJcblx0XHRcdC5hZGRUZXh0KCh0ZXh0KSA9PlxyXG5cdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignT2JzaWRpYW5NaXJyb3IubWQnKVxyXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmZpbGVOYW1lKVxyXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5maWxlTmFtZSA9IHZhbHVlXHJcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmZpbGVOYW1lR3JhcGggPSB2YWx1ZS5zdWJzdHJpbmcoMCwgdmFsdWUubGVuZ3RoIC0gMikgKyBcIl9ncmFwaC5tZFwiXHJcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0fSksXHJcblx0XHRcdCk7XHJcblxyXG5cclxuXHR9XHJcbn1cclxuIl0sIm5hbWVzIjpbIlBsdWdpbiIsIk5vdGljZSIsIk1vZGFsIiwiUGx1Z2luU2V0dGluZ1RhYiIsIlNldHRpbmciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF1REE7QUFDTyxTQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUU7QUFDN0QsSUFBSSxTQUFTLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxPQUFPLEtBQUssWUFBWSxDQUFDLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLFVBQVUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUU7QUFDaEgsSUFBSSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUU7QUFDL0QsUUFBUSxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ25HLFFBQVEsU0FBUyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ3RHLFFBQVEsU0FBUyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFO0FBQ3RILFFBQVEsSUFBSSxDQUFDLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFVBQVUsSUFBSSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQzlFLEtBQUssQ0FBQyxDQUFDO0FBQ1A7O0FDbkVBLE1BQU0sZ0JBQWdCLEdBQTJCO0lBQ2hELFFBQVEsRUFBRSxLQUFLO0lBQ2YsS0FBSyxFQUFFLEVBQUU7SUFDVCxRQUFRLEVBQUUsbUJBQW1CO0lBQzdCLGFBQWEsRUFBRSx5QkFBeUI7Q0FDeEMsQ0FBQTtNQUVvQixtQkFBb0IsU0FBUUEsZUFBTTtJQUF2RDs7UUFHQyx1QkFBa0IsR0FBWSxLQUFLLENBQUM7UUFDcEMsc0JBQWlCLEdBQVksS0FBSyxDQUFDO1FBQ25DLGVBQVUsR0FBVSxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztLQXVKdkQ7SUFySk0sTUFBTTs7WUFDWCxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFFOUIsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFFMUIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLEVBQUU7Z0JBQzdDLElBQUlDLGVBQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO2FBQ2hDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBRW5ELElBQUksQ0FBQyxVQUFVLENBQUM7Z0JBQ2YsRUFBRSxFQUFFLG1CQUFtQjtnQkFDdkIsSUFBSSxFQUFFLG1CQUFtQjs7OztnQkFJekIsYUFBYSxFQUFFLENBQUMsUUFBaUI7b0JBQ2hDLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQztvQkFDekMsSUFBSSxJQUFJLEVBQUU7d0JBQ1QsSUFBSSxDQUFDLFFBQVEsRUFBRTs0QkFDZCxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7eUJBQ2pDO3dCQUNELE9BQU8sSUFBSSxDQUFDO3FCQUNaO29CQUNELE9BQU8sS0FBSyxDQUFDO2lCQUNiO2FBQ0QsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLHdCQUF3QixDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUVqRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxFQUFxQjtnQkFDN0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUM7YUFDOUIsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxHQUFlO2dCQUN4RCxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQzthQUMxQixDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBRTNGLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUU7Z0JBRWxDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQTtnQkFDaEQsSUFBSSxDQUFDLFVBQVUsRUFBRTtvQkFDaEIsT0FBTTtpQkFDTjtnQkFFRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7YUFHaEIsQ0FBQSxDQUFDLENBQUE7WUFHRixJQUFJLENBQUMsYUFBYSxDQUNqQixJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FDOUQsQ0FBQztTQUdGO0tBQUE7SUFFSyxZQUFZLENBQUMsSUFBbUI7O1lBRXJDLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNoRSxPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2xHLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUE7WUFDOUYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDckUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXRDLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7Z0JBQzdCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFO29CQUNySyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUN0QixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztpQkFDNUI7YUFDRDtpQkFBTTtnQkFDTixJQUFJLENBQUMsa0JBQWtCLEdBQUcsS0FBSyxDQUFDO2FBQ2hDO1NBQ0Q7S0FBQTtJQUdLLFFBQVE7O1lBRWIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUVyRCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRXhCLFVBQVUsQ0FBQztnQkFDVixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQzthQUN6QixFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBRVI7S0FBQTtJQUlLLGlCQUFpQjs7WUFHdEIsSUFBSSxVQUFVLEdBQVUsSUFBSSxDQUFDLFVBQVUsQ0FBQztZQUN4QyxJQUFJLFdBQVcsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sT0FBTyxDQUFDLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFBLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sT0FBTyxDQUFDLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzUCxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFBO1lBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDeEIsSUFBSSxDQUFDLFdBQVcsRUFBRTtnQkFDakIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUN0SSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFBO2dCQUN0QixXQUFXLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxPQUFPLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxPQUFPLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFBLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3RQO1lBQ0QsSUFBSSxVQUFVLElBQUksSUFBSSxJQUFJLFVBQVUsSUFBSSxTQUFTLEVBQUU7Z0JBQ2xELE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUV0RCxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBRTFEO1NBR0Q7S0FBQTtJQUdLLG9CQUFvQjs7WUFDekIsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxPQUFPLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxPQUFPLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFOU4sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRzNDLElBQUksY0FBYyxHQUFHLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUMzRSxJQUFJLFVBQVUsR0FBVSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxDQUFDLElBQUksSUFBSSxjQUFjLENBQUEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFHdEcsSUFBSSxVQUFVLEVBQUU7Z0JBQ2YsSUFBSSxDQUFBLFVBQVUsYUFBVixVQUFVLHVCQUFWLFVBQVUsQ0FBRSxJQUFJLEtBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLENBQUMsSUFBSSxFQUFFO29CQUNoRSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDO29CQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUNuRCxJQUFJQSxlQUFNLENBQUMsbUJBQW1CLFVBQVUsQ0FBQyxRQUFRLGNBQWMsRUFBRSxJQUFJLENBQUMsQ0FBQztpQkFDdkU7cUJBQU07b0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO2lCQUNwRDthQUNEO1NBQ0Q7S0FBQTtJQUVELFFBQVE7UUFDUCxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7S0FDaEM7SUFFSyxZQUFZOztZQUNqQixJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7U0FDM0U7S0FBQTtJQUVLLFlBQVk7O1lBQ2pCLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDbkM7S0FBQTtDQUNEO0FBRUQsTUFBTSxXQUFZLFNBQVFDLGNBQUs7SUFDOUIsWUFBWSxHQUFRO1FBQ25CLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUNYO0lBRUQsTUFBTTtRQUNMLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDekIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztLQUMzQjtJQUVELE9BQU87UUFDTixJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBQ3pCLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztLQUNsQjtDQUNEO0FBRUQsTUFBTSx3QkFBeUIsU0FBUUMseUJBQWdCO0lBR3RELFlBQVksR0FBUSxFQUFFLE1BQTJCO1FBQ2hELEtBQUssQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7S0FDckI7SUFFRCxPQUFPO1FBRU4sTUFBTSxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQztRQUM3QixXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFcEIsV0FBVyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsNEJBQTRCLEVBQUUsQ0FBQyxDQUFDO1FBRW5FLElBQUlDLGdCQUFPLENBQUMsV0FBVyxDQUFDO2FBQ3RCLE9BQU8sQ0FBQyxxQ0FBcUMsQ0FBQzthQUM5QyxPQUFPLENBQ1Asd0ZBQXdGO1lBQ3hGLHNIQUFzSCxDQUN0SDthQUNBLFNBQVMsQ0FBQyxDQUFDLE1BQU0sS0FDakIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLO1lBQzdELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7WUFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDZixDQUFDLENBQ0YsQ0FBQztRQUVILElBQUlBLGdCQUFPLENBQUMsV0FBVyxDQUFDO2FBQ3RCLE9BQU8sQ0FBQyxZQUFZLENBQUM7YUFDckIsT0FBTyxDQUNQLDZFQUE2RSxDQUM3RTthQUNBLE9BQU8sQ0FBQyxDQUFDLElBQUksS0FDYixJQUFJO2FBQ0YsY0FBYyxDQUFDLGFBQWEsQ0FBQzthQUM3QixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO2FBQ3BDLFFBQVEsQ0FBQyxDQUFPLEtBQUs7WUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQTtZQUNsQyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7U0FDakMsQ0FBQSxDQUFDLENBQ0gsQ0FBQztRQUVILElBQUlBLGdCQUFPLENBQUMsV0FBVyxDQUFDO2FBQ3RCLE9BQU8sQ0FBQyxhQUFhLENBQUM7YUFDdEIsT0FBTyxDQUNQLG9KQUFvSixDQUNwSjthQUNBLE9BQU8sQ0FBQyxDQUFDLElBQUksS0FDYixJQUFJO2FBQ0YsY0FBYyxDQUFDLG1CQUFtQixDQUFDO2FBQ25DLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7YUFDdkMsUUFBUSxDQUFDLENBQU8sS0FBSztZQUNyQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFBO1lBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQTtZQUN2RixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7U0FDakMsQ0FBQSxDQUFDLENBQ0gsQ0FBQztLQUdIOzs7OzsifQ== 224 | -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import { App, Modal, Notice, Plugin, PluginSettingTab, Setting, TAbstractFile, TFile, Vault } from 'obsidian'; 2 | import { fileURLToPath } from 'url'; 3 | 4 | interface ObsidianMirrorSettings { 5 | isMirror: boolean; 6 | vault: string 7 | fileName: string; 8 | fileNameGraph: string; 9 | } 10 | 11 | const DEFAULT_SETTINGS: ObsidianMirrorSettings = { 12 | isMirror: false, 13 | vault: "", 14 | fileName: "ObsidianMirror.md", 15 | fileNameGraph: "ObsidianMirror_graph.md" 16 | } 17 | 18 | export default class ObidianMirrorPlugin extends Plugin { 19 | settings: ObsidianMirrorSettings; 20 | 21 | openedByThisPlugin: boolean = false; 22 | wroteByThisPlugin: boolean = false; 23 | activeFile: TFile = this.app.workspace.getActiveFile(); 24 | 25 | async onload() { 26 | console.log('loading plugin'); 27 | 28 | await this.loadSettings(); 29 | 30 | this.addRibbonIcon('dice', 'Obsidian Mirror', () => { 31 | new Notice('This is a notice!'); 32 | }); 33 | 34 | this.addStatusBarItem().setText('Obsidian Mirror'); 35 | 36 | this.addCommand({ 37 | id: 'open-sample-modal', 38 | name: 'Open Sample Modal', 39 | // callback: () => { 40 | // console.log('Simple Callback'); 41 | // }, 42 | checkCallback: (checking: boolean) => { 43 | let leaf = this.app.workspace.activeLeaf; 44 | if (leaf) { 45 | if (!checking) { 46 | new SampleModal(this.app).open(); 47 | } 48 | return true; 49 | } 50 | return false; 51 | } 52 | }); 53 | 54 | this.addSettingTab(new ObsidianMirrorSettingTab(this.app, this)); 55 | 56 | this.registerCodeMirror((cm: CodeMirror.Editor) => { 57 | console.log('codemirror', cm); 58 | }); 59 | 60 | this.registerDomEvent(document, 'click', (evt: MouseEvent) => { 61 | console.log('click', evt); 62 | }); 63 | 64 | this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); 65 | 66 | this.app.workspace.on('file-open', async () => { 67 | 68 | const activeLeaf = this.app.workspace.activeLeaf 69 | if (!activeLeaf) { 70 | return 71 | } 72 | 73 | this.lastFile(); 74 | 75 | 76 | }) 77 | 78 | 79 | this.registerEvent( 80 | this.app.vault.on('modify', (file) => this.onChangeFile(file)) 81 | ); 82 | 83 | 84 | } 85 | 86 | async onChangeFile(file: TAbstractFile) { 87 | 88 | console.log("this.settings.isMirror:" + this.settings.isMirror); 89 | console.log("vault this.settings.fileName:" + this.settings.vault + "/" + this.settings.fileName); 90 | console.log("vault + filnemagraph:" + this.settings.vault + "/" + this.settings.fileNameGraph) 91 | console.log("active file:" + this.app.workspace.getActiveFile().path) 92 | console.log("file.path:" + file.path); 93 | 94 | if (!this.openedByThisPlugin) { 95 | if (this.settings.isMirror && file.path == this.settings.vault + "/" + this.settings.fileName || !this.settings.isMirror && file.path == this.settings.fileNameGraph) { 96 | console.log("passed"); 97 | this.readActiveOpenedFile(); 98 | } 99 | } else { 100 | this.openedByThisPlugin = false; 101 | } 102 | } 103 | 104 | 105 | async lastFile() { 106 | 107 | this.activeFile = this.app.workspace.getActiveFile(); 108 | 109 | console.log("lastFile"); 110 | 111 | setTimeout(() => { 112 | this.watchFileAndWrite(); 113 | }, 800); 114 | 115 | } 116 | 117 | 118 | 119 | async watchFileAndWrite() { 120 | 121 | 122 | var activeFile: TFile = this.activeFile; 123 | var sideCarFile = !this.settings.isMirror ? this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileName })[0] : this.app.vault.getFiles().filter(f => { return f.path == this.settings.vault + "/" + this.settings.fileNameGraph })[0]; 124 | console.log("sideCarFile:") 125 | console.log(sideCarFile) 126 | if (!sideCarFile) { 127 | this.app.vault.create(!this.settings.isMirror ? this.settings.fileName : this.settings.vault + "/" + this.settings.fileNameGraph, ""); 128 | console.log("passato") 129 | sideCarFile = this.settings.isMirror ? this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileName })[0] : this.app.vault.getFiles().filter(f => { return f.path == this.settings.vault + "/" + this.settings.fileNameGraph })[0]; 130 | } 131 | if (activeFile != null && activeFile != undefined) { 132 | console.log(`this is active file ${activeFile.name}`); 133 | 134 | await this.app.vault.modify(sideCarFile, activeFile.name); 135 | 136 | } 137 | 138 | 139 | } 140 | 141 | 142 | async readActiveOpenedFile() { 143 | var sideCarFile = this.settings.isMirror ? this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileName })[0] : this.app.vault.getFiles().filter(f => { return f.name == this.settings.fileNameGraph })[0]; 144 | 145 | console.log("sideCar:" + sideCarFile.name); 146 | 147 | 148 | var fileNameToOpen = await (await this.app.vault.read(sideCarFile)).trim(); 149 | var fileToOpen: TFile = this.app.vault.getFiles().filter(f => { return f.name == fileNameToOpen })[0]; 150 | 151 | 152 | if (fileToOpen) { 153 | if (fileToOpen?.name != this.app.workspace.getActiveFile().name) { 154 | this.openedByThisPlugin = true; 155 | this.app.workspace.activeLeaf.openFile(fileToOpen); 156 | new Notice(`ObsidianMirror: ${fileToOpen.basename} file opened`, 5000); 157 | } else { 158 | console.log("invalid file found or already opened"); 159 | } 160 | } 161 | } 162 | 163 | onunload() { 164 | console.log('unloading plugin'); 165 | } 166 | 167 | async loadSettings() { 168 | this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); 169 | } 170 | 171 | async saveSettings() { 172 | await this.saveData(this.settings); 173 | } 174 | } 175 | 176 | class SampleModal extends Modal { 177 | constructor(app: App) { 178 | super(app); 179 | } 180 | 181 | onOpen() { 182 | let { contentEl } = this; 183 | contentEl.setText('Woah!'); 184 | } 185 | 186 | onClose() { 187 | let { contentEl } = this; 188 | contentEl.empty(); 189 | } 190 | } 191 | 192 | class ObsidianMirrorSettingTab extends PluginSettingTab { 193 | plugin: ObidianMirrorPlugin; 194 | 195 | constructor(app: App, plugin: ObidianMirrorPlugin) { 196 | super(app, plugin); 197 | this.plugin = plugin; 198 | } 199 | 200 | display(): void { 201 | 202 | const { containerEl } = this; 203 | containerEl.empty(); 204 | 205 | containerEl.createEl('h2', { text: 'Obsidian Mirror - Settings' }); 206 | 207 | new Setting(containerEl) 208 | .setName('Is this Obsidian instance a Mirror?') 209 | .setDesc( 210 | 'If enabled, this instance will "follow" whatever the main Obsidian instance has opened' + 211 | 'PS: In order to launch multiple Obsidian instances you have to follow a workaround suggested in this community Forum' 212 | ) 213 | .addToggle((toggle) => 214 | toggle.setValue(this.plugin.settings.isMirror).onChange((value) => { 215 | this.plugin.settings.isMirror = value; 216 | this.plugin.saveData(this.plugin.settings); 217 | this.display(); 218 | }), 219 | ); 220 | 221 | new Setting(containerEl) 222 | .setName('Vault Name') 223 | .setDesc( 224 | 'Please enter the Vault name your are using in the main instance of Obsidian', 225 | ) 226 | .addText((text) => 227 | text 228 | .setPlaceholder('MyVaultName') 229 | .setValue(this.plugin.settings.vault) 230 | .onChange(async (value) => { 231 | this.plugin.settings.vault = value 232 | await this.plugin.saveSettings(); 233 | }), 234 | ); 235 | 236 | new Setting(containerEl) 237 | .setName('Mirror File') 238 | .setDesc( 239 | 'Please enter the file name you want to use. This plugin will use it in order to watch the active file opned. PS: You can use a name of your choice', 240 | ) 241 | .addText((text) => 242 | text 243 | .setPlaceholder('ObsidianMirror.md') 244 | .setValue(this.plugin.settings.fileName) 245 | .onChange(async (value) => { 246 | this.plugin.settings.fileName = value 247 | this.plugin.settings.fileNameGraph = value.substring(0, value.length - 2) + "_graph.md" 248 | await this.plugin.saveSettings(); 249 | }), 250 | ); 251 | 252 | 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "obsidian-mirror", 3 | "name": "Obsidian Mirror", 4 | "version": "0.0.1", 5 | "minAppVersion": "0.9.12", 6 | "description": "This plugins allows to sync the active open file among different Obsidian instances. Why? well, if you have multiple monitors and you want to use the local graph in a separate monitor, there is no chance to do it now. So I had the idea to run multiple instances of Obsidian using the workaround via symbolinc links. This way the 2 instances are not in sync. This plugin closes the gap and syncs the active opened file among multiple Obsidian instances", 7 | "author": "Francesco Pistillo", 8 | "authorUrl": "https://github.com/wildspecial/obsidian-mirror", 9 | "isDesktopOnly": false 10 | } 11 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-sample-plugin", 3 | "version": "0.12.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "obsidian-sample-plugin", 9 | "version": "0.12.0", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@rollup/plugin-commonjs": "^18.0.0", 13 | "@rollup/plugin-node-resolve": "^11.2.1", 14 | "@rollup/plugin-typescript": "^8.2.1", 15 | "@types/node": "^14.14.37", 16 | "obsidian": "^0.12.0", 17 | "rollup": "^2.32.1", 18 | "tslib": "^2.2.0", 19 | "typescript": "^4.2.4" 20 | } 21 | }, 22 | "node_modules/@rollup/plugin-commonjs": { 23 | "version": "18.1.0", 24 | "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-18.1.0.tgz", 25 | "integrity": "sha512-h3e6T9rUxVMAQswpDIobfUHn/doMzM9sgkMrsMWCFLmB84PSoC8mV8tOloAJjSRwdqhXBqstlX2BwBpHJvbhxg==", 26 | "dev": true, 27 | "dependencies": { 28 | "@rollup/pluginutils": "^3.1.0", 29 | "commondir": "^1.0.1", 30 | "estree-walker": "^2.0.1", 31 | "glob": "^7.1.6", 32 | "is-reference": "^1.2.1", 33 | "magic-string": "^0.25.7", 34 | "resolve": "^1.17.0" 35 | }, 36 | "engines": { 37 | "node": ">= 8.0.0" 38 | }, 39 | "peerDependencies": { 40 | "rollup": "^2.30.0" 41 | } 42 | }, 43 | "node_modules/@rollup/plugin-node-resolve": { 44 | "version": "11.2.1", 45 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", 46 | "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", 47 | "dev": true, 48 | "dependencies": { 49 | "@rollup/pluginutils": "^3.1.0", 50 | "@types/resolve": "1.17.1", 51 | "builtin-modules": "^3.1.0", 52 | "deepmerge": "^4.2.2", 53 | "is-module": "^1.0.0", 54 | "resolve": "^1.19.0" 55 | }, 56 | "engines": { 57 | "node": ">= 10.0.0" 58 | }, 59 | "peerDependencies": { 60 | "rollup": "^1.20.0||^2.0.0" 61 | } 62 | }, 63 | "node_modules/@rollup/plugin-typescript": { 64 | "version": "8.2.5", 65 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.5.tgz", 66 | "integrity": "sha512-QL/LvDol/PAGB2O0S7/+q2HpSUNodpw7z6nGn9BfoVCPOZ0r4EALrojFU29Bkoi2Hr2jgTocTejJ5GGWZfOxbQ==", 67 | "dev": true, 68 | "dependencies": { 69 | "@rollup/pluginutils": "^3.1.0", 70 | "resolve": "^1.17.0" 71 | }, 72 | "engines": { 73 | "node": ">=8.0.0" 74 | }, 75 | "peerDependencies": { 76 | "rollup": "^2.14.0", 77 | "tslib": "*", 78 | "typescript": ">=3.7.0" 79 | } 80 | }, 81 | "node_modules/@rollup/pluginutils": { 82 | "version": "3.1.0", 83 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", 84 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", 85 | "dev": true, 86 | "dependencies": { 87 | "@types/estree": "0.0.39", 88 | "estree-walker": "^1.0.1", 89 | "picomatch": "^2.2.2" 90 | }, 91 | "engines": { 92 | "node": ">= 8.0.0" 93 | }, 94 | "peerDependencies": { 95 | "rollup": "^1.20.0||^2.0.0" 96 | } 97 | }, 98 | "node_modules/@rollup/pluginutils/node_modules/estree-walker": { 99 | "version": "1.0.1", 100 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", 101 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", 102 | "dev": true 103 | }, 104 | "node_modules/@types/codemirror": { 105 | "version": "0.0.108", 106 | "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz", 107 | "integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==", 108 | "dev": true, 109 | "dependencies": { 110 | "@types/tern": "*" 111 | } 112 | }, 113 | "node_modules/@types/estree": { 114 | "version": "0.0.39", 115 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 116 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 117 | "dev": true 118 | }, 119 | "node_modules/@types/node": { 120 | "version": "14.17.12", 121 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.12.tgz", 122 | "integrity": "sha512-vhUqgjJR1qxwTWV5Ps5txuy2XMdf7Fw+OrdChRboy8BmWUPkckOhphaohzFG6b8DW7CrxaBMdrdJ47SYFq1okw==", 123 | "dev": true 124 | }, 125 | "node_modules/@types/resolve": { 126 | "version": "1.17.1", 127 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", 128 | "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", 129 | "dev": true, 130 | "dependencies": { 131 | "@types/node": "*" 132 | } 133 | }, 134 | "node_modules/@types/tern": { 135 | "version": "0.23.4", 136 | "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", 137 | "integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==", 138 | "dev": true, 139 | "dependencies": { 140 | "@types/estree": "*" 141 | } 142 | }, 143 | "node_modules/balanced-match": { 144 | "version": "1.0.2", 145 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 146 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 147 | "dev": true 148 | }, 149 | "node_modules/brace-expansion": { 150 | "version": "1.1.11", 151 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 152 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 153 | "dev": true, 154 | "dependencies": { 155 | "balanced-match": "^1.0.0", 156 | "concat-map": "0.0.1" 157 | } 158 | }, 159 | "node_modules/builtin-modules": { 160 | "version": "3.2.0", 161 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", 162 | "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", 163 | "dev": true, 164 | "engines": { 165 | "node": ">=6" 166 | }, 167 | "funding": { 168 | "url": "https://github.com/sponsors/sindresorhus" 169 | } 170 | }, 171 | "node_modules/commondir": { 172 | "version": "1.0.1", 173 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 174 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 175 | "dev": true 176 | }, 177 | "node_modules/concat-map": { 178 | "version": "0.0.1", 179 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 180 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 181 | "dev": true 182 | }, 183 | "node_modules/deepmerge": { 184 | "version": "4.2.2", 185 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 186 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", 187 | "dev": true, 188 | "engines": { 189 | "node": ">=0.10.0" 190 | } 191 | }, 192 | "node_modules/estree-walker": { 193 | "version": "2.0.2", 194 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 195 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 196 | "dev": true 197 | }, 198 | "node_modules/fs.realpath": { 199 | "version": "1.0.0", 200 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 201 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 202 | "dev": true 203 | }, 204 | "node_modules/fsevents": { 205 | "version": "2.3.2", 206 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 207 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 208 | "dev": true, 209 | "hasInstallScript": true, 210 | "optional": true, 211 | "os": [ 212 | "darwin" 213 | ], 214 | "engines": { 215 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 216 | } 217 | }, 218 | "node_modules/function-bind": { 219 | "version": "1.1.1", 220 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 221 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 222 | "dev": true 223 | }, 224 | "node_modules/glob": { 225 | "version": "7.1.7", 226 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 227 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 228 | "dev": true, 229 | "dependencies": { 230 | "fs.realpath": "^1.0.0", 231 | "inflight": "^1.0.4", 232 | "inherits": "2", 233 | "minimatch": "^3.0.4", 234 | "once": "^1.3.0", 235 | "path-is-absolute": "^1.0.0" 236 | }, 237 | "engines": { 238 | "node": "*" 239 | }, 240 | "funding": { 241 | "url": "https://github.com/sponsors/isaacs" 242 | } 243 | }, 244 | "node_modules/has": { 245 | "version": "1.0.3", 246 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 247 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 248 | "dev": true, 249 | "dependencies": { 250 | "function-bind": "^1.1.1" 251 | }, 252 | "engines": { 253 | "node": ">= 0.4.0" 254 | } 255 | }, 256 | "node_modules/inflight": { 257 | "version": "1.0.6", 258 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 259 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 260 | "dev": true, 261 | "dependencies": { 262 | "once": "^1.3.0", 263 | "wrappy": "1" 264 | } 265 | }, 266 | "node_modules/inherits": { 267 | "version": "2.0.4", 268 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 269 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 270 | "dev": true 271 | }, 272 | "node_modules/is-core-module": { 273 | "version": "2.6.0", 274 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", 275 | "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", 276 | "dev": true, 277 | "dependencies": { 278 | "has": "^1.0.3" 279 | }, 280 | "funding": { 281 | "url": "https://github.com/sponsors/ljharb" 282 | } 283 | }, 284 | "node_modules/is-module": { 285 | "version": "1.0.0", 286 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 287 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", 288 | "dev": true 289 | }, 290 | "node_modules/is-reference": { 291 | "version": "1.2.1", 292 | "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", 293 | "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", 294 | "dev": true, 295 | "dependencies": { 296 | "@types/estree": "*" 297 | } 298 | }, 299 | "node_modules/magic-string": { 300 | "version": "0.25.7", 301 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", 302 | "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", 303 | "dev": true, 304 | "dependencies": { 305 | "sourcemap-codec": "^1.4.4" 306 | } 307 | }, 308 | "node_modules/minimatch": { 309 | "version": "3.0.4", 310 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 311 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 312 | "dev": true, 313 | "dependencies": { 314 | "brace-expansion": "^1.1.7" 315 | }, 316 | "engines": { 317 | "node": "*" 318 | } 319 | }, 320 | "node_modules/moment": { 321 | "version": "2.29.1", 322 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", 323 | "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", 324 | "dev": true, 325 | "engines": { 326 | "node": "*" 327 | } 328 | }, 329 | "node_modules/obsidian": { 330 | "version": "0.12.11", 331 | "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.12.11.tgz", 332 | "integrity": "sha512-Kv4m1n4nfd17FzpqHZfqFS2YZAyY+cxAUM7/5jqh1bmbPlmKoNd1XJZC7o9KvkXfTCxALiXfGRdrjHB+GUFAEA==", 333 | "dev": true, 334 | "dependencies": { 335 | "@types/codemirror": "0.0.108", 336 | "moment": "2.29.1" 337 | } 338 | }, 339 | "node_modules/once": { 340 | "version": "1.4.0", 341 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 342 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 343 | "dev": true, 344 | "dependencies": { 345 | "wrappy": "1" 346 | } 347 | }, 348 | "node_modules/path-is-absolute": { 349 | "version": "1.0.1", 350 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 351 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 352 | "dev": true, 353 | "engines": { 354 | "node": ">=0.10.0" 355 | } 356 | }, 357 | "node_modules/path-parse": { 358 | "version": "1.0.7", 359 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 360 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 361 | "dev": true 362 | }, 363 | "node_modules/picomatch": { 364 | "version": "2.3.0", 365 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 366 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 367 | "dev": true, 368 | "engines": { 369 | "node": ">=8.6" 370 | }, 371 | "funding": { 372 | "url": "https://github.com/sponsors/jonschlinkert" 373 | } 374 | }, 375 | "node_modules/resolve": { 376 | "version": "1.20.0", 377 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 378 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 379 | "dev": true, 380 | "dependencies": { 381 | "is-core-module": "^2.2.0", 382 | "path-parse": "^1.0.6" 383 | }, 384 | "funding": { 385 | "url": "https://github.com/sponsors/ljharb" 386 | } 387 | }, 388 | "node_modules/rollup": { 389 | "version": "2.56.3", 390 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.56.3.tgz", 391 | "integrity": "sha512-Au92NuznFklgQCUcV96iXlxUbHuB1vQMaH76DHl5M11TotjOHwqk9CwcrT78+Tnv4FN9uTBxq6p4EJoYkpyekg==", 392 | "dev": true, 393 | "bin": { 394 | "rollup": "dist/bin/rollup" 395 | }, 396 | "engines": { 397 | "node": ">=10.0.0" 398 | }, 399 | "optionalDependencies": { 400 | "fsevents": "~2.3.2" 401 | } 402 | }, 403 | "node_modules/sourcemap-codec": { 404 | "version": "1.4.8", 405 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 406 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 407 | "dev": true 408 | }, 409 | "node_modules/tslib": { 410 | "version": "2.3.1", 411 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 412 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", 413 | "dev": true 414 | }, 415 | "node_modules/typescript": { 416 | "version": "4.4.2", 417 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", 418 | "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", 419 | "dev": true, 420 | "bin": { 421 | "tsc": "bin/tsc", 422 | "tsserver": "bin/tsserver" 423 | }, 424 | "engines": { 425 | "node": ">=4.2.0" 426 | } 427 | }, 428 | "node_modules/wrappy": { 429 | "version": "1.0.2", 430 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 431 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 432 | "dev": true 433 | } 434 | }, 435 | "dependencies": { 436 | "@rollup/plugin-commonjs": { 437 | "version": "18.1.0", 438 | "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-18.1.0.tgz", 439 | "integrity": "sha512-h3e6T9rUxVMAQswpDIobfUHn/doMzM9sgkMrsMWCFLmB84PSoC8mV8tOloAJjSRwdqhXBqstlX2BwBpHJvbhxg==", 440 | "dev": true, 441 | "requires": { 442 | "@rollup/pluginutils": "^3.1.0", 443 | "commondir": "^1.0.1", 444 | "estree-walker": "^2.0.1", 445 | "glob": "^7.1.6", 446 | "is-reference": "^1.2.1", 447 | "magic-string": "^0.25.7", 448 | "resolve": "^1.17.0" 449 | } 450 | }, 451 | "@rollup/plugin-node-resolve": { 452 | "version": "11.2.1", 453 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", 454 | "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", 455 | "dev": true, 456 | "requires": { 457 | "@rollup/pluginutils": "^3.1.0", 458 | "@types/resolve": "1.17.1", 459 | "builtin-modules": "^3.1.0", 460 | "deepmerge": "^4.2.2", 461 | "is-module": "^1.0.0", 462 | "resolve": "^1.19.0" 463 | } 464 | }, 465 | "@rollup/plugin-typescript": { 466 | "version": "8.2.5", 467 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.5.tgz", 468 | "integrity": "sha512-QL/LvDol/PAGB2O0S7/+q2HpSUNodpw7z6nGn9BfoVCPOZ0r4EALrojFU29Bkoi2Hr2jgTocTejJ5GGWZfOxbQ==", 469 | "dev": true, 470 | "requires": { 471 | "@rollup/pluginutils": "^3.1.0", 472 | "resolve": "^1.17.0" 473 | } 474 | }, 475 | "@rollup/pluginutils": { 476 | "version": "3.1.0", 477 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", 478 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", 479 | "dev": true, 480 | "requires": { 481 | "@types/estree": "0.0.39", 482 | "estree-walker": "^1.0.1", 483 | "picomatch": "^2.2.2" 484 | }, 485 | "dependencies": { 486 | "estree-walker": { 487 | "version": "1.0.1", 488 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", 489 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", 490 | "dev": true 491 | } 492 | } 493 | }, 494 | "@types/codemirror": { 495 | "version": "0.0.108", 496 | "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz", 497 | "integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==", 498 | "dev": true, 499 | "requires": { 500 | "@types/tern": "*" 501 | } 502 | }, 503 | "@types/estree": { 504 | "version": "0.0.39", 505 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 506 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 507 | "dev": true 508 | }, 509 | "@types/node": { 510 | "version": "14.17.12", 511 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.12.tgz", 512 | "integrity": "sha512-vhUqgjJR1qxwTWV5Ps5txuy2XMdf7Fw+OrdChRboy8BmWUPkckOhphaohzFG6b8DW7CrxaBMdrdJ47SYFq1okw==", 513 | "dev": true 514 | }, 515 | "@types/resolve": { 516 | "version": "1.17.1", 517 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", 518 | "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", 519 | "dev": true, 520 | "requires": { 521 | "@types/node": "*" 522 | } 523 | }, 524 | "@types/tern": { 525 | "version": "0.23.4", 526 | "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", 527 | "integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==", 528 | "dev": true, 529 | "requires": { 530 | "@types/estree": "*" 531 | } 532 | }, 533 | "balanced-match": { 534 | "version": "1.0.2", 535 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 536 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 537 | "dev": true 538 | }, 539 | "brace-expansion": { 540 | "version": "1.1.11", 541 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 542 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 543 | "dev": true, 544 | "requires": { 545 | "balanced-match": "^1.0.0", 546 | "concat-map": "0.0.1" 547 | } 548 | }, 549 | "builtin-modules": { 550 | "version": "3.2.0", 551 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", 552 | "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", 553 | "dev": true 554 | }, 555 | "commondir": { 556 | "version": "1.0.1", 557 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 558 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 559 | "dev": true 560 | }, 561 | "concat-map": { 562 | "version": "0.0.1", 563 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 564 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 565 | "dev": true 566 | }, 567 | "deepmerge": { 568 | "version": "4.2.2", 569 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 570 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", 571 | "dev": true 572 | }, 573 | "estree-walker": { 574 | "version": "2.0.2", 575 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 576 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 577 | "dev": true 578 | }, 579 | "fs.realpath": { 580 | "version": "1.0.0", 581 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 582 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 583 | "dev": true 584 | }, 585 | "fsevents": { 586 | "version": "2.3.2", 587 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 588 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 589 | "dev": true, 590 | "optional": true 591 | }, 592 | "function-bind": { 593 | "version": "1.1.1", 594 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 595 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 596 | "dev": true 597 | }, 598 | "glob": { 599 | "version": "7.1.7", 600 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 601 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 602 | "dev": true, 603 | "requires": { 604 | "fs.realpath": "^1.0.0", 605 | "inflight": "^1.0.4", 606 | "inherits": "2", 607 | "minimatch": "^3.0.4", 608 | "once": "^1.3.0", 609 | "path-is-absolute": "^1.0.0" 610 | } 611 | }, 612 | "has": { 613 | "version": "1.0.3", 614 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 615 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 616 | "dev": true, 617 | "requires": { 618 | "function-bind": "^1.1.1" 619 | } 620 | }, 621 | "inflight": { 622 | "version": "1.0.6", 623 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 624 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 625 | "dev": true, 626 | "requires": { 627 | "once": "^1.3.0", 628 | "wrappy": "1" 629 | } 630 | }, 631 | "inherits": { 632 | "version": "2.0.4", 633 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 634 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 635 | "dev": true 636 | }, 637 | "is-core-module": { 638 | "version": "2.6.0", 639 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", 640 | "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", 641 | "dev": true, 642 | "requires": { 643 | "has": "^1.0.3" 644 | } 645 | }, 646 | "is-module": { 647 | "version": "1.0.0", 648 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 649 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", 650 | "dev": true 651 | }, 652 | "is-reference": { 653 | "version": "1.2.1", 654 | "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", 655 | "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", 656 | "dev": true, 657 | "requires": { 658 | "@types/estree": "*" 659 | } 660 | }, 661 | "magic-string": { 662 | "version": "0.25.7", 663 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", 664 | "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", 665 | "dev": true, 666 | "requires": { 667 | "sourcemap-codec": "^1.4.4" 668 | } 669 | }, 670 | "minimatch": { 671 | "version": "3.0.4", 672 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 673 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 674 | "dev": true, 675 | "requires": { 676 | "brace-expansion": "^1.1.7" 677 | } 678 | }, 679 | "moment": { 680 | "version": "2.29.1", 681 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", 682 | "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", 683 | "dev": true 684 | }, 685 | "obsidian": { 686 | "version": "0.12.11", 687 | "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.12.11.tgz", 688 | "integrity": "sha512-Kv4m1n4nfd17FzpqHZfqFS2YZAyY+cxAUM7/5jqh1bmbPlmKoNd1XJZC7o9KvkXfTCxALiXfGRdrjHB+GUFAEA==", 689 | "dev": true, 690 | "requires": { 691 | "@types/codemirror": "0.0.108", 692 | "moment": "2.29.1" 693 | } 694 | }, 695 | "once": { 696 | "version": "1.4.0", 697 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 698 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 699 | "dev": true, 700 | "requires": { 701 | "wrappy": "1" 702 | } 703 | }, 704 | "path-is-absolute": { 705 | "version": "1.0.1", 706 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 707 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 708 | "dev": true 709 | }, 710 | "path-parse": { 711 | "version": "1.0.7", 712 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 713 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 714 | "dev": true 715 | }, 716 | "picomatch": { 717 | "version": "2.3.0", 718 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 719 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 720 | "dev": true 721 | }, 722 | "resolve": { 723 | "version": "1.20.0", 724 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 725 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 726 | "dev": true, 727 | "requires": { 728 | "is-core-module": "^2.2.0", 729 | "path-parse": "^1.0.6" 730 | } 731 | }, 732 | "rollup": { 733 | "version": "2.56.3", 734 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.56.3.tgz", 735 | "integrity": "sha512-Au92NuznFklgQCUcV96iXlxUbHuB1vQMaH76DHl5M11TotjOHwqk9CwcrT78+Tnv4FN9uTBxq6p4EJoYkpyekg==", 736 | "dev": true, 737 | "requires": { 738 | "fsevents": "~2.3.2" 739 | } 740 | }, 741 | "sourcemap-codec": { 742 | "version": "1.4.8", 743 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 744 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 745 | "dev": true 746 | }, 747 | "tslib": { 748 | "version": "2.3.1", 749 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 750 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", 751 | "dev": true 752 | }, 753 | "typescript": { 754 | "version": "4.4.2", 755 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", 756 | "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", 757 | "dev": true 758 | }, 759 | "wrappy": { 760 | "version": "1.0.2", 761 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 762 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 763 | "dev": true 764 | } 765 | } 766 | } 767 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-sample-plugin", 3 | "version": "0.12.0", 4 | "description": "This is a sample plugin for Obsidian (https://obsidian.md)", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "rollup --config rollup.config.js -w", 8 | "build": "rollup --config rollup.config.js --environment BUILD:production" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "@rollup/plugin-commonjs": "^18.0.0", 15 | "@rollup/plugin-node-resolve": "^11.2.1", 16 | "@rollup/plugin-typescript": "^8.2.1", 17 | "@types/node": "^14.14.37", 18 | "obsidian": "^0.12.0", 19 | "rollup": "^2.32.1", 20 | "tslib": "^2.2.0", 21 | "typescript": "^4.2.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from '@rollup/plugin-typescript'; 2 | import {nodeResolve} from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | 5 | const isProd = (process.env.BUILD === 'production'); 6 | 7 | const banner = 8 | `/* 9 | THIS IS A GENERATED/BUNDLED FILE BY ROLLUP 10 | if you want to view the source visit the plugins github repository 11 | */ 12 | `; 13 | 14 | export default { 15 | input: 'main.ts', 16 | output: { 17 | dir: '.', 18 | sourcemap: 'inline', 19 | sourcemapExcludeSources: isProd, 20 | format: 'cjs', 21 | exports: 'default', 22 | banner, 23 | }, 24 | external: ['obsidian'], 25 | plugins: [ 26 | typescript(), 27 | nodeResolve({browser: true}), 28 | commonjs(), 29 | ] 30 | }; -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildspecial/obsidian-mirror/c32614d4b893578bb4bfd7ca05326f7c649c904e/styles.css -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "es6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "lib": [ 13 | "dom", 14 | "es5", 15 | "scripthost", 16 | "es2015" 17 | ] 18 | }, 19 | "include": [ 20 | "**/*.ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "1.0.1": "0.9.12", 3 | "1.0.0": "0.9.7" 4 | } 5 | --------------------------------------------------------------------------------