From 02b5de68a4c67747afc66623ef16191e242ccd9a Mon Sep 17 00:00:00 2001 From: Markus Moser Date: Mon, 5 Jan 2026 18:56:39 +0100 Subject: [PATCH] Fixed test vault not having all files included --- .gitignore | 5 +- .../.obsidian/plugins/private-mode/data.json | 4 + .../.obsidian/plugins/private-mode/main.js | 7 + .../plugins/private-mode/manifest.json | 10 + .../.obsidian/plugins/private-mode/styles.css | 413 ++++++ .../plugins/private-mode/styles.scss | 66 + .../supercharged-links-obsidian/data.json | 15 + .../supercharged-links-obsidian/main.js | 1277 +++++++++++++++++ .../supercharged-links-obsidian/styles.css | 11 + 9 files changed, 1807 insertions(+), 1 deletion(-) create mode 100644 private-mode-testvault/.obsidian/plugins/private-mode/data.json create mode 100644 private-mode-testvault/.obsidian/plugins/private-mode/main.js create mode 100644 private-mode-testvault/.obsidian/plugins/private-mode/manifest.json create mode 100644 private-mode-testvault/.obsidian/plugins/private-mode/styles.css create mode 100644 private-mode-testvault/.obsidian/plugins/private-mode/styles.scss create mode 100644 private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/data.json create mode 100644 private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/main.js create mode 100644 private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/styles.css diff --git a/.gitignore b/.gitignore index 4cd8999..0c01c90 100644 --- a/.gitignore +++ b/.gitignore @@ -24,5 +24,8 @@ data.json .DS_Store # Exclude release -private-mode/ +/private-mode/ private-mode.zip +!private-mode-testvault/**/main.js +!private-mode-testvault/**/data.json +!private-mode-testvault/**/styles.css diff --git a/private-mode-testvault/.obsidian/plugins/private-mode/data.json b/private-mode-testvault/.obsidian/plugins/private-mode/data.json new file mode 100644 index 0000000..599b1e0 --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/private-mode/data.json @@ -0,0 +1,4 @@ +{ + "currentScreenshareProtection": true, + "blurLinksToo": false +} \ No newline at end of file diff --git a/private-mode-testvault/.obsidian/plugins/private-mode/main.js b/private-mode-testvault/.obsidian/plugins/private-mode/main.js new file mode 100644 index 0000000..cdc9ed6 --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/private-mode/main.js @@ -0,0 +1,7 @@ +/* + * THIS IS A GENERATED/BUNDLED FILE BY ESBUILD + * if you want to view the source, please visit the github repository of this plugin: + * https://github.com/markusmo3/obsidian-private-mode + */ + +var n=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var h=(l,a)=>{for(var r in a)n(l,r,{get:a[r],enumerable:!0})},d=(l,a,r,s)=>{if(a&&typeof a=="object"||typeof a=="function")for(let e of c(a))!v.call(l,e)&&e!==r&&n(l,e,{get:()=>a[e],enumerable:!(s=o(a,e))||s.enumerable});return l};var u=l=>d(n({},"__esModule",{value:!0}),l);var S={};h(S,{default:()=>i});module.exports=u(S);var t=require("obsidian");var p={currentScreenshareProtection:!0,blurLinksToo:!0},i=class extends t.Plugin{constructor(){super(...arguments);this.currentLevel="reveal-on-hover"}async onload(){this.settings=Object.assign({},p,await this.loadData()),this.statusBar=this.addStatusBarItem(),this.statusBar.addClass("mod-clickable"),this.statusBar.ariaLabel="Toggle private mode",this.statusBar.setAttr("data-tooltip-position","top"),this.statusBar.onClickEvent(r=>{if(r.button!=0){let s=new t.Menu;s.addItem(e=>e.setTitle("Reveal all").setIcon("ph--eye").setChecked(this.currentLevel=="reveal-all").onClick(()=>{this.currentLevel="reveal-all",this.updateGlobalRevealStyle()})),s.addItem(e=>e.setTitle("Reveal on hover").setIcon("ph--eye-hand").setChecked(this.currentLevel=="reveal-on-hover").onClick(()=>{this.currentLevel="reveal-on-hover",this.updateGlobalRevealStyle()})),s.addItem(e=>e.setTitle("Reveal never").setIcon("ph--eye-closed").setChecked(this.currentLevel=="hide-private").onClick(()=>{this.currentLevel="hide-private",this.updateGlobalRevealStyle()})),s.addSeparator(),s.addItem(e=>e.setTitle("Blur Links too").setIcon("ph--link").setChecked(this.settings.blurLinksToo).onClick(()=>{this.settings.blurLinksToo=!this.settings.blurLinksToo,e.setChecked(!this.settings.blurLinksToo),this.updateGlobalRevealStyle()})),s.addItem(e=>e.setTitle("Visibility when screensharing").setIcon("ph--screencast").setChecked(!this.settings.currentScreenshareProtection).onClick(()=>{this.settings.currentScreenshareProtection=!this.settings.currentScreenshareProtection,e.setChecked(!this.settings.currentScreenshareProtection),this.updateGlobalRevealStyle()})),s.showAtMouseEvent(r)}else r.altKey?(this.settings.currentScreenshareProtection=!this.settings.currentScreenshareProtection,this.updateGlobalRevealStyle()):(this.cycleCurrentLevel(),this.updateGlobalRevealStyle())}),this.statusBarSpan=this.statusBar.createSpan({text:""}),(0,t.addIcon)("ph--eye",g),(0,t.addIcon)("ph--eye-hand",L),(0,t.addIcon)("ph--eye-closed",m),(0,t.addIcon)("ph--screencast",C),(0,t.addIcon)("ph--link",R),this.addCommand({id:"hide-private",name:"Hide #private",callback:()=>{this.currentLevel="hide-private",this.updateGlobalRevealStyle()}}),this.addCommand({id:"reveal-on-hover",name:"Reveal #private on hover",callback:()=>{this.currentLevel="reveal-on-hover",this.updateGlobalRevealStyle()}}),this.addCommand({id:"reveal-all",name:"Reveal #private always",callback:()=>{this.currentLevel="reveal-all",this.updateGlobalRevealStyle()}}),this.addCommand({id:"cycle-mode",name:"Cycle #private mode",callback:()=>{this.cycleCurrentLevel(),this.updateGlobalRevealStyle()}}),this.addCommand({id:"toggle-screenshare-protection",name:"Toggle screenshare protection",callback:()=>{this.settings.currentScreenshareProtection=!this.settings.currentScreenshareProtection,this.updateGlobalRevealStyle()}}),this.app.workspace.onLayoutReady(()=>{this.updateGlobalRevealStyle()})}cycleCurrentLevel(){switch(this.currentLevel){case"hide-private":this.currentLevel="reveal-on-hover";break;case"reveal-on-hover":this.currentLevel="reveal-all";break;case"reveal-all":this.currentLevel="hide-private";break}}async saveSettings(){await this.saveData(this.settings)}updateGlobalRevealStyle(){this.saveSettings(),this.removeAllClasses(),this.setClassToDocumentBody(),t.Platform.isDesktopApp&&window.require("electron").remote.getCurrentWindow().setContentProtection(this.settings.currentScreenshareProtection)}removeAllClasses(){document.body.removeClass("private-mode-reveal-all","private-mode-reveal-on-hover","private-mode-unprotected-screenshare","private-mode-blur-links-too")}setClassToDocumentBody(){switch(this.settings.currentScreenshareProtection||document.body.classList.add("private-mode-unprotected-screenshare"),this.settings.blurLinksToo&&document.body.classList.add("private-mode-blur-links-too"),this.currentLevel){case"hide-private":(0,t.setIcon)(this.statusBarSpan,"ph--eye-closed");break;case"reveal-on-hover":document.body.classList.add("private-mode-reveal-on-hover"),(0,t.setIcon)(this.statusBarSpan,"ph--eye-hand");break;case"reveal-all":document.body.classList.add("private-mode-reveal-all"),(0,t.setIcon)(this.statusBarSpan,"ph--eye");break}}},m='',L='',g='',C='',R=''; diff --git a/private-mode-testvault/.obsidian/plugins/private-mode/manifest.json b/private-mode-testvault/.obsidian/plugins/private-mode/manifest.json new file mode 100644 index 0000000..7267823 --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/private-mode/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "private-mode", + "name": "Private Mode", + "version": "1.1.8", + "minAppVersion": "1.6.0", + "description": "Simple #private mode", + "author": "markusmo3", + "authorUrl": "https://github.com/markusmo3", + "isDesktopOnly": false +} \ No newline at end of file diff --git a/private-mode-testvault/.obsidian/plugins/private-mode/styles.css b/private-mode-testvault/.obsidian/plugins/private-mode/styles.css new file mode 100644 index 0000000..61bb21e --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/private-mode/styles.css @@ -0,0 +1,413 @@ +/* + * Original Source: community plugin privacy glasses + * Modified by markusmo3 + * Last updated: 2024-10-29 + */ +:root { + --blur-level: 0.5rem; +} + +body.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title { + filter: blur(calc(var(--blur-level) * 1)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line { + filter: blur(calc(var(--blur-level) * 1)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas) { + filter: blur(calc(var(--blur-level) * 4)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5) { + filter: blur(calc(var(--blur-level) * 1)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block { + filter: blur(calc(var(--blur-level) * 1)); +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed { + filter: blur(calc(var(--blur-level) * 1)); +} + +body.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title).inline-title:focus-within { + filter: unset !important; +} + +body.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title):hover { + filter: unset !important; +} + +body.private-mode-reveal-all.private-mode-blur-links-too .data-link-text[data-link-tags*="#private"]:not(.tree-item-inner, .suggestion-title) { + filter: unset !important; +} + +body.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]).inline-title:focus-within { + filter: unset !important; +} + +body.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]):hover { + filter: unset !important; +} + +body.private-mode-reveal-all.private-mode-blur-links-too .dataview tr:has(a[data-link-tags*="#private"]) { + filter: unset !important; +} + +body.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]).inline-title:focus-within { + filter: unset !important; +} + +body.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]):hover { + filter: unset !important; +} + +body.private-mode-reveal-all.private-mode-blur-links-too .suggestion-item:has([data-link-tags*="#private"]) { + filter: unset !important; +} + +body.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]).inline-title:focus-within { + filter: unset !important; +} + +body.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]):hover { + filter: unset !important; +} + +body.private-mode-reveal-all.private-mode-blur-links-too .nav-file-title:has([data-link-tags*="#private"]) { + filter: unset !important; +} + +body.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]).inline-title:focus-within { + filter: unset !important; +} + +body.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]):hover { + filter: unset !important; +} + +body.private-mode-reveal-all.private-mode-blur-links-too .search-result:has([data-link-tags*="#private"]) { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title.inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title.cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title.is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title.has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title:has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title:hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .inline-title { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line.inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line.cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line.is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line.has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line:has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line:hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-line { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property).inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property):hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(.metadata-property) { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas).inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas):hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .view-content :is(img, video, svg, canvas) { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5).inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5).cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5).is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5).has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5):has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5):hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5) { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block.inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block.cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block.is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block.has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block:has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block:hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .cm-embed-block { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed.inline-title:focus-within { + filter: unset !important; +} + +body .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed.cm-active { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed.is-selected { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed.has-focus { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed:has(.has-focus) { + filter: unset !important; +} + +body.private-mode-reveal-on-hover .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed:hover { + filter: unset !important; +} + +body.private-mode-reveal-all .workspace-tabs:has(.is-active [data-link-tags*="#private"]) .internal-embed { + filter: unset !important; +} + +/* add a private callout */ +.callout[data-callout=private] { + --callout-color: 158, 158, 158; + --callout-icon: lucide-lock; +} + +body:not(.private-mode-reveal-all) .callout[data-callout=private]:not(.is-collapsed) > .callout-content { + filter: blur(0.5rem); +} + +body.private-mode-reveal-on-hover .callout[data-callout=private]:not(.is-collapsed) > .callout-content:hover { + filter: none; +} + +/* screenshare protection */ +body.private-mode-unprotected-screenshare .status-bar-item.plugin-private-mode { + color: var(--text-error); +} + +/*# sourceMappingURL=styles.css.map */ diff --git a/private-mode-testvault/.obsidian/plugins/private-mode/styles.scss b/private-mode-testvault/.obsidian/plugins/private-mode/styles.scss new file mode 100644 index 0000000..892c2be --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/private-mode/styles.scss @@ -0,0 +1,66 @@ +/* + * Original Source: community plugin privacy glasses + * Modified by markusmo3 + * Last updated: 2024-10-29 + */ + +:root { + --blur-level: 0.5rem; +} + +$element-selectors: ( + ".private-mode-blur-links-too" ".data-link-text[data-link-tags*='#private']:not(.tree-item-inner,.suggestion-title)" 1, // Link items + ".private-mode-blur-links-too" ".dataview tr:has(a[data-link-tags*='#private'])" 1, // dataview tables + ".private-mode-blur-links-too" ".suggestion-item:has([data-link-tags*='#private'])" 1, // Search results + ".private-mode-blur-links-too" ".nav-file-title:has([data-link-tags*='#private'])" 1, // "Files" tree + ".private-mode-blur-links-too" ".search-result:has([data-link-tags*='#private'])" 1, // Sidebar search + + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .inline-title" 1, + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .cm-line" 1, + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .view-content :is(.metadata-property)" 1, + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .view-content :is(img, video, svg, canvas)" 4, + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .markdown-preview-view :is(li, p, h1, h2, h3, h4, h5)" 1, + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .cm-embed-block" 1, + "" ".workspace-tabs:has(.is-active [data-link-tags*='#private']) .internal-embed" 1, +); + +@each $bodySelector, $selector, $m in $element-selectors { + body#{$bodySelector} #{$selector} { + filter: blur(calc(var(--blur-level) * #{$m})); + } +} + +$reveal-templates: ( + "" ".inline-title:focus-within", + "" ".cm-active", + ".private-mode-reveal-on-hover" ".is-selected", + ".private-mode-reveal-on-hover" ".has-focus", + ".private-mode-reveal-on-hover" ":has(.has-focus)", + ".private-mode-reveal-on-hover" ":hover", + ".private-mode-reveal-all" +); + +@each $bodySelector, $selector, $m in $element-selectors { + @each $bodyPrefix, $suffix in $reveal-templates { + body#{$bodyPrefix}#{$bodySelector} #{$selector}#{$suffix} { + filter: unset !important; + } + } +} + +/* add a private callout */ +.callout[data-callout="private"] { + --callout-color: 158, 158, 158; + --callout-icon: lucide-lock; +} +body:not(.private-mode-reveal-all) .callout[data-callout="private"]:not(.is-collapsed) > .callout-content { + filter: blur(0.5rem); +} +body.private-mode-reveal-on-hover .callout[data-callout="private"]:not(.is-collapsed) > .callout-content:hover { + filter: none; +} + +/* screenshare protection */ +body.private-mode-unprotected-screenshare .status-bar-item.plugin-private-mode { + color: var(--text-error); +} diff --git a/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/data.json b/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/data.json new file mode 100644 index 0000000..39a2802 --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/data.json @@ -0,0 +1,15 @@ +{ + "targetAttributes": [ + "tags" + ], + "targetTags": true, + "getFromInlineField": true, + "enableTabHeader": true, + "activateSnippet": true, + "enableEditor": true, + "enableFileList": true, + "enableBacklinks": true, + "enableQuickSwitcher": true, + "enableSuggestor": true, + "selectors": [] +} \ No newline at end of file diff --git a/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/main.js b/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/main.js new file mode 100644 index 0000000..10a08a0 --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/main.js @@ -0,0 +1,1277 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ROLLUP +if you want to view the source visit the plugins github repository +*/ + +'use strict'; + +var obsidian = require('obsidian'); +var state = require('@codemirror/state'); +var view = require('@codemirror/view'); +var language = require('@codemirror/language'); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +const matchTypes = { + 'exact': "Exact match", + 'contains': "Contains value", + 'whiteSpace': "Value within whitespace separated words", + 'startswith': "Starts with this value", + 'endswith': "Ends with this value" +}; +const matchSign = { + 'exact': "", + 'contains': "*", + 'startswith': "^", + 'endswith': "$", + 'whiteSpace': "~" +}; +const matchPreview = { + 'exact': "with value", + 'contains': "containing", + 'whiteSpace': "containing", + 'startswith': "starting with", + 'endswith': "ending with" +}; +const matchPreviewPath = { + 'exact': "is", + 'contains': "contains", + 'whiteSpace': "contains", + 'startswith': "starts with", + 'endswith': "ends with" +}; +const selectorType = { + 'attribute': 'Attribute value', + 'tag': 'Tag', + 'path': 'Note path' +}; +class CSSLink { + constructor() { + this.type = 'attribute'; + this.name = ""; + this.value = ""; + this.matchCaseSensitive = false; + this.match = "exact"; + let s4 = () => { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + }; + //return id of format 'aaaaaaaa'-'aaaa'-'aaaa'-'aaaa'-'aaaaaaaaaaaa' + this.uid = s4() + "-" + s4(); + this.selectText = true; + this.selectAppend = true; + this.selectPrepend = true; + this.selectBackground = true; + } +} + +function displayText(link, settings) { + if (link.type === 'tag') { + if (!link.value) { + return "Please choose a tag"; + } + return `Note has tag #${link.value}`; + } + else if (link.type === 'attribute') { + if (settings.targetAttributes.length === 0) { + return `No attributes added to "Target attributes". Go to plugin settings to add them.`; + } + if (!link.name) { + return "Please choose an attribute name."; + } + if (!link.value) { + return "Please choose an attribute value."; + } + return `Note has attribute ${link.name} ${matchPreview[link.match]} ${link.value}.`; + } + if (!link.value) { + return "Please choose a path."; + } + return `The path of the note ${matchPreviewPath[link.match]} ${link.value}`; +} +function updateDisplay(textArea, link, settings) { + let toDisplay = displayText(link, settings); + let disabled = false; + if (link.type === 'tag') { + if (!link.value) { + disabled = true; + } + } + else if (link.type === 'attribute') { + if (settings.targetAttributes.length === 0) { + disabled = true; + } + else if (!link.name) { + disabled = true; + } + else if (!link.value) { + disabled = true; + } + } + else { + if (!link.value) { + disabled = true; + } + } + textArea.innerHTML = toDisplay; + return disabled; +} +class CSSBuilderModal extends obsidian.Modal { + constructor(plugin, saveCallback, cssLink = null) { + super(plugin.app); + this.cssLink = cssLink; + if (!cssLink) { + this.cssLink = new CSSLink(); + } + this.plugin = plugin; + this.saveCallback = saveCallback; + } + onOpen() { + this.titleEl.setText(`Select what links to style!`); + // is tag + const matchAttrPlaceholder = "Attribute value to match."; + const matchTagPlaceholder = "Note tag to match (without #)."; + const matchPathPlaceholder = "File path to match."; + const matchAttrTxt = "Attribute value"; + const matchTagTxt = "Tag"; + const matchPathTxt = "Path"; + const cssLink = this.cssLink; + const plugin = this.plugin; + this.contentEl.addClass("supercharged-modal"); + // Type + new obsidian.Setting(this.contentEl) + .setName("Type of selector") + .setDesc("Attributes selects YAML and DataView attributes" + + ", tags chooses the tags of a note, and path considers the name of the note including in what folder it is.") + .addDropdown(dc => { + Object.keys(selectorType).forEach((type) => { + dc.addOption(type, selectorType[type]); + if (type === this.cssLink.type) { + dc.setValue(type); + } + }); + dc.onChange((type) => { + cssLink.type = type; + updateContainer(cssLink.type); + saveButton.setDisabled(updateDisplay(preview, this.cssLink, this.plugin.settings)); + }); + }); + // attribute name + const attrName = new obsidian.Setting(this.contentEl) + .setName("Attribute name") + .setDesc("What attribute to target? Make sure to first add target attributes to the settings at the top!") + .addDropdown(dc => { + plugin.settings.targetAttributes.forEach((attribute) => { + dc.addOption(attribute, attribute); + if (attribute === cssLink.name) { + dc.setValue(attribute); + } + }); + dc.onChange(name => { + cssLink.name = name; + saveButton.setDisabled(updateDisplay(preview, cssLink, plugin.settings)); + }); + }); + // attribute value + const attrValue = new obsidian.Setting(this.contentEl) + .setName("Value to match") + .setDesc("TODO") + .addText(t => { + t.setValue(cssLink.value); + t.onChange(value => { + cssLink.value = value; + saveButton.setDisabled(updateDisplay(preview, cssLink, plugin.settings)); + }); + }); + this.contentEl.createEl('h4', { text: 'Advanced' }); + // matching type + const matchingType = new obsidian.Setting(this.contentEl) + .setName("Matching type") + .setDesc("How to compare the attribute or path with the given value.") + .addDropdown(dc => { + Object.keys(matchTypes).forEach((key) => { + dc.addOption(key, matchTypes[key]); + if (key == cssLink.match) { + dc.setValue(key); + } + }); + dc.onChange((value) => { + cssLink.match = value; + saveButton.setDisabled(updateDisplay(preview, cssLink, plugin.settings)); + }); + }); + // case sensitive + const caseSensitiveTogglerContainer = new obsidian.Setting(this.contentEl) + .setName("Case sensitive matching") + .setDesc("Should the matching of the value be case sensitive?") + .addToggle(b => { + b.setValue(cssLink.matchCaseSensitive); + b.onChange(value => { + cssLink.matchCaseSensitive = value; + b.setDisabled(updateDisplay(preview, cssLink, plugin.settings)); + }); + }); + if (!this.cssLink.name && this.plugin.settings.targetAttributes.length > 0) { + this.cssLink.name = this.plugin.settings.targetAttributes[0]; + } + const updateContainer = function (type) { + if (type === 'attribute') { + attrName.settingEl.show(); + attrValue.nameEl.setText(matchAttrTxt); + attrValue.descEl.setText(matchAttrPlaceholder); + matchingType.settingEl.show(); + caseSensitiveTogglerContainer.settingEl.show(); + } + else if (type === 'tag') { + attrName.settingEl.hide(); + attrValue.nameEl.setText(matchTagTxt); + attrValue.descEl.setText(matchTagPlaceholder); + matchingType.settingEl.hide(); + caseSensitiveTogglerContainer.settingEl.hide(); + } + else { + attrName.settingEl.hide(); + attrValue.nameEl.setText(matchPathTxt); + attrValue.descEl.setText(matchPathPlaceholder); + matchingType.settingEl.show(); + caseSensitiveTogglerContainer.settingEl.show(); + } + }; + new obsidian.Setting(this.contentEl) + .setName("Style options") + .setDesc("What styling options are active? " + + "Disabling options you won't use can improve performance slightly.") + .addToggle(t => { + t.onChange(value => { + cssLink.selectText = value; + }); + t.setValue(cssLink.selectText); + t.setTooltip("Style link text"); + }) + .addToggle(t => { + t.onChange(value => { + cssLink.selectPrepend = value; + }); + t.setValue(cssLink.selectPrepend); + t.setTooltip("Add content before link"); + }) + .addToggle(t => { + t.onChange(value => { + cssLink.selectAppend = value; + }); + t.setValue(cssLink.selectAppend); + t.setTooltip("Add content after link"); + }) + .addToggle(t => { + t.onChange(value => { + cssLink.selectBackground = value; + }); + t.setValue(cssLink.selectBackground); + t.setTooltip("Add optional background or underline to link"); + }); + this.contentEl.createEl('h4', { text: 'Result' }); + const modal = this; + const saveButton = new obsidian.Setting(this.contentEl) + .setName("Preview") + .setDesc("") + .addButton(b => { + b.setButtonText("Save"); + b.onClick(() => { + modal.saveCallback(cssLink); + modal.close(); + }); + }); + // generate button + const preview = saveButton.nameEl; + updateContainer(cssLink.type); + saveButton.setDisabled(updateDisplay(preview, this.cssLink, this.plugin.settings)); + } +} + +const colorSet = [[ + '#0089BA', + '#2C73D2', + '#008E9B', + '#0081CF', + '#008F7A', + '#008E9B', + ], [ + '#D65DB1', + '#0082C1', + '#9270D3', + '#007F93', + '#007ED9', + '#007660', + ], [ + '#FF9671', + '#A36AAA', + '#F27D88', + '#6967A9', + '#D26F9D', + '#1b6299', + ], [ + '#FFC75F', + '#4C9A52', + '#C3BB4E', + '#00855B', + '#88AC4B', + '#006F61', + ], [ + '#FF6F91', + '#6F7F22', + '#E07250', + '#257A3E', + '#AC7C26', + '#006F5F', + ], [ + '#d9d867', + '#2FAB63', + '#B8E067', + '#008E63', + '#78C664', + '#007160', + ]]; +const colors = []; +for (const i of Array(6).keys()) { + for (const j of Array(6).keys()) { + colors.push(colorSet[j][i]); + } +} +function hash(uid) { + let hash = 0; + for (let i = 0; i < uid.length; i++) { + const char = uid.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; // Convert to 32bit integer + } + hash = Math.abs(hash); + return hash; +} +function buildCSS(selectors, plugin) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const instructions = [ + "/* WARNING: This file will be overwritten by the plugin.", + "Do not edit this file directly! First copy this file and rename it if you want to edit things. */", + "", + ":root {" + ]; + selectors.forEach((selector, i) => { + if (selector.selectText) { + instructions.push(` --${selector.uid}-color: ${colors[hash(selector.uid) % 36]};`); + instructions.push(` --${selector.uid}-weight: initial;`); + } + if (selector.selectPrepend) { + instructions.push(` --${selector.uid}-before: '';`); + } + if (selector.selectAppend) { + instructions.push(` --${selector.uid}-after: '';`); + } + if (selector.selectBackground) { + instructions.push(` --${selector.uid}-background-color: #ffffff;`); + instructions.push(` --${selector.uid}-decoration: initial;`); + } + }); + instructions.push("}"); + selectors.forEach(selector => { + let cssSelector; + if (selector.type === 'attribute') { + cssSelector = `[data-link-${selector.name}${matchSign[selector.match]}="${selector.value}" ${selector.matchCaseSensitive ? "" : " i"}]`; + } + else if (selector.type === 'tag') { + cssSelector = `[data-link-tags*="${selector.value}" i]`; + } + else { + cssSelector = `[data-link-path${matchSign[selector.match]}="${selector.value}" ${selector.matchCaseSensitive ? "" : "i"}]`; + } + if (selector.selectText) { + instructions.push(...[ + "", + `div[data-id="${selector.uid}"] div.setting-item-description,`, + cssSelector + " {", + ` color: var(--${selector.uid}-color) !important;`, + ` font-weight: var(--${selector.uid}-weight);`, + "}" + ]); + } + if (selector.selectBackground) { + instructions.push(...["", + `.c-${selector.uid}-use-background div[data-id="${selector.uid}"] div.setting-item-description,`, + `.c-${selector.uid}-use-background .data-link-text${cssSelector} {`, + ` background-color: var(--${selector.uid}-background-color) !important;`, + ` border-radius: 5px;`, + ` padding-left: 2px;`, + ` padding-right: 2px;`, + ` text-decoration: var(--${selector.uid}-decoration) !important;`, + "}"]); + } + if (selector.selectPrepend) { + instructions.push(...["", + `div[data-id="${selector.uid}"] div.setting-item-description::before,`, + `.data-link-icon${cssSelector}::before {`, + ` content: var(--${selector.uid}-before);`, + "}"]); + } + if (selector.selectAppend) { + instructions.push(...["", + `div[data-id="${selector.uid}"] div.setting-item-description::after,`, + `.data-link-icon-after${cssSelector}::after {`, + ` content: var(--${selector.uid}-after);`, + "}"]); + } + }); + instructions.push(...[ + "/* @settings", + "name: Supercharged Links", + "id: supercharged-links", + "settings:", + ]); + selectors.forEach((selector, i) => { + let name = selector.name; + let value = selector.value; + if (selector.type === 'tag') { + name = 'tag'; + // value = "\#" + value; + } + else if (selector.type === 'path') { + name = 'path'; + } + instructions.push(...[ + " - ", + ` id: ${selector.uid}`, + ` title: ${name} is ${value}`, + ` description: Example note`, + " type: heading", + " collapsed: true", + " level: 3" + ]); + if (selector.selectText) { + instructions.push(...[ + " - ", + ` id: ${selector.uid}-color`, + ` title: Link color`, + " type: variable-color", + " format: hex", + ` default: '${colors[hash(selector.uid) % 36]}'`, + " - ", + ` id: ${selector.uid}-weight`, + ` title: Font weight`, + " type: variable-select", + ` default: initial`, + ` options:`, + ` - initial`, + ` - lighter`, + ` - normal`, + ` - bold`, + ` - bolder`, + " - ", + ` id: ${selector.uid}-decoration`, + ` title: Font decoration`, + " type: variable-select", + ` default: initial`, + ` options:`, + ` - initial`, + ` - underline`, + ` - overline`, + ` - line-through` + ]); + } + if (selector.selectPrepend) { + instructions.push(...[" - ", + ` id: ${selector.uid}-before`, + ` title: Prepend text`, + ` description: Add some text, such as an emoji, before the links.`, + " type: variable-text", + ` default: ''`, + ` quotes: true`]); + } + if (selector.selectAppend) { + instructions.push(...[" - ", + ` id: ${selector.uid}-after`, + ` title: Append text`, + ` description: Add some text, such as an emoji, after the links.`, + " type: variable-text", + ` default: ''`, + ` quotes: true`]); + } + if (selector.selectBackground) { + instructions.push(...[" - ", + ` id: c-${selector.uid}-use-background`, + ` title: Use background color`, + ` description: Adds a background color to the link. This can look buggy in live preview.`, + " type: class-toggle", + " - ", + ` id: ${selector.uid}-background-color`, + ` title: Background color`, + " type: variable-color", + " format: hex", + ` default: '#ffffff'`]); + } + }); + instructions.push("*/"); + const vault = plugin.app.vault; + const configDir = (_a = vault.configDir) !== null && _a !== void 0 ? _a : ".obsidian"; + const pathDir = configDir + "/snippets"; + yield vault.adapter.mkdir(pathDir); + const path = pathDir + "/supercharged-links-gen.css"; + if (yield vault.adapter.exists(path)) { + yield vault.adapter.remove(path); + } + yield plugin.app.vault.create(path, instructions.join('\n')); + // Activate snippet + if (plugin.settings.activateSnippet) { + // @ts-ignore + const customCss = plugin.app.customCss; + customCss.enabledSnippets.add('supercharged-links-gen'); + customCss.requestLoadSnippets(); + } + // Ensure Style Settings reads changes + plugin.app.workspace.trigger("parse-style-settings"); + }); +} + +function clearExtraAttributes(link) { + Object.values(link.attributes).forEach(attr => { + if (attr.name.includes("data-link")) { + link.removeAttribute(attr.name); + } + }); +} +function fetchTargetAttributesSync(app, settings, dest, addDataHref) { + var _a; + let new_props = { tags: "" }; + const cache = app.metadataCache.getFileCache(dest); + if (!cache) + return new_props; + const frontmatter = cache.frontmatter; + if (frontmatter) { + settings.targetAttributes.forEach(attribute => { + if (Object.keys(frontmatter).includes(attribute)) { + if (attribute === 'tag' || attribute === 'tags') { + new_props['tags'] += frontmatter[attribute]; + } + else { + new_props[attribute] = frontmatter[attribute]; + } + } + }); + } + if (settings.targetTags) { + new_props["tags"] += obsidian.getAllTags(cache).join(' '); + } + if (addDataHref) { + new_props['data-href'] = dest.basename; + } + new_props['path'] = dest.path; + //@ts-ignore + const getResults = (api) => { + const page = api.page(dest.path); + if (!page) { + return; + } + settings.targetAttributes.forEach((field) => { + const value = page[field]; + if (value) + new_props[field] = value; + }); + }; + if (settings.getFromInlineField && app.plugins.enabledPlugins.has("dataview")) { + const api = (_a = app.plugins.plugins.dataview) === null || _a === void 0 ? void 0 : _a.api; + if (api) { + getResults(api); + } + else + this.plugin.registerEvent(this.app.metadataCache.on("dataview:api-ready", (api) => getResults(api))); + } + return new_props; +} +function setLinkNewProps(link, new_props) { + // @ts-ignore + for (const a of link.attributes) { + if (a.name.includes("data-link") && !(a.name in new_props)) { + link.removeAttribute(a.name); + } + } + Object.keys(new_props).forEach(key => { + const name = "data-link-" + key; + const newValue = new_props[key]; + const curValue = link.getAttribute(name); + // Only update if value is different + if (!newValue || curValue != newValue) { + link.setAttribute("data-link-" + key, new_props[key]); + } + }); + if (!link.hasClass("data-link-icon")) { + link.addClass("data-link-icon"); + } + if (!link.hasClass("data-link-icon-after")) { + link.addClass("data-link-icon-after"); + } + if (!link.hasClass("data-link-text")) { + link.addClass("data-link-text"); + } +} +function updateLinkExtraAttributes(app, settings, link, destName) { + const linkHref = link.getAttribute('href').split('#')[0]; + const dest = app.metadataCache.getFirstLinkpathDest(linkHref, destName); + if (dest) { + const new_props = fetchTargetAttributesSync(app, settings, dest, false); + setLinkNewProps(link, new_props); + } +} +function updateDivExtraAttributes(app, settings, link, destName, linkName) { + if (!linkName) { + linkName = link.textContent; + } + const dest = app.metadataCache.getFirstLinkpathDest(obsidian.getLinkpath(linkName), destName); + if (dest) { + const new_props = fetchTargetAttributesSync(app, settings, dest, true); + setLinkNewProps(link, new_props); + } +} +function updateElLinks(app, plugin, el, ctx) { + const settings = plugin.settings; + const links = el.querySelectorAll('a.internal-link'); + const destName = ctx.sourcePath.replace(/(.*).md/, "$1"); + links.forEach((link) => { + updateLinkExtraAttributes(app, settings, link, destName); + }); +} +function updateVisibleLinks(app, plugin) { + const settings = plugin.settings; + app.workspace.iterateRootLeaves((leaf) => { + if (leaf.view instanceof obsidian.MarkdownView && leaf.view.file) { + const file = leaf.view.file; + const cachedFile = app.metadataCache.getFileCache(file); + //@ts-ignore + const tabHeader = leaf.tabHeaderInnerTitleEl; + if (settings.enableTabHeader) { + // Supercharge tab headers + updateDivExtraAttributes(app, settings, tabHeader, ""); + } + else { + clearExtraAttributes(tabHeader); + } + if (cachedFile.links) { + cachedFile.links.forEach((link) => { + const fileName = file.path.replace(/(.*).md/, "$1"); + const dest = app.metadataCache.getFirstLinkpathDest(link.link, fileName); + if (dest) { + const new_props = fetchTargetAttributesSync(app, settings, dest, false); + const internalLinks = leaf.view.containerEl.querySelectorAll(`a.internal-link[href="${link.link}"]`); + internalLinks.forEach((internalLink) => setLinkNewProps(internalLink, new_props)); + } + }); + } + } + }); +} + +class SuperchargedLinksSettingTab extends obsidian.PluginSettingTab { + constructor(app, plugin) { + super(app, plugin); + this.plugin = plugin; + this.debouncedGenerate = obsidian.debounce(this._generateSnippet, 1000, true); + } + display() { + let { containerEl } = this; + containerEl.empty(); + /* Managing extra attirbutes for a.internal-link */ + new obsidian.Setting(containerEl) + .setName('Target Attributes for styling') + .setDesc('Frontmatter attributes to target, comma separated') + .addTextArea((text) => { + text + .setPlaceholder('Enter attributes as string, comma separated') + .setValue(this.plugin.settings.targetAttributes.join(', ')) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.targetAttributes = value.replace(/\s/g, '').split(','); + if (this.plugin.settings.targetAttributes.length === 1 && !this.plugin.settings.targetAttributes[0]) { + this.plugin.settings.targetAttributes = []; + } + yield this.plugin.saveSettings(); + })); + text.inputEl.rows = 6; + text.inputEl.cols = 25; + }); + containerEl.createEl('h4', { text: 'Styling' }); + const styleSettingDescription = containerEl.createDiv(); + styleSettingDescription.innerHTML = ` +Styling can be done using the Style Settings plugin. +
    +
  1. Create selectors down below.
  2. +
  3. Go to the Style Settings tab and style your links!
  4. +
