diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index fb4b2c9..3fc22d7 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -178,7 +178,7 @@ Configured systems live in `settings.dateSystems`, where array order is menu ord | `journal` | Journal | `periodic/journal` | `YYYY-MM-DD - [Journal]` | green (`#22c55e`) | one | | `meetings` | Meeting | `periodic/meetings` | `YYYY-MM-DD - {title}` | violet (`#a855f7`) | many | -The default calendar mode is `systems`, while `any` preserves the older one-neutral-dot behaviour. Template file fields in both Periodic Notes and Date systems use a native `datalist` populated from every Markdown path in the vault (without the optional `.md` extension), so templates stored outside a conventional `Templates/` folder remain discoverable. +The default calendar mode is `systems`, while `any` preserves the older one-neutral-dot behaviour. Existing installs that silently persisted the pre-`systems` default of `any` are promoted to `systems` exactly once, on load, via a `data.json`-level `indicatorModeMigrated` flag; a value chosen after that flag is set (including `any`) is never touched again. Template file fields in both Periodic Notes and Date systems use `TemplateFileSuggest`, an `AbstractInputSuggest` (the same base class Templater's own template pickers use — Obsidian's native fuzzy-suggest popup, not an unstyled ``), searching every Markdown path in the vault. `AbstractInputSuggest` requires Obsidian ≥1.4.10, hence `manifest.json`'s `minAppVersion`. ### Templater folder triggers diff --git a/main.js b/main.js index 717b172..61ef0e4 100644 --- a/main.js +++ b/main.js @@ -2,26 +2,26 @@ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */ -var _=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var he=Object.getOwnPropertyNames;var ue=Object.prototype.hasOwnProperty;var ge=(p,d)=>{for(var e in d)_(p,e,{get:d[e],enumerable:!0})},fe=(p,d,e,n)=>{if(d&&typeof d=="object"||typeof d=="function")for(let i of he(d))!ue.call(p,i)&&i!==e&&_(p,i,{get:()=>d[i],enumerable:!(n=me(d,i))||n.enumerable});return p};var ye=p=>fe(_({},"__esModule",{value:!0}),p);var Se={};ge(Se,{default:()=>q});module.exports=ye(Se);var f=require("obsidian");var $={name:"",folder:"",nameFormat:"YYYY-MM-DD - {title}",templateFile:"",typeProperty:"",icon:"file",indicatorColor:"#64748b"},T={calendar:{firstDayOfWeek:1,showNoteIndicators:!0,indicatorMode:"systems",dailyIndicatorColor:"#3b82f6"},daily:{folder:"periodic/daily",templateFile:"Templates/Daily note",nameFormat:"YYYY-MM-DD",typeProperty:"daily-note"},weekly:{folder:"periodic/weekly",templateFile:"Templates/Weekly note",nameFormat:"GGGG-[W]WW",typeProperty:"weekly-note"},monthly:{folder:"periodic/monthly",templateFile:"Templates/Monthly note",nameFormat:"YYYY-MM",typeProperty:"monthly-note"},quarterly:{folder:"periodic/quarterly",templateFile:"Templates/Quarterly note",nameFormat:"YYYY-[Q]Q",typeProperty:"quarterly-note"},yearly:{folder:"periodic/yearly",templateFile:"Templates/Yearly note",nameFormat:"YYYY",typeProperty:"yearly-note"},dateSystems:[{id:"journal",name:"Journal",folder:"periodic/journal",nameFormat:"YYYY-MM-DD - [Journal]",templateFile:"",typeProperty:"journal",icon:"book-open",indicatorColor:"#22c55e"},{id:"meetings",name:"Meeting",folder:"periodic/meetings",nameFormat:"YYYY-MM-DD - {title}",templateFile:"",typeProperty:"meeting",icon:"users",indicatorColor:"#a855f7"}],recentFiles:{maxItems:50,updateOn:"file-open",omittedPaths:[],omittedTags:[],filterTags:[]},display:{rowSize:26,rowSpacing:2,indentSize:16,fontSize:13,iconSize:16,calendarCellSize:32}};var v=require("obsidian");var se="{title}";function R(p){let d=p.indexOf(se);return d<0?{before:p,after:"",hasTitle:!1}:{before:p.slice(0,d),after:p.slice(d+se.length),hasTitle:!0}}function Q(p,d){if(!d)return!0;let e=d.endsWith("/")?d:`${d}/`;return p.startsWith(e)}function U(p,d,e,n){return n?!d||p.length|#^[\]]/g;function re(p){return p.replace(ve,"-").replace(/\s+/g," ").trim()}function A(p){let{before:d}=R(p),e=d.replace(/\[[^\]]*\]/g,"");return/[YMDQGWEwdgeo]/.test(e)}var z=class extends v.PluginSettingTab{constructor(e,n,i,a){super(e,n);this.activeTab="calendar";this.plugin=n,this.settings=i,this.onSettingsChange=a}display(){let{containerEl:e}=this;e.empty();let n=e.createDiv({cls:"waypoint-settings-tabs"}),i=[{key:"calendar",label:"Calendar"},{key:"periodic",label:"Periodic Notes"},{key:"systems",label:"Date systems"},{key:"recent",label:"Recent Files"},{key:"display",label:"Display"},{key:"about",label:"About"}];for(let t of i)n.createEl("button",{cls:`waypoint-settings-tab${this.activeTab===t.key?" is-active":""}`,text:t.label}).addEventListener("click",()=>{this.activeTab=t.key,this.display()});let a=e.createDiv({cls:"waypoint-settings-content"});switch(this.activeTab){case"calendar":this.renderCalendarTab(a);break;case"periodic":this.renderPeriodicTab(a);break;case"systems":this.renderSystemsTab(a);break;case"recent":this.renderRecentTab(a);break;case"display":this.renderDisplayTab(a);break;case"about":this.renderAboutTab(a);break}}renderCalendarTab(e){new v.Setting(e).setName("First day of week").setDesc("Which day the calendar week starts on.").addDropdown(n=>{n.addOption("0","Sunday").addOption("1","Monday").setValue(String(this.settings.calendar.firstDayOfWeek)).onChange(i=>{this.settings.calendar.firstDayOfWeek=parseInt(i,10),this.saveAndRefresh()})}),new v.Setting(e).setName("Show note indicators").setDesc("Show a dot on days that have existing notes.").addToggle(n=>{n.setValue(this.settings.calendar.showNoteIndicators).onChange(i=>{this.settings.calendar.showNoteIndicators=i,this.saveAndRefresh()})}),new v.Setting(e).setName("Indicator style").setDesc("Show one neutral dot for any dated note, or one coloured dot for each configured date system.").addDropdown(n=>{n.addOption("any","Single dot").addOption("systems","Colour by note system").setValue(this.settings.calendar.indicatorMode).onChange(i=>{this.settings.calendar.indicatorMode=i,this.saveAndRefresh()})}),new v.Setting(e).setName("Daily indicator colour").setDesc("Colour for daily-note dots when using \u201CColour by note system\u201D.").addColorPicker(n=>{n.setValue(this.settings.calendar.dailyIndicatorColor).onChange(i=>{this.settings.calendar.dailyIndicatorColor=i,this.saveAndRefresh()})})}renderPeriodicTab(e){let n=this.createTemplateSuggestions(e);this.addPeriodNoteSettings(e,"Daily",this.settings.daily,n),this.addPeriodNoteSettings(e,"Weekly",this.settings.weekly,n),this.addPeriodNoteSettings(e,"Monthly",this.settings.monthly,n),this.addPeriodNoteSettings(e,"Quarterly",this.settings.quarterly,n),this.addPeriodNoteSettings(e,"Yearly",this.settings.yearly,n)}addPeriodNoteSettings(e,n,i,a){new v.Setting(e).setHeading().setName(n),new v.Setting(e).setName("Folder").setDesc(`Folder path for ${n.toLowerCase()} notes.`).addText(t=>{t.setPlaceholder("periodic/daily"),t.setValue(i.folder),t.onChange(s=>{i.folder=s,this.saveAndRefresh()})}),new v.Setting(e).setName("Name format").setDesc(`Date format for ${n.toLowerCase()} note filenames (moment.js format).`).addText(t=>{t.setPlaceholder("yyyy-MM-dd"),t.setValue(i.nameFormat),t.onChange(s=>{i.nameFormat=s,this.saveAndRefresh()})}),new v.Setting(e).setName("Template file").setDesc("Path to the template file. The .md extension is optional.").addText(t=>{t.setPlaceholder("Templates/Daily note"),t.setValue(i.templateFile),t.inputEl.setAttr("list",a),t.onChange(s=>{i.templateFile=s,this.saveAndRefresh()})}),new v.Setting(e).setName("Type property").setDesc("Value for the 'type' frontmatter property.").addText(t=>{t.setPlaceholder("daily-note"),t.setValue(i.typeProperty),t.onChange(s=>{i.typeProperty=s,this.saveAndRefresh()})})}renderSystemsTab(e){let n=new DocumentFragment;n.createDiv({text:"A date system is a folder of notes whose filenames start with a date. Each one appears in the calendar's right-click menu for that day."}),n.createDiv({text:"The daily note is configured under Periodic Notes and always comes first in that menu."}),n.createDiv({text:"Name format is a moment.js format. Literal words need bracket escaping, e.g. YYYY-MM-DD - [Journal]."}),n.createDiv({text:"Include {title} for systems that hold many notes per date, such as meetings: the text before the token finds the existing notes, and the token marks where a typed title goes. Without it, a date has exactly one note."}),new v.Setting(e).setHeading().setName("Date systems").setDesc(n);let i=this.createTemplateSuggestions(e);this.settings.dateSystems.forEach((a,t,s)=>{new v.Setting(e).setHeading().setName(a.name||"Untitled system").addExtraButton(r=>{r.setIcon("arrow-up").setTooltip("Move up").setDisabled(t===0).onClick(async()=>{if(t===0)return;let c=s[t-1];s[t-1]=s[t],s[t]=c,await this.saveAndRefresh(),this.display()})}).addExtraButton(r=>{r.setIcon("arrow-down").setTooltip("Move down").setDisabled(t===s.length-1).onClick(async()=>{if(t===s.length-1)return;let c=s[t+1];s[t+1]=s[t],s[t]=c,await this.saveAndRefresh(),this.display()})}).addExtraButton(r=>{r.setIcon("trash").setTooltip("Delete this date system").onClick(async()=>{s.splice(t,1),await this.saveAndRefresh(),this.display()})}),this.addSystemTextSetting(e,"Name","Label shown in the calendar right-click menu.",a,"name","Journal"),this.addSystemTextSetting(e,"Folder","Folder these notes live in.",a,"folder","periodic/journal");let o=this.addSystemTextSetting(e,"Name format","Filename format (moment.js format). Include {title} for many notes per date.",a,"nameFormat","YYYY-MM-DD - {title}");a.nameFormat&&!A(a.nameFormat)&&o.descEl.createDiv({cls:"waypoint-settings-warning",text:"This name format has no date placeholder, so it will never match or create dated notes."}),this.addSystemTextSetting(e,"Template file","Path to the template file. The .md extension is optional.",a,"templateFile","resources/template/journal",i),this.addSystemTextSetting(e,"Type property","Fallback value for the 'type' frontmatter property, used when no template is found.",a,"typeProperty","journal-note"),this.addSystemTextSetting(e,"Icon","Lucide icon name for the menu item. Browse names at lucide.dev.",a,"icon","book-open"),new v.Setting(e).setName("Indicator colour").setDesc("Colour for this system\u2019s dot when using \u201CColour by note system\u201D.").addColorPicker(r=>{r.setValue(a.indicatorColor).onChange(c=>{a.indicatorColor=c,this.saveAndRefresh()})})}),new v.Setting(e).addButton(a=>a.setButtonText("Add date system").setCta().onClick(async()=>{this.settings.dateSystems.push(Object.assign({id:`ds-${Date.now()}-${Math.random().toString(36).slice(2,6)}`},$)),await this.saveAndRefresh(),this.display()}))}addSystemTextSetting(e,n,i,a,t,s,o){return new v.Setting(e).setName(n).setDesc(i).addText(r=>{r.setPlaceholder(s),r.setValue(a[t]),o&&r.inputEl.setAttr("list",o),r.onChange(c=>{a[t]=c,this.saveAndRefresh()})})}createTemplateSuggestions(e){let n="waypoint-template-suggestions",i=e.createEl("datalist",{attr:{id:n}}),a=this.app.vault.getMarkdownFiles().map(t=>t.path.replace(/\.md$/,"")).sort((t,s)=>t.localeCompare(s));for(let t of a)i.createEl("option",{value:t});return n}renderRecentTab(e){new v.Setting(e).setName("Max items").setDesc("Maximum number of recent files to track.").addText(t=>{t.inputEl.setAttr("type","number"),t.inputEl.setAttr("placeholder","50"),t.setValue(String(this.settings.recentFiles.maxItems)),t.inputEl.onblur=()=>{let s=parseInt(t.getValue(),10);!isNaN(s)&&s>0&&(this.settings.recentFiles.maxItems=s,this.saveAndRefresh())}}),new v.Setting(e).setName("Update on").setDesc("When to add a file to the recent list.").addDropdown(t=>{t.addOption("file-open","File opened").addOption("file-edit","File changed").setValue(this.settings.recentFiles.updateOn).onChange(s=>{this.settings.recentFiles.updateOn=s,this.saveAndRefresh()})});let n=new DocumentFragment;n.appendText("Regex patterns for paths to exclude. One per line."),new v.Setting(e).setName("Omitted paths").setDesc(n).addTextArea(t=>{t.inputEl.setAttr("rows",4),t.setPlaceholder(`^archives/ -\\.png$`),t.setValue(this.settings.recentFiles.omittedPaths.join(` -`)),t.inputEl.onblur=()=>{this.settings.recentFiles.omittedPaths=t.getValue().split(` -`).filter(s=>s.trim()),this.saveAndRefresh()}});let i=new DocumentFragment;i.appendText("Regex patterns for frontmatter tags to exclude. One per line."),new v.Setting(e).setName("Omitted tags").setDesc(i).addTextArea(t=>{t.inputEl.setAttr("rows",4),t.setPlaceholder(`ignore -archive`),t.setValue(this.settings.recentFiles.omittedTags.join(` -`)),t.inputEl.onblur=()=>{this.settings.recentFiles.omittedTags=t.getValue().split(` -`).filter(s=>s.trim()),this.saveAndRefresh()}});let a=new DocumentFragment;a.appendText("Tags to show as filter pills above the file list. One per line. Leave empty to auto-detect from frontmatter `type` property."),new v.Setting(e).setName("Filter tags").setDesc(a).addTextArea(t=>{t.inputEl.setAttr("rows",4),t.setPlaceholder(`meeting +var Q=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var ge=Object.prototype.hasOwnProperty;var fe=(p,d)=>{for(var e in d)Q(p,e,{get:d[e],enumerable:!0})},ye=(p,d,e,n)=>{if(d&&typeof d=="object"||typeof d=="function")for(let a of ue(d))!ge.call(p,a)&&a!==e&&Q(p,a,{get:()=>d[a],enumerable:!(n=he(d,a))||n.enumerable});return p};var ve=p=>ye(Q({},"__esModule",{value:!0}),p);var Fe={};fe(Fe,{default:()=>G});module.exports=ve(Fe);var f=require("obsidian");var $={name:"",folder:"",nameFormat:"YYYY-MM-DD - {title}",templateFile:"",typeProperty:"",icon:"file",indicatorColor:"#64748b"},T={calendar:{firstDayOfWeek:1,showNoteIndicators:!0,indicatorMode:"systems",dailyIndicatorColor:"#3b82f6"},daily:{folder:"periodic/daily",templateFile:"Templates/Daily note",nameFormat:"YYYY-MM-DD",typeProperty:"daily-note"},weekly:{folder:"periodic/weekly",templateFile:"Templates/Weekly note",nameFormat:"GGGG-[W]WW",typeProperty:"weekly-note"},monthly:{folder:"periodic/monthly",templateFile:"Templates/Monthly note",nameFormat:"YYYY-MM",typeProperty:"monthly-note"},quarterly:{folder:"periodic/quarterly",templateFile:"Templates/Quarterly note",nameFormat:"YYYY-[Q]Q",typeProperty:"quarterly-note"},yearly:{folder:"periodic/yearly",templateFile:"Templates/Yearly note",nameFormat:"YYYY",typeProperty:"yearly-note"},dateSystems:[{id:"journal",name:"Journal",folder:"periodic/journal",nameFormat:"YYYY-MM-DD - [Journal]",templateFile:"",typeProperty:"journal",icon:"book-open",indicatorColor:"#22c55e"},{id:"meetings",name:"Meeting",folder:"periodic/meetings",nameFormat:"YYYY-MM-DD - {title}",templateFile:"",typeProperty:"meeting",icon:"users",indicatorColor:"#a855f7"}],recentFiles:{maxItems:50,updateOn:"file-open",omittedPaths:[],omittedTags:[],filterTags:[]},display:{rowSize:26,rowSpacing:2,indentSize:16,fontSize:13,iconSize:16,calendarCellSize:32}};var v=require("obsidian");var oe="{title}";function R(p){let d=p.indexOf(oe);return d<0?{before:p,after:"",hasTitle:!1}:{before:p.slice(0,d),after:p.slice(d+oe.length),hasTitle:!0}}function U(p,d){if(!d)return!0;let e=d.endsWith("/")?d:`${d}/`;return p.startsWith(e)}function Z(p,d,e,n){return n?!d||p.length|#^[\]]/g;function le(p){return p.replace(ke,"-").replace(/\s+/g," ").trim()}function A(p){let{before:d}=R(p),e=d.replace(/\[[^\]]*\]/g,"");return/[YMDQGWEwdgeo]/.test(e)}var z=class extends v.AbstractInputSuggest{constructor(e,n){super(e,n);this.inputEl=n}getSuggestions(e){let n=e.toLowerCase();return this.app.vault.getMarkdownFiles().filter(a=>a.path.toLowerCase().includes(n)).slice(0,200)}renderSuggestion(e,n){n.setText(e.path.replace(/\.md$/,""))}selectSuggestion(e){this.setValue(e.path.replace(/\.md$/,"")),this.inputEl.trigger("input"),this.close()}},V=class extends v.PluginSettingTab{constructor(e,n,a,t){super(e,n);this.activeTab="calendar";this.plugin=n,this.settings=a,this.onSettingsChange=t}display(){let{containerEl:e}=this;e.empty();let n=e.createDiv({cls:"waypoint-settings-tabs"}),a=[{key:"calendar",label:"Calendar"},{key:"periodic",label:"Periodic Notes"},{key:"systems",label:"Date systems"},{key:"recent",label:"Recent Files"},{key:"display",label:"Display"},{key:"about",label:"About"}];for(let i of a)n.createEl("button",{cls:`waypoint-settings-tab${this.activeTab===i.key?" is-active":""}`,text:i.label}).addEventListener("click",()=>{this.activeTab=i.key,this.display()});let t=e.createDiv({cls:"waypoint-settings-content"});switch(this.activeTab){case"calendar":this.renderCalendarTab(t);break;case"periodic":this.renderPeriodicTab(t);break;case"systems":this.renderSystemsTab(t);break;case"recent":this.renderRecentTab(t);break;case"display":this.renderDisplayTab(t);break;case"about":this.renderAboutTab(t);break}}renderCalendarTab(e){new v.Setting(e).setName("First day of week").setDesc("Which day the calendar week starts on.").addDropdown(n=>{n.addOption("0","Sunday").addOption("1","Monday").setValue(String(this.settings.calendar.firstDayOfWeek)).onChange(a=>{this.settings.calendar.firstDayOfWeek=parseInt(a,10),this.saveAndRefresh()})}),new v.Setting(e).setName("Show note indicators").setDesc("Show a dot on days that have existing notes.").addToggle(n=>{n.setValue(this.settings.calendar.showNoteIndicators).onChange(a=>{this.settings.calendar.showNoteIndicators=a,this.saveAndRefresh()})}),new v.Setting(e).setName("Indicator style").setDesc("Show one neutral dot for any dated note, or one coloured dot for each configured date system.").addDropdown(n=>{n.addOption("any","Single dot").addOption("systems","Colour by note system").setValue(this.settings.calendar.indicatorMode).onChange(a=>{this.settings.calendar.indicatorMode=a,this.saveAndRefresh()})}),new v.Setting(e).setName("Daily indicator colour").setDesc("Colour for daily-note dots when using \u201CColour by note system\u201D.").addColorPicker(n=>{n.setValue(this.settings.calendar.dailyIndicatorColor).onChange(a=>{this.settings.calendar.dailyIndicatorColor=a,this.saveAndRefresh()})})}renderPeriodicTab(e){this.addPeriodNoteSettings(e,"Daily",this.settings.daily),this.addPeriodNoteSettings(e,"Weekly",this.settings.weekly),this.addPeriodNoteSettings(e,"Monthly",this.settings.monthly),this.addPeriodNoteSettings(e,"Quarterly",this.settings.quarterly),this.addPeriodNoteSettings(e,"Yearly",this.settings.yearly)}addPeriodNoteSettings(e,n,a){new v.Setting(e).setHeading().setName(n),new v.Setting(e).setName("Folder").setDesc(`Folder path for ${n.toLowerCase()} notes.`).addText(t=>{t.setPlaceholder("periodic/daily"),t.setValue(a.folder),t.onChange(i=>{a.folder=i,this.saveAndRefresh()})}),new v.Setting(e).setName("Name format").setDesc(`Date format for ${n.toLowerCase()} note filenames (moment.js format).`).addText(t=>{t.setPlaceholder("yyyy-MM-dd"),t.setValue(a.nameFormat),t.onChange(i=>{a.nameFormat=i,this.saveAndRefresh()})}),new v.Setting(e).setName("Template file").setDesc("Path to the template file. The .md extension is optional.").addText(t=>{t.setPlaceholder("Templates/Daily note"),t.setValue(a.templateFile),new z(this.app,t.inputEl),t.onChange(i=>{a.templateFile=i,this.saveAndRefresh()})}),new v.Setting(e).setName("Type property").setDesc("Value for the 'type' frontmatter property.").addText(t=>{t.setPlaceholder("daily-note"),t.setValue(a.typeProperty),t.onChange(i=>{a.typeProperty=i,this.saveAndRefresh()})})}renderSystemsTab(e){let n=new DocumentFragment;n.createDiv({text:"A date system is a folder of notes whose filenames start with a date. Each one appears in the calendar's right-click menu for that day."}),n.createDiv({text:"The daily note is configured under Periodic Notes and always comes first in that menu."}),n.createDiv({text:"Name format is a moment.js format. Literal words need bracket escaping, e.g. YYYY-MM-DD - [Journal]."}),n.createDiv({text:"Include {title} for systems that hold many notes per date, such as meetings: the text before the token finds the existing notes, and the token marks where a typed title goes. Without it, a date has exactly one note."}),new v.Setting(e).setHeading().setName("Date systems").setDesc(n),this.settings.dateSystems.forEach((a,t,i)=>{new v.Setting(e).setHeading().setName(a.name||"Untitled system").addExtraButton(s=>{s.setIcon("arrow-up").setTooltip("Move up").setDisabled(t===0).onClick(async()=>{if(t===0)return;let r=i[t-1];i[t-1]=i[t],i[t]=r,await this.saveAndRefresh(),this.display()})}).addExtraButton(s=>{s.setIcon("arrow-down").setTooltip("Move down").setDisabled(t===i.length-1).onClick(async()=>{if(t===i.length-1)return;let r=i[t+1];i[t+1]=i[t],i[t]=r,await this.saveAndRefresh(),this.display()})}).addExtraButton(s=>{s.setIcon("trash").setTooltip("Delete this date system").onClick(async()=>{i.splice(t,1),await this.saveAndRefresh(),this.display()})}),this.addSystemTextSetting(e,"Name","Label shown in the calendar right-click menu.",a,"name","Journal"),this.addSystemTextSetting(e,"Folder","Folder these notes live in.",a,"folder","periodic/journal");let o=this.addSystemTextSetting(e,"Name format","Filename format (moment.js format). Include {title} for many notes per date.",a,"nameFormat","YYYY-MM-DD - {title}");a.nameFormat&&!A(a.nameFormat)&&o.descEl.createDiv({cls:"waypoint-settings-warning",text:"This name format has no date placeholder, so it will never match or create dated notes."}),this.addSystemTextSetting(e,"Template file","Path to the template file. The .md extension is optional.",a,"templateFile","resources/template/journal",!0),this.addSystemTextSetting(e,"Type property","Fallback value for the 'type' frontmatter property, used when no template is found.",a,"typeProperty","journal-note"),this.addSystemTextSetting(e,"Icon","Lucide icon name for the menu item. Browse names at lucide.dev.",a,"icon","book-open"),new v.Setting(e).setName("Indicator colour").setDesc("Colour for this system\u2019s dot when using \u201CColour by note system\u201D.").addColorPicker(s=>{s.setValue(a.indicatorColor).onChange(r=>{a.indicatorColor=r,this.saveAndRefresh()})})}),new v.Setting(e).addButton(a=>a.setButtonText("Add date system").setCta().onClick(async()=>{this.settings.dateSystems.push(Object.assign({id:`ds-${Date.now()}-${Math.random().toString(36).slice(2,6)}`},$)),await this.saveAndRefresh(),this.display()}))}addSystemTextSetting(e,n,a,t,i,o,s){return new v.Setting(e).setName(n).setDesc(a).addText(r=>{r.setPlaceholder(o),r.setValue(t[i]),s&&new z(this.app,r.inputEl),r.onChange(c=>{t[i]=c,this.saveAndRefresh()})})}renderRecentTab(e){new v.Setting(e).setName("Max items").setDesc("Maximum number of recent files to track.").addText(i=>{i.inputEl.setAttr("type","number"),i.inputEl.setAttr("placeholder","50"),i.setValue(String(this.settings.recentFiles.maxItems)),i.inputEl.onblur=()=>{let o=parseInt(i.getValue(),10);!isNaN(o)&&o>0&&(this.settings.recentFiles.maxItems=o,this.saveAndRefresh())}}),new v.Setting(e).setName("Update on").setDesc("When to add a file to the recent list.").addDropdown(i=>{i.addOption("file-open","File opened").addOption("file-edit","File changed").setValue(this.settings.recentFiles.updateOn).onChange(o=>{this.settings.recentFiles.updateOn=o,this.saveAndRefresh()})});let n=new DocumentFragment;n.appendText("Regex patterns for paths to exclude. One per line."),new v.Setting(e).setName("Omitted paths").setDesc(n).addTextArea(i=>{i.inputEl.setAttr("rows",4),i.setPlaceholder(`^archives/ +\\.png$`),i.setValue(this.settings.recentFiles.omittedPaths.join(` +`)),i.inputEl.onblur=()=>{this.settings.recentFiles.omittedPaths=i.getValue().split(` +`).filter(o=>o.trim()),this.saveAndRefresh()}});let a=new DocumentFragment;a.appendText("Regex patterns for frontmatter tags to exclude. One per line."),new v.Setting(e).setName("Omitted tags").setDesc(a).addTextArea(i=>{i.inputEl.setAttr("rows",4),i.setPlaceholder(`ignore +archive`),i.setValue(this.settings.recentFiles.omittedTags.join(` +`)),i.inputEl.onblur=()=>{this.settings.recentFiles.omittedTags=i.getValue().split(` +`).filter(o=>o.trim()),this.saveAndRefresh()}});let t=new DocumentFragment;t.appendText("Tags to show as filter pills above the file list. One per line. Leave empty to auto-detect from frontmatter `type` property."),new v.Setting(e).setName("Filter tags").setDesc(t).addTextArea(i=>{i.inputEl.setAttr("rows",4),i.setPlaceholder(`meeting person -project`),t.setValue(this.settings.recentFiles.filterTags.join(` -`)),t.inputEl.onblur=()=>{this.settings.recentFiles.filterTags=t.getValue().split(` -`).filter(s=>s.trim()),this.saveAndRefresh()}})}renderDisplayTab(e){new v.Setting(e).setHeading().setName("Bookmarks"),this.addSliderSetting(e,"Row size","Height of bookmark items.",this.settings.display,"rowSize",18,40,1,"px"),this.addSliderSetting(e,"Row spacing","Gap between bookmark items.",this.settings.display,"rowSpacing",0,12,1,"px"),this.addSliderSetting(e,"Indent size","Indent per nesting depth.",this.settings.display,"indentSize",8,32,2,"px"),this.addSliderSetting(e,"Font size","Label font size.",this.settings.display,"fontSize",10,18,1,"px"),this.addSliderSetting(e,"Icon size","Bookmark icon size.",this.settings.display,"iconSize",12,24,1,"px"),new v.Setting(e).setHeading().setName("Calendar"),this.addSliderSetting(e,"Cell size","Height of calendar day cells.",this.settings.display,"calendarCellSize",20,48,2,"px"),new v.Setting(e).addButton(n=>n.setButtonText("Reset to defaults").onClick(()=>{this.settings.display={...T.display},this.saveAndRefresh(),this.display()}))}addSliderSetting(e,n,i,a,t,s,o,r,c){let l=new v.Setting(e).setName(n).setDesc(`${i} (${a[t]}${c})`);l.addSlider(h=>{h.setLimits(s,o,r).setValue(a[t]).setDynamicTooltip().onChange(u=>{a[t]=u,l.setDesc(`${i} (${u}${c})`),this.saveAndRefresh()})})}async saveAndRefresh(){await this.plugin.saveSettings(),this.onSettingsChange()}renderAboutTab(e){let n=this.plugin.manifest.version,i=e.createDiv();i.style.display="flex",i.style.alignItems="center",i.style.gap="12px",i.style.marginBottom="16px";let a=i.createDiv();a.style.display="flex",a.style.alignItems="center",a.style.justifyContent="center",a.style.width="48px",a.style.height="48px",a.style.borderRadius="12px",a.style.background="var(--interactive-accent)",a.style.color="var(--text-on-accent)",a.style.fontSize="24px",(0,v.setIcon)(a,"compass");let t=i.createDiv(),s=t.createEl("h2",{text:"Waypoint Sidebar"});s.style.margin="0",s.style.lineHeight="1.2";let o=t.createDiv({text:`v${n}`});o.style.color="var(--text-muted)",o.style.fontSize="var(--font-ui-small)";let r=e.createDiv();r.style.marginBottom="20px",r.style.lineHeight="1.6",r.style.color="var(--text-normal)",r.innerHTML=["

