You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10 lines
39 KiB
10 lines
39 KiB
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var oe=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var Ie=Object.prototype.hasOwnProperty;var Se=(g,t)=>{for(var e in t)oe(g,e,{get:t[e],enumerable:!0})},Ae=(g,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ce(t))!Ie.call(g,s)&&s!==e&&oe(g,s,{get:()=>t[s],enumerable:!(n=xe(t,s))||n.enumerable});return g};var De=g=>Ae(oe({},"__esModule",{value:!0}),g);var He={};Se(He,{default:()=>re});module.exports=De(He);var ae=require("obsidian");var I=require("obsidian");var Pe=require("obsidian");var j=class{constructor(){this.values=new Map}put(t,e){this.values.set(t,e)}get(t,e){var n;return(n=this.values.get(t))!=null?n:e}getOrNull(t){var e;return(e=this.values.get(t))!=null?e:null}getFirst(t,e){for(let n=0;n<t.length;n++){let s=t[n];if(this.containsKey(s))return this.get(s,e)}return e}containsKey(t){return this.values.has(t)}getKeys(){return Array.from(this.values.keys())}removeKey(t){return this.values.delete(t)}clear(){this.values.clear()}};var le=require("obsidian"),R=class{static getFilePathWithNewExtension(t,e){var n;return(0,le.normalizePath)(`${(n=t.parent)==null?void 0:n.path}/${t.basename}.${e}`)}static getFilePathExcludingExtension(t){var e;return(0,le.normalizePath)(`${(e=t.parent)==null?void 0:e.path}/${t.basename}`)}};var o=class o{static init(t){o.vaultFileAdapter=t}static setExternalFilePaths(t){o.externalFilePaths=t}static setActive(t){o.isActive=t,o.isActive||this.clear()}static setAutoExpire(t){o.baseMinutesToExpire=t!=null?t:0,o.updateExpiryTime()}static getLevel(){return o.level}static setLevel(t){if(o.level!=t){if(o.allLevels.contains(t)){o.level=t;return}o.level=o.LevelFilename,this.clear()}}static updateExpiryTime(){o.baseMinutesToExpire==0||o.baseMinutesToExpire==null?o.expiryTime=null:o.expiryTime=Date.now()+o.baseMinutesToExpire*1e3*60}static putByFile(t,e){if(!o.isActive)return;let n=o.getFileCacheKey(e);this.putByKey(n,t),o.updateExpiryTime()}static async getByFile(t){if(!o.isActive)return o.blankPasswordAndHint;this.clearIfExpired(),o.updateExpiryTime();let e=o.getFileCacheKey(t);return await this.getByKeyAsync(e,o.blankPasswordAndHint)}static putByPath(t,e){if(!o.isActive)return;let n=o.getPathCacheKey(e);this.putByKey(n,t),o.updateExpiryTime()}static getByPath(t){if(!o.isActive)return o.blankPasswordAndHint;this.clearIfExpired(),o.updateExpiryTime();let e=o.getPathCacheKey(t);return this.getByKey(e,o.blankPasswordAndHint)}static async getByPathAsync(t){if(!o.isActive)return o.blankPasswordAndHint;this.clearIfExpired(),o.updateExpiryTime();let e=o.getPathCacheKey(t);return await this.getByKeyAsync(e,o.blankPasswordAndHint)}static getPathCacheKey(t){return o.level==o.LevelExternalFile||o.level==o.LevelVault?"$"+o.level:o.level==o.LevelParentPath?t.split("/").slice(0,-1).join("/"):t}static getFileCacheKey(t){return o.level==o.LevelExternalFile||o.level==o.LevelVault?"$"+o.level:o.level==o.LevelParentPath?t.parent.path:R.getFilePathExcludingExtension(t)}static clearIfExpired(){o.expiryTime!=null&&(Date.now()<o.expiryTime||this.clear())}static clearForFile(t){let e=o.getFileCacheKey(t);this.cache.removeKey(e)}static clear(){let t=this.cache.getKeys().length;return this.cache.clear(),t}static putByKey(t,e){o.level!=o.LevelExternalFile&&this.cache.put(t,e)}static getByKey(t,e){return console.debug("SessionPasswordService.getByKey",{level:o.level,key:t,defaultValue:e}),this.cache.get(t,e)}static async getByKeyAsync(t,e){if(o.level==o.LevelExternalFile){for(let n=0;n<this.externalFilePaths.length;n++){let s=this.externalFilePaths[n];try{return{password:await this.fetchFileContents(s),hint:""}}catch(i){console.error(i,{relFilePath:s})}}return new Pe.Notice("External password file not found",1e4),e}return this.cache.get(t,e)}static async canFetchContents(t){if(o.vaultFileAdapter==null)return!1;try{let e=await this.fetchFileContents(t);return!0}catch(e){return!1}}static async fetchFileContents(t){if(o.vaultFileAdapter==null)throw new Error("SessionPasswordService.vaultFileAdapter == null");let e=o.vaultFileAdapter.getResourcePath(t),s=await(await fetch(e)).text();if(s.length==0)throw new Error("File contents empty");return s}};o.vaultFileAdapter=null,o.isActive=!0,o.blankPasswordAndHint={password:"",hint:""},o.cache=new j,o.baseMinutesToExpire=0,o.expiryTime=null,o.LevelFilename="filename",o.LevelParentPath="parentPath",o.LevelVault="vault",o.LevelExternalFile="externalFile",o.allLevels=[o.LevelFilename,o.LevelParentPath,o.LevelVault,o.LevelExternalFile],o.level=o.LevelVault,o.externalFilePaths=[];var p=o;var K=class extends I.PluginSettingTab{constructor(t,e,n,s){super(t,e),this.plugin=e,this.settings=n,this.features=s}display(){let{containerEl:t}=this;t.empty(),new I.Setting(t).setName("Confirm password?").setDesc("Confirm password when encrypting. (Recommended)").addToggle(r=>{r.setValue(this.settings.confirmPassword).onChange(async a=>{this.settings.confirmPassword=a,await this.plugin.saveSettings()})});let e=()=>{if(!this.settings.rememberPassword){s.settingEl.hide(),n.settingEl.hide();return}this.settings.rememberPasswordLevel!=p.LevelExternalFile?(s.settingEl.show(),i.settingEl.hide()):(s.settingEl.hide(),i.settingEl.show()),n.settingEl.show();let r=this.settings.rememberPasswordTimeout,a=`For ${r} minutes`;r==0&&(a="Until Obsidian is closed"),s.setName(`Remember Password (${a})`)};new I.Setting(t).setName("Remember password?").setDesc("Remember the last used passwords when encrypting or decrypting. Passwords are remembered until they timeout or Obsidian is closed").addToggle(r=>{r.setValue(this.settings.rememberPassword).onChange(async a=>{this.settings.rememberPassword=a,await this.plugin.saveSettings(),p.setActive(this.settings.rememberPassword),e()})});let n=new I.Setting(t).setName("Remember passwords by:").setDesc(this.buildRememberPasswordDescription()).addDropdown(r=>{r.addOption(p.LevelVault,"Vault").addOption(p.LevelParentPath,"Folder").addOption(p.LevelFilename,"File").addOption(p.LevelExternalFile,"External File").setValue(this.settings.rememberPasswordLevel).onChange(async a=>{console.debug("rememberPasswordLevelSetting.onChange",{value:a}),this.settings.rememberPasswordLevel=a,await this.plugin.saveSettings(),p.setLevel(this.settings.rememberPasswordLevel),e()})}),s=new I.Setting(t).setDesc("The number of minutes to remember passwords.").addSlider(r=>{r.setLimits(0,120,5).setValue(this.settings.rememberPasswordTimeout).onChange(async a=>{this.settings.rememberPasswordTimeout=a,await this.plugin.saveSettings(),p.setAutoExpire(this.settings.rememberPasswordTimeout),e()})}),i=new I.Setting(t).setName("External File Paths").setDesc("When needed the password is read from one of these filepaths. Paths must be relative to vault root").addTextArea(r=>{r.setValue(this.settings.rememberPasswordExternalFilePaths.join(`
|
|
`)).onChange(async a=>{this.settings.rememberPasswordExternalFilePaths=a.trim().split(`
|
|
`),await this.plugin.saveSettings(),p.setExternalFilePaths(this.settings.rememberPasswordExternalFilePaths)}),r.inputEl.placeholder="Enter one relative path per line",r.inputEl.style.whiteSpace="pre",r.inputEl.style.width="100%",r.inputEl.rows=4}).addButton(r=>{r.setIcon("check").setTooltip("Check Paths").onClick(async()=>{let a=this.settings.rememberPasswordExternalFilePaths;for(let l of a)await p.canFetchContents(l)?new I.Notice(`\u2714\uFE0F ${l}`):new I.Notice(`\u274C ${l}`)})});i.controlEl.style.width="80%",e(),this.features.forEach(r=>{r.buildSettingsUi(t,async()=>await this.plugin.saveSettings())})}buildRememberPasswordDescription(){let t=new DocumentFragment,e=t.createEl("table").createTBody(),n=e.createEl("tr");return n.createEl("th",{text:"Vault:",attr:{align:"right"}}),n.createEl("td",{text:"Typically, you'll use the same password every time."}),n=e.createEl("tr"),n.createEl("th",{text:"Folder:",attr:{align:"right"}}),n.createEl("td",{text:"Typically, you'll use the same password for each note within a folder."}),n=e.createEl("tr"),n.createEl("th",{text:"File:",attr:{align:"right"}}),n.createEl("td",{text:"Typically, each note will have a unique password."}),n=e.createEl("tr"),n.createEl("th",{text:"External File:",attr:{align:"right",style:"width:12em;"}}),n.createEl("td",{text:"When needed the password/key is read from one of these filepaths."}),t}};var x=require("obsidian");var M=require("obsidian"),V=class extends M.Modal{constructor(e,n,s=""){super(e);this.decryptInPlace=!1;this.save=!1;this.canDecryptInPlace=!0;this.titleEl.setText(n),this.text=s}onOpen(){var r;let{contentEl:e}=this;e.empty(),e.classList.add("meld-encrypt-decrypt-modal");let n;(r=new M.Setting(e).addTextArea(a=>{n=a,a.setValue(this.text),a.inputEl.setSelectionRange(0,0),a.inputEl.rows=10}).settingEl.querySelector(".setting-item-info"))==null||r.remove();let i=new M.Setting(e);i.addButton(a=>{a.setButtonText("Save").onClick(l=>{this.save=!0,this.text=n.getValue(),this.close()})}),i.addButton(a=>{a.setButtonText("Copy").onClick(l=>{navigator.clipboard.writeText(n.getValue()),new M.Notice("Copied!")})}),this.canDecryptInPlace&&i.addButton(a=>{a.setWarning().setButtonText("Decrypt in-place").onClick(l=>{this.decryptInPlace=!0,this.text=n.getValue(),this.close()})})}};var E=require("obsidian");var X=require("obsidian"),A=class{static isSettingsModalOpen(){return document.querySelector(".mod-settings")!==null}static buildPasswordSetting({container:t,name:e,desc:n="",autoFocus:s=!1,placeholder:i="",initialValue:r="",onChangeCallback:a,onEnterCallback:l}){let c=new X.Setting(t).setName(e).setDesc(n).addButton(h=>{h.setIcon("reading-glasses").onClick(y=>{let w=c.components.find((f,d,u)=>f instanceof X.TextComponent);w instanceof X.TextComponent&&(w.inputEl.type=w.inputEl.type=="password"?"text":"password")})}).addText(h=>{h.setPlaceholder(i),h.setValue(r),h.inputEl.type="password",a!=null&&h.onChange(a),l!=null&&(h.inputEl.onkeydown=y=>{y.key==="Enter"&&(y.preventDefault(),l(h.getValue()))}),s&&setTimeout(()=>h.inputEl.focus(),0)});return c}};var H=class extends E.Modal{constructor(e,n,s,i,r=null,a=null,l=!1){super(e);this.defaultPassword=null;this.resultConfirmed=!1;this.resultPassword=null;this.resultShowInReadingView=null;this.resultTextToEncrypt=null;this.defaultPassword=r,this.confirmPassword=s,this.showInReadingView=i,this.isEncrypting=n,this.defaultHint=a!=null?a:"",this.showTextToEncrypt=l}onOpen(){var f;let{contentEl:e}=this;e.empty(),e.classList.add("meld-encrypt-password-modal"),this.invalidate();let n=(f=this.defaultPassword)!=null?f:"",s="",i=this.defaultHint,r=this.showInReadingView,a="";new E.Setting(e).setHeading().setName(this.isEncrypting?"Encrypting":"Decrypting"),A.buildPasswordSetting({container:e,name:"Password:",placeholder:this.isEncrypting||i.length==0?"":`Hint: ${i}`,initialValue:n,autoFocus:!0,onChangeCallback:d=>{n=d,this.invalidate()},onEnterCallback:d=>{if(n=d,this.invalidate(),n.length>0)if(l.settingEl.isShown()){let u=l.components.find(m=>m instanceof E.TextComponent);u instanceof E.TextComponent&&u.inputEl.focus()}else if(c.settingEl.isShown()){let u=c.components.find(m=>m instanceof E.TextComponent);u instanceof E.TextComponent&&u.inputEl.focus()}else w()&&this.close()}});let l=A.buildPasswordSetting({container:e,name:"Confirm Password:",onChangeCallback:d=>{s=d,this.invalidate()},onEnterCallback:d=>{if(s=d,this.invalidate(),s.length>0&&w()&&c.settingEl.isShown()){let u=c.components.find(m=>m instanceof E.TextComponent);u instanceof E.TextComponent&&u.inputEl.focus()}}});this.confirmPassword||l.settingEl.hide();let c=new E.Setting(e).setName("Optional Password Hint").addText(d=>{d.inputEl.placeholder="Password Hint",d.setValue(i),d.onChange(u=>i=u),d.inputEl.on("keypress","*",(u,m)=>{u.key=="Enter"&&m instanceof HTMLInputElement&&m.value.length>0&&(u.preventDefault(),w()&&this.close())})});this.isEncrypting||c.settingEl.hide();let h=new E.Setting(e).setName("Show encrypted marker in Reading view").addToggle(d=>{d.setValue(r).onChange(u=>{r=u})});this.isEncrypting||h.settingEl.hide();let y=new E.Setting(e).setName("Text to encrypt").addTextArea(d=>{d.setValue("").onChange(u=>a=u),d.inputEl.rows=5,d.inputEl.style.width="100%"});this.showTextToEncrypt||y.settingEl.hide(),new E.Setting(e).addButton(d=>{d.setButtonText("Confirm").onClick(u=>{w()&&this.close()})});let w=()=>(this.invalidate(),l.setDesc(""),this.confirmPassword&&n!=s?(l.setDesc("Passwords don't match"),!1):(this.resultConfirmed=!0,this.resultPassword=n,this.resultHint=i,this.resultShowInReadingView=r,this.resultTextToEncrypt=a,!0))}invalidate(){this.resultConfirmed=!1,this.resultPassword=null,this.resultHint="",this.resultTextToEncrypt=""}};var ce=new TextEncoder,ke=new TextDecoder,Le=1e3,Be=ce.encode("XHWnDAT6ehMVY2zD"),W=class{async deriveKey(t){let e=ce.encode(t),n=await crypto.subtle.importKey("raw",e,{name:"PBKDF2"},!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",hash:{name:"SHA-256"},iterations:Le,salt:Be},n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async encryptToBytes(t,e){let n=await this.deriveKey(e),s=ce.encode(t),i=crypto.getRandomValues(new Uint8Array(16)),r=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:i},n,s)),a=new Uint8Array(i.byteLength+r.byteLength);return a.set(i,0),a.set(r,i.byteLength),a}convertToString(t){let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return e}async encryptToBase64(t,e){let n=await this.encryptToBytes(t,e);return btoa(this.convertToString(n))}stringToArray(t){let e=[];for(let n=0;n<t.length;n++)e.push(t.charCodeAt(n));return new Uint8Array(e)}async decryptFromBytes(t,e){try{let n=t.slice(0,16),s=t.slice(16),i=await this.deriveKey(e),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:n},i,s);return ke.decode(r)}catch(n){return null}}async decryptFromBase64(t,e){try{let n=this.stringToArray(atob(t));return await this.decryptFromBytes(n,e)}catch(n){return null}}};var O=class{constructor(t,e,n){this.vectorSize=t,this.saltSize=e,this.iterations=n}async deriveKey(t,e){let s=new TextEncoder().encode(t),i=await crypto.subtle.importKey("raw",s,"PBKDF2",!1,["deriveKey"]);return await crypto.subtle.deriveKey({name:"PBKDF2",hash:"SHA-512",salt:e,iterations:this.iterations},i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async encryptToBytes(t,e){let n=crypto.getRandomValues(new Uint8Array(this.saltSize)),s=await this.deriveKey(e,n),r=new TextEncoder().encode(t),a=crypto.getRandomValues(new Uint8Array(this.vectorSize)),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:a},s,r)),c=new Uint8Array(a.byteLength+n.byteLength+l.byteLength);return c.set(a,0),c.set(n,a.byteLength),c.set(l,a.byteLength+n.byteLength),c}convertToString(t){let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return e}async encryptToBase64(t,e){let n=await this.encryptToBytes(t,e);return btoa(this.convertToString(n))}stringToArray(t){let e=[];for(let n=0;n<t.length;n++)e.push(t.charCodeAt(n));return new Uint8Array(e)}async decryptFromBytes(t,e){try{let n,s;n=0,s=n+this.vectorSize;let i=t.slice(n,s);n=s,s=n+this.saltSize;let r=t.slice(n,s);n=s,s=void 0;let a=t.slice(n),l=await this.deriveKey(e,r),c=await crypto.subtle.decrypt({name:"AES-GCM",iv:i},l,a);return new TextDecoder().decode(c)}catch(n){return null}}async decryptFromBase64(t,e){try{let n=this.stringToArray(atob(t));return await this.decryptFromBytes(n,e)}catch(n){return null}}};var pe={name:"AES-GCM",iv:new Uint8Array([196,190,240,190,188,78,41,132,15,220,84,211]),tagLength:128},J=class{async buildKey(t){let n=new TextEncoder().encode(t),s=await crypto.subtle.digest({name:"SHA-256"},n);return await crypto.subtle.importKey("raw",s,pe,!1,["encrypt","decrypt"])}async encryptToBase64(t,e){let n=await this.buildKey(e),i=new TextEncoder().encode(t),r=new Uint8Array(await crypto.subtle.encrypt(pe,n,i));return btoa(String.fromCharCode(...r))}stringToArray(t){let e=[];for(let n=0;n<t.length;n++)e.push(t.charCodeAt(n));return new Uint8Array(e)}async decryptFromBase64(t,e){try{let n=this.stringToArray(atob(t)),s=await this.buildKey(e),i=await crypto.subtle.decrypt(pe,s,n);return new TextDecoder().decode(i)}catch(n){return null}}};var D=class g{static BuildDefault(){return new O(16,16,21e4)}static BuildFromFileDataOrThrow(t){let e=g.BuildFromFileDataOrNull(t);if(e!=null)return e;throw new Error(`Unable to determine ICryptoHelper for File ver ${t.version}`)}static BuildFromFileDataOrNull(t){return t.version=="1.0"?new W:t.version=="2.0"?new O(16,16,21e4):null}static BuildFromDecryptableOrThrow(t){let e=g.BuildFromDecryptableOrNull(t);if(e!=null)return e;throw new Error(`Unable to determine ICryptoHelper for Decryptable ver ${t.version}`)}static BuildFromDecryptableOrNull(t){return t.version==0?new J:t.version==1?new W:t.version==2?new O(16,16,21e4):null}};var q=class{};var Q="%%\u{1F510}\u03B2 ",Z="\u{1F510}\u03B2 ",de="%%\u{1F510}\u03B1 ",ue="\u{1F510}\u03B1 ",he="%%\u{1F510} ",ge="\u{1F510} ",ve=Q,be=Z,B=[Q,Z,de,ue,he,ge],fe=" \u{1F510}%%",ye=" \u{1F510}",N=[fe,ye],k="\u{1F4A1}";var Y=class{constructor(t){this.process(t)}process(t){var e,n;if(this.processedText=t,this.isEmpty=t.length===0,this.prefix=(e=B.find(s=>t.startsWith(s)))!=null?e:"",this.suffix=(n=N.find(s=>t.endsWith(s)))!=null?n:"",this.hasEncryptedPrefix=this.prefix.length>0,this.hasEncryptedSuffix=this.suffix.length>0,this.hasObsoleteEncryptedPrefix=this.prefix===he||this.prefix===ge,this.containsEncryptedMarkers=[...B,...N].some(s=>t.includes(s)),this.canDecrypt=this.hasEncryptedPrefix&&this.hasEncryptedSuffix,this.canEncrypt=!this.hasEncryptedPrefix&&!this.containsEncryptedMarkers,this.canDecrypt){let s=this.parseDecryptableContent(t);s!=null?this.decryptable=s:this.canDecrypt=!1}}parseDecryptableContent(t){let e=new q;if(!this.hasEncryptedPrefix||!this.hasEncryptedSuffix)return null;this.hasObsoleteEncryptedPrefix?e.version=0:this.prefix==Q||this.prefix==Z?e.version=2:(this.prefix==de||this.prefix==ue)&&(e.version=1);let n=t.substring(this.prefix.length,t.length-this.suffix.length);if([...B,...N].some(s=>n.includes(s)))return null;if(n.substring(0,k.length)==k){let s=n.indexOf(k,k.length);if(s<0)return null;e.hint=n.substring(k.length,s),e.base64CipherText=n.substring(s+k.length)}else e.base64CipherText=n;return e.showInReadingView=!this.prefix.includes("%%"),e}};var Fe=2e3,$=class{async onload(t,e){this.plugin=t,this.pluginSettings=e,this.featureSettings=e.featureInplaceEncrypt,this.plugin.registerMarkdownPostProcessor((n,s)=>this.processEncryptedCodeBlockProcessor(n,s)),t.addCommand({id:"meld-encrypt-in-place",name:"Encrypt/Decrypt In-place",icon:"file-lock",editorCheckCallback:(n,s,i)=>this.processEncryptDecryptCommand(n,s,!1)}),this.plugin.addRibbonIcon("file-lock","Encrypt/Decrypt In-place",n=>{let s=this.plugin.app.workspace.getActiveViewOfType(x.MarkdownView);if(s!=null)return this.processEncryptDecryptCommand(!1,s.editor,!1)})}onunload(){}replaceMarkersRecursive(t,e=0){if(t instanceof HTMLElement){for(let s of Array.from(t.childNodes)){var n=this.replaceMarkersRecursive(s,e+1);s.replaceWith(...n)}return[t]}if(t instanceof Text){let s=t.textContent;if(s==null)return[t];if(!s.contains("\u{1F510}"))return[t];let i=/🔐(.*?)🔐/g,r=s.split(i),a=[];for(let l=0;l<r.length;l++){let c=r[l];if(l%2!=0){let h=createSpan({cls:"meld-encrypt-inline-reading-marker",text:"\u{1F510}",attr:{"data-meld-encrypt-encrypted":`\u{1F510}${c}\u{1F510}`}});a.push(h)}else a.push(new Text(c))}return a}return[t]}async processEncryptedCodeBlockProcessor(t,e){let n=this.replaceMarkersRecursive(t);t.replaceWith(...n);let s=t.querySelectorAll(".meld-encrypt-inline-reading-marker");this.bindReadingIndicatorEventHandlers(e.sourcePath,s)}bindReadingIndicatorEventHandlers(t,e){e.forEach(n=>{let s=n;s!=null&&s.onClickEvent(async i=>{let r=i.target;if(r==null)return;let a=r.dataset.meldEncryptEncrypted;if(a==null)return;let l=new Y(a);await this.handleReadingIndicatorClick(t,l.decryptable)})})}async handleReadingIndicatorClick(t,e){if(e==null){new x.Notice("\u274C Decryption failed!");return}if(await this.showDecryptedTextIfPasswordKnown(t,e))return;let n=await this.fetchPasswordFromUser(e.hint);n!=null&&(await this.showDecryptedResultForPassword(e,n)?p.putByPath({password:n,hint:e.hint},t):new x.Notice("\u274C Decryption failed!"))}async showDecryptedResultForPassword(t,e){let s=await D.BuildFromDecryptableOrThrow(t).decryptFromBase64(t.base64CipherText,e);return s===null?!1:new Promise(i=>{let r=new V(this.plugin.app,"\u{1F513}",s);r.canDecryptInPlace=!1,r.onClose=()=>{i(!0)},r.open()})}async fetchPasswordFromUser(t){return new Promise(e=>{let n=new H(this.plugin.app,!1,!1,this.featureSettings.showMarkerWhenReadingDefault,"",t);n.onClose=()=>{e(n.resultPassword)},n.open()})}async showDecryptedTextIfPasswordKnown(t,e){let n=await p.getByPathAsync(t);return n.password==null?!1:await this.showDecryptedResultForPassword(e,n.password)}buildSettingsUi(t,e){new x.Setting(t).setHeading().setName("In-place encryption"),new x.Setting(t).setName("Expand selection to whole line?").setDesc("Partial selections will get expanded to the whole line.").addToggle(n=>{n.setValue(this.featureSettings.expandToWholeLines).onChange(async s=>{this.featureSettings.expandToWholeLines=s,await e()})}),new x.Setting(t).setName("By default, show encrypted marker when reading").setDesc("When encrypting inline text, should the default be to have a visible marker in Reading view?").addToggle(n=>{n.setValue(this.featureSettings.showMarkerWhenReadingDefault).onChange(async s=>{this.featureSettings.showMarkerWhenReadingDefault=s,await e()})})}processEncryptDecryptCommand(t,e,n){if(t&&A.isSettingsModalOpen())return!0;let s=e.getCursor("from"),i=e.getCursor("to");if(this.featureSettings.expandToWholeLines){s={line:s.line,ch:0};let l=i.line,c=e.getLine(l);i={line:l,ch:c.length}}else if(!e.somethingSelected()){let a=this.getClosestPrefixCursorPos(e,Fe),l=this.getClosestSuffixCursorPos(e,Fe);if(a==null||l==null||s.line<a.line||i.line>l.line)return this.promptForTextToEncrypt(t,e,s);s=a,i=l}let r=e.getRange(s,i);return this.processSelection(t,e,r,s,i,n)}promptForTextToEncrypt(t,e,n){let s=this.plugin.app.workspace.getActiveFile();if(s==null)return!1;if(t)return!0;let i="",r="";if(this.pluginSettings.rememberPassword){let c=p.getByPath(s.path);i=c.password,r=c.hint}let a=this.pluginSettings.confirmPassword,l=new H(this.plugin.app,!0,a,this.featureSettings.showMarkerWhenReadingDefault,i,r,!0);return l.onClose=async()=>{var f,d,u,m;if(!l.resultConfirmed)return;let c=(f=l.resultPassword)!=null?f:"",h=(d=l.resultHint)!=null?d:"",y=(u=l.resultTextToEncrypt)!=null?u:"",w=new ee;w.text=y,w.hint=h,this.encryptSelection(e,w,c,n,n,(m=l.resultShowInReadingView)!=null?m:this.featureSettings.showMarkerWhenReadingDefault),p.putByPath({password:c,hint:h},s.path)},l.open(),!1}getClosestPrefixCursorPos(t,e){let n=B.reduce((r,a,l)=>l==0||a.length>r.length?a:r),s=t.posToOffset(t.getCursor("from"))+n.length,i=Math.max(s-e,0);for(let r=s;r>=i;r--){let a=t.offsetToPos(r);for(let l of B){let c=r-l.length,h=t.offsetToPos(c);if(t.getRange(h,a)==l)return t.offsetToPos(c)}}return null}getClosestSuffixCursorPos(t,e){let n=B.reduce((a,l,c)=>c==0||l.length>a.length?l:a),s=t.posToOffset(t.getCursor("from"))-n.length+1,i=t.lastLine(),r=Math.min(s+e,t.posToOffset({line:i,ch:t.getLine(i).length}));for(let a=s;a<=r;a++){let l=t.offsetToPos(a);for(let c of N){let h=a+c.length,y=t.offsetToPos(h);if(t.getRange(l,y)==c)return y}}return null}processSelection(t,e,n,s,i,r,a=!0){var d;let l=new Y(n);if(l.isEmpty)return t||new x.Notice("Nothing to Encrypt."),!1;if(!l.canDecrypt&&!l.canEncrypt)return t||new x.Notice("Unable to Encrypt or Decrypt that."),!1;if(l.canEncrypt&&!a)return!1;let c=this.plugin.app.workspace.getActiveFile();if(c==null)return!1;if(t)return!0;let h="",y=(d=l.decryptable)==null?void 0:d.hint;if(this.pluginSettings.rememberPassword){let u=p.getByPath(c.path);h=u.password,y=y!=null?y:u.hint}let w=l.canEncrypt&&this.pluginSettings.confirmPassword,f=new H(this.plugin.app,l.canEncrypt,w,this.featureSettings.showMarkerWhenReadingDefault,h,y);return f.onClose=async()=>{var we,me,Ee;if(!f.resultConfirmed)return;let u=(we=f.resultPassword)!=null?we:"",m=(me=f.resultHint)!=null?me:"";if(l.canEncrypt){let G=new ee;G.text=n,G.hint=m,this.encryptSelection(e,G,u,s,i,(Ee=f.resultShowInReadingView)!=null?Ee:this.featureSettings.showMarkerWhenReadingDefault),p.putByPath({password:u,hint:m},c.path)}else l.decryptable&&await this.decryptSelection(e,l.decryptable,u,s,i,r)&&p.putByPath({password:u,hint:m},c.path)},f.open(),!0}async encryptSelection(t,e,n,s,i,r){let a=D.BuildDefault(),l=this.encodeEncryption(await a.encryptToBase64(e.text,n),e.hint,r);t.setSelection(s,i),t.replaceSelection(l)}async decryptSelection(t,e,n,s,i,r){let l=await D.BuildFromDecryptableOrThrow(e).decryptFromBase64(e.base64CipherText,n);if(l===null)return new x.Notice("\u274C Decryption failed!"),!1;if(r)t.setSelection(s,i),t.replaceSelection(l);else{let c=new V(this.plugin.app,"\u{1F513}",l);c.onClose=async()=>{var h;if(t.focus(),c.decryptInPlace)t.setSelection(s,i),t.replaceSelection(c.text);else if(c.save){let y=D.BuildDefault(),w=this.encodeEncryption(await y.encryptToBase64(c.text,n),(h=e.hint)!=null?h:"",e.showInReadingView);t.setSelection(s,i),t.replaceSelection(w)}},c.open()}return!0}encodeEncryption(t,e,n){if(!B.some(s=>t.includes(s))&&!N.some(s=>t.includes(s))){let s=n?be:ve,i=n?ye:fe;return e.length>0?s.concat(k,e,k,t,i):s.concat(t,i)}return t}},ee=class{};var T=require("obsidian");var b=require("obsidian");var S=class extends b.Modal{constructor(e,n,s,i,r){super(e);this.resultConfirmed=!1;this.title=n,this.defaultPassword=r,this.confirmPassword=i,this.isEncrypting=s}onOpen(){var c,h,y,w;let{contentEl:e}=this;e.empty(),this.invalidate();let n=(h=(c=this.defaultPassword)==null?void 0:c.password)!=null?h:"",s="",i=(w=(y=this.defaultPassword)==null?void 0:y.hint)!=null?w:"";new b.Setting(e).setHeading().setName(this.title),A.buildPasswordSetting({container:e,name:"Password:",placeholder:this.isEncrypting?"":`Hint: ${i}`,initialValue:n,autoFocus:n=="",onChangeCallback:f=>{n=f,this.invalidate()},onEnterCallback:f=>{if(n=f,this.invalidate(),n.length>0)if(r.settingEl.isShown()){let d=r.components.find(u=>u instanceof b.TextComponent);d instanceof b.TextComponent&&d.inputEl.focus()}else if(a.settingEl.isShown()){let d=a.components.find(u=>u instanceof b.TextComponent);d instanceof b.TextComponent&&d.inputEl.focus()}else l()&&this.close()}});let r=A.buildPasswordSetting({container:e,name:"Confirm Password:",autoFocus:n!="",onChangeCallback:f=>{s=f,this.invalidate()},onEnterCallback:f=>{if(s=f,this.invalidate(),s.length>0&&l()&&a.settingEl.isShown()){let d=a.components.find(u=>u instanceof b.TextComponent);d instanceof b.TextComponent&&d.inputEl.focus()}}});this.confirmPassword||r.settingEl.hide();let a=new b.Setting(e).setName("Optional Password Hint").addText(f=>{f.inputEl.placeholder="Password Hint",f.setValue(i),f.onChange(d=>i=d),f.inputEl.on("keypress","*",(d,u)=>{d.key=="Enter"&&u instanceof HTMLInputElement&&u.value.length>0&&(d.preventDefault(),l()&&this.close())})});this.isEncrypting||a.settingEl.hide(),new b.Setting(e).addButton(f=>{f.setButtonText("Confirm").onClick(d=>{l()&&this.close()})});let l=()=>(this.invalidate(),r.setDesc(""),this.confirmPassword&&n!=s?(r.setDesc("Passwords don't match"),!1):(this.resultConfirmed=!0,this.resultPassword={password:n,hint:i},!0))}open2Async(){return new Promise((e,n)=>{this.onClose=()=>{this.resultConfirmed==!0?e(this.resultPassword):e(null)},this.open()})}openAsync(){return new Promise((e,n)=>{this.onClose=()=>{this.resultConfirmed==!0?e(this.resultPassword):n()},this.open()})}invalidate(){this.resultConfirmed=!1,this.resultPassword={password:"",hint:""}}};var te=class{constructor(t,e,n){this.version="1.0";this.version=t,this.hint=e,this.encodedData=n}},ne=class ne{static async encrypt(t,e,n){let i=await D.BuildDefault().encryptToBase64(n,t);return new te(ne.DEFAULT_VERSION,e,i)}static async decrypt(t,e){return t.encodedData==""?"":await D.BuildFromFileDataOrThrow(t).decryptFromBase64(t.encodedData,e)}};ne.DEFAULT_VERSION="2.0";var F=ne,P=class{static encode(t){return JSON.stringify(t,null,2)}static isEncoded(t){try{return JSON.parse(t),!0}catch(e){return!1}}static decode(t){return t===""?new te(F.DEFAULT_VERSION,"",""):JSON.parse(t)}};var Me="encrypted",Te="mdenc",se=Te,C=[Te,Me];var U=require("obsidian");var ie=class ie extends U.MarkdownView{constructor(){super(...arguments);this.passwordAndHint=null;this.encryptedData=null;this.isSavingEnabled=!1;this.isLoadingFileInProgress=!1;this.isSavingInProgress=!1;this.allowNoFile=!1}getViewType(){return ie.VIEW_TYPE}canAcceptExtension(e){return C.includes(e)}async onLoadFile(e){if(this.setUnencryptedViewData("",!0),!this.app.workspace.layoutReady){this.leaf.detach();return}let n=await this.app.vault.read(e);this.encryptedData=P.decode(n),this.passwordAndHint=await p.getByFile(e),this.passwordAndHint.hint=this.encryptedData.hint;let s=await F.decrypt(this.encryptedData,this.passwordAndHint.password);for(;s==null;){if(this.passwordAndHint=await new S(this.app,`Decypting "${e.basename}"`,!1,!1,{password:"",hint:this.encryptedData.hint}).open2Async(),this.passwordAndHint==null){this.leaf.detach();return}s=await F.decrypt(this.encryptedData,this.passwordAndHint.password),s==null&&new U.Notice("Decryption failed")}if(s==null){this.leaf.detach();return}this.passwordAndHint!=null&&p.putByFile(this.passwordAndHint,e),this.setUnencryptedViewData(s,!0),this.isSavingEnabled=!0,this.isLoadingFileInProgress=!0;try{this.origFile=e,await super.onLoadFile(e)}finally{this.isLoadingFileInProgress=!1}}detachSafely(){this.save(),this.isSavingEnabled=!1,this.leaf.detach()}async onUnloadFile(e){this.passwordAndHint==null||this.encryptedData==null||await super.onUnloadFile(e)}async onRename(e){this.origFile&&p.clearForFile(this.origFile),this.passwordAndHint!=null&&p.putByFile(this.passwordAndHint,e),await super.onRename(e)}getUnencryptedViewData(){return super.getViewData()}getViewData(){if(this.isSavingInProgress){if(this.encryptedData==null)throw new Error("encryptedData is unexpectedly null");return P.encode(this.encryptedData)}return this.getUnencryptedViewData()}setUnencryptedViewData(e,n){super.setViewData(e,n)}setViewData(e,n){if(this.file==null){console.debug("View data will not be set because file is null");return}if(!this.isLoadingFileInProgress){if(P.isEncoded(e)){if(console.debug("View is being set with already encoded data, trying to decode",{data:e}),this.passwordAndHint==null){console.error("passwordAndHint == null");return}let s=P.decode(e);F.decrypt(s,this.passwordAndHint.password).then(i=>{if(i==null){console.error("View was being set with already encoceded data but the decryption failed, closing view"),this.isSavingEnabled=!1,this.leaf.detach();return}this.setUnencryptedViewData(i,n)});return}this.setUnencryptedViewData(e,n)}}async save(e){if(this.isSavingInProgress){console.debug("Saving was prevented because another save is in progress, Obsidian will try again later if the content changed.");return}this.isSavingInProgress=!0;try{if(this.file==null){console.debug("Saving was prevented beacuse there is no file loaded in the view yet");return}if(!C.includes(this.file.extension)){console.debug("Saving was prevented because the file is not an encrypted file");return}if(!this.isSavingEnabled){console.debug("Saving was prevented because the file was not yet loaded with a password or was explicitly disabled");return}if(this.passwordAndHint==null){console.debug("Saving was prevented beacuse there is no password set");return}let n=this.getUnencryptedViewData();if(P.isEncoded(n)){console.debug("Saving was prevented beacuse the data was already encoded but it was expected to not be");return}this.encryptedData=await F.encrypt(this.passwordAndHint.password,this.passwordAndHint.hint,n),await super.save(e)}finally{this.isSavingInProgress=!1}}async changePassword(){if(this.file==null){console.debug("Unable to change password beacuse there is no file loaded in the view yet");return}let e=new S(this.app,`Change password for "${this.file.basename}"`,!0,!0,await p.getByFile(this.file));try{let n=await e.openAsync();this.passwordAndHint=n,p.putByFile(n,this.file),await this.save(),new U.Notice("Password changed")}catch(n){new U.Notice("Password wasn't changed")}}};ie.VIEW_TYPE="meld-encrypted-view";var v=ie;var z=class{async onload(t,e){this.plugin=t,this.plugin.addCommand({id:"meld-encrypt-convert-to-or-from-encrypted-note",name:"Convert to or from an Encrypted note",icon:"file-lock-2",checkCallback:n=>this.processCommandConvertActiveNote(n)}),this.plugin.addRibbonIcon("file-lock-2","Convert to or from an Encrypted note",n=>this.processCommandConvertActiveNote(!1)),this.plugin.registerEvent(this.plugin.app.workspace.on("file-menu",(n,s)=>{s instanceof T.TFile&&(s.extension=="md"&&n.addItem(i=>{i.setTitle("Encrypt note").setIcon("file-lock-2").onClick(()=>this.processCommandEncryptNote(s))}),C.contains(s.extension)&&n.addItem(i=>{i.setTitle("Decrypt note").setIcon("file").onClick(()=>this.processCommandDecryptNote(s))}))}))}onunload(){}buildSettingsUi(t,e){}checkCanEncryptFile(t){return t==null?!1:t.extension=="md"}checkCanDecryptFile(t){return t==null?!1:C.contains(t.extension)}processCommandEncryptNote(t){this.getPasswordAndEncryptFile(t).catch(e=>{e&&new T.Notice(e,1e4)})}processCommandDecryptNote(t){this.getPasswordAndDecryptFile(t).catch(e=>{e&&new T.Notice(e,1e4)})}processCommandConvertActiveNote(t){let e=this.plugin.app.workspace.getActiveFile();if(t)return this.checkCanEncryptFile(e)||this.checkCanDecryptFile(e);(e==null?void 0:e.extension)=="md"&&this.getPasswordAndEncryptFile(e).catch(n=>{n&&new T.Notice(n,1e4)}),e&&C.contains(e.extension)&&this.getPasswordAndDecryptFile(e).catch(n=>{n&&new T.Notice(n,1e4)})}async getPasswordAndEncryptFile(t){if(!this.checkCanEncryptFile(t))throw new Error("Unable to encrypt file");try{let e=await p.getByFile(t);e.password==""&&(e=await new S(this.plugin.app,"Encrypt Note",!0,!0,e).openAsync());let n=await this.encryptFile(t,e);await this.closeUpdateRememberPasswordThenReopen(t,se,n,e),new T.Notice("\u{1F510} Note was encrypted \u{1F510}")}catch(e){e&&new T.Notice(e,1e4)}}async getPasswordAndDecryptFile(t){if(!this.checkCanDecryptFile(t))throw new Error("Unable to decrypt file");let e=await p.getByFile(t);if(e.password!=""){let r=await this.decryptFile(t,e.password);if(r!=null){await this.closeUpdateRememberPasswordThenReopen(t,"md",r,e);return}}let n=await this.plugin.app.vault.read(t),s=P.decode(n),i=new S(this.plugin.app,"Decrypt Note",!1,!1,{password:"",hint:s.hint});try{if(e=await i.openAsync(),!i.resultConfirmed)return;let r=await this.decryptFile(t,e.password);if(r==null)throw new Error("Decryption failed");await this.closeUpdateRememberPasswordThenReopen(t,"md",r,e),new T.Notice("\u{1F513} Note was decrypted \u{1F513}")}catch(r){r&&new T.Notice(r,1e4)}}async closeUpdateRememberPasswordThenReopen(t,e,n,s){let i=!1;this.plugin.app.workspace.iterateAllLeaves(r=>{r.view instanceof T.TextFileView&&r.view.file==t&&(r.view instanceof v?r.view.detachSafely():r.detach(),i=!0)});try{let r=R.getFilePathWithNewExtension(t,e);await this.plugin.app.fileManager.renameFile(t,r),await this.plugin.app.vault.modify(t,n),p.putByFile(s,t)}finally{i&&await this.plugin.app.workspace.getLeaf(!0).openFile(t)}}async encryptFile(t,e){let n=await this.plugin.app.vault.read(t),s=await F.encrypt(e.password,e.hint,n);return P.encode(s)}async decryptFile(t,e){let n=await this.plugin.app.vault.read(t),s=P.decode(n);return await F.decrypt(s,e)}};var L=require("obsidian");var _=class{async onload(t){this.plugin=t,this.plugin.addRibbonIcon("file-lock-2","New encrypted note",async e=>{await this.processCreateNewEncryptedNoteCommand(this.getDefaultFileFolder())}),this.plugin.addCommand({id:"meld-encrypt-create-new-note",name:"Create new encrypted note",icon:"file-lock-2",callback:async()=>await this.processCreateNewEncryptedNoteCommand(this.getDefaultFileFolder())}),this.plugin.registerEvent(this.plugin.app.workspace.on("file-menu",(e,n)=>{n instanceof L.TFolder&&e.addItem(s=>{s.setTitle("New encrypted note").setIcon("file-lock-2").onClick(()=>this.processCreateNewEncryptedNoteCommand(n))})})),this.statusIndicator=this.plugin.addStatusBarItem(),this.statusIndicator.hide(),this.statusIndicator.setText("\u{1F510}"),this.plugin.registerEvent(this.plugin.app.workspace.on("editor-menu",(e,n,s)=>{s.file==null||!C.includes(s.file.extension)||s instanceof v&&(e.addItem(i=>{i.setTitle("Change Password").setIcon("key-round").onClick(async()=>await s.changePassword())}),e.addItem(i=>{i.setTitle("Lock & Close").setIcon("lock").onClick(()=>this.lockAndClose(s))}))})),this.plugin.registerEvent(this.plugin.app.workspace.on("file-menu",(e,n)=>{if(!(n instanceof L.TFile)||!C.includes(n.extension))return;let s=this.plugin.app.workspace.getActiveViewOfType(v);s==null||s.file!=n||(e.addItem(i=>{i.setTitle("Change Password").setIcon("key-round").onClick(async()=>await s.changePassword())}),e.addItem(i=>{i.setTitle("Lock & Close").setIcon("lock").onClick(()=>this.lockAndClose(s))}))})),this.plugin.registerView(v.VIEW_TYPE,e=>new v(e)),this.plugin.registerExtensions(C,v.VIEW_TYPE),this.plugin.registerEvent(this.plugin.app.workspace.on("layout-change",()=>{if(this.plugin.app.workspace.getActiveViewOfType(v)==null){this.statusIndicator.hide();return}this.statusIndicator.show()})),this.plugin.registerEvent(this.plugin.app.workspace.on("active-leaf-change",async e=>{if(e!=null&&!(e.view instanceof v)&&e.view instanceof L.MarkdownView){let n=e.view.file;if(n==null)return;if(C.includes(n.extension)){let s=e.getViewState();s.type=v.VIEW_TYPE,await e.setViewState(s);return}}}))}lockAndClose(t){t.detachSafely(),t.file!=null&&p.clearForFile(t.file)}getDefaultFileFolder(){let t=this.plugin.app.workspace.getActiveFile();return t!=null?this.plugin.app.fileManager.getNewFileParent(t.path):this.plugin.app.fileManager.getNewFileParent("")}async processCreateNewEncryptedNoteCommand(t){let e=(0,L.moment)().format(`[Untitled] YYYYMMDD hhmmss[.${se}]`),n=(0,L.normalizePath)(t.path+"/"+e),s;if(p.getLevel()==p.LevelExternalFile&&(s=await p.getByPathAsync(n)),!s){let c=new S(this.plugin.app,"Please provide a password for encryption",!0,!0,await p.getByPathAsync(n));try{s=await c.openAsync()}catch(h){return}}let i=await F.encrypt(s.password,s.hint,""),r=P.encode(i),a=await this.plugin.app.vault.create(n,r);p.putByFile(s,a),await this.plugin.app.workspace.getLeaf(!0).openFile(a)}onunload(){this.plugin.app.workspace.detachLeavesOfType(v.VIEW_TYPE)}buildSettingsUi(t,e){}};var re=class extends ae.Plugin{constructor(){super(...arguments);this.enabledFeatures=[]}async onload(){p.init(this.app.vault.adapter),await this.loadSettings(),this.enabledFeatures.push(new _,new z,new $),this.addSettingTab(new K(this.app,this,this.settings,this.enabledFeatures)),this.addCommand({id:"meld-encrypt-clear-password-cache",name:"Clear Session Password Cache",icon:"shield-ellipsis",callback:()=>{let e=p.clear();new ae.Notice(`Items cleared: ${e}`)}}),this.enabledFeatures.forEach(async e=>{await e.onload(this,this.settings)})}onunload(){this.enabledFeatures.forEach(async e=>{e.onunload()}),super.onunload()}async loadSettings(){let e={confirmPassword:!0,rememberPassword:!0,rememberPasswordTimeout:30,rememberPasswordLevel:p.LevelVault,rememberPasswordExternalFilePaths:[],featureWholeNoteEncrypt:{},featureInplaceEncrypt:{expandToWholeLines:!1,showMarkerWhenReadingDefault:!0}};this.settings=Object.assign(e,await this.loadData()),p.setActive(this.settings.rememberPassword),p.setAutoExpire(this.settings.rememberPasswordTimeout==0?null:this.settings.rememberPasswordTimeout),p.setLevel(this.settings.rememberPasswordLevel),p.setExternalFilePaths(this.settings.rememberPasswordExternalFilePaths)}async saveSettings(){await this.saveData(this.settings)}};
|
|
|
|
/* nosourcemap */ |