1
0
Fork 0

initial creation

This commit is contained in:
KemoNine 2024-12-03 18:58:57 -05:00
commit aa09d69012
45 changed files with 39017 additions and 0 deletions

1
.gitignote Normal file
View file

@ -0,0 +1 @@
.trash

17
.obsidian/app.json vendored Normal file
View file

@ -0,0 +1,17 @@
{
"livePreview": false,
"autoPairBrackets": false,
"autoPairMarkdown": false,
"trashOption": "local",
"alwaysUpdateLinks": true,
"newLinkFormat": "absolute",
"useMarkdownLinks": true,
"showUnsupportedFiles": true,
"mobileQuickRibbonItem": "command-palette:Open command palette",
"mobileToolbarCommands": [
"command-palette:open",
"editor:undo",
"editor:redo",
"editor:configure-toolbar"
]
}

5
.obsidian/appearance.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"interfaceFontFamily": "Atkinson Hyperlegible",
"textFontFamily": "Atkinson Hyperlegible",
"monospaceFontFamily": "DejaVu Sans Mono"
}

6
.obsidian/command-palette.json vendored Normal file
View file

@ -0,0 +1,6 @@
{
"pinned": [
"templater-obsidian:create-_Templates/Habit.md",
"obsidian-trash-explorer:show-trash-explorer"
]
}

9
.obsidian/community-plugins.json vendored Normal file
View file

@ -0,0 +1,9 @@
[
"colored-tags-wrangler",
"folder-notes",
"waypoint",
"obsidian-trash-explorer",
"templater-obsidian",
"dataview",
"automatic-table-of-contents"
]

30
.obsidian/core-plugins.json vendored Normal file
View file

@ -0,0 +1,30 @@
{
"file-explorer": true,
"global-search": false,
"switcher": false,
"graph": false,
"backlink": false,
"canvas": false,
"outgoing-link": false,
"tag-pane": false,
"properties": false,
"page-preview": false,
"daily-notes": false,
"templates": false,
"note-composer": false,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": false,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": false,
"word-count": false,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": false
}

View file