Waypoint is a sidebar plugin that brings three essential panels into one view:

",'
    ',"
  • Calendar \u2014 a monthly grid for your periodic notes (daily, weekly, monthly, quarterly, yearly). Click any day, week, or month to open or create the corresponding note.
  • ","
  • Recent Files \u2014 a list of recently opened files with type filtering, drag-and-drop, and right-click actions.
  • ","
  • Bookmarks \u2014 custom bookmarks with icons, groups, nesting, and drag-and-drop reordering. Separate from Obsidian's native bookmarks.
  • ","
",'

Made by Olivier. Licensed under MIT.

'].join(` -`)}};var m=require("obsidian");var C=require("obsidian");function le(p,d,e){let n=(0,C.moment)({year:p,month:d,day:1}),i=(0,C.moment)(n).endOf("month"),a=(0,C.moment)(n).subtract((n.day()-e+7)%7,"days"),t=(0,C.moment)().startOf("day"),s=[],o=(0,C.moment)(a);for(;o.isBefore(i)||o.month()===d;){let r=[];for(let c=0;c<7;c++)r.push({date:(0,C.moment)(o),dayOfMonth:o.date(),isToday:o.isSame(t,"day"),isCurrentMonth:o.month()===d,isoWeekNumber:o.isoWeek()}),o.add(1,"day");if(s.push({weekNumber:r[0].isoWeekNumber,days:r}),s.length>=6)break}return s}var E="waypoint-view";function ke(p){return p.dragManager}var W=class extends m.ItemView{constructor(e,n){super(e);this.redraw=()=>{this.contentEl.empty(),this.contentEl.addClass("waypoint-view");let e=this.plugin.settings.display;this.contentEl.style.setProperty("--wp-row-size",e.rowSize+"px"),this.contentEl.style.setProperty("--wp-row-spacing",e.rowSpacing+"px"),this.contentEl.style.setProperty("--wp-indent-size",e.indentSize+"px"),this.contentEl.style.setProperty("--wp-font-size",e.fontSize+"px"),this.contentEl.style.setProperty("--wp-icon-size",e.iconSize+"px"),this.contentEl.style.setProperty("--wp-cal-cell-size",e.calendarCellSize+"px"),this.renderFavorites(),this.renderRecentFiles(),this.renderCalendar()};this.currentDisplayMonth=(0,m.moment)().month();this.currentDisplayYear=(0,m.moment)().year();this.dragId=null;this.dropZones=new WeakMap;this.recentFilesFilter=null;this.plugin=n}getViewType(){return E}getDisplayText(){return"Waypoint"}getIcon(){return"compass"}async onOpen(){this.redraw()}async onClose(){}renderCalendar(){let n=this.contentEl.createDiv({cls:"waypoint-section"}).createDiv({cls:"waypoint-calendar"}),i=(0,m.moment)(),a=(0,m.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth,day:1}),t=n.createDiv({cls:"waypoint-calendar-top"}),s=t.createDiv({cls:"waypoint-calendar-breadcrumb"}),o=a.format("[Q]Q"),r=s.createSpan({cls:"waypoint-clickable",text:o});r.addEventListener("click",()=>{this.plugin.openPeriodNote("quarter",a)}),r.addEventListener("mousedown",D=>{D.button===1&&(D.preventDefault(),this.plugin.openPeriodNote("quarter",a,this.app.workspace.getLeaf("tab")))});let c=a.format("MMMM"),l=s.createSpan({cls:"waypoint-clickable",text:c});l.addEventListener("click",()=>{this.plugin.openPeriodNote("month",a)}),l.addEventListener("mousedown",D=>{D.button===1&&(D.preventDefault(),this.plugin.openPeriodNote("month",a,this.app.workspace.getLeaf("tab")))});let h=a.format("YYYY"),u=s.createSpan({cls:"waypoint-clickable",text:h});u.addEventListener("click",()=>{this.plugin.openPeriodNote("year",a)}),u.addEventListener("mousedown",D=>{D.button===1&&(D.preventDefault(),this.plugin.openPeriodNote("year",a,this.app.workspace.getLeaf("tab")))});let g=t.createDiv({cls:"waypoint-calendar-today-group"}),S=g.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,m.setIcon)(S,"chevron-left"),S.addEventListener("click",()=>this.navigateMonth(-1)),g.createEl("button",{cls:"waypoint-calendar-today-btn",text:"Today"}).addEventListener("click",()=>{this.currentDisplayMonth=(0,m.moment)().month(),this.currentDisplayYear=(0,m.moment)().year(),this.redraw()});let w=g.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,m.setIcon)(w,"chevron-right"),w.addEventListener("click",()=>this.navigateMonth(1));let b=n.createEl("table"),y=b.createEl("thead").createEl("tr");y.createEl("th",{text:""});let L=["sun","mon","tue","wed","thu","fri","sat"],G=this.plugin.settings.calendar.firstDayOfWeek;for(let D=0;D<7;D++){let N=(G+D)%7;y.createEl("th",{text:L[N]})}let P=b.createEl("tbody"),ee=le(this.currentDisplayYear,this.currentDisplayMonth,this.plugin.settings.calendar.firstDayOfWeek),K=this.plugin.settings.calendar.showNoteIndicators&&this.plugin.settings.calendar.indicatorMode==="systems"?this.plugin.getDateSystemIndicators(ee.reduce((D,N)=>D.concat(N.days.map(Y=>Y.date)),[])):null;for(let D of ee){let N=P.createEl("tr"),Y=N.createEl("td",{cls:"waypoint-weeknum"});Y.setText(String(D.weekNumber));let te=D.days[0].date;Y.addEventListener("click",()=>{this.plugin.openPeriodNote("week",te)}),Y.addEventListener("mousedown",x=>{x.button===1&&(x.preventDefault(),this.plugin.openPeriodNote("week",te,this.app.workspace.getLeaf("tab")))});for(let x of D.days){let M=N.createEl("td",{cls:"waypoint-day"});if(M.setText(String(x.dayOfMonth)),x.isCurrentMonth||M.addClass("other-month"),x.isToday&&M.addClass("today"),this.plugin.settings.calendar.showNoteIndicators){let I=x.date.format("YYYY-MM-DD");if(this.plugin.settings.calendar.indicatorMode==="any")this.plugin.hasNoteForDate(I)&&M.addClass("has-note");else{let ne=(K==null?void 0:K.get(I))||[];if(ne.length>0){let pe=M.createDiv({cls:"waypoint-day-indicators"});for(let ie of ne){let ae=pe.createSpan({cls:"waypoint-day-indicator"});ae.style.setProperty("--waypoint-indicator-color",ie.color),(0,m.setTooltip)(ae,ie.name)}}}}M.addEventListener("click",()=>{this.plugin.openPeriodNote("day",x.date)}),M.addEventListener("mousedown",I=>{I.button===1&&(I.preventDefault(),this.plugin.openPeriodNote("day",x.date,this.app.workspace.getLeaf("tab")))}),M.addEventListener("contextmenu",I=>{I.preventDefault(),I.stopPropagation(),this.showDayContextMenu(I,x.date)})}}}navigateMonth(e){let n=(0,m.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth}).add(e,"month");this.currentDisplayMonth=n.month(),this.currentDisplayYear=n.year(),this.redraw()}showDayContextMenu(e,n){let i=new m.Menu;i.addItem(a=>a.setTitle(n.format("dddd, MMMM D, YYYY")).setIsLabel(!0));for(let a of this.plugin.findDateSystemNotes(n)){let t=a.multiple||a.notes.length===0;if(a.notes.length+(t?1:0)===0)continue;i.addSeparator();for(let o of a.notes)i.addItem(r=>r.setTitle(o.label).setIcon(a.system.icon).onClick(c=>this.focusFile(o.file,m.Keymap.isModEvent(c))));if(!t)continue;let s=a.system.name.toLowerCase();i.addItem(o=>o.setTitle(a.multiple?`New ${s} note\u2026`:`New ${s} note`).setIcon("plus").onClick(r=>this.createDateSystemNote(a,n,m.Keymap.isModEvent(r))))}i.showAtPosition({x:e.clientX,y:e.clientY})}createDateSystemNote(e,n,i){if(!e.multiple){this.plugin.openDateSystemNote(e.system,n,{leaf:i?this.app.workspace.getLeaf(i):void 0});return}let a=e.system.name;new V(this.app,{title:`New ${a.toLowerCase()} note`,placeholder:`${a} with\u2026`,cta:"Create"},t=>{this.plugin.openDateSystemNote(e.system,n,{title:t,leaf:i?this.app.workspace.getLeaf(i):void 0})}).open()}renderRecentFiles(){var r,c;let e=this.contentEl.createDiv({cls:"waypoint-section waypoint-recent-files"});if(e.createDiv({cls:"waypoint-section-header",text:"Recent Files"}),this.plugin.recentFiles.length===0){e.createDiv({cls:"nav-file",text:"No recent files"});return}let n=this.plugin.settings.recentFiles.filterTags||[],i={};if(n.length>0){for(let l of n)i[l]=0;for(let l of this.plugin.recentFiles){let h=this.app.vault.getAbstractFileByPath(l.path);if(h instanceof m.TFile){let u=this.app.metadataCache.getFileCache(h),g=(r=u==null?void 0:u.frontmatter)==null?void 0:r.type;g&&typeof g=="string"&&i.hasOwnProperty(g)&&i[g]++}}}else for(let l of this.plugin.recentFiles){let h=this.app.vault.getAbstractFileByPath(l.path);if(h instanceof m.TFile){let u=this.app.metadataCache.getFileCache(h),g=(c=u==null?void 0:u.frontmatter)==null?void 0:c.type;g&&typeof g=="string"&&(i[g]=(i[g]||0)+1)}}if(Object.keys(i).length>0){let l=e.createDiv({cls:"waypoint-recent-filter"});l.createSpan({cls:`waypoint-recent-pill${this.recentFilesFilter?"":" is-active"}`,text:"all"}).addEventListener("click",()=>{this.recentFilesFilter=null,this.redraw()});let u=n.length>0?Object.entries(i):Object.entries(i).sort((g,S)=>S[1]-g[1]);for(let[g,S]of u){let F=l.createSpan({cls:`waypoint-recent-pill${this.recentFilesFilter===g?" is-active":""}`});F.setText(`${g} ${S}`),F.addEventListener("click",()=>{this.recentFilesFilter=this.recentFilesFilter===g?null:g,this.redraw()})}}let a=this.plugin.recentFiles;this.recentFilesFilter&&(a=this.plugin.recentFiles.filter(l=>{var u;let h=this.app.vault.getAbstractFileByPath(l.path);if(h instanceof m.TFile){let g=this.app.metadataCache.getFileCache(h);return((u=g==null?void 0:g.frontmatter)==null?void 0:u.type)===this.recentFilesFilter}return!1}));let t=this.app.workspace.getActiveFile(),s=e.createDiv({cls:"nav-folder mod-root"}),o=s.createDiv({cls:"nav-folder-children"});for(let l of a){let h=o.createDiv({cls:"tree-item nav-file"}),u=h.createDiv({cls:"tree-item-self is-clickable nav-file-title"});u.createDiv({cls:"tree-item-inner nav-file-title-content"}).setText(l.basename);let S=u.createDiv({cls:"tree-item-spacer"}),F=u.createDiv({cls:"waypoint-recent-remove"});(0,m.setIcon)(F,"x"),F.addEventListener("click",w=>{w.stopPropagation(),this.plugin.recentFiles=this.plugin.recentFiles.filter(b=>b.path!==l.path),this.plugin.persistRecentFiles(),this.redraw()}),(0,m.setTooltip)(h,l.path),t&&l.path===t.path&&u.addClass("is-active"),u.setAttr("draggable","true"),u.addEventListener("dragstart",w=>{let b=this.app.metadataCache.getFirstLinkpathDest(l.path,"");if(b){let k=ke(this.app),y=k.dragFile(w,b);k.onDragStart(w,y)}}),u.addEventListener("mouseover",w=>{this.app.workspace.trigger("hover-link",{event:w,source:E,hoverParent:s,targetEl:h,linktext:l.path})}),u.addEventListener("contextmenu",w=>{let b=new m.Menu;b.addItem(y=>y.setSection("action").setTitle("Open in new tab").setIcon("file-plus").onClick(()=>this.focusFile(l,"tab"))),b.addItem(y=>y.setSection("action").setTitle("Add to bookmarks").setIcon("bookmark").onClick(()=>{this.plugin.addBookmark(l.path,l.basename,"file"),new m.Notice(`Bookmarked: ${l.basename}`)}));let k=this.app.vault.getAbstractFileByPath(l.path);k&&this.app.workspace.trigger("file-menu",b,k,"link-context-menu"),b.showAtPosition({x:w.clientX,y:w.clientY})}),u.addEventListener("click",w=>{let b=m.Keymap.isModEvent(w);this.focusFile(l,b)}),u.addEventListener("mousedown",w=>{w.button===1&&(w.preventDefault(),this.focusFile(l,"tab"))})}}focusFile(e,n){let i=this.app.vault.getFiles().find(a=>a.path===e.path);i?this.app.workspace.getLeaf(n).openFile(i):(new m.Notice("Cannot find file"),this.plugin.recentFiles=this.plugin.recentFiles.filter(a=>a.path!==e.path),this.plugin.persistRecentFiles(),this.redraw())}renderFavorites(){let e=this.contentEl.createDiv({cls:"waypoint-section waypoint-favorites"}),n=e.createDiv({cls:"waypoint-section-header"});n.setText("Waypoint Bookmarks");let i=n.createEl("button",{cls:"waypoint-header-more"});if((0,m.setIcon)(i,"more-horizontal"),(0,m.setTooltip)(i,"Add bookmark"),i.addEventListener("click",a=>{let t=new m.Menu;t.addItem(s=>{s.setTitle("Add current file").setIcon("file-plus").onClick(()=>{let o=this.app.workspace.getActiveFile();o&&this.plugin.addBookmark(o.path,o.basename,"file")})}),t.addItem(s=>{s.setTitle("Add as parent note").setIcon("folder-plus").onClick(()=>{let o=this.app.workspace.getActiveFile();if(!o)return;let r=this.plugin.addBookmark(o.path,o.basename,"group","");r.filePath=o.path,this.plugin.saveWaypointData(),this.redraw()})}),t.addItem(s=>{s.setTitle("New group").setIcon("folder-plus").onClick(()=>{this.plugin.addBookmark("","New Group","group","")})}),t.addSeparator(),t.addItem(s=>{s.setTitle("Add separator").setIcon("minus").onClick(()=>{this.plugin.addBookmark("","","separator")})}),t.addItem(s=>{s.setTitle("Add spacer").setIcon("space").onClick(()=>{this.plugin.addBookmark("","","spacer")})}),t.showAtPosition({x:a.clientX,y:a.clientY})}),this.plugin.waypointData.bookmarks.length===0){e.createDiv({cls:"waypoint-bookmark-item",text:"No bookmarks"});return}this.renderBookmarkList(e,this.plugin.waypointData.bookmarks,0)}renderBookmarkList(e,n,i){for(let a=0;a{c.stopPropagation(),c.preventDefault(),this.showBookmarkContextMenu(c,t)});continue}if(t.type==="spacer"){let r=e.createDiv({cls:"waypoint-bookmark-item waypoint-bookmark-spacer"});r.setAttr("draggable","true"),r.setAttr("data-bm-id",t.id),r.style.paddingLeft=`${8+i*16}px`,r.style.cursor="grab",this.attachBookmarkDragHandlers(r,e,t,!1),r.addEventListener("contextmenu",c=>{c.stopPropagation(),c.preventDefault(),this.showBookmarkContextMenu(c,t)});continue}let s=t.type==="group",o=e.createDiv({cls:`waypoint-bookmark-item${s?" waypoint-bookmark-group":""}${t.collapsed?" collapsed":""}`});if(o.setAttr("draggable","true"),o.setAttr("data-bm-id",t.id),s||(o.style.paddingLeft=`${8+i*16}px`),this.attachBookmarkDragHandlers(o,e,t,!0),s){let r=o.createDiv({cls:"waypoint-bm-icon"});t.icon&&(0,m.setIcon)(r,t.icon);let c=o.createDiv({cls:"waypoint-bm-label",text:t.label}),l=o.createDiv({cls:"waypoint-bm-chevron"});(0,m.setIcon)(l,"chevron-down"),l.addEventListener("click",u=>{u.stopPropagation(),this.plugin.updateBookmark(t.id,{collapsed:!t.collapsed})}),o.addEventListener("click",u=>{if(t.filePath){let g=this.app.vault.getFileByPath(t.filePath);if(g){let S=m.Keymap.isModEvent(u);this.app.workspace.getLeaf(S).openFile(g);return}}this.plugin.updateBookmark(t.id,{collapsed:!t.collapsed})}),o.addEventListener("mousedown",u=>{if(u.button===1&&t.filePath){u.preventDefault();let g=this.app.vault.getFileByPath(t.filePath);g&&this.app.workspace.getLeaf("tab").openFile(g)}});let h=e.createDiv({cls:`waypoint-bookmark-children${t.collapsed?" collapsed":""}`});t.children&&t.children.length>0&&this.renderBookmarkList(h,t.children,i+1)}else{let r=o.createDiv({cls:"waypoint-bm-icon"});t.icon&&(0,m.setIcon)(r,t.icon);let c=o.createDiv({cls:"waypoint-bm-label",text:t.label});if(t.children&&t.children.length>0){let l=o.createDiv({cls:"waypoint-bm-chevron"});(0,m.setIcon)(l,"chevron-down"),l.addEventListener("click",h=>{h.stopPropagation(),this.plugin.updateBookmark(t.id,{collapsed:!t.collapsed})}),t.collapsed&&(o.addClass("collapsed"),l.style.transform="rotate(-90deg)")}if((0,m.setTooltip)(o,t.filePath),o.addEventListener("click",l=>{if(t.filePath){let h=this.app.vault.getFileByPath(t.filePath);if(h){let u=m.Keymap.isModEvent(l);this.app.workspace.getLeaf(u).openFile(h)}else new m.Notice("File not found"),this.plugin.removeBookmark(t.id)}}),o.addEventListener("mousedown",l=>{if(l.button===1&&t.filePath){l.preventDefault();let h=this.app.vault.getFileByPath(t.filePath);h&&this.app.workspace.getLeaf("tab").openFile(h)}}),t.children&&t.children.length>0){let l=e.createDiv({cls:`waypoint-bookmark-children${t.collapsed?" collapsed":""}`});this.renderBookmarkList(l,t.children,i+1)}}o.addEventListener("contextmenu",r=>{r.stopPropagation(),r.preventDefault(),this.showBookmarkContextMenu(r,t)})}}showBookmarkContextMenu(e,n){let i=new m.Menu;if(n.type==="separator"||n.type==="spacer"){i.addItem(a=>a.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(n.id))),i.showAtPosition({x:e.clientX,y:e.clientY});return}n.type==="file"?(i.addItem(a=>a.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let t=this.app.vault.getFileByPath(n.filePath);t&&this.app.workspace.getLeaf("tab").openFile(t)})),i.addSeparator(),i.addItem(a=>a.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(n))),i.addItem(a=>a.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(n))),i.addSeparator(),i.addItem(a=>a.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(n.id)))):n.type==="group"&&(n.filePath&&(i.addItem(a=>a.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let t=this.app.vault.getFileByPath(n.filePath);t&&this.app.workspace.getLeaf("tab").openFile(t)})),i.addSeparator()),i.addItem(a=>a.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(n))),i.addItem(a=>a.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(n))),i.addSeparator(),i.addItem(a=>a.setTitle("Add child bookmark").setIcon("file-plus").onClick(()=>{let t=this.app.workspace.getActiveFile();if(!t){new m.Notice("No active file");return}let s={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"file",label:t.basename,filePath:t.path,icon:"",children:[],collapsed:!1,indent:n.indent+1};n.children.push(s),this.plugin.saveWaypointData(),this.redraw()})),i.addItem(a=>a.setTitle("Add child note").setIcon("folder-plus").onClick(()=>{let t=this.app.workspace.getActiveFile();if(!t){new m.Notice("No active file");return}let s={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:t.basename,filePath:t.path,icon:"",children:[],collapsed:!1,indent:n.indent+1};n.children.push(s),this.plugin.saveWaypointData(),this.redraw()})),i.addItem(a=>a.setTitle("New sub-group").setIcon("folder-plus").onClick(()=>{let t={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:"New Group",filePath:"",icon:"",children:[],collapsed:!1,indent:n.indent+1};n.children.push(t),this.plugin.saveWaypointData(),this.redraw()})),i.addSeparator(),i.addItem(a=>a.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(n.id)))),i.showAtPosition({x:e.clientX,y:e.clientY})}attachBookmarkDragHandlers(e,n,i,a){let t=()=>{e.removeClass("waypoint-bm-drop-line"),e.removeClass("waypoint-bm-drop-below"),e.removeClass("waypoint-bm-drop-into")};e.addEventListener("dragstart",s=>{this.dragId=i.id,s.dataTransfer.effectAllowed="move",s.dataTransfer.setData("text/plain",i.id),e.addClass("waypoint-bm-dragging")}),e.addEventListener("dragend",()=>{this.dragId=null,n.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below, .waypoint-bm-drop-into").forEach(s=>{s.removeClass("waypoint-bm-dragging"),s.removeClass("waypoint-bm-drop-line"),s.removeClass("waypoint-bm-drop-below"),s.removeClass("waypoint-bm-drop-into")})}),e.addEventListener("dragenter",s=>{s.preventDefault(),!(!this.dragId||this.dragId===i.id)&&this.showDropIndicator(e,s,a)}),e.addEventListener("dragover",s=>{s.preventDefault(),!(!this.dragId||this.dragId===i.id)&&this.showDropIndicator(e,s,a)}),e.addEventListener("dragleave",t),e.addEventListener("drop",s=>{var c,l;s.preventDefault(),this.dragId=null,t();let o=(c=s.dataTransfer)==null?void 0:c.getData("text/plain");if(!o||o===i.id)return;let r=this.dropZones.get(e);a&&(r!=null&&r.into)?i.type==="group"?this.moveBookmarkToGroup(o,i.id):this.createParentNoteAndMove(o,i.id):this.moveBookmarkToPosition(o,i.id,(l=r==null?void 0:r.above)!=null?l:!1)})}showDropIndicator(e,n,i){let a=e.parentElement;a&&a.querySelectorAll(".waypoint-bm-drop-line, .waypoint-bm-drop-below, .waypoint-bm-drop-into").forEach(o=>{o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below"),o.removeClass("waypoint-bm-drop-into")});let t=e.getBoundingClientRect(),s=n.clientY;if(i){let o=t.top+t.height*.25,r=t.top+t.height*.75;sr?(e.addClass("waypoint-bm-drop-line"),e.addClass("waypoint-bm-drop-below"),this.dropZones.set(e,{above:!1,into:!1})):(e.addClass("waypoint-bm-drop-into"),this.dropZones.set(e,{above:!1,into:!0}))}else{let o=s{let s=t.findIndex(o=>o.id===e);if(s>=0){let[o]=t.splice(s,1);return o}for(let o of t){let r=i(o.children);if(r)return r}return null},a=i(this.plugin.waypointData.bookmarks);if(a){if(n){let t=(s,o)=>s.id===o?!0:s.children.some(r=>t(r,o));if(a.id===n||t(a,n))return}if(n){let t=o=>{for(let r of o){if(r.id===n)return r;let c=t(r.children);if(c)return c}return null},s=t(this.plugin.waypointData.bookmarks);s&&(a.indent=s.indent+1,s.children.push(a))}else a.indent=0,this.plugin.waypointData.bookmarks.push(a);this.plugin.saveWaypointData(),this.redraw()}}createParentNoteAndMove(e,n){let i=o=>{let r=o.findIndex(c=>c.id===e);if(r>=0){let[c]=o.splice(r,1);return c}for(let c of o)if(c.children){let l=i(c.children);if(l)return l}return null},a=i(this.plugin.waypointData.bookmarks);if(!a)return;let t=o=>{for(let r of o){if(r.id===n)return r;if(r.children){let c=t(r.children);if(c)return c}}return null},s=t(this.plugin.waypointData.bookmarks);s&&(a.indent=s.indent+1,s.children.push(a),this.plugin.saveWaypointData(),this.redraw())}moveBookmarkToPosition(e,n,i){let a=r=>{let c=r.findIndex(l=>l.id===e);if(c>=0){let[l]=r.splice(c,1);return{item:l,parent:r}}for(let l of r)if(l.children){let h=a(l.children);if(h.item)return h}return{item:null,parent:[]}},{item:t}=a(this.plugin.waypointData.bookmarks);if(!t)return;let s=r=>{let c=r.findIndex(l=>l.id===n);if(c>=0)return{parent:r,idx:c};for(let l of r)if(l.children){let h=s(l.children);if(h)return h}return null},o=s(this.plugin.waypointData.bookmarks);if(!o)t.indent=0,this.plugin.waypointData.bookmarks.push(t);else{let r=i?o.idx:o.idx+1;o.parent.splice(r,0,t)}this.plugin.saveWaypointData(),this.redraw()}promptRename(e){new V(this.app,{title:"Rename bookmark",initialValue:e.label},n=>{n&&n.trim()&&this.plugin.updateBookmark(e.id,{label:n.trim()})}).open()}promptIcon(e){new Z(this.app,e.icon,n=>{this.plugin.updateBookmark(e.id,{icon:n})}).open()}},V=class extends m.Modal{constructor(d,e,n){super(d),this.options=e,this.onSubmit=n}onOpen(){var a,t,s;this.titleEl.setText(this.options.title);let d=this.contentEl.createEl("input",{type:"text",value:(a=this.options.initialValue)!=null?a:"",placeholder:(t=this.options.placeholder)!=null?t:""});d.style.width="100%",d.style.marginBottom="12px",d.focus(),d.select();let e=this.contentEl.createDiv({cls:"modal-button-container"}),n=e.createEl("button",{text:"Cancel",cls:"mod-cta"});n.style.marginRight="8px",n.addEventListener("click",()=>this.close()),e.createEl("button",{text:(s=this.options.cta)!=null?s:"Save",cls:"mod-cta"}).addEventListener("click",()=>{this.onSubmit(d.value),this.close()}),d.addEventListener("keydown",o=>{o.key==="Enter"&&(this.onSubmit(d.value),this.close())})}onClose(){this.contentEl.empty()}},H=null;function we(){return H||(H=(async()=>{try{return await(await fetch("https://cdn.jsdelivr.net/npm/lucide-static@0.517.0/tags.json")).json()}catch(p){try{return await(await fetch("https://lucide.dev/api/tags")).json()}catch(d){return H=null,be}}})()),H}var Z=class extends m.Modal{constructor(e,n,i){super(e);this.allIcons=[];this.tagsMap={};this.loaded=!1;this.selected=n,this.onSubmit=i}async onOpen(){let e=this.contentEl;e.style.display="flex",e.style.flexDirection="column",e.style.gap="10px",this.titleEl.setText("Change icon");let n=e.createDiv({cls:"waypoint-icon-preview"});n.style.display="flex",n.style.alignItems="center",n.style.gap="10px",n.style.padding="12px 16px",n.style.borderRadius="8px",n.style.background="var(--background-secondary)",n.style.minHeight="48px";let i=n.createSpan();i.style.display="flex",this.selected&&(0,m.setIcon)(i,this.selected);let a=n.createSpan();a.style.fontWeight="var(--font-medium)",a.style.fontSize="var(--font-ui-medium)",a.setText(this.selected||"No icon");let t=e.createEl("input",{type:"text",placeholder:"Type to search (e.g. arrow, chart, home)..."});Object.assign(t.style,{width:"100%",boxSizing:"border-box",padding:"8px 10px",borderRadius:"6px",border:"1px solid var(--background-modifier-border)",background:"var(--background-primary)",color:"var(--text-normal)",fontSize:"var(--font-ui-medium)"}),t.focus();let s=e.createDiv({cls:"waypoint-icon-grid"});s.style.display="grid",s.style.gridTemplateColumns="repeat(auto-fill, minmax(52px, 1fr))",s.style.gap="4px",s.style.maxHeight="320px",s.style.overflowY="auto",s.style.padding="2px 0";let o=e.createDiv();o.style.display="flex",o.style.justifyContent="space-between",o.style.alignItems="center",o.style.fontSize="var(--font-ui-smaller)",o.style.color="var(--text-muted)",o.style.padding="0 4px";let r=o.createSpan();r.setText("Loading\u2026"),this.loadIcons().then(()=>{this.loaded=!0,r.setText(this.allIcons.length+" icons"),l(t.value)});let c,l=F=>{if(s.empty(),!this.loaded){s.createDiv({text:"Loading\u2026"});return}let w=F.toLowerCase().trim(),b=w?this.allIcons.filter(k=>{if(k.includes(w))return!0;let y=this.tagsMap[k];return y?y.some(L=>L.includes(w)):!1}).slice(0,80):this.allIcons.slice(0,80);if(b.length===0){let k=s.createDiv();k.style.gridColumn="1 / -1",k.style.textAlign="center",k.style.color="var(--text-muted)",k.style.padding="20px",k.setText('No icons match "'+F+'"');return}for(let k of b){let y=s.createDiv();y.setAttr("data-icon",k),y.style.display="flex",y.style.alignItems="center",y.style.justifyContent="center",y.style.aspectRatio="1",y.style.borderRadius="6px",y.style.cursor="var(--cursor-link, pointer)",y.style.transition="background 80ms",y.setAttr("title",k),k===this.selected?(y.style.background="var(--interactive-accent)",y.style.color="var(--text-on-accent)"):y.style.color="var(--text-muted)";let L=y.createSpan();L.style.display="flex",(0,m.setIcon)(L,k),y.addEventListener("mouseenter",()=>{k!==this.selected&&(y.style.background="var(--background-modifier-hover)")}),y.addEventListener("mouseleave",()=>{k!==this.selected&&(y.style.background="")}),y.addEventListener("click",()=>{this.selected=k,l(F),i.empty(),(0,m.setIcon)(i,k),a.setText(k),s.querySelectorAll("div[data-icon]").forEach(G=>{let P=G;P.getAttr("data-icon")===k?(P.style.background="var(--interactive-accent)",P.style.color="var(--text-on-accent)"):(P.style.background="",P.style.color="var(--text-muted)")})})}r.setText(b.length+" of "+this.allIcons.length+" icons")};t.addEventListener("input",()=>{window.clearTimeout(c),c=window.setTimeout(()=>l(t.value),60)}),t.addEventListener("keydown",F=>{F.key==="Escape"&&this.close()});let h=e.createDiv({cls:"modal-button-container"});h.createEl("button",{text:"No icon",cls:"waypoint-icon-clear"}).addEventListener("click",()=>{this.onSubmit(""),this.close()}),h.createEl("button",{text:"Cancel"}).addEventListener("click",()=>this.close());let S=h.createEl("button",{text:"Save",cls:"mod-cta"});S.style.marginLeft="8px",S.addEventListener("click",()=>{this.onSubmit(this.selected),this.close()})}onClose(){this.contentEl.empty()}async loadIcons(){let e=await we();this.tagsMap=e,this.allIcons=Object.keys(e).sort()}},be={file:[],folder:[],star:[],heart:[],bookmark:[],flag:[],pin:[],tag:[],book:[],"book-open":[],library:[],calendar:[],"calendar-days":[],clock:[],home:[],inbox:[],mail:[],search:[],settings:[],cog:[],user:[],users:[],zap:[],sparkles:[],target:[],link:[],globe:[],edit:[],pencil:[],anchor:[],award:[],bell:[],"bell-ring":[],brain:[],briefcase:[],camera:[],"chart-bar":[],"chart-line":[],"chart-pie":[],check:[],"check-circle":[],"chevron-down":[],"chevron-left":[],"chevron-right":[],"chevron-up":[],circle:[],clipboard:[],code:[],command:[],compass:[],copy:[],"credit-card":[],crown:[],database:[],download:[],"external-link":[],eye:[],"eye-off":[],"file-text":[],filter:[],fingerprint:[],flashlight:[],"folder-open":[],"folder-plus":[],gift:[],"git-branch":[],"git-commit":[],"git-merge":[],"git-pull-request":[],github:[],grid:[],hash:[],headphones:[],image:[],info:[],key:[],layers:[],layout:[],"life-buoy":[],"link-2":[],list:[],loader:[],lock:[],"log-in":[],"log-out":[],map:[],"map-pin":[],maximize:[],megaphone:[],menu:[],"message-circle":[],"message-square":[],mic:[],minimize:[],moon:[],"more-horizontal":[],"more-vertical":[],"mouse-pointer":[],move:[],music:[],navigation:[],"navigation-2":[],package:[],palette:[],paperclip:[],pause:[],phone:[],play:[],plus:[],"plus-circle":[],power:[],printer:[],radio:[],"refresh-cw":[],repeat:[],"rotate-ccw":[],"rotate-cw":[],rss:[],save:[],scissors:[],screen:[],send:[],server:[],share:[],"share-2":[],shield:[],"shield-off":[],"shopping-bag":[],"shopping-cart":[],shuffle:[],sidebar:[],slack:[],slash:[],sliders:[],smartphone:[],smile:[],speaker:[],square:[],"stop-circle":[],sun:[],sunrise:[],sunset:[],swords:[],table:[],tablet:[],terminal:[],thermometer:[],"thumbs-down":[],"thumbs-up":[],"toggle-left":[],"toggle-right":[],tool:[],trash:[],"trash-2":[],trello:[],"trending-down":[],"trending-up":[],triangle:[],truck:[],tv:[],twitter:[],type:[],umbrella:[],unlock:[],upload:[],"user-check":[],"user-minus":[],"user-plus":[],"user-x":[],video:[],"video-off":[],voicemail:[],volume:[],"volume-1":[],"volume-2":[],"volume-x":[],watch:[],wifi:[],"wifi-off":[],wind:[],x:[],"x-circle":[],"x-square":[],youtube:[],"zap-off":[],"zoom-in":[],"zoom-out":[],"arrow-down":[],"arrow-left":[],"arrow-right":[],"arrow-up":[],airplay:[],"alarm-clock":[],archive:[],armchair:[],atom:[],baby:[],backpack:[],badge:[],"badge-check":[],ban:[],banknote:[],barcode:[],bath:[],battery:[],"battery-charging":[],beer:[],bike:[],bird:[],bluetooth:[],bolt:[],bone:[],"bookmark-plus":[],bot:[],box:[],bug:[],building:[],bus:[],cake:[],calculator:[],car:[],"clipboard-check":[],cloud:[],"cloud-download":[],"cloud-lightning":[],"cloud-rain":[],"cloud-sun":[],"cloud-upload":[],clover:[],coffee:[],coins:[],contact:[],cookie:[],"corner-down-left":[],"corner-down-right":[],"corner-up-left":[],"corner-up-right":[],crosshair:[],"dice-1":[],"dice-6":[],"dollar-sign":[],"door-open":[],drama:[],droplet:[],drum:[],egg:[],equal:[],euro:[],factory:[],fan:[],feather:[],film:[],fish:[],flame:[],flask:[],flower:[],frown:[],fuel:[],gamepad:[],gauge:[],gem:[],ghost:[],glasses:[],"graduation-cap":[],hammer:[],"hard-drive":[],haze:[],"help-circle":[],"ice-cream":[],infinity:[],italic:[],"japanese-yen":[],keyboard:[],knife:[],lamp:[],landmark:[],languages:[],laptop:[],laugh:[],leaf:[],lightbulb:[],"list-plus":[],magnet:[],"mail-plus":[],meh:[],microscope:[],milestone:[],"minimize-2":[],monitor:[],mountain:[],mouse:[],network:[],newspaper:[],"package-check":[],"package-search":[],"paint-bucket":[],parking:[],"party-popper":[],"pen-tool":[],percent:[],"person-standing":[],"picture-in-picture-2":[],plane:[],plug:[],podcast:[],pointer:[],"pound-sterling":[],puzzle:[],"qr-code":[],rabbit:[],radar:[],rainbow:[],rocket:[],"roller-coaster":[],route:[],ruler:[],sailboat:[],scale:[],scan:[],school:[],ship:[],shirt:[],"shopping-basket":[],shovel:[],sigma:[],siren:[],skull:[],snowflake:[],soup:[],space:[],sparkle:[],stamp:[],store:[],subscript:[],superscript:[],syringe:[],tent:[],"tent-tree":[],"test-tube":[],theater:[],timer:[],train:[],"tree-deciduous":[],"tree-pine":[],trophy:[],typing:[],utensils:[],vibrate:[],wallet:[],wand:[],warehouse:[],waves:[],webcam:[],wheat:[],wine:[],wrench:[]};function J(p,d,e){return!p||!d?null:p===d?e:p.startsWith(d+"/")?e+p.slice(d.length):null}var q=class extends f.Plugin{constructor(){super(...arguments);this.recentFiles=[];this.savePromise=Promise.resolve();this.markdownBasenames=new Set;this.dateSystemIndicators=null;this.dateSystemIndicatorKey=""}async onload(){console.debug("Waypoint: loading plugin v"+this.manifest.version);let e=await this.loadData();this.applySettings(e),this.applyWaypointData(e),this.registerView(E,s=>new W(s,this)),this.addSettingTab(new z(this.app,this,this.settings,()=>{this.enforceRecentFilesLimit(),this.invalidateDateSystemIndicators(),this.redrawAll()})),this.addCommand({id:"waypoint-open-view",name:"Open Waypoint sidebar",callback:async()=>{let s=this.app.workspace.getLeavesOfType(E);if(s.length>0)await this.app.workspace.revealLeaf(s[0]);else{let o=this.app.workspace.getLeftLeaf(!1);o&&(await o.setViewState({type:E}),await this.app.workspace.revealLeaf(o))}}}),this.addCommand({id:"waypoint-add-bookmark",name:"Add current file as Waypoint bookmark",callback:async()=>{let s=this.app.workspace.getActiveFile();if(!s){new f.Notice("No active file");return}this.addBookmark(s.path,s.basename,"file"),new f.Notice(`Bookmarked: ${s.basename}`)}}),this.addCommand({id:"waypoint-go-to-daily",name:"Go to daily note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"d"}],callback:async()=>{await this.openPeriodNote("day",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-weekly",name:"Go to weekly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"w"}],callback:async()=>{await this.openPeriodNote("week",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-monthly",name:"Go to monthly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"m"}],callback:async()=>{await this.openPeriodNote("month",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-quarterly",name:"Go to quarterly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"q"}],callback:async()=>{await this.openPeriodNote("quarter",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-yearly",name:"Go to yearly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"y"}],callback:async()=>{await this.openPeriodNote("year",(0,f.moment)())}});let n=["next","prev"],i=["daily","weekly","monthly","quarterly","yearly"],a={next:"Next",prev:"Previous"};for(let s of i)for(let o of n){let r=`waypoint-go-to-${o}-${s}`,c=`${a[o]} ${s} note`;this.addCommand({id:r,name:c,callback:async()=>{await this.navigatePeriodNote(o)}})}this.registerEvent(this.app.workspace.on("file-open",s=>{s&&this.onFileOpen(s)})),this.registerEvent(this.app.vault.on("create",s=>this.onVaultCreate(s))),this.registerEvent(this.app.vault.on("delete",s=>this.onVaultDelete(s))),this.registerEvent(this.app.vault.on("rename",(s,o)=>this.onRename(s,o))),this.registerEvent(this.app.vault.on("modify",s=>this.onFileModify(s))),this.app.workspace.onLayoutReady(()=>{if(this.buildMarkdownIndex(),this.app.workspace.getLeavesOfType(E).length===0){let o=this.app.workspace.getLeftLeaf(!1);o&&o.setViewState({type:E})}else this.broadcastRedraw()});let t=new Date().toDateString();this.registerInterval(window.setInterval(()=>{let s=new Date().toDateString();s!==t&&(t=s,this.redrawAll())},6e5))}async onunload(){this.app.workspace.detachLeavesOfType(E)}applySettings(e){let n=(e==null?void 0:e.settings)||{};this.settings=Object.assign({},T,n),this.settings.recentFiles=Object.assign({},T.recentFiles,n.recentFiles||{}),this.settings.calendar=Object.assign({},T.calendar,n.calendar||{}),this.settings.display=Object.assign({},T.display,n.display||{});for(let i of De)this.settings[i]=Object.assign({},T[i],n[i]||{});this.settings.dateSystems=Array.isArray(n.dateSystems)?n.dateSystems.map(i=>{let a=T.dateSystems.find(t=>t.id===i.id);return Object.assign({},a||$,i)}):T.dateSystems.map(i=>Object.assign({},i))}applyWaypointData(e){let n=(e==null?void 0:e.waypointData)||{};this.waypointData={bookmarks:Array.isArray(n.bookmarks)?n.bookmarks:[],recentFiles:Array.isArray(n.recentFiles)?n.recentFiles:[]},this.recentFiles=this.waypointData.recentFiles,this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems),this.waypointData.recentFiles=this.recentFiles)}persistAll(){let e=this.savePromise.then(()=>(this.waypointData.recentFiles=this.recentFiles,this.saveData({settings:this.settings,waypointData:this.waypointData})));return this.savePromise=e.catch(()=>{}),e}async saveSettings(){await this.persistAll()}async saveWaypointData(){await this.persistAll()}enforceRecentFilesLimit(){this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems),this.persistRecentFiles())}persistRecentFiles(){this.waypointData.recentFiles=this.recentFiles,window.clearTimeout(this.recentFilesSaveTimer),this.recentFilesSaveTimer=window.setTimeout(()=>{this.saveWaypointData()},300)}onFileOpen(e){this.settings.recentFiles.updateOn==="file-open"&&this.addToRecentFiles(e)}onFileModify(e){this.settings.recentFiles.updateOn==="file-edit"&&e instanceof f.TFile&&(this.recentFiles.length>0&&this.recentFiles[0].path===e.path||this.addToRecentFiles(e))}addToRecentFiles(e){this.isOmittedFromRecentFiles(e)||(this.recentFiles=this.recentFiles.filter(n=>n.path!==e.path),this.recentFiles.unshift({path:e.path,basename:e.basename}),this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems)),this.persistRecentFiles(),this.broadcastRedraw())}isOmittedFromRecentFiles(e){for(let s of this.settings.recentFiles.omittedPaths)try{if(new RegExp(s).test(e.path))return!0}catch(o){}let n=this.settings.recentFiles.omittedTags;if(n.length===0)return!1;let i=this.app.metadataCache.getFileCache(e),a=(i?(0,f.getAllTags)(i):null)||[];if(a.length===0)return!1;let t=a.map(s=>s.replace(/^#/,""));for(let s of n)try{let o=new RegExp(s);if(t.some(r=>o.test(r)))return!0}catch(o){}return!1}onRename(e,n){this.invalidateDateSystemIndicators();let i=this.syncIndexForRename(e,n),a=!1;for(let s of this.recentFiles){let o=J(s.path,n,e.path);o!==null&&(s.path=o,s.basename=de(o),a=!0)}let t=s=>{for(let o of s){if(o.filePath){let r=J(o.filePath,n,e.path);r!==null&&(o.filePath=r,a=!0)}o.children&&t(o.children)}};t(this.waypointData.bookmarks),a&&(this.waypointData.recentFiles=this.recentFiles,this.persistAll()),(a||i)&&this.broadcastRedraw()}onVaultCreate(e){e instanceof f.TFile&&e.extension==="md"&&(this.markdownBasenames.add(e.basename),this.invalidateDateSystemIndicators()),this.broadcastRedraw()}onVaultDelete(e){e instanceof f.TFile&&e.extension==="md"&&(this.removeFromMarkdownIndex(e.basename,e.path),this.invalidateDateSystemIndicators()),this.broadcastRedraw()}buildMarkdownIndex(){this.markdownBasenames.clear();for(let e of this.app.vault.getMarkdownFiles())this.markdownBasenames.add(e.basename)}invalidateDateSystemIndicators(){this.dateSystemIndicators=null,this.dateSystemIndicatorKey=""}removeFromMarkdownIndex(e,n){return!this.markdownBasenames.has(e)||this.app.vault.getMarkdownFiles().some(a=>a.basename===e&&a.path!==n)?!1:(this.markdownBasenames.delete(e),!0)}syncIndexForRename(e,n){if(!(e instanceof f.TFile))return!1;let i=!1,a=de(n);return n.toLowerCase().endsWith(".md")&&(a!==e.basename||e.extension!=="md")&&(i=this.removeFromMarkdownIndex(a,n)),e.extension==="md"&&!this.markdownBasenames.has(e.basename)&&(this.markdownBasenames.add(e.basename),i=!0),i}hasNoteForDate(e){return this.markdownBasenames.has(e)}addBookmark(e,n,i="file",a=""){let s={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:i,label:n,filePath:i==="file"?e:"",icon:a,children:[],collapsed:!1,indent:0};return this.waypointData.bookmarks.push(s),this.saveWaypointData(),this.broadcastRedraw(),s}removeBookmark(e){let n=i=>{let a=i.findIndex(t=>t.id===e);if(a>=0)return i.splice(a,1),!0;for(let t of i)if(t.children&&n(t.children))return!0;return!1};n(this.waypointData.bookmarks),this.saveWaypointData(),this.broadcastRedraw()}updateBookmark(e,n){let i=t=>{for(let s of t){if(s.id===e)return s;if(s.children){let o=i(s.children);if(o)return o}}return null},a=i(this.waypointData.bookmarks);a&&(Object.assign(a,n),this.saveWaypointData(),this.broadcastRedraw())}periodAsDateSystem(e){let n=j[e],i=this.settings[n.key];return{id:n.key,name:n.label,folder:i.folder,nameFormat:i.nameFormat,templateFile:i.templateFile,typeProperty:i.typeProperty,icon:"calendar",indicatorColor:this.settings.calendar.dailyIndicatorColor}}dateSystems(){return[this.periodAsDateSystem("day"),...this.settings.dateSystems]}findDateSystemNotes(e){let n=this.dateSystems().map(i=>{let a=R(i.nameFormat);return{result:{system:i,notes:[],multiple:a.hasTitle},before:B(e,a.before),after:B(e,a.after),hasTitle:a.hasTitle,skip:!A(i.nameFormat)}});for(let i of this.app.vault.getMarkdownFiles())for(let a of n){if(a.skip)continue;let t=a.result.system;Q(i.path,t.folder)&&U(i.basename,a.before,a.after,a.hasTitle)&&a.result.notes.push({file:i,label:a.hasTitle?oe(i.basename,a.before,a.after):t.name})}for(let i of n)i.result.notes.sort((a,t)=>a.file.basename.localeCompare(t.file.basename));return n.filter(i=>!i.skip).map(i=>i.result)}getDateSystemIndicators(e){var o;let n=e.map(r=>r.format("YYYY-MM-DD")),i=this.dateSystems().filter(r=>A(r.nameFormat)).map(r=>{let c=R(r.nameFormat);return{system:r,hasTitle:c.hasTitle,dates:e.map((l,h)=>({dateStr:n[h],before:B(l,c.before),after:B(l,c.after)}))}}),a=JSON.stringify({dates:n,systems:i.map(({system:r})=>[r.id,r.name,r.folder,r.nameFormat,r.indicatorColor])});if(this.dateSystemIndicators&&this.dateSystemIndicatorKey===a)return this.dateSystemIndicators;let t=new Map;for(let r of n)t.set(r,new Set);for(let r of this.app.vault.getMarkdownFiles())for(let c of i)if(Q(r.path,c.system.folder))for(let l of c.dates)U(r.basename,l.before,l.after,c.hasTitle)&&((o=t.get(l.dateStr))==null||o.add(c.system.id));let s=new Map;for(let r of n){let c=t.get(r);s.set(r,i.filter(({system:l})=>c==null?void 0:c.has(l.id)).map(({system:l})=>({id:l.id,name:l.name,color:l.indicatorColor})))}return this.dateSystemIndicatorKey=a,this.dateSystemIndicators=s,s}async openDateSystemNote(e,n,i){if(!A(e.nameFormat)){new f.Notice(`Waypoint: ${e.name||"This"} name format needs a date placeholder.`);return}let a=R(e.nameFormat),t=B(n,a.before),s=B(n,a.after),o;if(a.hasTitle){let h=re((i==null?void 0:i.title)||"");if(!h){new f.Notice(`Waypoint: a ${e.name.toLowerCase()} note needs a title.`);return}o=t+h+s}else o=t+s;let r=e.folder?`${e.folder}/${o}.md`:`${o}.md`,c=this.app.vault.getFileByPath(r);if(!c&&(c=await this.createDatedNote(r,e,n),!c))return;await((i==null?void 0:i.leaf)||this.app.workspace.getLeaf(!1)).openFile(c)}async openPeriodNote(e,n,i){await this.openDateSystemNote(this.periodAsDateSystem(e),n,{leaf:i})}async createDatedNote(e,n,i){let a=n.name.toLowerCase(),t=e.lastIndexOf("/"),s=t<0?"":e.slice(0,t);try{await this.ensureFolderExists(s)}catch(h){return new f.Notice(`Waypoint: could not create the folder "${s}" for the ${a} note. -${X(h)} -Check Settings \u2192 Waypoint Sidebar \u2192 Periodic Notes.`,O),null}let o=n.templateFile,r=this.resolveTemplateFile(o),c;if(r)try{c=await this.app.vault.read(r)}catch(h){return new f.Notice(`Waypoint: could not read the template "${r.path}" for the ${a} note. -`+X(h),O),null}else c=`--- +project`),i.setValue(this.settings.recentFiles.filterTags.join(` +`)),i.inputEl.onblur=()=>{this.settings.recentFiles.filterTags=i.getValue().split(` +`).filter(o=>o.trim()),this.saveAndRefresh()}})}renderDisplayTab(e){new v.Setting(e).setHeading().setName("Bookmarks"),this.addSliderSetting(e,"Row size","Height of bookmark items.",this.settings.display,"rowSize",18,40,1,"px"),this.addSliderSetting(e,"Row spacing","Gap between bookmark items.",this.settings.display,"rowSpacing",0,12,1,"px"),this.addSliderSetting(e,"Indent size","Indent per nesting depth.",this.settings.display,"indentSize",8,32,2,"px"),this.addSliderSetting(e,"Font size","Label font size.",this.settings.display,"fontSize",10,18,1,"px"),this.addSliderSetting(e,"Icon size","Bookmark icon size.",this.settings.display,"iconSize",12,24,1,"px"),new v.Setting(e).setHeading().setName("Calendar"),this.addSliderSetting(e,"Cell size","Height of calendar day cells.",this.settings.display,"calendarCellSize",20,48,2,"px"),new v.Setting(e).addButton(n=>n.setButtonText("Reset to defaults").onClick(()=>{this.settings.display={...T.display},this.saveAndRefresh(),this.display()}))}addSliderSetting(e,n,a,t,i,o,s,r,c){let l=new v.Setting(e).setName(n).setDesc(`${a} (${t[i]}${c})`);l.addSlider(h=>{h.setLimits(o,s,r).setValue(t[i]).setDynamicTooltip().onChange(u=>{t[i]=u,l.setDesc(`${a} (${u}${c})`),this.saveAndRefresh()})})}async saveAndRefresh(){await this.plugin.saveSettings(),this.onSettingsChange()}renderAboutTab(e){let n=this.plugin.manifest.version,a=e.createDiv();a.style.display="flex",a.style.alignItems="center",a.style.gap="12px",a.style.marginBottom="16px";let t=a.createDiv();t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.width="48px",t.style.height="48px",t.style.borderRadius="12px",t.style.background="var(--interactive-accent)",t.style.color="var(--text-on-accent)",t.style.fontSize="24px",(0,v.setIcon)(t,"compass");let i=a.createDiv(),o=i.createEl("h2",{text:"Waypoint Sidebar"});o.style.margin="0",o.style.lineHeight="1.2";let s=i.createDiv({text:`v${n}`});s.style.color="var(--text-muted)",s.style.fontSize="var(--font-ui-small)";let r=e.createDiv();r.style.marginBottom="20px",r.style.lineHeight="1.6",r.style.color="var(--text-normal)",r.innerHTML=["