`; + const selectorDiv = containerEl.createDiv(); + this.drawSelectors(selectorDiv); + containerEl.createEl('h4', { text: 'Settings' }); + new obsidian.Setting(containerEl) + .setName('Enable in Editor') + .setDesc('If true, this will also supercharge internal links in the editor view of a note.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.enableEditor); + toggle.onChange(value => { + this.plugin.settings.enableEditor = value; + this.plugin.saveSettings(); + updateVisibleLinks(app, this.plugin); + }); + }); + new obsidian.Setting(containerEl) + .setName('Enable in tab headers') + .setDesc('If true, this will also supercharge the headers of a tab.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.enableTabHeader); + toggle.onChange(value => { + this.plugin.settings.enableTabHeader = value; + this.plugin.saveSettings(); + updateVisibleLinks(app, this.plugin); + }); + }); + new obsidian.Setting(containerEl) + .setName('Enable in File Browser') + .setDesc('If true, this will also supercharge the file browser.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.enableFileList); + toggle.onChange(value => { + this.plugin.settings.enableFileList = value; + this.plugin.saveSettings(); + }); + }); + new obsidian.Setting(containerEl) + .setName('Enable in Plugins') + .setDesc('If true, this will also supercharge plugins like the backlinks and forward links panels.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.enableBacklinks); + toggle.onChange(value => { + this.plugin.settings.enableBacklinks = value; + this.plugin.saveSettings(); + }); + }); + new obsidian.Setting(containerEl) + .setName('Enable in Quick Switcher') + .setDesc('If true, this will also supercharge the quick switcher.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.enableQuickSwitcher); + toggle.onChange(value => { + this.plugin.settings.enableQuickSwitcher = value; + this.plugin.saveSettings(); + }); + }); + new obsidian.Setting(containerEl) + .setName('Enable in Link Autocompleter') + .setDesc('If true, this will also supercharge the link autocompleter.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.enableSuggestor); + toggle.onChange(value => { + this.plugin.settings.enableSuggestor = value; + this.plugin.saveSettings(); + }); + }); + containerEl.createEl('h4', { text: 'Advanced' }); + // Managing choice wether you want to parse tags both from normal tags and in the frontmatter + new obsidian.Setting(containerEl) + .setName('Parse all tags in the file') + .setDesc('Sets the `data-link-tags`-attribute to look for tags both in the frontmatter and in the file as #tag-name') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.targetTags); + toggle.onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.targetTags = value; + yield this.plugin.saveSettings(); + })); + }); + // Managing choice wether you get attributes from inline fields and frontmatter or only frontmater + new obsidian.Setting(containerEl) + .setName('Search for attribute in Inline fields like ') + .setDesc('Sets the `data-link-`-attribute to the value of inline fields') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.getFromInlineField); + toggle.onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.getFromInlineField = value; + yield this.plugin.saveSettings(); + })); + }); + // Automatically activate snippet + new obsidian.Setting(containerEl) + .setName('Automatically activate snippet') + .setDesc('If true, this will automatically activate the generated CSS snippet "supercharged-links-gen.css". ' + + 'Turn this off if you don\'t want this to happen.') + .addToggle(toggle => { + toggle.setValue(this.plugin.settings.activateSnippet); + toggle.onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.activateSnippet = value; + yield this.plugin.saveSettings(); + })); + }); + /* Managing predefined values for properties */ + /* Manage menu options display*/ + new obsidian.Setting(containerEl) + .setName("Display field options in context menu") + .setDesc("This feature has been migrated to metadata-menu plugin https://github.com/mdelobelle/metadatamenu"); + } + generateSnippet() { + this.debouncedGenerate(); + } + _generateSnippet() { + return __awaiter(this, void 0, void 0, function* () { + yield buildCSS(this.plugin.settings.selectors, this.plugin); + // new Notice("Generated supercharged-links-gen.css"); + }); + } + drawSelectors(div) { + div.empty(); + this.generateSnippet(); + const selectors = this.plugin.settings.selectors; + selectors.forEach((selector, i) => { + const s = new obsidian.Setting(div) + .addButton(button => { + button.onClick(() => { + const oldSelector = selectors[i + 1]; + selectors[i + 1] = selector; + selectors[i] = oldSelector; + this.drawSelectors(div); + }); + button.setIcon("down-arrow-with-tail"); + button.setTooltip("Move selector down"); + if (i === selectors.length - 1) { + button.setDisabled(true); + } + }) + .addButton(button => { + button.onClick(() => { + const oldSelector = selectors[i - 1]; + selectors[i - 1] = selector; + selectors[i] = oldSelector; + this.drawSelectors(div); + }); + button.setIcon("up-arrow-with-tail"); + button.setTooltip("Move selector up"); + if (i === 0) { + button.setDisabled(true); + } + }) + .addButton(button => { + button.onClick(() => { + const formModal = new CSSBuilderModal(this.plugin, (newSelector) => { + this.plugin.settings.selectors[i] = newSelector; + this.plugin.saveSettings(); + updateDisplay(s.nameEl, selector, this.plugin.settings); + this.generateSnippet(); + }, selector); + formModal.open(); + }); + button.setIcon("pencil"); + button.setTooltip("Edit selector"); + }) + .addButton(button => { + button.onClick(() => { + this.plugin.settings.selectors.remove(selector); + this.plugin.saveSettings(); + this.drawSelectors(div); + }); + button.setIcon("cross"); + button.setTooltip("Remove selector"); + }); + updateDisplay(s.nameEl, selector, this.plugin.settings); + }); + new obsidian.Setting(div) + .setName("New selector") + .setDesc("Create a new selector to style with Style Settings.") + .addButton(button => { + button.onClick(() => { + const formModal = new CSSBuilderModal(this.plugin, (newSelector) => { + this.plugin.settings.selectors.push(newSelector); + this.plugin.saveSettings(); + this.drawSelectors(div); + // TODO: Force redraw somehow? + }); + formModal.open(); + }); + button.setButtonText("New"); + }); + } +} + +const DEFAULT_SETTINGS = { + targetAttributes: [], + targetTags: true, + getFromInlineField: true, + enableTabHeader: true, + activateSnippet: true, + enableEditor: true, + enableFileList: true, + enableBacklinks: true, + enableQuickSwitcher: true, + enableSuggestor: true, + selectors: [] +}; + +function buildCMViewPlugin(app, _settings) { + // Implements the live preview supercharging + // Code structure based on https://github.com/nothingislost/obsidian-cm6-attributes/blob/743d71b0aa616407149a0b6ea5ffea28e2154158/src/main.ts + // Code help credits to @NothingIsLost! They have been a great help getting this to work properly. + class HeaderWidget extends view.WidgetType { + constructor(attributes, after) { + super(); + this.attributes = attributes; + this.after = after; + } + toDOM() { + let headerEl = document.createElement("span"); + headerEl.setAttrs(this.attributes); + if (this.after) { + headerEl.addClass('data-link-icon-after'); + } + else { + headerEl.addClass('data-link-icon'); + } + // create a naive bread crumb + return headerEl; + } + ignoreEvent() { + return true; + } + } + const settings = _settings; + const viewPlugin = view.ViewPlugin.fromClass(class { + constructor(view) { + this.decorations = this.buildDecorations(view); + } + update(update) { + if (update.docChanged || update.viewportChanged) { + this.decorations = this.buildDecorations(update.view); + } + } + destroy() { + } + buildDecorations(view$1) { + let builder = new state.RangeSetBuilder(); + if (!settings.enableEditor) { + return builder.finish(); + } + const mdView = view$1.state.field(obsidian.editorViewField); + let lastAttributes = {}; + let iconDecoAfter = null; + let iconDecoAfterWhere = null; + let mdAliasFrom = null; + let mdAliasTo = null; + for (let { from, to } of view$1.visibleRanges) { + language.syntaxTree(view$1.state).iterate({ + from, + to, + enter: (node) => { + const tokenProps = node.type.prop(language.tokenClassNodeProp); + if (tokenProps) { + const props = new Set(tokenProps.split(" ")); + const isLink = props.has("hmd-internal-link"); + const isAlias = props.has("link-alias"); + const isPipe = props.has("link-alias-pipe"); + // The 'alias' of the md link + const isMDLink = props.has('link'); + // The 'internal link' of the md link + const isMDUrl = props.has('url'); + const isMDFormatting = props.has('formatting-link'); + if (isMDLink && !isMDFormatting) { + // Link: The 'alias' + // URL: The internal link + mdAliasFrom = node.from; + mdAliasTo = node.to; + } + if (!isPipe && !isAlias) { + if (iconDecoAfter) { + builder.add(iconDecoAfterWhere, iconDecoAfterWhere, iconDecoAfter); + iconDecoAfter = null; + iconDecoAfterWhere = null; + } + } + if (isLink && !isAlias && !isPipe || isMDUrl) { + let linkText = view$1.state.doc.sliceString(node.from, node.to); + linkText = linkText.split("#")[0]; + let file = app.metadataCache.getFirstLinkpathDest(linkText, mdView.file.basename); + if (isMDUrl && !file) { + try { + file = app.vault.getAbstractFileByPath(decodeURIComponent(linkText)); + } + catch (e) { } + } + if (file) { + let _attributes = fetchTargetAttributesSync(app, settings, file, true); + let attributes = {}; + for (let key in _attributes) { + attributes["data-link-" + key] = _attributes[key]; + } + let deco = view.Decoration.mark({ + attributes, + class: "data-link-text" + }); + let iconDecoBefore = view.Decoration.widget({ + widget: new HeaderWidget(attributes, false), + }); + iconDecoAfter = view.Decoration.widget({ + widget: new HeaderWidget(attributes, true), + }); + if (isMDUrl) { + // Apply retroactively to the alias found before + let deco = view.Decoration.mark({ + attributes: attributes, + class: "data-link-text" + }); + builder.add(mdAliasFrom, mdAliasFrom, iconDecoBefore); + builder.add(mdAliasFrom, mdAliasTo, deco); + if (iconDecoAfter) { + builder.add(mdAliasTo, mdAliasTo, iconDecoAfter); + iconDecoAfter = null; + iconDecoAfterWhere = null; + mdAliasFrom = null; + mdAliasTo = null; + } + } + else { + builder.add(node.from, node.from, iconDecoBefore); + } + builder.add(node.from, node.to, deco); + lastAttributes = attributes; + iconDecoAfterWhere = node.to; + } + } + else if (isLink && isAlias) { + let deco = view.Decoration.mark({ + attributes: lastAttributes, + class: "data-link-text" + }); + builder.add(node.from, node.to, deco); + if (iconDecoAfter) { + builder.add(node.to, node.to, iconDecoAfter); + iconDecoAfter = null; + iconDecoAfterWhere = null; + } + } + } + } + }); + } + return builder.finish(); + } + }, { + decorations: v => v.decorations + }); + return viewPlugin; +} + +class SuperchargedLinks extends obsidian.Plugin { + constructor() { + super(...arguments); + this.modalObservers = []; + } + onload() { + return __awaiter(this, void 0, void 0, function* () { + console.log('Supercharged links loaded'); + yield this.loadSettings(); + this.addSettingTab(new SuperchargedLinksSettingTab(this.app, this)); + this.registerMarkdownPostProcessor((el, ctx) => { + updateElLinks(this.app, this, el, ctx); + }); + // Plugins watching + this.registerEvent(this.app.metadataCache.on('changed', obsidian.debounce((_file) => { + updateVisibleLinks(this.app, this); + this.observers.forEach(([observer, type, own_class]) => { + const leaves = this.app.workspace.getLeavesOfType(type); + leaves.forEach(leaf => { + this.updateContainer(leaf.view.containerEl, this, own_class); + }); + }); + // Debounced to prevent lag when writing + }, 4500, true))); + // Live preview + const ext = state.Prec.lowest(buildCMViewPlugin(this.app, this.settings)); + this.registerEditorExtension(ext); + this.observers = []; + this.app.workspace.onLayoutReady(() => { + this.initViewObservers(this); + this.initModalObservers(this, document); + updateVisibleLinks(this.app, this); + }); + this.registerEvent(this.app.workspace.on("window-open", (window, win) => this.initModalObservers(this, window.getContainer().doc))); + this.registerEvent(this.app.workspace.on("layout-change", () => this.initViewObservers(this))); + }); + } + initViewObservers(plugin) { + var _a, _b, _c, _d, _e, _f; + // Reset observers + plugin.observers.forEach(([observer, type]) => { + observer.disconnect(); + }); + plugin.observers = []; + // Register new observers + plugin.registerViewType('backlink', plugin, ".tree-item-inner", true); + plugin.registerViewType('outgoing-link', plugin, ".tree-item-inner", true); + plugin.registerViewType('search', plugin, ".tree-item-inner"); + plugin.registerViewType('BC-matrix', plugin, '.BC-Link'); + plugin.registerViewType('BC-ducks', plugin, '.internal-link'); + plugin.registerViewType('BC-tree', plugin, 'a.internal-link'); + plugin.registerViewType('graph-analysis', plugin, '.internal-link'); + plugin.registerViewType('starred', plugin, '.nav-file-title-content'); + plugin.registerViewType('file-explorer', plugin, '.nav-file-title-content'); + plugin.registerViewType('recent-files', plugin, '.nav-file-title-content'); + // If backlinks in editor is on + // @ts-ignore + if ((_f = (_e = (_d = (_c = (_b = (_a = plugin.app) === null || _a === void 0 ? void 0 : _a.internalPlugins) === null || _b === void 0 ? void 0 : _b.plugins) === null || _c === void 0 ? void 0 : _c.backlink) === null || _d === void 0 ? void 0 : _d.instance) === null || _e === void 0 ? void 0 : _e.options) === null || _f === void 0 ? void 0 : _f.backlinkInDocument) { + plugin.registerViewType('markdown', plugin, '.tree-item-inner', true); + } + } + initModalObservers(plugin, doc) { + const config = { + subtree: false, + childList: true, + attributes: false + }; + this.modalObservers.push(new MutationObserver(records => { + records.forEach((mutation) => { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach(n => { + if ('className' in n && + // @ts-ignore + (n.className.includes('modal-container') && plugin.settings.enableQuickSwitcher + // @ts-ignore + || n.className.includes('suggestion-container') && plugin.settings.enableSuggestor)) { + let selector = ".suggestion-title, .suggestion-note, .another-quick-switcher__item__title, .omnisearch-result__title"; + // @ts-ignore + if (n.className.includes('suggestion-container')) { + selector = ".suggestion-title, .suggestion-note"; + } + plugin.updateContainer(n, plugin, selector); + plugin._watchContainer(null, n, plugin, selector); + } + }); + } + }); + })); + this.modalObservers.last().observe(doc.body, config); + } + registerViewType(viewTypeName, plugin, selector, updateDynamic = false) { + const leaves = this.app.workspace.getLeavesOfType(viewTypeName); + if (leaves.length > 1) { + for (let i = 0; i < leaves.length; i++) { + const container = leaves[i].view.containerEl; + if (updateDynamic) { + plugin._watchContainerDynamic(viewTypeName + i, container, plugin, selector); + } + else { + plugin._watchContainer(viewTypeName + i, container, plugin, selector); + } + } + } + else if (leaves.length < 1) + return; + else { + const container = leaves[0].view.containerEl; + this.updateContainer(container, plugin, selector); + if (updateDynamic) { + plugin._watchContainerDynamic(viewTypeName, container, plugin, selector); + } + else { + plugin._watchContainer(viewTypeName, container, plugin, selector); + } + } + } + updateContainer(container, plugin, selector) { + if (!plugin.settings.enableBacklinks) + return; + const nodes = container.findAll(selector); + for (let i = 0; i < nodes.length; ++i) { + const el = nodes[i]; + updateDivExtraAttributes(plugin.app, plugin.settings, el, ""); + } + } + removeFromContainer(container, selector) { + const nodes = container.findAll(selector); + for (let i = 0; i < nodes.length; ++i) { + const el = nodes[i]; + clearExtraAttributes(el); + } + } + _watchContainer(viewType, container, plugin, selector) { + let observer = new MutationObserver((records, _) => { + plugin.updateContainer(container, plugin, selector); + }); + observer.observe(container, { subtree: true, childList: true, attributes: false }); + if (viewType) { + plugin.observers.push([observer, viewType, selector]); + } + } + _watchContainerDynamic(viewType, container, plugin, selector, own_class = 'tree-item-inner', parent_class = 'tree-item') { + // Used for efficient updating of the backlinks panel + // Only loops through newly added DOM nodes instead of changing all of them + let observer = new MutationObserver((records, _) => { + records.forEach((mutation) => { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach((n) => { + if ('className' in n) { + // @ts-ignore + if (n.className.includes && typeof n.className.includes === 'function' && n.className.includes(parent_class)) { + const fileDivs = n.getElementsByClassName(own_class); + for (let i = 0; i < fileDivs.length; ++i) { + const link = fileDivs[i]; + updateDivExtraAttributes(plugin.app, plugin.settings, link, ""); + } + } + } + }); + } + }); + }); + observer.observe(container, { subtree: true, childList: true, attributes: false }); + plugin.observers.push([observer, viewType, selector]); + } + onunload() { + this.observers.forEach(([observer, type, own_class]) => { + observer.disconnect(); + const leaves = this.app.workspace.getLeavesOfType(type); + leaves.forEach(leaf => { + this.removeFromContainer(leaf.view.containerEl, own_class); + }); + }); + for (const observer of this.modalObservers) { + observer.disconnect(); + } + console.log('Supercharged links unloaded'); + } + loadSettings() { + return __awaiter(this, void 0, void 0, function* () { + this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData()); + }); + } + saveSettings() { + return __awaiter(this, void 0, void 0, function* () { + yield this.saveData(this.settings); + }); + } +} + +module.exports = SuperchargedLinks; + + +/* nosourcemap */ \ No newline at end of file diff --git a/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/styles.css b/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/styles.css new file mode 100644 index 0000000..b80f841 --- /dev/null +++ b/private-mode-testvault/.obsidian/plugins/supercharged-links-obsidian/styles.css @@ -0,0 +1,11 @@ +.css-boilerplate-result { + width: 30em +} + +div.supercharged-modal { + height: 70vh; +} + +div.supercharged-modal h4 { + margin: 0; +} \ No newline at end of file