@ -0,0 +1,303 @@
let Plugin = class {}
let MarkdownRenderer = {}
let MarkdownRenderChild = class {}
let htmlToMarkdown = (html) => html
if (isObsidian()) {
const obsidian = require('obsidian')
Plugin = obsidian.Plugin
MarkdownRenderer = obsidian.MarkdownRenderer
MarkdownRenderChild = obsidian.MarkdownRenderChild
htmlToMarkdown = obsidian.htmlToMarkdown
}
const codeblockId = 'table-of-contents'
const codeblockIdShort = 'toc'
const availableOptions = {
title: {
type: 'string',
default: '',
comment: '',
},
style: {
type: 'value',
default: 'nestedList',
values: ['nestedList', 'nestedOrderedList', 'inlineFirstLevel'],
comment: 'TOC style (nestedList|nestedOrderedList|inlineFirstLevel)',
},
minLevel: {
type: 'number',
default: 0,
comment: 'Include headings from the specified level',
},
maxLevel: {
type: 'number',
default: 0,
comment: 'Include headings up to the specified level',
},
includeLinks: {
type: 'boolean',
default: true,
comment: 'Make headings clickable',
},
hideWhenEmpty: {
type: 'boolean',
default: false,
comment: 'Hide TOC if no headings are found'
},
debugInConsole: {
type: 'boolean',
default: false,
comment: 'Print debug info in Obsidian console',
},
}
class ObsidianAutomaticTableOfContents extends Plugin {
async onload() {
const handler = (sourceText, element, context) => {
context.addChild(new Renderer(this.app, element, context.sourcePath, sourceText))
}
this.registerMarkdownCodeBlockProcessor(codeblockId, handler)
this.registerMarkdownCodeBlockProcessor(codeblockIdShort, handler)
this.addCommand({
id: 'insert-automatic-table-of-contents',
name: 'Insert table of contents',
editorCallback: onInsertToc,
})
this.addCommand({
id: 'insert-automatic-table-of-contents-docs',
name: 'Insert table of contents (documented)',
editorCallback: onInsertTocWithDocs,
})
}
}
function onInsertToc(editor) {
const markdown = '```' + codeblockId + '\n```'
editor.replaceRange(markdown, editor.getCursor())
}
function onInsertTocWithDocs(editor) {
let markdown = ['```' + codeblockId]
Object.keys(availableOptions).forEach((optionName) => {
const option = availableOptions[optionName]
const comment = option.comment.length > 0 ? ` # ${option.comment}` : ''
markdown.push(`${optionName}: ${option.default}${comment}`)
})
markdown.push('```')
editor.replaceRange(markdown.join('\n'), editor.getCursor())
}
class Renderer extends MarkdownRenderChild {
constructor(app, element, sourcePath, sourceText) {
super(element)
this.app = app
this.element = element
this.sourcePath = sourcePath
this.sourceText = sourceText
}
// Render on load
onload() {
this.render()
this.registerEvent(this.app.metadataCache.on('changed', this.onMetadataChange.bind(this)))
}
// Render on file change
onMetadataChange() {
this.render()
}
render() {
try {
const options = parseOptionsFromSourceText(this.sourceText)
if (options.debugInConsole) debug('Options', options)
const metadata = this.app.metadataCache.getCache(this.sourcePath)
const headings = metadata && metadata.headings ? metadata.headings : []
if (options.debugInConsole) debug('Headings', headings)
const markdown = getMarkdownFromHeadings(headings, options)
if (options.debugInConsole) debug('Markdown', markdown)
this.element.empty()
MarkdownRenderer.renderMarkdown(markdown, this.element, this.sourcePath, this)
} catch(error) {
const readableError = `_💥 Could not render table of contents (${error.message})_`
MarkdownRenderer.renderMarkdown(readableError, this.element, this.sourcePath, this)
}
}
}
function getMarkdownFromHeadings(headings, options) {
const markdownHandlersByStyle = {
nestedList: getMarkdownNestedListFromHeadings,
nestedOrderedList: getMarkdownNestedOrderedListFromHeadings,
inlineFirstLevel: getMarkdownInlineFirstLevelFromHeadings,
}
let titleMarkdown = ''
if (options.title && options.title.length > 0) {
titleMarkdown += options.title + '\n'
}
const markdownHeadings = markdownHandlersByStyle[options.style](headings, options)
if (markdownHeadings === null) {
if (options.hideWhenEmpty) {
return ''
}
return titleMarkdown + '_Table of contents: no headings found_'
}
return titleMarkdown + markdownHeadings
}
function getMarkdownNestedListFromHeadings(headings, options) {
return getMarkdownListFromHeadings(headings, false, options)
}
function getMarkdownNestedOrderedListFromHeadings(headings, options) {
return getMarkdownListFromHeadings(headings, true, options)
}
function getMarkdownListFromHeadings(headings, isOrdered, options) {
const prefix = isOrdered ? '1.' : '-'
const lines = []
const minLevel = options.minLevel > 0
? options.minLevel
: Math.min(...headings.map((heading) => heading.level))
headings.forEach((heading) => {
if (heading.level < minLevel) return
if (options.maxLevel > 0 && heading.level > options.maxLevel) return
lines.push(`${'\t'.repeat(heading.level - minLevel)}${prefix} ${getMarkdownHeading(heading, options)}`)
})
return lines.length > 0 ? lines.join('\n') : null
}
function getMarkdownInlineFirstLevelFromHeadings(headings, options) {
const minLevel = options.minLevel > 0
? options.minLevel
: Math.min(...headings.map((heading) => heading.level))
const items = headings
.filter((heading) => heading.level === minLevel)
.map((heading) => {
return getMarkdownHeading(heading, options)
})
return items.length > 0 ? items.join(' | ') : null
}
function getMarkdownHeading(heading, options) {
const stripMarkdown = (text) => {
text = text.replaceAll('*', '').replaceAll('_', '').replaceAll('`', '')
text = text.replaceAll('==', '').replaceAll('~~', '')
text = text.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Strip markdown links
return text
}
const stripHtml = (text) => stripMarkdown(htmlToMarkdown(text))
const stripWikilinks = (text, isForLink) => {
// Strip [[link|text]] format
// For the text part of the final link we only keep "text"
// For the link part we need the text + link
// Example: "# Some [[file.md|heading]]" must be translated to "[[#Some file.md heading|Some heading]]"
text = text.replace(/\[\[([^\]]+)\|([^\]]+)\]\]/g, isForLink ? '$1 $2' : '$2')
text = text.replace(/\[\[([^\]]+)\]\]/g, '$1') // Strip [[link]] format
// Replace malformed links & reserved wikilinks chars
text = text.replaceAll('[[', '').replaceAll('| ', isForLink ? '' : '- ').replaceAll('|', isForLink ? ' ' : '-')
return text
}
const stripTags = (text) => text.replaceAll('#', '')
if (options.includeLinks) {
// Remove markdown, HTML & wikilinks from text for readability, as they are not rendered in a wikilink
let text = heading.heading
text = stripMarkdown(text)
text = stripHtml(text)
text = stripWikilinks(text, false)
// Remove wikilinks & tags from link or it won't be clickable (on the other hand HTML & markdown must stay)
let link = heading.heading
link = stripWikilinks(link, true)
link = stripTags(link)
// Return wiklink style link
return `[[#${link}|${text}]]`
// Why not markdown links? Because even if it looks like the text part would have a better compatibility
// with complex headings (as it would support HTML, markdown, etc) the link part is messy,
// because it requires some encoding that looks buggy and undocumented; official docs state the link must be URL encoded
// (https://help.obsidian.md/Linking+notes+and+files/Internal+links#Supported+formats+for+internal+links)
// but it doesn't work properly, example: "## Some <em>heading</em> with simple HTML" must be encoded as:
// [Some <em>heading</em> with simple HTML](#Some%20<em>heading</em>%20with%20simpler%20HTML)
// and not
// [Some <em>heading</em> with simple HTML](#Some%20%3Cem%3Eheading%3C%2Fem%3E%20with%20simpler%20HTML)
// Also it won't be clickable at all if the heading contains #tags or more complex HTML
// (example: ## Some <em style="background: red">heading</em> #with-a-tag)
// (unless there is a way to encode these use cases that I didn't find)
}
return heading.heading
}
function parseOptionsFromSourceText(sourceText = '') {
const options = {}
Object.keys(availableOptions).forEach((option) => {
options[option] = availableOptions[option].default
})
sourceText.split('\n').forEach((line) => {
const option = parseOptionFromSourceLine(line)
if (option !== null) {
options[option.name] = option.value
}
})
return options
}
function parseOptionFromSourceLine(line) {
const matches = line.match(/([a-zA-Z0-9._ ]+):(.*)/)
if (line.startsWith('#') || !matches) return null
const possibleName = matches[1].trim()
const optionParams = availableOptions[possibleName]
let possibleValue = matches[2].trim()
if (!optionParams || optionParams.type !== 'string') {
// Strip comments from values except for strings (as a string may contain markdown)
possibleValue = possibleValue.replace(/#[^#]*$/, '').trim()
}
const valueError = new Error(`Invalid value for \`${possibleName}\``)
if (optionParams && optionParams.type === 'number') {
const value = parseInt(possibleValue)
if (value < 0) throw valueError
return { name: possibleName, value }
}
if (optionParams && optionParams.type === 'boolean') {
if (!['true', 'false'].includes(possibleValue)) throw valueError
return { name: possibleName, value: possibleValue === 'true' }
}
if (optionParams && optionParams.type === 'value') {
if (!optionParams.values.includes(possibleValue)) throw valueError
return { name: possibleName, value: possibleValue }
}
if (optionParams && optionParams.type === 'string') {
return { name: possibleName, value: possibleValue }
}
return null
}
function debug(type, data) {
console.log(...[
`%cAutomatic Table Of Contents %c${type}:\n`,
'color: orange; font-weight: bold',
'font-weight: bold',
data,
])
}
function isObsidian() {
if (typeof process !== 'object') {
return true // Obsidian mobile doesn't have a global process object
}
return !process.env || !process.env.JEST_WORKER_ID // Jest runtime is not Obsidian
}
if (isObsidian()) {
module.exports = ObsidianAutomaticTableOfContents
} else {
module.exports = {
parseOptionsFromSourceText,
getMarkdownFromHeadings,
}
}
/* nosourcemap */

View file

@ -0,0 +1,10 @@
{
"id": "automatic-table-of-contents",
"name": "Automatic Table Of Contents",
"version": "1.5.0",
"minAppVersion": "1.3.0",
"description": "Create a table of contents in a note, that updates itself when the note changes",
"author": "Johan Satgé",
"authorUrl": "https://github.com/johansatge",
"isDesktopOnly": false
}

View file

@ -0,0 +1,90 @@
{
"TagColors": {
"ColorPicker": [
{
"tag_name": "Habit1",
"color": {
"r": 251,
"g": 0,
"b": 255
},
"background_color": {
"r": 100,
"g": 100,
"b": 100
},
"luminance_offset": 0.15
},
{
"tag_name": "Habit2",
"color": {
"r": 0,
"g": 213,
"b": 255
},
"background_color": {
"r": 100,
"g": 100,
"b": 100
},
"luminance_offset": 0.15
}
],
"EnableMultipleTags": true,
"EnableSeparateBackground": true,
"EnableBackgroundOpacity": false,
"Values": {
"BackgroundOpacity": 0.45,
"LuminanceOffset": 0.15
}
},
"CSS": {
"NoteTags": true,
"NoteProperties": true,
"NoteBackgrounds": false,
"TagsNoWrap": true,
"TagsNoWrapText": "pre"
},
"FolderNote": {
"Enable": false,
"FolderTagLinks": [],
"EnableAutoDetect": true,
"EnableBackgroundOpacity": false,
"Values": {
"BackgroundOpacity": 0.45,
"ForceImportant": true,
"BorderRadius": "12px",
"Padding": "5px"
}
},
"Kanban": {
"Enable": false,
"EnableCards": false,
"EnableLists": false,
"HideHashtags": false,
"EnableBackgroundOpacity": false,
"Values": {
"BackgroundOpacity": 0.45,
"CardBackgroundOpacity": 0.2,
"CardBorderOpacity": 0.3,
"ListBackgroundOpacity": 0.2,
"ListBorderOpacity": 0.3
}
},
"Canvas": {
"Enable": false,
"EnableBackgroundOpacity": false,
"Values": {
"BackgroundOpacity": 0.45,
"CardBorderOpacity": 0.3,
"CardBackgroundLuminanceOffset": 0.15
}
},
"Debug": {
"Enable": false,
"EnableExperimentalCommands": false
},
"Info": {
"SettingsVersion": 14
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
{
"id": "colored-tags-wrangler",
"name": "Colored Tags Wrangler",
"version": "0.19.3",
"minAppVersion": "0.15.0",
"description": "Assign colors to tags. Has integrations with other plugins, like Kanban.",
"author": "AndreasSasDev",
"authorUrl": "https://github.com/AndreasSas",
"fundingUrl": "https://ko-fi.com/andreassasdev",
"isDesktopOnly": false
}

View file

@ -0,0 +1,14 @@
/* Text area for Multi Tags */
.cwt-settings-tab .setting-item:has(textarea)>.setting-item-info {
display: none;
}
.cwt-settings-tab textarea {
width: 100%;
}
.cwt-setting-tags .setting-item-control:nth-child(-n+4) {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}

27
.obsidian/plugins/dataview/data.json vendored Normal file
View file

@ -0,0 +1,27 @@
{
"renderNullAs": "\\-",
"taskCompletionTracking": false,
"taskCompletionUseEmojiShorthand": false,
"taskCompletionText": "completion",
"taskCompletionDateFormat": "yyyy-MM-dd",
"recursiveSubTaskCompletion": false,
"warnOnEmptyResult": true,
"refreshEnabled": true,
"refreshInterval": 2500,
"defaultDateFormat": "yyyy-MM-dd",
"defaultDateTimeFormat": "yyyy-MM-dd hh:mm",
"maxRecursiveRenderDepth": 4,
"tableIdColumnName": "File",
"tableGroupColumnName": "Group",
"showResultCount": false,
"allowHtml": true,
"inlineQueryPrefix": "=",
"inlineJsQueryPrefix": "$=",
"inlineQueriesInCodeblocks": false,
"enableInlineDataview": false,
"enableDataviewJs": true,
"enableInlineDataviewJs": false,
"prettyRenderInlineFields": false,
"prettyRenderInlineFieldsInLivePreview": false,
"dataviewJsKeyword": "dataviewjs"
}

20725
.obsidian/plugins/dataview/main.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,11 @@
{
"id": "dataview",
"name": "Dataview",
"version": "0.5.67",
"minAppVersion": "0.13.11",
"description": "Complex data views for the data-obsessed.",
"author": "Michael Brenan <blacksmithgu@gmail.com>",
"authorUrl": "https://github.com/blacksmithgu",
"helpUrl": "https://blacksmithgu.github.io/obsidian-dataview/",
"isDesktopOnly": false
}

146
.obsidian/plugins/dataview/styles.css vendored Normal file
View file

@ -0,0 +1,146 @@
/** Live Preview padding fixes, specifically for DataviewJS custom HTML elements. */
.is-live-preview .block-language-dataviewjs > p, .is-live-preview .block-language-dataviewjs > span {
line-height: 1.0;
}
.block-language-dataview {
overflow-y: auto;
}
/*****************/
/** Table Views **/
/*****************/
/* List View Default Styling; rendered internally as a table. */
.table-view-table {
width: 100%;
}
.table-view-table > thead > tr, .table-view-table > tbody > tr {
margin-top: 1em;
margin-bottom: 1em;
text-align: left;
}
.table-view-table > tbody > tr:hover {
background-color: var(--table-row-background-hover);
}
.table-view-table > thead > tr > th {
font-weight: 700;
font-size: larger;
border-top: none;
border-left: none;
border-right: none;
border-bottom: solid;
max-width: 100%;
}
.table-view-table > tbody > tr > td {
text-align: left;
border: none;
font-weight: 400;
max-width: 100%;
}
.table-view-table ul, .table-view-table ol {
margin-block-start: 0.2em !important;
margin-block-end: 0.2em !important;
}
/** Rendered value styling for any view. */
.dataview-result-list-root-ul {
padding: 0em !important;
margin: 0em !important;
}
.dataview-result-list-ul {
margin-block-start: 0.2em !important;
margin-block-end: 0.2em !important;
}
/** Generic grouping styling. */
.dataview.result-group {
padding-left: 8px;
}
/*******************/
/** Inline Fields **/
/*******************/
.dataview.inline-field-key {
padding-left: 8px;
padding-right: 8px;
font-family: var(--font-monospace);
background-color: var(--background-primary-alt);
color: var(--text-nav-selected);
}
.dataview.inline-field-value {
padding-left: 8px;
padding-right: 8px;
font-family: var(--font-monospace);
background-color: var(--background-secondary-alt);
color: var(--text-nav-selected);
}
.dataview.inline-field-standalone-value {
padding-left: 8px;
padding-right: 8px;
font-family: var(--font-monospace);
background-color: var(--background-secondary-alt);
color: var(--text-nav-selected);
}
/***************/
/** Task View **/
/***************/
.dataview.task-list-item, .dataview.task-list-basic-item {
margin-top: 3px;
margin-bottom: 3px;
transition: 0.4s;
}
.dataview.task-list-item:hover, .dataview.task-list-basic-item:hover {
background-color: var(--text-selection);
box-shadow: -40px 0 0 var(--text-selection);
cursor: pointer;
}
/*****************/
/** Error Views **/
/*****************/
div.dataview-error-box {
width: 100%;
min-height: 150px;
display: flex;
align-items: center;
justify-content: center;
border: 4px dashed var(--background-secondary);
}
.dataview-error-message {
color: var(--text-muted);
text-align: center;
}
/*************************/
/** Additional Metadata **/
/*************************/
.dataview.small-text {
font-size: smaller;
color: var(--text-muted);
margin-left: 3px;
}
.dataview.small-text::before {
content: "(";
}
.dataview.small-text::after {
content: ")";
}

View file

@ -0,0 +1,93 @@
{
"syncFolderName": true,
"ctrlKey": true,
"altKey": false,
"hideFolderNote": true,
"templatePath": "_Templates/Folder Note.md",
"autoCreate": true,
"enableCollapsing": false,
"excludeFolders": [],
"whitelistFolders": [],
"showDeleteConfirmation": true,
"underlineFolder": true,
"stopWhitespaceCollapsing": true,
"underlineFolderInPath": true,
"openFolderNoteOnClickInPath": true,
"openInNewTab": false,
"folderNoteName": "{{folder_name}}",
"folderNoteType": ".md",
"disableFolderHighlighting": false,
"newFolderNoteName": "{{folder_name}}",
"storageLocation": "insideFolder",
"syncDelete": false,
"showRenameConfirmation": true,
"defaultOverview": {
"id": "",
"folderPath": "",
"title": "{{folderName}} overview",
"showTitle": false,
"depth": 3,
"includeTypes": [
"folder",
"markdown"
],
"style": "list",
"disableFileTag": false,
"sortBy": "name",
"sortByAsc": true,
"showEmptyFolders": false,
"onlyIncludeSubfolders": false,
"storeFolderCondition": true,
"showFolderNotes": false,
"disableCollapseIcon": true
},
"useSubmenus": true,
"syncMove": true,
"frontMatterTitle": {
"enabled": false,
"explorer": true,
"path": true
},
"settingsTab": "general",
"supportedFileTypes": [
"md"
],
"boldName": false,
"boldNameInPath": false,
"cursiveName": false,
"cursiveNameInPath": false,
"disableOpenFolderNoteOnClick": false,
"openByClick": true,
"openWithCtrl": false,
"openWithAlt": false,
"excludeFolderDefaultSettings": {
"type": "folder",
"path": "",
"subFolders": true,
"disableSync": true,
"disableAutoCreate": true,
"disableFolderNote": false,
"enableCollapsing": false,
"position": 0,
"excludeFromFolderOverview": false,
"string": "",
"hideInSettings": false
},
"excludePatternDefaultSettings": {
"type": "pattern",
"path": "",
"subFolders": true,
"disableSync": true,
"disableAutoCreate": true,
"disableFolderNote": false,
"enableCollapsing": false,
"position": 0,
"excludeFromFolderOverview": false,
"string": "",
"hideInSettings": false
},
"hideCollapsingIcon": false,
"tabManagerEnabled": true,
"ignoreAttachmentFolder": true,
"deleteFilesAction": "obsidianTrash"
}

5908
.obsidian/plugins/folder-notes/main.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
{
"id": "folder-notes",
"name": "Folder notes",
"version": "1.7.32",
"minAppVersion": "0.15.0",
"description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.",
"author": "Lost Paul",
"authorUrl": "https://github.com/LostPaul",
"fundingUrl": "https://ko-fi.com/paul305844",
"helpUrl": "https://lostpaul.github.io/obsidian-folder-notes/",
"isDesktopOnly": false
}

View file

@ -0,0 +1,273 @@
.fn-whitespace-stop-collapsing .nav-folder-title-content {
flex-grow: 1 !important;
display: flex;
padding-bottom: 4px !important;
padding-top: 4px !important;
}
.version-1-7-2.fn-whitespace-stop-collapsing .nav-files-container .collapse-icon {
padding-top: 4px !important;
}
.mod-rtl .fn-whitespace-stop-collapsing .nav-folder-title-content {
padding-left: 8px !important;
}
.fn-whitespace-stop-collapsing .nav-folder-title {
padding-bottom: 0 !important;
padding-top: 0 !important;
}
body:not(.mod-rtl).fn-whitespace-stop-collapsing .nav-folder-title {
padding-right: 0 !important;
}
.mod-rtl.fn-whitespace-stop-collapsing .nav-folder-title {
padding-left: 0 !important;
}
.fn-whitespace-stop-collapsing .nav-folder-collapse-indicator {
margin-top: 4px !important;
}
body:not(.is-grabbing) .tree-item-self.fn-is-active:hover,
body:not(.disable-folder-highlight) .tree-item-self.fn-is-active {
color: var(--nav-item-color-active);
background-color: var(--nav-item-background-active);
font-weight: var(--nav-item-weight-active);
}
.has-folder-note .nav-folder-title-content:hover,
.has-folder-note.view-header-breadcrumb:hover {
cursor: pointer;
}
.hide-folder-note .is-folder-note {
display: none;
}
.hide-folder .folder-name {
display: none;
}
.nav-folder-collapse-indicator:hover {
cursor: pointer;
}
.fn-excluded-folder-heading {
margin-top: 0 !important;
border-top: 1px solid var(--background-modifier-border);
}
.add-exclude-folder-item {
padding-bottom: 0 !important;
}
.fn-exclude-folder-list {
padding-bottom: 0 !important;
}
.fn-exclude-folder-list.setting-item {
border-top: 0 !important;
border-bottom: 0 !important;
}
.fn-exclude-folder-list .setting-item-control {
display: flex;
justify-content: flex-start !important;
}
.fn-exclude-folder-list .setting-item-info {
display: none !important;
}
.fn-exclude-folder-list .search-input-container {
width: 100%;
}
.fn-confirmation-modal {
padding-bottom: 0;
}
:not(.is-phone) .fn-confirmation-modal-button {
margin-right: 0.7rem;
}
:not(.is-phone) .fn-delete-confirmation-modal-buttons {
display: flex;
align-items: center;
margin-top: 10px;
}
.fn-delete-confirmation-modal-buttons span:hover,
.fn-delete-confirmation-modal-buttons input:hover {
cursor: pointer;
}
:not(.is-phone) .fn-delete-confirmation-modal-buttons .fn-confirmation-modal-button {
margin-left: auto;
}
:not(.is-phone) .fn-delete-confirmation-modal-buttons input[type="checkbox"] {
margin-right: 5px;
}
.is-phone .fn-delete-confirmation-modal-buttons {
display: flex;
flex-direction: column;
align-items: center;
}
.is-phone .fn-delete-confirmation-modal-buttons .fn-confirmation-modal-button {
margin-top: 10px;
}
/* Folder overview */
.fn-folder-overview-collapse-icon {
display: block !important;
}
.fn-has-no-files .collapse-icon {
display: none !important;
}
.folder-overview-list {
margin-top: 0 !important;
margin-bottom: 0 !important;
padding-bottom: 1.200 !important;
padding-top: 1.200 !important;
}
.folder-overview-list-item {
display: flex;
}
.folder-overview-list::marker {
color: var(--text-faint);
}
.folder-list::marker {
color: var(--text-normal) !important;
}
.folder-overview-grid {
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(3, 1fr);
}
.folder-overview-grid-item-article article {
padding: 15px;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.folder-overview-grid-item-article a {
text-decoration: none !important;
}
.folder-overview-grid-item-article h1 {
font-size: 1.2rem;
}
.folder-overview-grid-item {
flex: 1 1 auto;
margin-right: 1.200rem;
margin-bottom: 1.200rem;
}
.fn-confirmation-modal .setting-item {
border-top: 0 !important;
padding-top: 0 !important;
}
.pointer-cursor {
cursor: pointer !important;
}
/* Setting tab style */
.fn-settings-tab-bar {
display: flex;
flex-direction: row;
padding-bottom: 1rem;
}
.fn-settings-tab {
display: flex;
flex-direction: row;
align-items: center;
gap: var(--size-4-2);
padding: 10px;
border: 1px solid var(--background-modifier-border)
}
.fn-settings-tab-active {
background-color: var(--color-accent);
color: var(--text-on-accent);
}
.fn-settings-tab-name {
font-weight: bold;
}
.fn-settings-tab-icon {
display: flex;
}
/* File explorer & path styles */
.folder-note-underline .has-folder-note .nav-folder-title-content {
text-decoration-line: underline;
text-decoration-color: var(--text-faint);
text-decoration-thickness: 2px;
text-underline-offset: 1px;
}
.folder-note-underline-path .has-folder-note.view-header-breadcrumb {
text-decoration-line: underline;
text-decoration-color: var(--text-faint);
text-decoration-thickness: 1px;
text-underline-offset: 2px;
}
.folder-note-bold .has-folder-note .nav-folder-title-content,
.folder-note-bold-path .has-folder-note.view-header-breadcrumb {
font-weight: bold;
}
.folder-note-cursive .has-folder-note .nav-folder-title-content,
.folder-note-cursive-path .has-folder-note.view-header-breadcrumb {
font-style: italic;
}
.fn-hide-collapse-icon .has-folder-note.only-has-folder-note .tree-item-icon {
display: none;
}
.fn-hide-empty-collapse-icon .fn-empty-folder .tree-item-icon {
display: none;
}
/* .fn-suggestion-container {
position: absolute;
overflow: hidden;
display: flex;
flex-direction: column;
background-color: var(--background-primary);
max-width: 500px;
max-height: 300px;
border-radius: var(--radius-m);
border: 1px solid var(--background-modifier-border);
box-shadow: var(--shadow-s);
z-index: var(--layer-notice);
} */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
{
"id": "obsidian-trash-explorer",
"name": "Trash Explorer",
"version": "1.2.3",
"minAppVersion": "0.15.0",
"description": "Restore and delete files from the Obsidian .trash folder",
"author": "Per Mortensen",
"authorUrl": "https://permortensen.com",
"isDesktopOnly": false
}

View file

@ -0,0 +1,38 @@
{
"command_timeout": 5,
"templates_folder": "_Templates",
"templates_pairs": [
[
"",
""
]
],
"trigger_on_file_creation": true,
"auto_jump_to_cursor": false,
"enable_system_commands": false,
"shell_path": "",
"user_scripts_folder": "",
"enable_folder_templates": false,
"folder_templates": [
{
"folder": "",
"template": ""
}
],
"enable_file_templates": false,
"file_templates": [
{
"regex": ".*",
"template": ""
}
],
"syntax_highlighting": true,
"syntax_highlighting_mobile": false,
"enabled_templates_hotkeys": [
"_Templates/Habit.md",
"_Templates/Folder Note.md"
],
"startup_templates": [
""
]
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,11 @@
{
"id": "templater-obsidian",
"name": "Templater",
"version": "2.9.1",
"description": "Create and use templates",
"minAppVersion": "1.5.0",
"author": "SilentVoid",
"authorUrl": "https://github.com/SilentVoid13",
"helpUrl": "https://silentvoid13.github.io/Templater/",
"isDesktopOnly": false
}

View file

@ -0,0 +1,220 @@
.templater_search {
width: calc(100% - 20px);
}
.templater_div {
border-top: 1px solid var(--background-modifier-border);
}
.templater_div > .setting-item {
border-top: none !important;
align-self: center;
}
.templater_div > .setting-item > .setting-item-control {
justify-content: space-around;
padding: 0;
width: 100%;
}
.templater_div
> .setting-item
> .setting-item-control
> .setting-editor-extra-setting-button {
align-self: center;
}
.templater_donating {
margin: 10px;
}
.templater_title {
margin: 0;
padding: 0;
margin-top: 5px;
text-align: center;
}
.templater_template {
align-self: center;
margin-left: 5px;
margin-right: 5px;
width: 70%;
}
.templater_cmd {
margin-left: 5px;
margin-right: 5px;
font-size: 14px;
width: 100%;
}
.templater_div2 > .setting-item {
align-content: center;
justify-content: center;
}
.templater-prompt-div {
display: flex;
}
.templater-prompt-form {
display: flex;
flex-grow: 1;
}
.templater-prompt-input {
flex-grow: 1;
}
.templater-button-div {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 1rem;
}
textarea.templater-prompt-input {
height: 10rem;
}
textarea.templater-prompt-input:focus {
border-color: var(--interactive-accent);
}
.cm-s-obsidian .templater-command-bg {
left: 0px;
right: 0px;
background-color: var(--background-primary-alt);
}
.cm-s-obsidian .cm-templater-command {
font-size: 0.85em;
font-family: var(--font-monospace);
line-height: 1.3;
}
.cm-s-obsidian .templater-inline .cm-templater-command {
background-color: var(--background-primary-alt);
}
.cm-s-obsidian .cm-templater-command.cm-templater-opening-tag {
font-weight: bold;
}
.cm-s-obsidian .cm-templater-command.cm-templater-closing-tag {
font-weight: bold;
}
.cm-s-obsidian .cm-templater-command.cm-templater-interpolation-tag {
color: var(--code-property, #008bff);
}
.cm-s-obsidian .cm-templater-command.cm-templater-execution-tag {
color: var(--code-function, #c0d700);
}
.cm-s-obsidian .cm-templater-command.cm-keyword {
color: var(--code-keyword, #00a7aa);
font-weight: normal;
}
.cm-s-obsidian .cm-templater-command.cm-atom {
color: var(--code-normal, #f39b35);
}
.cm-s-obsidian .cm-templater-command.cm-value,
.cm-s-obsidian .cm-templater-command.cm-number,
.cm-s-obsidian .cm-templater-command.cm-type {
color: var(--code-value, #a06fca);
}
.cm-s-obsidian .cm-templater-command.cm-def,
.cm-s-obsidian .cm-templater-command.cm-type.cm-def {
color: var(--code-normal, var(--text-normal));
}
.cm-s-obsidian .cm-templater-command.cm-property,
.cm-s-obsidian .cm-templater-command.cm-property.cm-def,
.cm-s-obsidian .cm-templater-command.cm-attribute {
color: var(--code-function, #98e342);
}
.cm-s-obsidian .cm-templater-command.cm-variable,
.cm-s-obsidian .cm-templater-command.cm-variable-2,
.cm-s-obsidian .cm-templater-command.cm-variable-3,
.cm-s-obsidian .cm-templater-command.cm-meta {
color: var(--code-property, #d4d4d4);
}
.cm-s-obsidian .cm-templater-command.cm-callee,
.cm-s-obsidian .cm-templater-command.cm-operator,
.cm-s-obsidian .cm-templater-command.cm-qualifier,
.cm-s-obsidian .cm-templater-command.cm-builtin {
color: var(--code-operator, #fc4384);
}
.cm-s-obsidian .cm-templater-command.cm-tag {
color: var(--code-tag, #fc4384);
}
.cm-s-obsidian .cm-templater-command.cm-comment,
.cm-s-obsidian .cm-templater-command.cm-comment.cm-tag,
.cm-s-obsidian .cm-templater-command.cm-comment.cm-attribute {
color: var(--code-comment, #696d70);
}
.cm-s-obsidian .cm-templater-command.cm-string,
.cm-s-obsidian .cm-templater-command.cm-string-2 {
color: var(--code-string, #e6db74);
}
.cm-s-obsidian .cm-templater-command.cm-header,
.cm-s-obsidian .cm-templater-command.cm-hr {
color: var(--code-keyword, #da7dae);
}
.cm-s-obsidian .cm-templater-command.cm-link {
color: var(--code-normal, #696d70);
}
.cm-s-obsidian .cm-templater-command.cm-error {
border-bottom: 1px solid #c42412;
}
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}

17
.obsidian/plugins/waypoint/data.json vendored Normal file
View file

@ -0,0 +1,17 @@
{
"waypointFlag": "%% Waypoint %%",
"landmarkFlag": "%% Landmark %%",
"stopScanAtFolderNotes": false,
"showFolderNotes": false,
"showNonMarkdownFiles": true,
"debugLogging": false,
"useWikiLinks": true,
"useFrontMatterTitle": false,
"showEnclosingNote": false,
"folderNoteType": "INSIDE_FOLDER",
"ignorePaths": [
""
],
"useSpaces": false,
"numSpaces": 2
}

25
.obsidian/plugins/waypoint/main.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,10 @@
{
"id": "waypoint",
"name": "Waypoint",
"version": "2.1.0",
"minAppVersion": "0.12.0",
"description": "Easily generate dynamic content maps in your folder notes using waypoints. Enables folders to show up in the graph view and removes the need for messy tags!",
"author": "Idrees Hassan",
"authorUrl": "https://idreesinc.com",
"isDesktopOnly": false
}

144
.obsidian/workspace-mobile.json vendored Normal file
View file

@ -0,0 +1,144 @@
{
"main": {
"id": "29f7e98b75a28d05",
"type": "split",
"children": [
{
"id": "7058133cf8b8d59b",
"type": "tabs",
"children": [
{
"id": "9b8665f816678326",
"type": "leaf",
"pinned": true,
"state": {
"type": "markdown",
"state": {
"file": "_Dashboard.md",
"mode": "preview",
"backlinks": false,
"source": true
},
"pinned": true,
"icon": "lucide-file",
"title": "_Dashboard"
}
},
{
"id": "1bb5801bd00e9a5c",
"type": "leaf",
"pinned": true,
"state": {
"type": "markdown",
"state": {
"file": "Readme.md",
"mode": "preview",
"backlinks": false,
"source": true
},
"pinned": true,
"icon": "lucide-file",
"title": "Readme"
}
},
{
"id": "2952e2f6dda3b4fa",
"type": "leaf",
"pinned": true,
"state": {
"type": "markdown",
"state": {
"file": "Notes/__Using the vault.md",
"mode": "preview",
"backlinks": false,
"source": true
},
"pinned": true,
"icon": "lucide-file",
"title": "__Using the vault"
}
}
],
"currentTab": 1
}
],
"direction": "vertical"
},
"left": {
"id": "48f8345ad4cb8fea",
"type": "mobile-drawer",
"children": [
{
"id": "8f2e352342b69a27",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {
"sortOrder": "alphabetical"
},
"icon": "lucide-folder-closed",
"title": "Files"
}
},
{
"id": "d7634a21957b3a7c",
"type": "leaf",
"state": {
"type": "trash-explorer",
"state": {},
"icon": "trash",
"title": "Trash explorer"
}
}
],
"currentTab": 0
},
"right": {
"id": "eb3d9e708b3f11bc",
"type": "mobile-drawer",
"children": [],
"currentTab": 0
},
"left-ribbon": {
"hiddenItems": {
"command-palette:Open command palette": false,
"obsidian-trash-explorer:Open trash explorer": false,
"templater-obsidian:Templater": true
}
},
"active": "1bb5801bd00e9a5c",
"lastOpenFiles": [
"Notes/__Using the vault.md",
"_Dashboard.md",
"Readme.md",
"ToDo.md",
"Log/Log.md",
"Habit1 3/Habit1 3.md",
"_Templates/Habit.md",
"Log/Habit1/2024/12/2024-12-02-2233.md",
"Log/Habit1/2024",
"Log/Habit1/2024/12",
"2024/12/2024-12-02-2228.md",
"Log/Habit1/2024/12/2024-12-02-2229.md",
"Habit1/2024/12/2024-12-02-2228.md",
"Habit1/2024",
"Habit1",
"Habit1/2024/12",
"2024",
"2024/12",
"2024/12/2024-12-02-2225.md",
"2024-12-02-2224.md",
"2024-12-02-2221.md",
"2024-12-02-2220.md",
"2024-12-02-2219.md",
"2024/12/.md",
"2024-12-02-2209.md",
"Log/Habit2/2024/12",
"Log/Habit2/2024",
"Log/Habit1/Untitled.md",
"Log/Habit2",
"2024-12-02-2205.md",
"2024-12-02-2202.md",
"2024-12-02-2200.md"
]
}

196
.obsidian/workspace.json vendored Normal file
View file

@ -0,0 +1,196 @@
{
"main": {
"id": "fb35e87f9a0be9e7",
"type": "split",
"children": [
{
"id": "1f7502d5c9b81edf",
"type": "tabs",
"children": [
{
"id": "6eeca8e96c17e911",
"type": "leaf",
"pinned": true,
"state": {
"type": "markdown",
"state": {
"file": "Readme.md",
"mode": "preview",
"backlinks": false,
"source": true
},
"pinned": true,
"icon": "lucide-file",
"title": "Readme"
}
},
{
"id": "cc5977b479080d8b",
"type": "leaf",
"pinned": true,
"state": {
"type": "markdown",
"state": {
"file": "Notes/__Using the vault.md",
"mode": "preview",
"backlinks": false,
"source": true
},
"pinned": true,
"icon": "lucide-file",
"title": "__Using the vault"
}
},
{
"id": "1cb8b268a5f872ae",
"type": "leaf",
"pinned": true,
"state": {
"type": "markdown",
"state": {
"file": "_Dashboard.md",
"mode": "preview",
"backlinks": false,
"source": true
},
"pinned": true,
"icon": "lucide-file",
"title": "_Dashboard"
}
}
]
}
],
"direction": "vertical"
},
"left": {
"id": "d9ee092dacbb149d",
"type": "split",
"children": [
{
"id": "257093ac94fb5fb7",
"type": "tabs",
"children": [
{
"id": "e7fa495ba7f15f1c",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {
"sortOrder": "alphabetical"
},
"icon": "lucide-folder-closed",
"title": "Files"
}
},
{
"id": "dacd4495e5168baf",
"type": "leaf",
"state": {
"type": "trash-explorer",
"state": {},
"icon": "trash",
"title": "Trash explorer"
}
}
]
}
],
"direction": "horizontal",
"width": 300
},
"right": {
"id": "9ae638cd61801c0d",
"type": "split",
"children": [],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"left-ribbon": {
"hiddenItems": {
"command-palette:Open command palette": false,
"templater-obsidian:Templater": true,
"obsidian-trash-explorer:Open trash explorer": false
}
},
"floating": {
"id": "a458b7f91c704e9a",
"type": "floating",
"children": [
{
"id": "a53cb2e8996d36ed",
"type": "window",
"children": [
{
"id": "17fff774f04d07a7",
"type": "tabs",
"children": [
{
"id": "856dc500c0ff7c13",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "_Templates/Folder Note.md",
"mode": "source",
"backlinks": false,
"source": true
},
"icon": "lucide-file",
"title": "Folder Note"
}
}
]
}
],
"direction": "vertical",
"x": 1706,
"y": 0,
"width": 854,
"height": 1400,
"maximize": false,
"zoom": 0
}
]
},
"active": "6eeca8e96c17e911",
"lastOpenFiles": [
"New Text Document.txt",
"Notes/__Using the vault.md",
"_Dashboard.md",
"Readme.md",
"Notes/Notes.md",
"ToDo.md",
"_Templates/Folder Note.md",
"Notes/Untitled.md",
"Log/Habit2/Habit2.md",
"Log/Habit2/2024/2024.md",
"Log/Habit2/2024/12/03/2024-12-03-1708.md",
"Log/Habit2/2024/12/12.md",
"Log/Habit2/2024/12/03/03.md",
"Log/Habit2/2024/12/03",
"Log/Habit2/2024/12",
"Log/Habit2/2024",
"Log/Habit2",
"Untitled/Untitled.md",
"Untitled",
"Log/Habit2/2024/12/03/2024-12-03-1659.md",
"Log/Habit1/2024/2024.md",
"Log/Habit2/2024/12/03/2024-12-03-1657.md",
"Log/Habit2/2024/12/03/2024-12-03-1656.md",
"Log/Habit1/2024/12/12.md",
"Log/Habit1/2024/12/15/15.md",
"Log/Habit2/2024/12/30/30.md",
"Log/Habit1/2024/12/30/30.md",
"Log/Log.md",
"_Templates/_Templates.md",
"Log/Habit1/2023/09/09.md",
"Log/Habit1/2023/09/15/15.md",
"Log/Habit1/2023/09/15",
"Log/Habit1/2023/09/12",
"Log/Habit1/2023/09",
"Log/Habit1/2023/08/15",
"Log/Habit1/2023/08/01"
]
}

6
Log/Log.md Normal file
View file

@ -0,0 +1,6 @@
%% Begin Waypoint %%
%% End Waypoint %%

View file

@ -0,0 +1,19 @@
---
title: "Anti Bad Habit Notebook"
author: "KemoNine"
publishDate: 2018-03-29
---
Not going to lie : I have a few bad habits.
I'm trying to break them but lack a good 'visual cue' for how often I succumb and how bad/good I'm doing.
Whilst poking about the 'tubes the other day I stumbled across Habit Trackers for Bullet Journals (BuJo).
After noodling it for a bit I realized you could make an ANTI BAD Habit BuJo spread.
After talking with many people, it seems having a visual cue for how often you're doing something helps. Same goes for goofy additions (see the red in the above image) that reinforce the positive.
Time to see if this can help me. Feel free to adapt this as you see fit.
![](_attachments/bujo-anti-bad-habit.jpg)

9
Notes/Notes.md Normal file
View file

@ -0,0 +1,9 @@
%% Begin Waypoint %%
- [[__Using the vault]]
- **[[_attachments]]**
- [[_Troubleshooting The Vault]]
- [[2018-03-29-anti-bad-habit-notebook.md]]
%% End Waypoint %%

View file

@ -0,0 +1,13 @@
```table-of-contents
title: Contents
```
## Missing Files / Folders
Sometimes Obsidian won't properly refresh the folder tree when a new entry creates new folders. The only fix seems to be closing and re-opening Obsidian.
## Creating Additional Folders
This vault assumes no folders will be created outside of the `Log` directory. This vault is setup to auto-generate folder notes using a template that assumes new folders will be a sub-directory of the `Log` directory.
If you do need to create a folder outside of the `Log` directory, you'll want to update the auto-generated folder note or the `_Templates/Folder Note.md` file (this latter option is *not* recommended).

View file

@ -0,0 +1,70 @@
```table-of-contents
title: Contents
```
## Inspiration
This vault is based on the [analog Anti Bad Habit Notebook](Notes/2018-03-29-anti-bad-habit-notebook.md.md) [(external link)](https://blog.kemonine.info/blog/2018-03-29-anti-bad-habit-notebook/) that I created long ago. Due to some health hassles, I've had to stop using analog notebooks which has caused me to re-create my analog notebooks within Obsidian. This is one of many such notebook conversions.
## Setup
This vault requires a bit of setup. Below is everything that will need to be done prior to using this vault day to day.
- Edit `_Templates/Habit.md`
- Simply clicking the `_Templates` folder name will give you a link to the `Habits.md` file
- The array of habits needs to be updated: `["Habit1", "Habit2"]`
- The array of units needs to be updated: `["oz", "mg", "cigarette", "beer", "second", "session"]`
- Example: if you have "chewing-nails" habit you can track "sessions" or "time chewing as seconds"
- Add a note for each habit to the `Notes` directory
- Should have the same name as your habit (ie. `Habit1` or `Habit2`)
- Document anything you need to be aware of for this habit, such as:
- Goals
- Withdrawal symptoms
- Edit `_Dashboard.md`
- Update the links so they use your own habits instead of `Habit1`, `Habit2`, etc
- Remove unneeded links as needed (ie. you are only tracking one habit)
- Add any additional links as needed (ie. you are tracking more habits than the examples built into the vault)
- Update the `Colored Tags Wrangler` settings so each habit has it's own color defined
- Remove/replace the existing example habits that are configured
## Vault Layout & Use
- This vault assumes there will be no folders except the `Log` folder and no attachments added to notes
- The `Log` folder...
- Contains a folder tree that looks like `Habit/YYYY/MM/DD`
- Has folder notes for each folder within the tree that give a breakdown of habit information at each level
- Simply click the `Log` folder name and then click the links on each note to drill down
- Log entries should have zero content, just the front matter properties at the top of the note
- The `Notes` folder contains miscellaneous notes and clicking on the folder name will show a list of links, one for each note that's available
- The `_Dashboard` is the starting point of the vault
- It shows a high level overview of each habit so you can track progress "at a glance"
- It has links so you can jump into more detailed areas of the log
- Entered quantities should be *numeric*
- Whole numbers like `0`, `10`
- Decimal fractions like `0.5`, `0.33`, `0.2`
## Why not part of another vault?
This was setup as an independent vault to facilitate fast sync, opening the vault quickly and adding new entries quickly. Including this as part of a larger vault would make it cumbersome and slower to use.
Given this is suppose to help you track a bad habit so you can ultimately break it, this vault was designed around speed and efficiency.
That said, the files created by this vault *can* be copied into another vault if desired. Each note will be tagged with the habit it represents to facilitate use with other vaults.
## Troubleshooting
See the [_Troubleshooting The Vault](Notes/_Troubleshooting%20The%20Vault.md) note for more information.
## Going beyond bad habits
This vault can be helpful beyond simply tracking bad habits. Some additional capabilities of this vault:
- You can track withdrawal symptoms as a faux bad habit
- Setup a habit called "habit1-withdrawl-symptom1" or similar and add entries when you have withdrawal symptoms
- The "unit" can be whatever makes sense for a given withdrawal symptom
- Be sure to keep each withdrawal symptom separate so they are easier to track and trend over time
- You can "flip the script" and use this to develop good habits
- Example: tracking the days you miss taking your meds instead of tracking the days you do take your meds
- This vault can catch "extinction burst" events
- This vault can catch "spontaneous recovery" problems if you "keep it handy" after stopping a habit to track the "rare occasions" you partake of a bad habit even though it's been a long time
- Example: having an annual drink to celebrate the new year despite being sober otherwise

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,6 @@
%% Begin Waypoint %%
- [[A habits main note.png]]
- [[bujo-anti-bad-habit.jpg]]
- [[Directory list.png]]
%% End Waypoint %%

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

34
Readme.md Normal file
View file

@ -0,0 +1,34 @@
## The Anti Bad Habit Notebook
This is a template [Obsidian](https://obsidian.md) vault setup to act as a bad habit tracker. This is a form of the [Analog Anti Bad Habit Notebook](https://blog.kemonine.info/blog/2018-03-29-anti-bad-habit-notebook/) I developed in the past.
## Additional Details
Please see the [\_\_Using The Vault](Notes/__Using%20The%20Vault.md) file for additional detail.
## To use the vault template
- Download the files as a zip file (see below screenshot for detail)
- Extract the zip file
- Rename the folder contained within the zip file if desired
- Open the folder that was extracted in Obsidian as a vault
- Import any existing art as appropriate
- Enjoy
## Licensing
This project is licensed under the [Creative Commons BY-NC 4.0 International](https://creativecommons.org/licenses/by-nc/4.0/) license
## Screenshots
### Directory Listing
![](Notes/_attachments/Directory%20list.png)
### A habits main note
![](Notes/_attachments/A%20habits%20main%20note.png)
### Analog anti bad habit notebook
![](Notes/_attachments/bujo-anti-bad-habit.jpg)

11
_Dashboard.md Normal file
View file

@ -0,0 +1,11 @@
```table-of-contents
title: Contents
```
## Habit1
![](Log/Habit1/Habit1.md)
## Habit2
![](Log/Habit2/Habit2.md)

71
_Templates/Folder Note.md Normal file
View file

@ -0,0 +1,71 @@
<%*
let filename = tp.file.title
let path = tp.file.folder(true)
let splitpath = path.split("/")
let unitindex = 2
if (splitpath.length > 2) { unitindex = 3 }
if (splitpath.length > 3) { unitindex = 4 }
if (path != "Notes" && path != "_Templates" && path != "Log") { %>
```table-of-contents
title: Contents
```
## Chart
<%* if (splitpath.length == 5) { %>
```dataviewjs
let query = `
TABLE WITHOUT ID
habit as habit,
created_ts as time,
unit as unit,
quantity as quantity
WHERE
startswith(file.folder, this.file.folder)
AND quantity != null AND unit != null
`;
let result = await dv.tryQuery(query);
let headers = ["Habit", "Created", "Unit", "Quantity"];
dv.table(result.headers,
dv.array(result.values)
.sort(r => r[2], "asc")
.sort(r => r[1], "desc")
.sort(r => r[0], "asc"));
```
<%* } else { %>
```dataviewjs
let query = `
TABLE WITHOUT ID
nonnull(rows.habit)[0] as habit,
split(rows.file.folder[0], "/")[2] as year,
<%* if (splitpath.length > 2) { %>split(rows.file.folder[0], "/")[3] as month,<%* } %>
<%* if (splitpath.length > 3) { %>split(rows.file.folder[0], "/")[4] as day,<%* } %>
nonnull(rows.unit)[0] as unit,
average(nonnull(rows.quantity)) as qty_avg,
sum(nonnull(rows.quantity)) as qty_tot
WHERE
startswith(file.folder, this.file.folder)
AND file.folder != this.file.folder
AND quantity != null AND unit != null
GROUP BY habit
+ split(file.folder, "/")[2]
<%* if (splitpath.length > 2) { %>+ split(file.folder, "/")[3]<%* } %>
<%* if (splitpath.length > 3) { %>+ split(file.folder, "/")[4]<%* } %>
+ unit
`;
let result = await dv.tryQuery(query);
let headers = ["Habit", "Year",
<%* if (splitpath.length > 2) { %>"Month", <%* } %>
<%* if (splitpath.length > 3) { %>"Day", <%* } %>
"Unit", "qty_avg", "qty_tot"];
dv.table(result.headers,
dv.array(result.values)
.sort(r => r[<% unitindex %>], "asc")
.sort(r => r[1], "desc")
<%* if (splitpath.length > 2) { %>.sort(r => r[2], "desc")<%* } %>
<%* if (splitpath.length > 3) { %>.sort(r => r[3], "desc")<%* } %>
.sort(r => r[0], "asc"));
```
<%* } %>
## Navigation<%* } %>
<%* if (splitpath.length == 3 || splitpath.length == 2) {%><% "%" + "% Landmark %" + "%" %> <%*} else {%><% "%" + "% Waypoint %" + "%" %><%*} %>

17
_Templates/Habit.md Normal file
View file

@ -0,0 +1,17 @@
<%*
let habit = await tp.system.suggester((item) => item, ["Habit1", "Habit2"])
let current_ts = tp.date.now("YYYY-MM-DD HH:mm")
let filename = tp.file.title
if ( filename.startsWith("Untitled") ) {
filename = tp.date.now("YYYY-MM-DD-HHmm")
let path = "/Log/" + habit + tp.date.now("/YYYY/MM/DD/")
await tp.file.move(path + filename)
}
%>---
created_ts: <% current_ts %>
habit: <% habit %>
quantity: <% tp.system.prompt("Quantity", "", true, false) %>
unit: <% tp.system.suggester((item) => item, ["oz", "mg", "cigarette", "beer", "second", "session"]) %>
tags:
- <% habit %>
---

7
_Templates/_Templates.md Normal file
View file

@ -0,0 +1,7 @@
%% Begin Waypoint %%
- [[Folder Note]]
- [[Habit]]
%% End Waypoint %%