Waypoint is a sidebar plugin that brings three essential panels into one view:

",'
    ',"
  • Calendar \u2014 a monthly grid for your periodic notes (daily, weekly, monthly, quarterly, yearly). Click any day, week, or month to open or create the corresponding note.
  • ","
  • Recent Files \u2014 a list of recently opened files with type filtering, drag-and-drop, and right-click actions.
  • ","
  • Bookmarks \u2014 custom bookmarks with icons, groups, nesting, and drag-and-drop reordering. Separate from Obsidian's native bookmarks.
  • ","
",'

Made by Olivier. Licensed under MIT.

'].join(` +`)}};var m=require("obsidian");var C=require("obsidian");function ce(p,d,e){let n=(0,C.moment)({year:p,month:d,day:1}),a=(0,C.moment)(n).endOf("month"),t=(0,C.moment)(n).subtract((n.day()-e+7)%7,"days"),i=(0,C.moment)().startOf("day"),o=[],s=(0,C.moment)(t);for(;s.isBefore(a)||s.month()===d;){let r=[];for(let c=0;c<7;c++)r.push({date:(0,C.moment)(s),dayOfMonth:s.date(),isToday:s.isSame(i,"day"),isCurrentMonth:s.month()===d,isoWeekNumber:s.isoWeek()}),s.add(1,"day");if(o.push({weekNumber:r[0].isoWeekNumber,days:r}),o.length>=6)break}return o}var E="waypoint-view";function we(p){return p.dragManager}var W=class extends m.ItemView{constructor(e,n){super(e);this.redraw=()=>{this.contentEl.empty(),this.contentEl.addClass("waypoint-view");let e=this.plugin.settings.display;this.contentEl.style.setProperty("--wp-row-size",e.rowSize+"px"),this.contentEl.style.setProperty("--wp-row-spacing",e.rowSpacing+"px"),this.contentEl.style.setProperty("--wp-indent-size",e.indentSize+"px"),this.contentEl.style.setProperty("--wp-font-size",e.fontSize+"px"),this.contentEl.style.setProperty("--wp-icon-size",e.iconSize+"px"),this.contentEl.style.setProperty("--wp-cal-cell-size",e.calendarCellSize+"px"),this.renderFavorites(),this.renderRecentFiles(),this.renderCalendar()};this.currentDisplayMonth=(0,m.moment)().month();this.currentDisplayYear=(0,m.moment)().year();this.dragId=null;this.dropZones=new WeakMap;this.recentFilesFilter=null;this.plugin=n}getViewType(){return E}getDisplayText(){return"Waypoint"}getIcon(){return"compass"}async onOpen(){this.redraw()}async onClose(){}renderCalendar(){let n=this.contentEl.createDiv({cls:"waypoint-section"}).createDiv({cls:"waypoint-calendar"}),a=(0,m.moment)(),t=(0,m.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth,day:1}),i=n.createDiv({cls:"waypoint-calendar-top"}),o=i.createDiv({cls:"waypoint-calendar-breadcrumb"}),s=t.format("[Q]Q"),r=o.createSpan({cls:"waypoint-clickable",text:s});r.addEventListener("click",()=>{this.plugin.openPeriodNote("quarter",t)}),r.addEventListener("mousedown",D=>{D.button===1&&(D.preventDefault(),this.plugin.openPeriodNote("quarter",t,this.app.workspace.getLeaf("tab")))});let c=t.format("MMMM"),l=o.createSpan({cls:"waypoint-clickable",text:c});l.addEventListener("click",()=>{this.plugin.openPeriodNote("month",t)}),l.addEventListener("mousedown",D=>{D.button===1&&(D.preventDefault(),this.plugin.openPeriodNote("month",t,this.app.workspace.getLeaf("tab")))});let h=t.format("YYYY"),u=o.createSpan({cls:"waypoint-clickable",text:h});u.addEventListener("click",()=>{this.plugin.openPeriodNote("year",t)}),u.addEventListener("mousedown",D=>{D.button===1&&(D.preventDefault(),this.plugin.openPeriodNote("year",t,this.app.workspace.getLeaf("tab")))});let g=i.createDiv({cls:"waypoint-calendar-today-group"}),S=g.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,m.setIcon)(S,"chevron-left"),S.addEventListener("click",()=>this.navigateMonth(-1)),g.createEl("button",{cls:"waypoint-calendar-today-btn",text:"Today"}).addEventListener("click",()=>{this.currentDisplayMonth=(0,m.moment)().month(),this.currentDisplayYear=(0,m.moment)().year(),this.redraw()});let w=g.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,m.setIcon)(w,"chevron-right"),w.addEventListener("click",()=>this.navigateMonth(1));let b=n.createEl("table"),y=b.createEl("thead").createEl("tr");y.createEl("th",{text:""});let L=["sun","mon","tue","wed","thu","fri","sat"],K=this.plugin.settings.calendar.firstDayOfWeek;for(let D=0;D<7;D++){let N=(K+D)%7;y.createEl("th",{text:L[N]})}let P=b.createEl("tbody"),te=ce(this.currentDisplayYear,this.currentDisplayMonth,this.plugin.settings.calendar.firstDayOfWeek),_=this.plugin.settings.calendar.showNoteIndicators&&this.plugin.settings.calendar.indicatorMode==="systems"?this.plugin.getDateSystemIndicators(te.reduce((D,N)=>D.concat(N.days.map(Y=>Y.date)),[])):null;for(let D of te){let N=P.createEl("tr"),Y=N.createEl("td",{cls:"waypoint-weeknum"});Y.setText(String(D.weekNumber));let ie=D.days[0].date;Y.addEventListener("click",()=>{this.plugin.openPeriodNote("week",ie)}),Y.addEventListener("mousedown",x=>{x.button===1&&(x.preventDefault(),this.plugin.openPeriodNote("week",ie,this.app.workspace.getLeaf("tab")))});for(let x of D.days){let I=N.createEl("td",{cls:"waypoint-day"});if(I.setText(String(x.dayOfMonth)),x.isCurrentMonth||I.addClass("other-month"),x.isToday&&I.addClass("today"),this.plugin.settings.calendar.showNoteIndicators){let M=x.date.format("YYYY-MM-DD");if(this.plugin.settings.calendar.indicatorMode==="any")this.plugin.hasNoteForDate(M)&&I.addClass("has-note");else{let ne=(_==null?void 0:_.get(M))||[];if(ne.length>0){let me=I.createDiv({cls:"waypoint-day-indicators"});for(let ae of ne){let se=me.createSpan({cls:"waypoint-day-indicator"});se.style.setProperty("--waypoint-indicator-color",ae.color),(0,m.setTooltip)(se,ae.name)}}}}I.addEventListener("click",()=>{this.plugin.openPeriodNote("day",x.date)}),I.addEventListener("mousedown",M=>{M.button===1&&(M.preventDefault(),this.plugin.openPeriodNote("day",x.date,this.app.workspace.getLeaf("tab")))}),I.addEventListener("contextmenu",M=>{M.preventDefault(),M.stopPropagation(),this.showDayContextMenu(M,x.date)})}}}navigateMonth(e){let n=(0,m.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth}).add(e,"month");this.currentDisplayMonth=n.month(),this.currentDisplayYear=n.year(),this.redraw()}showDayContextMenu(e,n){let a=new m.Menu;a.addItem(t=>t.setTitle(n.format("dddd, MMMM D, YYYY")).setIsLabel(!0));for(let t of this.plugin.findDateSystemNotes(n)){let i=t.multiple||t.notes.length===0;if(t.notes.length+(i?1:0)===0)continue;a.addSeparator();for(let s of t.notes)a.addItem(r=>r.setTitle(s.label).setIcon(t.system.icon).onClick(c=>this.focusFile(s.file,m.Keymap.isModEvent(c))));if(!i)continue;let o=t.system.name.toLowerCase();a.addItem(s=>s.setTitle(t.multiple?`New ${o} note\u2026`:`New ${o} note`).setIcon("plus").onClick(r=>this.createDateSystemNote(t,n,m.Keymap.isModEvent(r))))}a.showAtPosition({x:e.clientX,y:e.clientY})}createDateSystemNote(e,n,a){if(!e.multiple){this.plugin.openDateSystemNote(e.system,n,{leaf:a?this.app.workspace.getLeaf(a):void 0});return}let t=e.system.name;new q(this.app,{title:`New ${t.toLowerCase()} note`,placeholder:`${t} with\u2026`,cta:"Create"},i=>{this.plugin.openDateSystemNote(e.system,n,{title:i,leaf:a?this.app.workspace.getLeaf(a):void 0})}).open()}renderRecentFiles(){var r,c;let e=this.contentEl.createDiv({cls:"waypoint-section waypoint-recent-files"});if(e.createDiv({cls:"waypoint-section-header",text:"Recent Files"}),this.plugin.recentFiles.length===0){e.createDiv({cls:"nav-file",text:"No recent files"});return}let n=this.plugin.settings.recentFiles.filterTags||[],a={};if(n.length>0){for(let l of n)a[l]=0;for(let l of this.plugin.recentFiles){let h=this.app.vault.getAbstractFileByPath(l.path);if(h instanceof m.TFile){let u=this.app.metadataCache.getFileCache(h),g=(r=u==null?void 0:u.frontmatter)==null?void 0:r.type;g&&typeof g=="string"&&a.hasOwnProperty(g)&&a[g]++}}}else for(let l of this.plugin.recentFiles){let h=this.app.vault.getAbstractFileByPath(l.path);if(h instanceof m.TFile){let u=this.app.metadataCache.getFileCache(h),g=(c=u==null?void 0:u.frontmatter)==null?void 0:c.type;g&&typeof g=="string"&&(a[g]=(a[g]||0)+1)}}if(Object.keys(a).length>0){let l=e.createDiv({cls:"waypoint-recent-filter"});l.createSpan({cls:`waypoint-recent-pill${this.recentFilesFilter?"":" is-active"}`,text:"all"}).addEventListener("click",()=>{this.recentFilesFilter=null,this.redraw()});let u=n.length>0?Object.entries(a):Object.entries(a).sort((g,S)=>S[1]-g[1]);for(let[g,S]of u){let F=l.createSpan({cls:`waypoint-recent-pill${this.recentFilesFilter===g?" is-active":""}`});F.setText(`${g} ${S}`),F.addEventListener("click",()=>{this.recentFilesFilter=this.recentFilesFilter===g?null:g,this.redraw()})}}let t=this.plugin.recentFiles;this.recentFilesFilter&&(t=this.plugin.recentFiles.filter(l=>{var u;let h=this.app.vault.getAbstractFileByPath(l.path);if(h instanceof m.TFile){let g=this.app.metadataCache.getFileCache(h);return((u=g==null?void 0:g.frontmatter)==null?void 0:u.type)===this.recentFilesFilter}return!1}));let i=this.app.workspace.getActiveFile(),o=e.createDiv({cls:"nav-folder mod-root"}),s=o.createDiv({cls:"nav-folder-children"});for(let l of t){let h=s.createDiv({cls:"tree-item nav-file"}),u=h.createDiv({cls:"tree-item-self is-clickable nav-file-title"});u.createDiv({cls:"tree-item-inner nav-file-title-content"}).setText(l.basename);let S=u.createDiv({cls:"tree-item-spacer"}),F=u.createDiv({cls:"waypoint-recent-remove"});(0,m.setIcon)(F,"x"),F.addEventListener("click",w=>{w.stopPropagation(),this.plugin.recentFiles=this.plugin.recentFiles.filter(b=>b.path!==l.path),this.plugin.persistRecentFiles(),this.redraw()}),(0,m.setTooltip)(h,l.path),i&&l.path===i.path&&u.addClass("is-active"),u.setAttr("draggable","true"),u.addEventListener("dragstart",w=>{let b=this.app.metadataCache.getFirstLinkpathDest(l.path,"");if(b){let k=we(this.app),y=k.dragFile(w,b);k.onDragStart(w,y)}}),u.addEventListener("mouseover",w=>{this.app.workspace.trigger("hover-link",{event:w,source:E,hoverParent:o,targetEl:h,linktext:l.path})}),u.addEventListener("contextmenu",w=>{let b=new m.Menu;b.addItem(y=>y.setSection("action").setTitle("Open in new tab").setIcon("file-plus").onClick(()=>this.focusFile(l,"tab"))),b.addItem(y=>y.setSection("action").setTitle("Add to bookmarks").setIcon("bookmark").onClick(()=>{this.plugin.addBookmark(l.path,l.basename,"file"),new m.Notice(`Bookmarked: ${l.basename}`)}));let k=this.app.vault.getAbstractFileByPath(l.path);k&&this.app.workspace.trigger("file-menu",b,k,"link-context-menu"),b.showAtPosition({x:w.clientX,y:w.clientY})}),u.addEventListener("click",w=>{let b=m.Keymap.isModEvent(w);this.focusFile(l,b)}),u.addEventListener("mousedown",w=>{w.button===1&&(w.preventDefault(),this.focusFile(l,"tab"))})}}focusFile(e,n){let a=this.app.vault.getFiles().find(t=>t.path===e.path);a?this.app.workspace.getLeaf(n).openFile(a):(new m.Notice("Cannot find file"),this.plugin.recentFiles=this.plugin.recentFiles.filter(t=>t.path!==e.path),this.plugin.persistRecentFiles(),this.redraw())}renderFavorites(){let e=this.contentEl.createDiv({cls:"waypoint-section waypoint-favorites"}),n=e.createDiv({cls:"waypoint-section-header"});n.setText("Waypoint Bookmarks");let a=n.createEl("button",{cls:"waypoint-header-more"});if((0,m.setIcon)(a,"more-horizontal"),(0,m.setTooltip)(a,"Add bookmark"),a.addEventListener("click",t=>{let i=new m.Menu;i.addItem(o=>{o.setTitle("Add current file").setIcon("file-plus").onClick(()=>{let s=this.app.workspace.getActiveFile();s&&this.plugin.addBookmark(s.path,s.basename,"file")})}),i.addItem(o=>{o.setTitle("Add as parent note").setIcon("folder-plus").onClick(()=>{let s=this.app.workspace.getActiveFile();if(!s)return;let r=this.plugin.addBookmark(s.path,s.basename,"group","");r.filePath=s.path,this.plugin.saveWaypointData(),this.redraw()})}),i.addItem(o=>{o.setTitle("New group").setIcon("folder-plus").onClick(()=>{this.plugin.addBookmark("","New Group","group","")})}),i.addSeparator(),i.addItem(o=>{o.setTitle("Add separator").setIcon("minus").onClick(()=>{this.plugin.addBookmark("","","separator")})}),i.addItem(o=>{o.setTitle("Add spacer").setIcon("space").onClick(()=>{this.plugin.addBookmark("","","spacer")})}),i.showAtPosition({x:t.clientX,y:t.clientY})}),this.plugin.waypointData.bookmarks.length===0){e.createDiv({cls:"waypoint-bookmark-item",text:"No bookmarks"});return}this.renderBookmarkList(e,this.plugin.waypointData.bookmarks,0)}renderBookmarkList(e,n,a){for(let t=0;t{c.stopPropagation(),c.preventDefault(),this.showBookmarkContextMenu(c,i)});continue}if(i.type==="spacer"){let r=e.createDiv({cls:"waypoint-bookmark-item waypoint-bookmark-spacer"});r.setAttr("draggable","true"),r.setAttr("data-bm-id",i.id),r.style.paddingLeft=`${8+a*16}px`,r.style.cursor="grab",this.attachBookmarkDragHandlers(r,e,i,!1),r.addEventListener("contextmenu",c=>{c.stopPropagation(),c.preventDefault(),this.showBookmarkContextMenu(c,i)});continue}let o=i.type==="group",s=e.createDiv({cls:`waypoint-bookmark-item${o?" waypoint-bookmark-group":""}${i.collapsed?" collapsed":""}`});if(s.setAttr("draggable","true"),s.setAttr("data-bm-id",i.id),o||(s.style.paddingLeft=`${8+a*16}px`),this.attachBookmarkDragHandlers(s,e,i,!0),o){let r=s.createDiv({cls:"waypoint-bm-icon"});i.icon&&(0,m.setIcon)(r,i.icon);let c=s.createDiv({cls:"waypoint-bm-label",text:i.label}),l=s.createDiv({cls:"waypoint-bm-chevron"});(0,m.setIcon)(l,"chevron-down"),l.addEventListener("click",u=>{u.stopPropagation(),this.plugin.updateBookmark(i.id,{collapsed:!i.collapsed})}),s.addEventListener("click",u=>{if(i.filePath){let g=this.app.vault.getFileByPath(i.filePath);if(g){let S=m.Keymap.isModEvent(u);this.app.workspace.getLeaf(S).openFile(g);return}}this.plugin.updateBookmark(i.id,{collapsed:!i.collapsed})}),s.addEventListener("mousedown",u=>{if(u.button===1&&i.filePath){u.preventDefault();let g=this.app.vault.getFileByPath(i.filePath);g&&this.app.workspace.getLeaf("tab").openFile(g)}});let h=e.createDiv({cls:`waypoint-bookmark-children${i.collapsed?" collapsed":""}`});i.children&&i.children.length>0&&this.renderBookmarkList(h,i.children,a+1)}else{let r=s.createDiv({cls:"waypoint-bm-icon"});i.icon&&(0,m.setIcon)(r,i.icon);let c=s.createDiv({cls:"waypoint-bm-label",text:i.label});if(i.children&&i.children.length>0){let l=s.createDiv({cls:"waypoint-bm-chevron"});(0,m.setIcon)(l,"chevron-down"),l.addEventListener("click",h=>{h.stopPropagation(),this.plugin.updateBookmark(i.id,{collapsed:!i.collapsed})}),i.collapsed&&(s.addClass("collapsed"),l.style.transform="rotate(-90deg)")}if((0,m.setTooltip)(s,i.filePath),s.addEventListener("click",l=>{if(i.filePath){let h=this.app.vault.getFileByPath(i.filePath);if(h){let u=m.Keymap.isModEvent(l);this.app.workspace.getLeaf(u).openFile(h)}else new m.Notice("File not found"),this.plugin.removeBookmark(i.id)}}),s.addEventListener("mousedown",l=>{if(l.button===1&&i.filePath){l.preventDefault();let h=this.app.vault.getFileByPath(i.filePath);h&&this.app.workspace.getLeaf("tab").openFile(h)}}),i.children&&i.children.length>0){let l=e.createDiv({cls:`waypoint-bookmark-children${i.collapsed?" collapsed":""}`});this.renderBookmarkList(l,i.children,a+1)}}s.addEventListener("contextmenu",r=>{r.stopPropagation(),r.preventDefault(),this.showBookmarkContextMenu(r,i)})}}showBookmarkContextMenu(e,n){let a=new m.Menu;if(n.type==="separator"||n.type==="spacer"){a.addItem(t=>t.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(n.id))),a.showAtPosition({x:e.clientX,y:e.clientY});return}n.type==="file"?(a.addItem(t=>t.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let i=this.app.vault.getFileByPath(n.filePath);i&&this.app.workspace.getLeaf("tab").openFile(i)})),a.addSeparator(),a.addItem(t=>t.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(n))),a.addItem(t=>t.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(n))),a.addSeparator(),a.addItem(t=>t.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(n.id)))):n.type==="group"&&(n.filePath&&(a.addItem(t=>t.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let i=this.app.vault.getFileByPath(n.filePath);i&&this.app.workspace.getLeaf("tab").openFile(i)})),a.addSeparator()),a.addItem(t=>t.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(n))),a.addItem(t=>t.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(n))),a.addSeparator(),a.addItem(t=>t.setTitle("Add child bookmark").setIcon("file-plus").onClick(()=>{let i=this.app.workspace.getActiveFile();if(!i){new m.Notice("No active file");return}let o={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"file",label:i.basename,filePath:i.path,icon:"",children:[],collapsed:!1,indent:n.indent+1};n.children.push(o),this.plugin.saveWaypointData(),this.redraw()})),a.addItem(t=>t.setTitle("Add child note").setIcon("folder-plus").onClick(()=>{let i=this.app.workspace.getActiveFile();if(!i){new m.Notice("No active file");return}let o={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:i.basename,filePath:i.path,icon:"",children:[],collapsed:!1,indent:n.indent+1};n.children.push(o),this.plugin.saveWaypointData(),this.redraw()})),a.addItem(t=>t.setTitle("New sub-group").setIcon("folder-plus").onClick(()=>{let i={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:"New Group",filePath:"",icon:"",children:[],collapsed:!1,indent:n.indent+1};n.children.push(i),this.plugin.saveWaypointData(),this.redraw()})),a.addSeparator(),a.addItem(t=>t.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(n.id)))),a.showAtPosition({x:e.clientX,y:e.clientY})}attachBookmarkDragHandlers(e,n,a,t){let i=()=>{e.removeClass("waypoint-bm-drop-line"),e.removeClass("waypoint-bm-drop-below"),e.removeClass("waypoint-bm-drop-into")};e.addEventListener("dragstart",o=>{this.dragId=a.id,o.dataTransfer.effectAllowed="move",o.dataTransfer.setData("text/plain",a.id),e.addClass("waypoint-bm-dragging")}),e.addEventListener("dragend",()=>{this.dragId=null,n.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below, .waypoint-bm-drop-into").forEach(o=>{o.removeClass("waypoint-bm-dragging"),o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below"),o.removeClass("waypoint-bm-drop-into")})}),e.addEventListener("dragenter",o=>{o.preventDefault(),!(!this.dragId||this.dragId===a.id)&&this.showDropIndicator(e,o,t)}),e.addEventListener("dragover",o=>{o.preventDefault(),!(!this.dragId||this.dragId===a.id)&&this.showDropIndicator(e,o,t)}),e.addEventListener("dragleave",i),e.addEventListener("drop",o=>{var c,l;o.preventDefault(),this.dragId=null,i();let s=(c=o.dataTransfer)==null?void 0:c.getData("text/plain");if(!s||s===a.id)return;let r=this.dropZones.get(e);t&&(r!=null&&r.into)?a.type==="group"?this.moveBookmarkToGroup(s,a.id):this.createParentNoteAndMove(s,a.id):this.moveBookmarkToPosition(s,a.id,(l=r==null?void 0:r.above)!=null?l:!1)})}showDropIndicator(e,n,a){let t=e.parentElement;t&&t.querySelectorAll(".waypoint-bm-drop-line, .waypoint-bm-drop-below, .waypoint-bm-drop-into").forEach(s=>{s.removeClass("waypoint-bm-drop-line"),s.removeClass("waypoint-bm-drop-below"),s.removeClass("waypoint-bm-drop-into")});let i=e.getBoundingClientRect(),o=n.clientY;if(a){let s=i.top+i.height*.25,r=i.top+i.height*.75;or?(e.addClass("waypoint-bm-drop-line"),e.addClass("waypoint-bm-drop-below"),this.dropZones.set(e,{above:!1,into:!1})):(e.addClass("waypoint-bm-drop-into"),this.dropZones.set(e,{above:!1,into:!0}))}else{let s=o{let o=i.findIndex(s=>s.id===e);if(o>=0){let[s]=i.splice(o,1);return s}for(let s of i){let r=a(s.children);if(r)return r}return null},t=a(this.plugin.waypointData.bookmarks);if(t){if(n){let i=(o,s)=>o.id===s?!0:o.children.some(r=>i(r,s));if(t.id===n||i(t,n))return}if(n){let i=s=>{for(let r of s){if(r.id===n)return r;let c=i(r.children);if(c)return c}return null},o=i(this.plugin.waypointData.bookmarks);o&&(t.indent=o.indent+1,o.children.push(t))}else t.indent=0,this.plugin.waypointData.bookmarks.push(t);this.plugin.saveWaypointData(),this.redraw()}}createParentNoteAndMove(e,n){let a=s=>{let r=s.findIndex(c=>c.id===e);if(r>=0){let[c]=s.splice(r,1);return c}for(let c of s)if(c.children){let l=a(c.children);if(l)return l}return null},t=a(this.plugin.waypointData.bookmarks);if(!t)return;let i=s=>{for(let r of s){if(r.id===n)return r;if(r.children){let c=i(r.children);if(c)return c}}return null},o=i(this.plugin.waypointData.bookmarks);o&&(t.indent=o.indent+1,o.children.push(t),this.plugin.saveWaypointData(),this.redraw())}moveBookmarkToPosition(e,n,a){let t=r=>{let c=r.findIndex(l=>l.id===e);if(c>=0){let[l]=r.splice(c,1);return{item:l,parent:r}}for(let l of r)if(l.children){let h=t(l.children);if(h.item)return h}return{item:null,parent:[]}},{item:i}=t(this.plugin.waypointData.bookmarks);if(!i)return;let o=r=>{let c=r.findIndex(l=>l.id===n);if(c>=0)return{parent:r,idx:c};for(let l of r)if(l.children){let h=o(l.children);if(h)return h}return null},s=o(this.plugin.waypointData.bookmarks);if(!s)i.indent=0,this.plugin.waypointData.bookmarks.push(i);else{let r=a?s.idx:s.idx+1;s.parent.splice(r,0,i)}this.plugin.saveWaypointData(),this.redraw()}promptRename(e){new q(this.app,{title:"Rename bookmark",initialValue:e.label},n=>{n&&n.trim()&&this.plugin.updateBookmark(e.id,{label:n.trim()})}).open()}promptIcon(e){new J(this.app,e.icon,n=>{this.plugin.updateBookmark(e.id,{icon:n})}).open()}},q=class extends m.Modal{constructor(d,e,n){super(d),this.options=e,this.onSubmit=n}onOpen(){var t,i,o;this.titleEl.setText(this.options.title);let d=this.contentEl.createEl("input",{type:"text",value:(t=this.options.initialValue)!=null?t:"",placeholder:(i=this.options.placeholder)!=null?i:""});d.style.width="100%",d.style.marginBottom="12px",d.focus(),d.select();let e=this.contentEl.createDiv({cls:"modal-button-container"}),n=e.createEl("button",{text:"Cancel",cls:"mod-cta"});n.style.marginRight="8px",n.addEventListener("click",()=>this.close()),e.createEl("button",{text:(o=this.options.cta)!=null?o:"Save",cls:"mod-cta"}).addEventListener("click",()=>{this.onSubmit(d.value),this.close()}),d.addEventListener("keydown",s=>{s.key==="Enter"&&(this.onSubmit(d.value),this.close())})}onClose(){this.contentEl.empty()}},H=null;function be(){return H||(H=(async()=>{try{return await(await fetch("https://cdn.jsdelivr.net/npm/lucide-static@0.517.0/tags.json")).json()}catch(p){try{return await(await fetch("https://lucide.dev/api/tags")).json()}catch(d){return H=null,De}}})()),H}var J=class extends m.Modal{constructor(e,n,a){super(e);this.allIcons=[];this.tagsMap={};this.loaded=!1;this.selected=n,this.onSubmit=a}async onOpen(){let e=this.contentEl;e.style.display="flex",e.style.flexDirection="column",e.style.gap="10px",this.titleEl.setText("Change icon");let n=e.createDiv({cls:"waypoint-icon-preview"});n.style.display="flex",n.style.alignItems="center",n.style.gap="10px",n.style.padding="12px 16px",n.style.borderRadius="8px",n.style.background="var(--background-secondary)",n.style.minHeight="48px";let a=n.createSpan();a.style.display="flex",this.selected&&(0,m.setIcon)(a,this.selected);let t=n.createSpan();t.style.fontWeight="var(--font-medium)",t.style.fontSize="var(--font-ui-medium)",t.setText(this.selected||"No icon");let i=e.createEl("input",{type:"text",placeholder:"Type to search (e.g. arrow, chart, home)..."});Object.assign(i.style,{width:"100%",boxSizing:"border-box",padding:"8px 10px",borderRadius:"6px",border:"1px solid var(--background-modifier-border)",background:"var(--background-primary)",color:"var(--text-normal)",fontSize:"var(--font-ui-medium)"}),i.focus();let o=e.createDiv({cls:"waypoint-icon-grid"});o.style.display="grid",o.style.gridTemplateColumns="repeat(auto-fill, minmax(52px, 1fr))",o.style.gap="4px",o.style.maxHeight="320px",o.style.overflowY="auto",o.style.padding="2px 0";let s=e.createDiv();s.style.display="flex",s.style.justifyContent="space-between",s.style.alignItems="center",s.style.fontSize="var(--font-ui-smaller)",s.style.color="var(--text-muted)",s.style.padding="0 4px";let r=s.createSpan();r.setText("Loading\u2026"),this.loadIcons().then(()=>{this.loaded=!0,r.setText(this.allIcons.length+" icons"),l(i.value)});let c,l=F=>{if(o.empty(),!this.loaded){o.createDiv({text:"Loading\u2026"});return}let w=F.toLowerCase().trim(),b=w?this.allIcons.filter(k=>{if(k.includes(w))return!0;let y=this.tagsMap[k];return y?y.some(L=>L.includes(w)):!1}).slice(0,80):this.allIcons.slice(0,80);if(b.length===0){let k=o.createDiv();k.style.gridColumn="1 / -1",k.style.textAlign="center",k.style.color="var(--text-muted)",k.style.padding="20px",k.setText('No icons match "'+F+'"');return}for(let k of b){let y=o.createDiv();y.setAttr("data-icon",k),y.style.display="flex",y.style.alignItems="center",y.style.justifyContent="center",y.style.aspectRatio="1",y.style.borderRadius="6px",y.style.cursor="var(--cursor-link, pointer)",y.style.transition="background 80ms",y.setAttr("title",k),k===this.selected?(y.style.background="var(--interactive-accent)",y.style.color="var(--text-on-accent)"):y.style.color="var(--text-muted)";let L=y.createSpan();L.style.display="flex",(0,m.setIcon)(L,k),y.addEventListener("mouseenter",()=>{k!==this.selected&&(y.style.background="var(--background-modifier-hover)")}),y.addEventListener("mouseleave",()=>{k!==this.selected&&(y.style.background="")}),y.addEventListener("click",()=>{this.selected=k,l(F),a.empty(),(0,m.setIcon)(a,k),t.setText(k),o.querySelectorAll("div[data-icon]").forEach(K=>{let P=K;P.getAttr("data-icon")===k?(P.style.background="var(--interactive-accent)",P.style.color="var(--text-on-accent)"):(P.style.background="",P.style.color="var(--text-muted)")})})}r.setText(b.length+" of "+this.allIcons.length+" icons")};i.addEventListener("input",()=>{window.clearTimeout(c),c=window.setTimeout(()=>l(i.value),60)}),i.addEventListener("keydown",F=>{F.key==="Escape"&&this.close()});let h=e.createDiv({cls:"modal-button-container"});h.createEl("button",{text:"No icon",cls:"waypoint-icon-clear"}).addEventListener("click",()=>{this.onSubmit(""),this.close()}),h.createEl("button",{text:"Cancel"}).addEventListener("click",()=>this.close());let S=h.createEl("button",{text:"Save",cls:"mod-cta"});S.style.marginLeft="8px",S.addEventListener("click",()=>{this.onSubmit(this.selected),this.close()})}onClose(){this.contentEl.empty()}async loadIcons(){let e=await be();this.tagsMap=e,this.allIcons=Object.keys(e).sort()}},De={file:[],folder:[],star:[],heart:[],bookmark:[],flag:[],pin:[],tag:[],book:[],"book-open":[],library:[],calendar:[],"calendar-days":[],clock:[],home:[],inbox:[],mail:[],search:[],settings:[],cog:[],user:[],users:[],zap:[],sparkles:[],target:[],link:[],globe:[],edit:[],pencil:[],anchor:[],award:[],bell:[],"bell-ring":[],brain:[],briefcase:[],camera:[],"chart-bar":[],"chart-line":[],"chart-pie":[],check:[],"check-circle":[],"chevron-down":[],"chevron-left":[],"chevron-right":[],"chevron-up":[],circle:[],clipboard:[],code:[],command:[],compass:[],copy:[],"credit-card":[],crown:[],database:[],download:[],"external-link":[],eye:[],"eye-off":[],"file-text":[],filter:[],fingerprint:[],flashlight:[],"folder-open":[],"folder-plus":[],gift:[],"git-branch":[],"git-commit":[],"git-merge":[],"git-pull-request":[],github:[],grid:[],hash:[],headphones:[],image:[],info:[],key:[],layers:[],layout:[],"life-buoy":[],"link-2":[],list:[],loader:[],lock:[],"log-in":[],"log-out":[],map:[],"map-pin":[],maximize:[],megaphone:[],menu:[],"message-circle":[],"message-square":[],mic:[],minimize:[],moon:[],"more-horizontal":[],"more-vertical":[],"mouse-pointer":[],move:[],music:[],navigation:[],"navigation-2":[],package:[],palette:[],paperclip:[],pause:[],phone:[],play:[],plus:[],"plus-circle":[],power:[],printer:[],radio:[],"refresh-cw":[],repeat:[],"rotate-ccw":[],"rotate-cw":[],rss:[],save:[],scissors:[],screen:[],send:[],server:[],share:[],"share-2":[],shield:[],"shield-off":[],"shopping-bag":[],"shopping-cart":[],shuffle:[],sidebar:[],slack:[],slash:[],sliders:[],smartphone:[],smile:[],speaker:[],square:[],"stop-circle":[],sun:[],sunrise:[],sunset:[],swords:[],table:[],tablet:[],terminal:[],thermometer:[],"thumbs-down":[],"thumbs-up":[],"toggle-left":[],"toggle-right":[],tool:[],trash:[],"trash-2":[],trello:[],"trending-down":[],"trending-up":[],triangle:[],truck:[],tv:[],twitter:[],type:[],umbrella:[],unlock:[],upload:[],"user-check":[],"user-minus":[],"user-plus":[],"user-x":[],video:[],"video-off":[],voicemail:[],volume:[],"volume-1":[],"volume-2":[],"volume-x":[],watch:[],wifi:[],"wifi-off":[],wind:[],x:[],"x-circle":[],"x-square":[],youtube:[],"zap-off":[],"zoom-in":[],"zoom-out":[],"arrow-down":[],"arrow-left":[],"arrow-right":[],"arrow-up":[],airplay:[],"alarm-clock":[],archive:[],armchair:[],atom:[],baby:[],backpack:[],badge:[],"badge-check":[],ban:[],banknote:[],barcode:[],bath:[],battery:[],"battery-charging":[],beer:[],bike:[],bird:[],bluetooth:[],bolt:[],bone:[],"bookmark-plus":[],bot:[],box:[],bug:[],building:[],bus:[],cake:[],calculator:[],car:[],"clipboard-check":[],cloud:[],"cloud-download":[],"cloud-lightning":[],"cloud-rain":[],"cloud-sun":[],"cloud-upload":[],clover:[],coffee:[],coins:[],contact:[],cookie:[],"corner-down-left":[],"corner-down-right":[],"corner-up-left":[],"corner-up-right":[],crosshair:[],"dice-1":[],"dice-6":[],"dollar-sign":[],"door-open":[],drama:[],droplet:[],drum:[],egg:[],equal:[],euro:[],factory:[],fan:[],feather:[],film:[],fish:[],flame:[],flask:[],flower:[],frown:[],fuel:[],gamepad:[],gauge:[],gem:[],ghost:[],glasses:[],"graduation-cap":[],hammer:[],"hard-drive":[],haze:[],"help-circle":[],"ice-cream":[],infinity:[],italic:[],"japanese-yen":[],keyboard:[],knife:[],lamp:[],landmark:[],languages:[],laptop:[],laugh:[],leaf:[],lightbulb:[],"list-plus":[],magnet:[],"mail-plus":[],meh:[],microscope:[],milestone:[],"minimize-2":[],monitor:[],mountain:[],mouse:[],network:[],newspaper:[],"package-check":[],"package-search":[],"paint-bucket":[],parking:[],"party-popper":[],"pen-tool":[],percent:[],"person-standing":[],"picture-in-picture-2":[],plane:[],plug:[],podcast:[],pointer:[],"pound-sterling":[],puzzle:[],"qr-code":[],rabbit:[],radar:[],rainbow:[],rocket:[],"roller-coaster":[],route:[],ruler:[],sailboat:[],scale:[],scan:[],school:[],ship:[],shirt:[],"shopping-basket":[],shovel:[],sigma:[],siren:[],skull:[],snowflake:[],soup:[],space:[],sparkle:[],stamp:[],store:[],subscript:[],superscript:[],syringe:[],tent:[],"tent-tree":[],"test-tube":[],theater:[],timer:[],train:[],"tree-deciduous":[],"tree-pine":[],trophy:[],typing:[],utensils:[],vibrate:[],wallet:[],wand:[],warehouse:[],waves:[],webcam:[],wheat:[],wine:[],wrench:[]};function X(p,d,e){return!p||!d?null:p===d?e:p.startsWith(d+"/")?e+p.slice(d.length):null}var G=class extends f.Plugin{constructor(){super(...arguments);this.recentFiles=[];this.savePromise=Promise.resolve();this.markdownBasenames=new Set;this.dateSystemIndicators=null;this.dateSystemIndicatorKey="";this.indicatorModeMigrated=!1}async onload(){console.debug("Waypoint: loading plugin v"+this.manifest.version);let e=await this.loadData(),n=this.applySettings(e);this.applyWaypointData(e),n&&this.persistAll(),this.registerView(E,s=>new W(s,this)),this.addSettingTab(new V(this.app,this,this.settings,()=>{this.enforceRecentFilesLimit(),this.invalidateDateSystemIndicators(),this.redrawAll()})),this.addCommand({id:"waypoint-open-view",name:"Open Waypoint sidebar",callback:async()=>{let s=this.app.workspace.getLeavesOfType(E);if(s.length>0)await this.app.workspace.revealLeaf(s[0]);else{let r=this.app.workspace.getLeftLeaf(!1);r&&(await r.setViewState({type:E}),await this.app.workspace.revealLeaf(r))}}}),this.addCommand({id:"waypoint-add-bookmark",name:"Add current file as Waypoint bookmark",callback:async()=>{let s=this.app.workspace.getActiveFile();if(!s){new f.Notice("No active file");return}this.addBookmark(s.path,s.basename,"file"),new f.Notice(`Bookmarked: ${s.basename}`)}}),this.addCommand({id:"waypoint-go-to-daily",name:"Go to daily note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"d"}],callback:async()=>{await this.openPeriodNote("day",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-weekly",name:"Go to weekly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"w"}],callback:async()=>{await this.openPeriodNote("week",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-monthly",name:"Go to monthly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"m"}],callback:async()=>{await this.openPeriodNote("month",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-quarterly",name:"Go to quarterly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"q"}],callback:async()=>{await this.openPeriodNote("quarter",(0,f.moment)())}}),this.addCommand({id:"waypoint-go-to-yearly",name:"Go to yearly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"y"}],callback:async()=>{await this.openPeriodNote("year",(0,f.moment)())}});let a=["next","prev"],t=["daily","weekly","monthly","quarterly","yearly"],i={next:"Next",prev:"Previous"};for(let s of t)for(let r of a){let c=`waypoint-go-to-${r}-${s}`,l=`${i[r]} ${s} note`;this.addCommand({id:c,name:l,callback:async()=>{await this.navigatePeriodNote(r)}})}this.registerEvent(this.app.workspace.on("file-open",s=>{s&&this.onFileOpen(s)})),this.registerEvent(this.app.vault.on("create",s=>this.onVaultCreate(s))),this.registerEvent(this.app.vault.on("delete",s=>this.onVaultDelete(s))),this.registerEvent(this.app.vault.on("rename",(s,r)=>this.onRename(s,r))),this.registerEvent(this.app.vault.on("modify",s=>this.onFileModify(s))),this.app.workspace.onLayoutReady(()=>{if(this.buildMarkdownIndex(),this.app.workspace.getLeavesOfType(E).length===0){let r=this.app.workspace.getLeftLeaf(!1);r&&r.setViewState({type:E})}else this.broadcastRedraw()});let o=new Date().toDateString();this.registerInterval(window.setInterval(()=>{let s=new Date().toDateString();s!==o&&(o=s,this.redrawAll())},6e5))}async onunload(){this.app.workspace.detachLeavesOfType(E)}applySettings(e){var i;let n=(e==null?void 0:e.settings)||{};this.settings=Object.assign({},T,n),this.settings.recentFiles=Object.assign({},T.recentFiles,n.recentFiles||{}),this.settings.calendar=Object.assign({},T.calendar,n.calendar||{}),this.settings.display=Object.assign({},T.display,n.display||{});for(let o of Se)this.settings[o]=Object.assign({},T[o],n[o]||{});this.settings.dateSystems=Array.isArray(n.dateSystems)?n.dateSystems.map(o=>{let s=T.dateSystems.find(r=>r.id===o.id);return Object.assign({},s||$,o)}):T.dateSystems.map(o=>Object.assign({},o));let a=(e==null?void 0:e.indicatorModeMigrated)===!0,t=!1;return!a&&((i=n.calendar)==null?void 0:i.indicatorMode)==="any"&&(this.settings.calendar.indicatorMode="systems",t=!0),this.indicatorModeMigrated=!0,t}applyWaypointData(e){let n=(e==null?void 0:e.waypointData)||{};this.waypointData={bookmarks:Array.isArray(n.bookmarks)?n.bookmarks:[],recentFiles:Array.isArray(n.recentFiles)?n.recentFiles:[]},this.recentFiles=this.waypointData.recentFiles,this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems),this.waypointData.recentFiles=this.recentFiles)}persistAll(){let e=this.savePromise.then(()=>(this.waypointData.recentFiles=this.recentFiles,this.saveData({settings:this.settings,waypointData:this.waypointData,indicatorModeMigrated:this.indicatorModeMigrated})));return this.savePromise=e.catch(()=>{}),e}async saveSettings(){await this.persistAll()}async saveWaypointData(){await this.persistAll()}enforceRecentFilesLimit(){this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems),this.persistRecentFiles())}persistRecentFiles(){this.waypointData.recentFiles=this.recentFiles,window.clearTimeout(this.recentFilesSaveTimer),this.recentFilesSaveTimer=window.setTimeout(()=>{this.saveWaypointData()},300)}onFileOpen(e){this.settings.recentFiles.updateOn==="file-open"&&this.addToRecentFiles(e)}onFileModify(e){this.settings.recentFiles.updateOn==="file-edit"&&e instanceof f.TFile&&(this.recentFiles.length>0&&this.recentFiles[0].path===e.path||this.addToRecentFiles(e))}addToRecentFiles(e){this.isOmittedFromRecentFiles(e)||(this.recentFiles=this.recentFiles.filter(n=>n.path!==e.path),this.recentFiles.unshift({path:e.path,basename:e.basename}),this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems)),this.persistRecentFiles(),this.broadcastRedraw())}isOmittedFromRecentFiles(e){for(let o of this.settings.recentFiles.omittedPaths)try{if(new RegExp(o).test(e.path))return!0}catch(s){}let n=this.settings.recentFiles.omittedTags;if(n.length===0)return!1;let a=this.app.metadataCache.getFileCache(e),t=(a?(0,f.getAllTags)(a):null)||[];if(t.length===0)return!1;let i=t.map(o=>o.replace(/^#/,""));for(let o of n)try{let s=new RegExp(o);if(i.some(r=>s.test(r)))return!0}catch(s){}return!1}onRename(e,n){this.invalidateDateSystemIndicators();let a=this.syncIndexForRename(e,n),t=!1;for(let o of this.recentFiles){let s=X(o.path,n,e.path);s!==null&&(o.path=s,o.basename=pe(s),t=!0)}let i=o=>{for(let s of o){if(s.filePath){let r=X(s.filePath,n,e.path);r!==null&&(s.filePath=r,t=!0)}s.children&&i(s.children)}};i(this.waypointData.bookmarks),t&&(this.waypointData.recentFiles=this.recentFiles,this.persistAll()),(t||a)&&this.broadcastRedraw()}onVaultCreate(e){e instanceof f.TFile&&e.extension==="md"&&(this.markdownBasenames.add(e.basename),this.invalidateDateSystemIndicators()),this.broadcastRedraw()}onVaultDelete(e){e instanceof f.TFile&&e.extension==="md"&&(this.removeFromMarkdownIndex(e.basename,e.path),this.invalidateDateSystemIndicators()),this.broadcastRedraw()}buildMarkdownIndex(){this.markdownBasenames.clear();for(let e of this.app.vault.getMarkdownFiles())this.markdownBasenames.add(e.basename)}invalidateDateSystemIndicators(){this.dateSystemIndicators=null,this.dateSystemIndicatorKey=""}removeFromMarkdownIndex(e,n){return!this.markdownBasenames.has(e)||this.app.vault.getMarkdownFiles().some(t=>t.basename===e&&t.path!==n)?!1:(this.markdownBasenames.delete(e),!0)}syncIndexForRename(e,n){if(!(e instanceof f.TFile))return!1;let a=!1,t=pe(n);return n.toLowerCase().endsWith(".md")&&(t!==e.basename||e.extension!=="md")&&(a=this.removeFromMarkdownIndex(t,n)),e.extension==="md"&&!this.markdownBasenames.has(e.basename)&&(this.markdownBasenames.add(e.basename),a=!0),a}hasNoteForDate(e){return this.markdownBasenames.has(e)}addBookmark(e,n,a="file",t=""){let o={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:a,label:n,filePath:a==="file"?e:"",icon:t,children:[],collapsed:!1,indent:0};return this.waypointData.bookmarks.push(o),this.saveWaypointData(),this.broadcastRedraw(),o}removeBookmark(e){let n=a=>{let t=a.findIndex(i=>i.id===e);if(t>=0)return a.splice(t,1),!0;for(let i of a)if(i.children&&n(i.children))return!0;return!1};n(this.waypointData.bookmarks),this.saveWaypointData(),this.broadcastRedraw()}updateBookmark(e,n){let a=i=>{for(let o of i){if(o.id===e)return o;if(o.children){let s=a(o.children);if(s)return s}}return null},t=a(this.waypointData.bookmarks);t&&(Object.assign(t,n),this.saveWaypointData(),this.broadcastRedraw())}periodAsDateSystem(e){let n=j[e],a=this.settings[n.key];return{id:n.key,name:n.label,folder:a.folder,nameFormat:a.nameFormat,templateFile:a.templateFile,typeProperty:a.typeProperty,icon:"calendar",indicatorColor:this.settings.calendar.dailyIndicatorColor}}dateSystems(){return[this.periodAsDateSystem("day"),...this.settings.dateSystems]}findDateSystemNotes(e){let n=this.dateSystems().map(a=>{let t=R(a.nameFormat);return{result:{system:a,notes:[],multiple:t.hasTitle},before:B(e,t.before),after:B(e,t.after),hasTitle:t.hasTitle,skip:!A(a.nameFormat)}});for(let a of this.app.vault.getMarkdownFiles())for(let t of n){if(t.skip)continue;let i=t.result.system;U(a.path,i.folder)&&Z(a.basename,t.before,t.after,t.hasTitle)&&t.result.notes.push({file:a,label:t.hasTitle?re(a.basename,t.before,t.after):i.name})}for(let a of n)a.result.notes.sort((t,i)=>t.file.basename.localeCompare(i.file.basename));return n.filter(a=>!a.skip).map(a=>a.result)}getDateSystemIndicators(e){var s;let n=e.map(r=>r.format("YYYY-MM-DD")),a=this.dateSystems().filter(r=>A(r.nameFormat)).map(r=>{let c=R(r.nameFormat);return{system:r,hasTitle:c.hasTitle,dates:e.map((l,h)=>({dateStr:n[h],before:B(l,c.before),after:B(l,c.after)}))}}),t=JSON.stringify({dates:n,systems:a.map(({system:r})=>[r.id,r.name,r.folder,r.nameFormat,r.indicatorColor])});if(this.dateSystemIndicators&&this.dateSystemIndicatorKey===t)return this.dateSystemIndicators;let i=new Map;for(let r of n)i.set(r,new Set);for(let r of this.app.vault.getMarkdownFiles())for(let c of a)if(U(r.path,c.system.folder))for(let l of c.dates)Z(r.basename,l.before,l.after,c.hasTitle)&&((s=i.get(l.dateStr))==null||s.add(c.system.id));let o=new Map;for(let r of n){let c=i.get(r);o.set(r,a.filter(({system:l})=>c==null?void 0:c.has(l.id)).map(({system:l})=>({id:l.id,name:l.name,color:l.indicatorColor})))}return this.dateSystemIndicatorKey=t,this.dateSystemIndicators=o,o}async openDateSystemNote(e,n,a){if(!A(e.nameFormat)){new f.Notice(`Waypoint: ${e.name||"This"} name format needs a date placeholder.`);return}let t=R(e.nameFormat),i=B(n,t.before),o=B(n,t.after),s;if(t.hasTitle){let h=le((a==null?void 0:a.title)||"");if(!h){new f.Notice(`Waypoint: a ${e.name.toLowerCase()} note needs a title.`);return}s=i+h+o}else s=i+o;let r=e.folder?`${e.folder}/${s}.md`:`${s}.md`,c=this.app.vault.getFileByPath(r);if(!c&&(c=await this.createDatedNote(r,e,n),!c))return;await((a==null?void 0:a.leaf)||this.app.workspace.getLeaf(!1)).openFile(c)}async openPeriodNote(e,n,a){await this.openDateSystemNote(this.periodAsDateSystem(e),n,{leaf:a})}async createDatedNote(e,n,a){let t=n.name.toLowerCase(),i=e.lastIndexOf("/"),o=i<0?"":e.slice(0,i);try{await this.ensureFolderExists(o)}catch(h){return new f.Notice(`Waypoint: could not create the folder "${o}" for the ${t} note. +${ee(h)} +Check Settings \u2192 Waypoint Sidebar \u2192 Periodic Notes.`,O),null}let s=n.templateFile,r=this.resolveTemplateFile(s),c;if(r)try{c=await this.app.vault.read(r)}catch(h){return new f.Notice(`Waypoint: could not read the template "${r.path}" for the ${t} note. +`+ee(h),O),null}else c=`--- type: ${n.typeProperty} -date: ${i.format("YYYY-MM-DD")} +date: ${a.format("YYYY-MM-DD")} --- -`;let l;try{l=await this.app.vault.create(e,c)}catch(h){return new f.Notice(`Waypoint: could not create the ${a} note at "${e}". -${X(h)}`,O),null}return o&&!r?new f.Notice(`Created ${a} note: ${l.basename} -Template "${o}" was not found, so a basic note was created instead.`,O):new f.Notice(`Created ${a} note: ${l.basename}`),l}async ensureFolderExists(e){if(!e||this.app.vault.getAbstractFileByPath(e)instanceof f.TFolder)return;let n="";for(let i of e.split("/"))if(i&&(n=n?`${n}/${i}`:i,!(this.app.vault.getAbstractFileByPath(n)instanceof f.TFolder)))try{await this.app.vault.createFolder(n)}catch(a){if(!(this.app.vault.getAbstractFileByPath(n)instanceof f.TFolder))throw a}}resolveTemplateFile(e){if(!e)return null;let n=e.toLowerCase().endsWith(".md")?e:`${e}.md`;return this.app.vault.getFileByPath(n)}detectPeriodType(e){for(let n of ce){let i=this.settings[j[n].key].nameFormat;if(!i)continue;let a=(0,f.moment)(e,i,!0);if(a.isValid())return{period:n,date:a}}return null}async navigatePeriodNote(e){let n=this.app.workspace.getActiveFile();if(!n){new f.Notice("No active file");return}let i=this.detectPeriodType(n.basename);if(!i){let r=ce.map(c=>`${j[c].label.toLowerCase()} "${this.settings[j[c].key].nameFormat}"`).join(", ");new f.Notice(`Waypoint: "${n.basename}" does not match any configured periodic note format. -Expected one of: ${r}.`,O);return}let{period:a,date:t}=i,s=e==="next"?1:-1,o=a==="quarter"?t.clone().add(s*3,"months"):t.clone().add(s,`${a}s`);await this.openPeriodNote(a,o)}redrawAll(){this.broadcastRedraw()}broadcastRedraw(){let e=this.app.workspace.getLeavesOfType(E);for(let n of e)n.view instanceof W&&n.view.redraw()}},De=["daily","weekly","monthly","quarterly","yearly"],j={day:{key:"daily",label:"Daily"},week:{key:"weekly",label:"Weekly"},month:{key:"monthly",label:"Monthly"},quarter:{key:"quarterly",label:"Quarterly"},year:{key:"yearly",label:"Yearly"}},ce=["day","week","month","quarter","year"];function de(p){return p.slice(p.lastIndexOf("/")+1).replace(/\.[^/.]+$/,"")}var O=1e4;function X(p){return p instanceof Error?p.message:String(p)}function B(p,d){return d?p.format(d):""} +`;let l;try{l=await this.app.vault.create(e,c)}catch(h){return new f.Notice(`Waypoint: could not create the ${t} note at "${e}". +${ee(h)}`,O),null}return s&&!r?new f.Notice(`Created ${t} note: ${l.basename} +Template "${s}" was not found, so a basic note was created instead.`,O):new f.Notice(`Created ${t} note: ${l.basename}`),l}async ensureFolderExists(e){if(!e||this.app.vault.getAbstractFileByPath(e)instanceof f.TFolder)return;let n="";for(let a of e.split("/"))if(a&&(n=n?`${n}/${a}`:a,!(this.app.vault.getAbstractFileByPath(n)instanceof f.TFolder)))try{await this.app.vault.createFolder(n)}catch(t){if(!(this.app.vault.getAbstractFileByPath(n)instanceof f.TFolder))throw t}}resolveTemplateFile(e){if(!e)return null;let n=e.toLowerCase().endsWith(".md")?e:`${e}.md`;return this.app.vault.getFileByPath(n)}detectPeriodType(e){for(let n of de){let a=this.settings[j[n].key].nameFormat;if(!a)continue;let t=(0,f.moment)(e,a,!0);if(t.isValid())return{period:n,date:t}}return null}async navigatePeriodNote(e){let n=this.app.workspace.getActiveFile();if(!n){new f.Notice("No active file");return}let a=this.detectPeriodType(n.basename);if(!a){let r=de.map(c=>`${j[c].label.toLowerCase()} "${this.settings[j[c].key].nameFormat}"`).join(", ");new f.Notice(`Waypoint: "${n.basename}" does not match any configured periodic note format. +Expected one of: ${r}.`,O);return}let{period:t,date:i}=a,o=e==="next"?1:-1,s=t==="quarter"?i.clone().add(o*3,"months"):i.clone().add(o,`${t}s`);await this.openPeriodNote(t,s)}redrawAll(){this.broadcastRedraw()}broadcastRedraw(){let e=this.app.workspace.getLeavesOfType(E);for(let n of e)n.view instanceof W&&n.view.redraw()}},Se=["daily","weekly","monthly","quarterly","yearly"],j={day:{key:"daily",label:"Daily"},week:{key:"weekly",label:"Weekly"},month:{key:"monthly",label:"Monthly"},quarter:{key:"quarterly",label:"Quarterly"},year:{key:"yearly",label:"Yearly"}},de=["day","week","month","quarter","year"];function pe(p){return p.slice(p.lastIndexOf("/")+1).replace(/\.[^/.]+$/,"")}var O=1e4;function ee(p){return p instanceof Error?p.message:String(p)}function B(p,d){return d?p.format(d):""} diff --git a/manifest.json b/manifest.json index 408b3bc..e1d67a2 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "id": "waypoint-sidebar", "name": "Waypoint Sidebar", "version": "1.7.0", - "minAppVersion": "1.4.4", + "minAppVersion": "1.4.10", "description": "Calendar, recent files, and custom bookmarks sidebar.", "author": "Olivier", "isDesktopOnly": false diff --git a/src/main.ts b/src/main.ts index 0809dac..a2a2443 100644 --- a/src/main.ts +++ b/src/main.ts @@ -61,14 +61,26 @@ export default class WaypointPlugin extends Plugin { /** Results for the displayed month; invalidated by markdown-file changes. */ private dateSystemIndicators: Map | null = null; private dateSystemIndicatorKey = ''; + /** + * True once `data.json` carries the post-migration schema. Set on every + * load and included in every save, so a single migration run is durable + * even if this session never triggers another settings write. + */ + private indicatorModeMigrated = false; async onload(): Promise { console.debug('Waypoint: loading plugin v' + this.manifest.version); // Load persisted data — data.json is read exactly once here. const saved = await this.loadData() as Record | null; - this.applySettings(saved); + const migrated = this.applySettings(saved); this.applyWaypointData(saved); + if (migrated) { + // Persist immediately: an install that only ever reads data.json + // (never changes a setting or bookmark this session) must still + // keep the migrated value instead of re-migrating every load. + void this.persistAll(); + } // Register the sidebar view this.registerView( @@ -245,9 +257,11 @@ export default class WaypointPlugin extends Plugin { /** * Merge persisted settings over the defaults. Nested objects are merged * individually so existing configs keep their values while picking up - * fields added in newer versions. + * fields added in newer versions. Returns true the one time a one-off + * migration (see `indicatorModeMigrated` below) actually changes a value, + * so the caller can persist that change immediately. */ - private applySettings(saved: Record | null): void { + private applySettings(saved: Record | null): boolean { const s = (saved?.settings || {}) as Partial; this.settings = Object.assign({}, DEFAULT_SETTINGS, s); this.settings.recentFiles = Object.assign({}, DEFAULT_SETTINGS.recentFiles, s.recentFiles || {}); @@ -267,6 +281,22 @@ export default class WaypointPlugin extends Plugin { return Object.assign({}, builtIn || DEFAULT_DATE_SYSTEM, sys); }) : DEFAULT_SETTINGS.dateSystems.map(sys => Object.assign({}, sys)); + + // `indicatorMode` shipped with a default of 'any' before per-system + // colours existed, so every install that loaded before that default + // changed silently persisted 'any' to disk as if it were a deliberate + // choice — changing DEFAULT_SETTINGS alone can never reach an install + // that already has an explicit value on disk. Promote that one-time + // default to the current default exactly once; any choice made after + // this flag is set is real and must never be touched again. + const alreadyMigrated = saved?.indicatorModeMigrated === true; + let didMigrateValue = false; + if (!alreadyMigrated && s.calendar?.indicatorMode === 'any') { + this.settings.calendar.indicatorMode = 'systems'; + didMigrateValue = true; + } + this.indicatorModeMigrated = true; + return didMigrateValue; } private applyWaypointData(saved: Record | null): void { @@ -301,6 +331,7 @@ export default class WaypointPlugin extends Plugin { return this.saveData({ settings: this.settings, waypointData: this.waypointData, + indicatorModeMigrated: this.indicatorModeMigrated, }); }); // Keep the queue usable after a failed write without leaving an diff --git a/src/settings-tab.ts b/src/settings-tab.ts index 8c56cdf..6494d2a 100644 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -1,8 +1,36 @@ -import { Setting, PluginSettingTab, App, setIcon } from 'obsidian'; +import { Setting, PluginSettingTab, App, setIcon, AbstractInputSuggest, TFile } from 'obsidian'; import type WaypointPlugin from 'src/main'; import { WaypointSettings, DEFAULT_SETTINGS, DEFAULT_DATE_SYSTEM, PeriodNoteSettings } from 'src/settings'; import { formatHasDateToken } from 'src/utils/date-systems'; +/** + * Vault-wide Markdown-file suggester for template-path fields, matching + * Obsidian's native suggest popup (same base class Templater's own template + * pickers use) rather than the browser's unstyled `` dropdown. + */ +class TemplateFileSuggest extends AbstractInputSuggest { + constructor(app: App, private inputEl: HTMLInputElement) { + super(app, inputEl); + } + + getSuggestions(query: string): TFile[] { + const q = query.toLowerCase(); + return this.app.vault.getMarkdownFiles() + .filter(file => file.path.toLowerCase().includes(q)) + .slice(0, 200); + } + + renderSuggestion(file: TFile, el: HTMLElement): void { + el.setText(file.path.replace(/\.md$/, '')); + } + + selectSuggestion(file: TFile): void { + this.setValue(file.path.replace(/\.md$/, '')); + this.inputEl.trigger('input'); + this.close(); + } +} + export class WaypointSettingTab extends PluginSettingTab { private plugin: WaypointPlugin; private settings: WaypointSettings; @@ -129,20 +157,14 @@ export class WaypointSettingTab extends PluginSettingTab { // ═══════════════════════════════ private renderPeriodicTab(container: HTMLElement): void { - const templateSuggestionsId = this.createTemplateSuggestions(container); - this.addPeriodNoteSettings(container, 'Daily', this.settings.daily, templateSuggestionsId); - this.addPeriodNoteSettings(container, 'Weekly', this.settings.weekly, templateSuggestionsId); - this.addPeriodNoteSettings(container, 'Monthly', this.settings.monthly, templateSuggestionsId); - this.addPeriodNoteSettings(container, 'Quarterly', this.settings.quarterly, templateSuggestionsId); - this.addPeriodNoteSettings(container, 'Yearly', this.settings.yearly, templateSuggestionsId); + this.addPeriodNoteSettings(container, 'Daily', this.settings.daily); + this.addPeriodNoteSettings(container, 'Weekly', this.settings.weekly); + this.addPeriodNoteSettings(container, 'Monthly', this.settings.monthly); + this.addPeriodNoteSettings(container, 'Quarterly', this.settings.quarterly); + this.addPeriodNoteSettings(container, 'Yearly', this.settings.yearly); } - private addPeriodNoteSettings( - container: HTMLElement, - label: string, - period: PeriodNoteSettings, - templateSuggestionsId: string, - ): void { + private addPeriodNoteSettings(container: HTMLElement, label: string, period: PeriodNoteSettings): void { new Setting(container).setHeading().setName(label); new Setting(container) @@ -175,7 +197,7 @@ export class WaypointSettingTab extends PluginSettingTab { .addText((text) => { text.setPlaceholder('Templates/Daily note'); text.setValue(period.templateFile); - text.inputEl.setAttr('list', templateSuggestionsId); + new TemplateFileSuggest(this.app, text.inputEl); text.onChange((value) => { period.templateFile = value; this.saveAndRefresh(); @@ -211,8 +233,6 @@ export class WaypointSettingTab extends PluginSettingTab { .setName('Date systems') .setDesc(intro); - const templateSuggestionsId = this.createTemplateSuggestions(container); - this.settings.dateSystems.forEach((system, i, arr) => { new Setting(container) .setHeading() @@ -279,7 +299,7 @@ export class WaypointSettingTab extends PluginSettingTab { this.addSystemTextSetting(container, 'Template file', 'Path to the template file. The .md extension is optional.', - system, 'templateFile', 'resources/template/journal', templateSuggestionsId, + system, 'templateFile', 'resources/template/journal', true, ); this.addSystemTextSetting(container, 'Type property', `Fallback value for the 'type' frontmatter property, used when no template is found.`, @@ -327,7 +347,7 @@ export class WaypointSettingTab extends PluginSettingTab { obj: Record, key: K, placeholder: string, - templateSuggestionsId?: string, + suggestTemplates?: boolean, ): Setting { return new Setting(container) .setName(name) @@ -335,7 +355,7 @@ export class WaypointSettingTab extends PluginSettingTab { .addText((text) => { text.setPlaceholder(placeholder); text.setValue(obj[key]); - if (templateSuggestionsId) text.inputEl.setAttr('list', templateSuggestionsId); + if (suggestTemplates) new TemplateFileSuggest(this.app, text.inputEl); text.onChange((value) => { obj[key] = value; this.saveAndRefresh(); @@ -343,22 +363,6 @@ export class WaypointSettingTab extends PluginSettingTab { }); } - /** - * Native datalist keeps template paths searchable without another custom - * modal, and accepts templates stored anywhere in the vault. - */ - private createTemplateSuggestions(container: HTMLElement): string { - const id = 'waypoint-template-suggestions'; - const list = container.createEl('datalist', { attr: { id } }); - const paths = this.app.vault.getMarkdownFiles() - .map(file => file.path.replace(/\.md$/, '')) - .sort((a, b) => a.localeCompare(b)); - for (const path of paths) { - list.createEl('option', { value: path }); - } - return id; - } - // ═══════════════════════════════ // Recent Files tab // ═══════════════════════════════