├── content ├── snippets │ ├── _index.md │ ├── read-file.md │ ├── adding-css.md │ ├── active-file-path.md │ ├── status-bar-border.md │ ├── retrieve-frontmatter.md │ ├── block-cursor.md │ ├── pdf-export-tweaks.md │ ├── lined-heading.md │ ├── bullet-relations.md │ ├── enlarge-image-on-hover.md │ ├── maintain-line-height-footnotes.md │ ├── bigger-popup-preview.md │ ├── collapsible-sidebars.md │ ├── responsive-type.md │ ├── set embed height.md │ ├── outliner-tree.md │ ├── folder-file-icons.md │ ├── stylish-quotes.md │ ├── vim-mode-line-focus.md │ ├── custom-hr.md │ ├── tag-colors.md │ ├── naked-embeds.md │ ├── display-tags-aside.md │ ├── fade-controls.md │ ├── builtin-icons.md │ ├── changing-fonts.md │ ├── collapsible-side-notes.md │ ├── pane-controls-hover.md │ ├── list-obsidian-commands.md │ ├── dataview-table-as-cards.md │ ├── birthdays.md │ └── people-nearby.md └── resources │ └── _index.md ├── templates ├── page.html ├── resources.html ├── section.html ├── kind │ ├── single.html │ └── list.html ├── tags │ ├── single.html │ └── list.html ├── index.html ├── macros │ ├── section.html │ └── snippet.html └── base.html ├── .github └── workflows │ └── ci.yml ├── config.toml ├── README.md ├── sass ├── search.scss └── styles.scss ├── .gitignore └── static ├── search.js └── reset.css /content/snippets/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Snippets 3 | template: section.html 4 | page_template: page.html 5 | paginate_by: 30 6 | --- -------------------------------------------------------------------------------- /templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% import "macros/snippet.html" as snippet %} 3 | 4 | 5 | {% block content %} 6 | {{snippet::snippet(page=page)}} 7 | {% endblock%} -------------------------------------------------------------------------------- /templates/resources.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
{{section.content | safe }}
6 |
7 | {% endblock%} -------------------------------------------------------------------------------- /templates/section.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% import "macros/section.html" as section %} 3 | 4 | {% block content %} 5 | {% set title = section.title %} 6 | {{section::section(paginator=paginator, title=title)}} 7 | {% endblock%} -------------------------------------------------------------------------------- /content/snippets/read-file.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Read File 3 | date: 2021-05-14 4 | 5 | taxonomies: 6 | tags: 7 | - development 8 | kind: 9 | - plugins 10 | extra: 11 | author: Dustin Knopoff 12 | --- 13 | 14 | ```js 15 | vault.read(file) // where file is a `TFile` 16 | ``` -------------------------------------------------------------------------------- /templates/kind/single.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% import "macros/snippet.html" as snippet %} 3 | {% import "macros/section.html" as section %} 4 | 5 | {% block content %} 6 | {% set title = term.name %} 7 | {{section::section(paginator=paginator, title=title, mono=true)}} 8 | {% endblock%} -------------------------------------------------------------------------------- /templates/tags/single.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% import "macros/snippet.html" as snippet %} 3 | {% import "macros/section.html" as section %} 4 | 5 | {% block content %} 6 | {% set title = term.name %} 7 | {{section::section(paginator=paginator, title=title, mono=true)}} 8 | {% endblock%} -------------------------------------------------------------------------------- /content/snippets/adding-css.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding CSS Snippets 3 | date: 2021-04-15 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | - theming 9 | kind: 10 | - styling 11 | extra: 12 | author: foreveryone 13 | --- 14 | 15 | -------------------------------------------------------------------------------- /content/snippets/active-file-path.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Active File Path 3 | date: 2021-05-14 4 | 5 | taxonomies: 6 | tags: 7 | - dataview 8 | kind: 9 | - plugins 10 | extra: 11 | author: Dustin Knopoff 12 | --- 13 | 14 | ```js 15 | app.workspace.getActiveFile().path // Can be a `string | null` 16 | ``` -------------------------------------------------------------------------------- /content/snippets/status-bar-border.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Status Bar Border 3 | date: 2021-05-21 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: SIRvb 12 | --- 13 | 14 | ```css 15 | .status-bar { 16 | border-left: 1px solid var(--text-normal); 17 | border-top: 1px solid var(--text-normal); 18 | } 19 | ``` -------------------------------------------------------------------------------- /templates/tags/list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |

Tags

4 | 13 | {% endblock%} -------------------------------------------------------------------------------- /templates/kind/list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

Kinds

5 | 14 | {% endblock%} -------------------------------------------------------------------------------- /content/snippets/retrieve-frontmatter.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Retrieving a File's Frontmatter 3 | date: 2021-05-15 4 | 5 | taxonomies: 6 | tags: 7 | - development 8 | kind: 9 | - plugins 10 | extra: 11 | author: Christian 12 | --- 13 | 14 | ```js 15 | if (file instanceof TFile) { 16 | this.app.metadataCache.getFileCache(file).frontmatter; // Is [key: string]: any | undefined 17 | } 18 | ``` -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Build site using Zola 2 | 3 | name: CI 4 | 5 | on: 6 | pull_request: 7 | types: [opened, synchronize, reopened, closed] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Install and Run Zola 16 | run: | 17 | sudo snap install --edge zola 18 | zola build -------------------------------------------------------------------------------- /content/snippets/block-cursor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Block Cursor 3 | date: 2020-06-17 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: rsdimitrov 12 | --- 13 | 14 | ```css 15 | .CodeMirror-cursor { 16 | border-left-width: 0.5em; 17 | opacity: 0.75; 18 | } 19 | ``` 20 | 21 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/9) -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% import "macros/snippet.html" as snippet %} 3 | 4 | {% block content %} 5 | {% set section = get_section(path="snippets/_index.md") %} 6 | {% for year, posts in section.pages | sort(attribute="year") | reverse | group_by(attribute="year") %} 7 |
8 |

{{ year }}

9 | 16 |
17 | {% endfor %} 18 | {% endblock%} -------------------------------------------------------------------------------- /content/snippets/pdf-export-tweaks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PDF Export Tweaks 3 | date: 2021-04-09 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: Mara-Li 11 | --- 12 | 13 | ## Page Break on `---` 14 | 15 | ```css 16 | @media print { 17 | hr { 18 | break-after:page; 19 | visibility: hidden; 20 | } 21 | } 22 | ``` 23 | 24 | ## Prevent Headings from being on bottom of Page 25 | 26 | ```css 27 | @media print { 28 | h1:after, h3:after, h2:after, h4:after, h5:after, h6:after{ 29 | content: ""; 30 | display: block; 31 | height: 100px; 32 | margin-bottom: -100px; 33 | } 34 | } 35 | ``` -------------------------------------------------------------------------------- /content/snippets/lined-heading.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Lined Heading 3 | date: 2021-01-06 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: frvkl 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/3/31bfb6c7a099447639685da0dfac6b5c0d2d714a_2_690x58.png) 14 | 15 | ```css 16 | h1 { 17 | display: flex; 18 | width: 100%; 19 | align-items: center; 20 | } 21 | h1:before, 22 | h1:after{ 23 | content: ''; 24 | background: gray; 25 | height: .1em; 26 | margin: .2em; 27 | flex: 1; 28 | } 29 | ``` 30 | 31 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/288) -------------------------------------------------------------------------------- /content/snippets/bullet-relations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bullet Point Relationship Lines 3 | date: 2020-06-16 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: deathau 12 | --- 13 | 14 | ```css 15 | .cm-hmd-list-indent .cm-tab, ul ul { position: relative; } 16 | .cm-hmd-list-indent .cm-tab::before, ul ul::before { 17 | content:''; 18 | border-left: 1px solid rgba(0, 122, 255, 0.25); 19 | position: absolute; 20 | } 21 | .cm-hmd-list-indent .cm-tab::before { left: 0; top: -5px; bottom: -4px; 22 | } 23 | ul ul::before { left: -11px; top: 0; bottom: 0; 24 | } 25 | 26 | ``` 27 | 28 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/2) -------------------------------------------------------------------------------- /templates/macros/section.html: -------------------------------------------------------------------------------- 1 | {% import "macros/snippet.html" as snippet %} 2 | {% macro section(paginator,title,mono=false) %} 3 |

{{title}}

4 | 5 | 12 | 13 | 21 | {% endmacro%} -------------------------------------------------------------------------------- /content/snippets/enlarge-image-on-hover.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Enlarge Image on Hover 3 | date: 2020-06-28 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: den 12 | --- 13 | 14 | 15 | ```css 16 | .markdown-preview-view img { 17 | display: block; 18 | margin-top: 20pt; 19 | margin-bottom: 20pt; 20 | margin-left: auto; 21 | margin-right: auto; 22 | width: 50%; /* experiment with values */ 23 | transition:transform 0.25s ease; 24 | } 25 | 26 | .markdown-preview-view img:hover { 27 | -webkit-transform:scale(1.8); /* experiment with values */ 28 | transform:scale(2); 29 | 30 | } 31 | 32 | ``` 33 | 34 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/29) -------------------------------------------------------------------------------- /content/snippets/maintain-line-height-footnotes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Maintain Line Height - Footnotes 3 | date: 2021-03-04 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: phlind 11 | --- 12 | 13 | Before: 14 | ![](https://forum.obsidian.md/uploads/default/original/2X/1/1e2c18708833addaf9abcb6dc06d6391f682eb97.png) 15 | 16 | After: 17 | ![](https://forum.obsidian.md/uploads/default/original/2X/3/3aaff87ddbb77e93983f40bf9e120578749e961f.png) 18 | 19 | ```css 20 | /* Stop footnotes affecting line height */ 21 | sup { 22 | vertical-align: top; 23 | position: relative; 24 | top: -0.3em; 25 | font-size: 0.75em; 26 | } 27 | ``` 28 | 29 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/342) -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | # The URL the site will be built for 2 | base_url = "https://obsidian-snippets.pages.dev" 3 | 4 | # Whether to automatically compile all Sass files in the sass directory 5 | compile_sass = true 6 | 7 | # Whether to build a search index to be used later on by a JavaScript library 8 | build_search_index = true 9 | 10 | feed_filename = "rss.xml" 11 | generate_feed = true 12 | 13 | taxonomies = [{name = "tags", rss = true, paginate_by = 30}, {name = "kind", rss = true, paginate_by = 30}] 14 | 15 | title = "Obsidian Snippets" 16 | 17 | [markdown] 18 | # Whether to do syntax highlighting 19 | # Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola 20 | highlight_code = true 21 | 22 | [extra] 23 | # Put all your custom variables here 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Obsidian Snippets 2 | 3 | Go to the [site](https://obsidian-snippets.pages.dev) 4 | 5 | If you'd like to add a snippet, fork this repository. 6 | 7 | Add your file inside `content/snippets` 8 | 9 | Make sure to have the following frontmatter: 10 | 11 | ```yaml 12 | --- 13 | title: # your title 14 | date: # today's date in YYYY-MM-DD format 15 | 16 | taxonomies: 17 | tags: # a list of tags 18 | kind: 19 | - # either: plugins or styling or tips 20 | extra: 21 | author: # your name or handles 22 | --- 23 | ``` 24 | 25 | Then commit and submit a PR to this repository. 26 | 27 | ## How to video from @foreveryone 28 | 29 | [![how to video](https://res.cloudinary.com/dcloudinary/video/upload/v1621627517/pr-example.png)](https://res.cloudinary.com/dcloudinary/video/upload/f_auto/v1621627517/pr-example.webm) 30 | -------------------------------------------------------------------------------- /content/snippets/bigger-popup-preview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bigger Popup Preview 3 | date: 2020-08-07 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: _ph 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/a/ac341460fac4f2ad5f1a9c823dec78e68954cf05_2_243x299.png) 14 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/0/04055fe997efda1e66868a45930a8fce5b992169_2_243x299.png) 15 | 16 | ```css 17 | /*============bigger link popup preview ================*/ 18 | .popover.hover-popover { 19 | transform: scale(0.8); /* makes the content smaller */ 20 | max-height: 800px; /* was 300 */ 21 | min-height: 100px; 22 | width: 500px; /* was 400 */ 23 | } 24 | ``` 25 | 26 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/82) -------------------------------------------------------------------------------- /content/snippets/collapsible-sidebars.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Collapsible Sidebars 3 | date: 2020-06-16 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: cmc2397 12 | --- 13 | 14 | ```css 15 | .workspace-ribbon.is-collapsed:not(:hover) .workspace-ribbon-collapse-btn, 16 | .workspace-ribbon.is-collapsed:not(:hover) .side-dock-actions, 17 | .workspace-ribbon.is-collapsed:not(:hover) .side-dock-settings {display:none;} 18 | .workspace-ribbon.is-collapsed:not(:hover) {width: 0;} 19 | .workspace-split.mod-left-split[style="width: 0px;"] {margin-left: 0;} 20 | .workspace-split.mod-right-split[style="width: 0px;"] {margin-right: 0;} 21 | .workspace-ribbon {transition: none} 22 | ``` 23 | 24 | Thanks to @mrjackphil and @MooddooM 25 | 26 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/3) -------------------------------------------------------------------------------- /content/snippets/responsive-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Responsive Type 3 | date: 2020-12-16 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: Shamama 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/c/c4dc735907db26f6745fc3435e70de42405af4ed_2_690x387.png) 14 | 15 | ```css 16 | :root 17 | { 18 | --font-size-normal: clamp(12px, 5vh, 20px); 19 | --font-size-code: clamp(12px, 5vh, 18px); 20 | --font-size-side-dock: clamp(12px, 5vh, 16px); 21 | --font-size-side-dock-title: clamp(12px, 5vh, 18px); 22 | --font-size-blockquote: clamp(16px, 5vh, 22px); 23 | --font-size-status-bar: clamp(16px, 5vh, 16px); 24 | --font-small: clamp(16px, 5vh, 18px); 25 | --font-medium: clamp(16px, 5vh, 21px); 26 | } 27 | ``` 28 | 29 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/258) -------------------------------------------------------------------------------- /content/snippets/set embed height.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Variable Embed Heights 3 | date: 2020-06-21 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: foreveryone 12 | --- 13 | This snippet will make embeds sit within a text without scrollbars by default. If a link is given the alias `[[short|document]]]` or `![[tall|document]]` it will be set to a limited height and given scroll bars if it exceeds the maximum height. 14 | ```css 15 | .markdown-preview-view .markdown-embed-content { 16 | max-height: unset; 17 | } 18 | 19 | .internal-embed.is-loaded[alt="short"] { 20 | max-height: 45vh !important; 21 | overflow: auto !important; 22 | padding-right: 0px!important; 23 | } 24 | 25 | .internal-embed.is-loaded[alt="tall"] { 26 | max-height: 80vh !important; 27 | overflow: auto !important; 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /content/snippets/outliner-tree.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Outliner for Outliners 3 | date: 2020-12-20 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: Shamama 11 | --- 12 | 13 | ```css 14 | 15 | .collapsible-item-collapse { 16 | padding: 2px 15px 2px 15px; 17 | left:1.5px; 18 | } 19 | div.collapsible-item-inner{ 20 | position:relative; 21 | padding-left: 15px; 22 | 23 | } 24 | .outline .collapsible-item-children { 25 | margin-left: 20px; 26 | border-left: 1px solid rgba(118,158,165,0.2); 27 | border-radius: 4px; 28 | transition:all 0.5s ease-in-out; 29 | } 30 | .outline .collapsible-item-children:hover { 31 | border-left-color: rgba(118,158,165,0.4); 32 | } 33 | ``` 34 | 35 | ![](https://forum.obsidian.md/uploads/default/original/2X/6/6d4e69dc5fea6f4ac779c8a6a559bf33e6a90146.png) -------------------------------------------------------------------------------- /content/snippets/folder-file-icons.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Folder and File Icons in Explorer 3 | date: 2020-09-15 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: deathau 11 | --- 12 | 13 | ```css 14 | .nav-folder-children .nav-file-title-content:first-child::before { content: '🗒 '; } 15 | .nav-folder-children .nav-folder-title-content::before { content: '📂 '; } 16 | ``` 17 | 18 | ## Using Wingdings or [IcoMoon](https://icomoon.io/#icons-icomoon/liga-font) 19 | 20 | ```css 21 | .nav-folder-children .nav-file-title-content:first-child::before { 22 | content: "\e924 "; 23 | font-family: 'IcoMoon-Free'; 24 | } 25 | .nav-folder-children .nav-folder-title-content::before { 26 | content: '\e930 '; 27 | font-family: 'IcoMoon-Free'; 28 | } 29 | ``` 30 | 31 | ![](https://forum.obsidian.md/uploads/default/original/2X/7/79c75764a0400ceff97f36e518c4002b2d2a764a.png) -------------------------------------------------------------------------------- /templates/macros/snippet.html: -------------------------------------------------------------------------------- 1 | {% macro snippet(page, short=false) %} 2 |
3 |
4 | 5 |

{{page.title}}

6 |
7 | {% set tag = page.taxonomies | get(key="kind") | first %} 8 | 9 | 10 | {{tag}} 11 | 12 | 13 |
14 | 23 | 24 |
{{ page.content | safe }}
25 |
26 | {% endmacro %} -------------------------------------------------------------------------------- /content/snippets/stylish-quotes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Stylish Blockquotes 3 | date: 2020-07-04 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: Thery 11 | --- 12 | 13 | ## Add quotation mark before quote 14 | 15 | ![](https://forum.obsidian.md/uploads/default/original/2X/a/a64ba8a02dea06dc2fa741f167d7a18b2b52db07.png) 16 | 17 | ```css 18 | /* Add quotation character before quote */ 19 | blockquote:before { 20 | font: 14px/20px italic Times, serif; 21 | content: "“"; 22 | font-size: 3em; 23 | line-height: 0.1em; 24 | vertical-align: -0.4em; 25 | } 26 | blockquote p { display: inline; } 27 | ``` 28 | 29 | ## Remove left margin 30 | 31 | ![](https://forum.obsidian.md/uploads/default/original/2X/c/ca4834dc2741c16320ec45873105c3d3804fb2a1.png) 32 | 33 | ```css 34 | /* Remove blockquote left margin */ 35 | blockquote { 36 | margin-inline-start: 0; 37 | } 38 | ``` 39 | 40 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/39) -------------------------------------------------------------------------------- /content/snippets/vim-mode-line-focus.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vim Mode Line Focus 3 | date: 2020-06-18 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: MooddooM 12 | --- 13 | 14 | ![](https://forum.obsidian.md/uploads/default/original/2X/7/7f61432e9579a1d9086d1caad3aabfd05c1f0abf.gif) 15 | 16 | ```css 17 | /* Cursor color in normal vim mode and opacity */ 18 | .cm-fat-cursor .CodeMirror-cursor, .cm-animate-fat-cursor { 19 | width: 0.5em; 20 | background: #d65d0e; 21 | opacity: 60% !important; 22 | } 23 | 24 | /*an active line highlight in vim normal mode */ 25 | .cm-fat-cursor .CodeMirror-activeline .CodeMirror-linebackground{ 26 | background-color: rgba(89, 75, 95, 0.99) !important; 27 | } 28 | 29 | /*if you want the highlight to present in both normal and insert mode of vim*/ 30 | .CodeMirror-activeline .CodeMirror-linebackground{ 31 | background-color: rgba(89, 75, 95, 0.99) !important; 32 | } 33 | ``` 34 | 35 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/17) -------------------------------------------------------------------------------- /content/snippets/custom-hr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Symbolic HR Line 3 | date: 2020-10-31 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: TriDiamond 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/3/33b0938f405dde20178572fc09afde697b8f38f7_2_373x500.png) 14 | 15 | ```css 16 | .markdown-preview-view hr { 17 | margin-block-start: 4em; 18 | margin-block-end: 4em; 19 | border: none; 20 | height: 1px; 21 | background-image: linear-gradient(to right, var(--background-primary), var(--text-accent), var(--background-primary)); 22 | } 23 | 24 | .markdown-preview-view hr::after { 25 | content: '§'; 26 | display: inline-block; 27 | position: absolute; 28 | left: 50%; 29 | transform: translate(-50%, -50%) rotate(60deg); 30 | transform-origin: 50% 50%; 31 | padding: 0.5rem; 32 | color: var(--text-sub-accent); 33 | background-color: var(--background-primary); 34 | } 35 | ``` 36 | 37 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/223) -------------------------------------------------------------------------------- /sass/search.scss: -------------------------------------------------------------------------------- 1 | .search-container { 2 | display: inline-block; 3 | position: relative; 4 | width: 300px; 5 | 6 | input { 7 | width: 100%; 8 | padding: 0.5rem; 9 | border-radius: 13px; 10 | border-width: 2px; 11 | border-style: solid; 12 | font-family: var(--monospace); 13 | } 14 | } 15 | 16 | .search-results { 17 | display: none; 18 | position: absolute; 19 | padding: 1rem; 20 | box-shadow: 2px 2px 2px 0 rgba(0, 0, 0, 0.5); 21 | background: white; 22 | border-radius: 13px; 23 | max-height: 500px; 24 | overflow: auto; 25 | width: 150%; 26 | right: 0; 27 | z-index: 100; 28 | 29 | &__items { 30 | list-style: none; 31 | } 32 | 33 | li { 34 | margin-top: 1rem; 35 | border-bottom: 1px solid #ccc; 36 | font-size: 0.9rem; 37 | 38 | &:first-of-type { 39 | margin-top: 0; 40 | } 41 | } 42 | 43 | &__item { 44 | margin-bottom: 1rem; 45 | 46 | a { 47 | font-size: 1.2rem; 48 | display: inline-block; 49 | margin-bottom: 0.5rem; 50 | } 51 | } 52 | } 53 | 54 | @media screen and (max-width: 768px) { 55 | .search-results { 56 | width: 80%; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /content/snippets/tag-colors.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tag Pills 3 | date: 2020-06-17 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: ph_ 12 | --- 13 | 14 | Insert your tag in place of `#obsidian`, `#important`, etc. to set the color specific to a tag. 15 | 16 | ![](https://forum.obsidian.md/uploads/default/original/2X/3/35df313dfde8fdbae555d251831bbc4ae8b51016.png) 17 | 18 | ```css 19 | tag { 20 | background-color: var(--text-accent); 21 | border: none; 22 | color: white; 23 | font-size: 11px; 24 | padding: 1px 8px; 25 | text-align: center; 26 | text-decoration: none; 27 | display: inline-block; 28 | margin: 0px 0px; 29 | cursor: pointer; 30 | border-radius: 14px; 31 | } 32 | .tag:hover { 33 | color: white; 34 | background-color: var(--text-accent-hover); 35 | } 36 | .tag[href^="#obsidian"] { 37 | background-color: #4d3ca6; 38 | } 39 | .tag[href^="#important"] { 40 | background-color: red; 41 | } 42 | .tag[href^="#complete"] { 43 | background-color: green; 44 | } 45 | .tag[href^="#inprogress"] { 46 | background-color: orange; 47 | } 48 | ``` 49 | 50 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/13) -------------------------------------------------------------------------------- /content/snippets/naked-embeds.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Naked Embeds 3 | date: 2020-06-18 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: deathau 12 | --- 13 | 14 | Embeds the contents of linked notes into the preview 15 | 16 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/d/d33d0de07d58894ab485b37c9806ff88a447fb6a_2_690x136.png) 17 | 18 | ```css 19 | /* Naked Embeds */ 20 | .markdown-embed-title { display: none; } 21 | .markdown-preview-view .markdown-embed-content>:first-child { margin-top: 0;} 22 | .markdown-preview-view .markdown-embed-content>:last-child { margin-bottom: 0;} 23 | 24 | /*remove the following two line, you will get border and scroll*/ 25 | .markdown-preview-view .markdown-embed { border:none; padding:0; margin:0; } 26 | .markdown-preview-view .markdown-embed-content { 27 | max-height: unset; 28 | background-color: var(--background-secondary); /*define different bg color*/ 29 | } 30 | 31 | /* the link on the top right corner*/ 32 | .markdown-embed-link { 33 | color: var(--text-faint) !important; 34 | } 35 | 36 | .markdown-embed-link:hover { 37 | color: var(--text-accent) !important; 38 | } 39 | ``` 40 | 41 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/19) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # macOS 3 | ############### 4 | # General 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | .com.apple.timemachine.donotpresent 24 | 25 | # Directories potentially created on remote AFP share 26 | .AppleDB 27 | .AppleDesktop 28 | Network Trash Folder 29 | Temporary Items 30 | .apdisk 31 | 32 | ############### 33 | # Vim 34 | ############### 35 | # Swap 36 | [._]*.s[a-v][a-z] 37 | !*.svg # comment out if you don't need vector files 38 | [._]*.sw[a-p] 39 | [._]s[a-rt-v][a-z] 40 | [._]ss[a-gi-z] 41 | [._]sw[a-p] 42 | 43 | # Session 44 | Session.vim 45 | Sessionx.vim 46 | 47 | # Temporary 48 | .netrwhist 49 | *~ 50 | # Auto-generated tag files 51 | # Persistent undo 52 | [._]*.un~ 53 | 54 | ############### 55 | # VisualStudioCode 56 | ############### 57 | .vscode/* 58 | !.vscode/settings.json 59 | !.vscode/tasks.json 60 | !.vscode/launch.json 61 | !.vscode/extensions.json 62 | *.code-workspace 63 | 64 | # Local History for Visual Studio Code 65 | .history/ 66 | 67 | 68 | 69 | public 70 | !tags -------------------------------------------------------------------------------- /content/snippets/display-tags-aside.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Display Tags Aside 3 | date: 2021-02-26 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: cmjn 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/d/d12f002545f09ee9486ecdaa7879912be533f9b9_2_690x98.jpeg) 14 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/1/1cf2b3239a24f3b0c3176580c1d88fc0b4f43fec_2_690x97.jpeg) 15 | 16 | ```css 17 | p > a.tag { 18 | font-size: 0; 19 | width: 0; 20 | padding: 0; 21 | margin: 0; 22 | background: none; 23 | text-decoration: none; 24 | border: none; 25 | } 26 | p > a.tag::before { 27 | content: '#'; 28 | font-size: 16px; 29 | } 30 | p > a.tag::after { 31 | content: attr(href); 32 | float: right; 33 | min-width: 3ch; 34 | max-width: 25%; 35 | margin-right: calc(-25% - 1.5em); 36 | margin-left: calc(-25% - 1.5em); 37 | position: relative; 38 | clear: right; 39 | white-space: nowrap; 40 | text-overflow: ellipsis; 41 | overflow: hidden; 42 | font-size: 16px; 43 | } 44 | 45 | p > a.tag:hover::after { 46 | max-width: fit-content !important; 47 | } 48 | ``` 49 | 50 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/327) -------------------------------------------------------------------------------- /content/snippets/fade-controls.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Auto fade controls 3 | date: 2020-06-17 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: rsdimitrov 12 | --- 13 | 14 | ## Auto fade note controls 15 | 16 | ```css 17 | .view-header:not(:hover) .view-actions { 18 | opacity: 0.1; 19 | transition: opacity .25s ease-in-out; 20 | } 21 | ``` 22 | 23 | ## Auto fade status bar 24 | 25 | ```css 26 | /* auto fades status bar items */ 27 | .status-bar:not(:hover) .status-bar-item { 28 | opacity: 0.25; 29 | transition: opacity .25s ease-in-out; 30 | } 31 | ``` 32 | 33 | ## Subtler scrollbars 34 | 35 | ```css 36 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, ::-webkit-scrollbar { 37 | width: 3px; 38 | height: 3px; 39 | } 40 | ``` 41 | 42 | ## Subtler folding arrows 43 | 44 | ```css 45 | /* Make subtler folding gutter arrows */ 46 | .CodeMirror-foldgutter-folded:after, .CodeMirror-foldgutter-open:after { 47 | opacity: 0.5; 48 | font-size: 60%; 49 | } 50 | 51 | .CodeMirror-foldgutter-folded:hover:after, .CodeMirror-foldgutter-open:hover:after { 52 | opacity: 1; 53 | } 54 | 55 | .CodeMirror-foldgutter-folded:after { 56 | content: "\25BA"; 57 | } 58 | 59 | .CodeMirror-foldgutter-open:after { 60 | content: "\25BC"; 61 | } 62 | 63 | ``` 64 | 65 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/10) -------------------------------------------------------------------------------- /content/resources/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Resources 3 | template: resources.html 4 | --- 5 | 6 | ## More Resources 7 | 8 | [Obsidian Roundup](https://obsidianroundup.org) 9 | 10 | * There's a new share & showcase for [Note and metadata/YAML templates](https://forum.obsidian.md/t/note-and-metadata-yaml-templates-snippets-showcase/16953) that is intended to serve as a handy meta thread for dataview, templater ( see also: [this showcase](https://forum.obsidian.md/t/templater-plugin-script-collection/17010) from `@pmbauer`)), and daily notes templates. 11 | * Templater now has [a showcase on github](https://github.com/SilentVoid13/Templater/discussions/categories/templates-showcase) where people can share useful templater scripts. `@Murf` also has some [gists](https://gist.github.com/GitMurf) that seem like useful templater scripts. 12 | * [Supercharged links](https://github.com/mdelobelle/obsidian_supercharged_links) allows for customization of internal links based on the target note's front-matter attributes. It also lets you trigger Array, Boolean and Number in front-matter values to style your internal links. There is a [showcase](https://forum.obsidian.md/t/supercharged-links-showcase/18219) on the forum. 13 | * There's a new [showcase for the buttons plugin](https://forum.obsidian.md/t/buttons-showcase/18044). 14 | * `@foreveryone` maintains a useful [repository of snippets](https://github.com/gitobsidiantutorial?tab=repositories), as do `@dmitry` & `@klaas` [here](https://github.com/Dmitriy-Shulha/obsidian-css-snippets). -------------------------------------------------------------------------------- /content/snippets/builtin-icons.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Built-in Icons 3 | date: 2021-05-05 4 | 5 | taxonomies: 6 | tags: 7 | - css 8 | kind: 9 | - styling 10 | extra: 11 | author: rpcm 12 | --- 13 | 14 | - 'logo-crystal' 15 | - 'create-new' 16 | - 'trash' 17 | - 'search' 18 | - 'right-triangle' 19 | - 'document' 20 | - 'folder' 21 | - 'pencil' 22 | - 'left-arrow' 23 | - 'right-arrow' 24 | - 'three-horizontal-bars' 25 | - 'dot-network' 26 | - 'audio-file' 27 | - 'image-file' 28 | - 'pdf-file' 29 | - 'gear' 30 | - 'documents' 31 | - 'blocks' 32 | - 'go-to-file' 33 | - 'presentation' 34 | - 'cross-in-box' 35 | - 'microphone' 36 | - 'microphone-filled' 37 | - 'two-columns' 38 | - 'link' 39 | - 'popup-open' 40 | - 'checkmark' 41 | - 'hashtag' 42 | - 'left-arrow-with-tail' 43 | - 'right-arrow-with-tail' 44 | - 'lines-of-text' 45 | - 'vertical-three-dots' 46 | - 'pin' 47 | - 'magnifying-glass' 48 | - 'info' 49 | - 'horizontal-split' 50 | - 'vertical-split' 51 | - 'calendar-with-checkmark' 52 | - 'sheets-in-box' 53 | - 'up-and-down-arrows' 54 | - 'broken-link' 55 | - 'cross' 56 | - 'any-key' 57 | - 'reset' 58 | - 'star' 59 | - 'crossed-star' 60 | - 'dice' 61 | - 'filled-pin' 62 | - 'enter' 63 | - 'help' 64 | - 'vault' 65 | - 'open-vault' 66 | - 'paper-plane' 67 | - 'bullet-list' 68 | - 'uppercase-lowercase-a' 69 | - 'star-list' 70 | - 'expand-vertically' 71 | - 'languages' 72 | - 'switch' 73 | - 'pane-layout' 74 | - 'install' 75 | 76 | [Original Forum Post](https://forum.obsidian.md/t/list-of-available-icons-for-component-seticon/16332/4) -------------------------------------------------------------------------------- /content/snippets/changing-fonts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Changing Font Styles/Sizes 3 | date: 2020-12-06 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: argentum 11 | --- 12 | 13 | ```css 14 | /*---------------------------------------------------------------- 15 | Font styles 16 | Preview mode and UI */ 17 | 18 | --text:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; 19 | 20 | /* Editor mode */ 21 | 22 | --text-editor:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; 23 | 24 | /* Code */ 25 | 26 | --font-monospace:Menlo,SFMono-Regular,Consolas,"Roboto Mono",monospace; 27 | 28 | /* Sizes, weights, padding */ 29 | 30 | --font-normal:16px; 31 | --font-small:13px; 32 | --font-smaller:11px; 33 | --font-smallest:10px; 34 | --normal-weight:400; /* Switch to 300 if you want thinner default text */ 35 | --bold-weight:600; /* Switch to 700 if you want thicker bold text */ 36 | --line-width:40rem; /* Maximum characters per line */ 37 | --line-height:1.5; 38 | --max-width:87%; /* Amount of padding around the text, use 90% for narrower padding */ 39 | --nested-padding:3.5%; /* Amount of padding for quotes and transclusions */ 40 | --icon-muted:0.4; 41 | --border-width:1px; 42 | --border-width-alt:1px; 43 | 44 | /*---------------------------------------------------------------- 45 | ``` 46 | 47 | [Original Snippet](https://github.com/kepano/obsidian-minimal/blob/master/obsidian.css#L116) 48 | 49 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/248) -------------------------------------------------------------------------------- /content/snippets/collapsible-side-notes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Collapsible Side Notes 3 | date: 2021-03-04 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: cmjn 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/optimized/2X/a/a64f3a0c95b262030c88ad5e82cabee7130f5884_2_690x237.jpeg) 14 | 15 | ```css 16 | blockquote { 17 | border: none !important; 18 | padding: 0 20px; 19 | } 20 | 21 | blockquote .task-list-item { 22 | font-family: var(--font-stack-ui) !important; 23 | font-size: var(--font-size-secondary) !important; 24 | line-height: 1.35em; 25 | font-style: normal; 26 | position: absolute; 27 | text-align: justify; 28 | z-index: 1; 29 | color: var(--text-faint) !important; 30 | right: min(calc(50% + 0.5 * var(--line-width) + 2.5em), calc(100% - 3.5em)); 31 | width: calc(50% - 0.5 * var(--line-width) - 3em); 32 | max-width: calc(0.66 * var(--line-width)); 33 | min-width: 3em; 34 | white-space: nowrap; 35 | overflow: hidden; 36 | text-overflow: ellipsis; 37 | margin-block-start: 0 !important; 38 | margin-block-end: 0 !important; 39 | text-indent: 0 !important; 40 | } 41 | blockquote .task-list-item > .task-list-item-checkbox { 42 | appearance: none; 43 | position: absolute; 44 | height: 100%; 45 | width: 100%; 46 | left: 0; 47 | top: 0; 48 | background: none !important; 49 | background-color: transparent !important; 50 | margin: 0 !important; 51 | border: none; 52 | cursor: pointer; 53 | } 54 | blockquote .task-list-item.is-checked { 55 | z-index: 999; 56 | color: var(--text-normal) !important; 57 | right: min(calc(50% + 0.5 * var(--line-width) + 2.5em), calc(100% - 12.5em)); 58 | min-width: 12em; 59 | overflow: visible; 60 | max-height: none; 61 | white-space: normal; 62 | text-decoration: none !important; 63 | } 64 | 65 | ``` 66 | 67 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/341) -------------------------------------------------------------------------------- /content/snippets/pane-controls-hover.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Show Pane Header Icons on Hover 3 | date: 2020-12-10 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: ShaneNZ 11 | --- 12 | 13 | ![](https://forum.obsidian.md/uploads/default/original/2X/2/2848c023dc2a3111efecc12cffc9525e78be4493.gif) 14 | 15 | ```css 16 | /* 17 | Fade the pane header controls unless hovered (just to reduce/minimise distraction) 18 | does this per individual control to easily leave link and pin slightly more visible even if not hovered, and 19 | as an easy way to do a snazzy transition delay stagger in and out ;) 20 | */ 21 | 22 | /* not hovered ie. on cursor exit from the header */ 23 | .view-header:not(:hover) a.view-action[aria-label*="Preview"], 24 | .view-header:not(:hover) a.view-action[aria-label*="Edit"] { 25 | opacity: 0.1; 26 | transition: opacity .25s ease-in-out; 27 | transition-delay: 0ms; 28 | } 29 | 30 | .view-header:not(:hover) a.view-action[aria-label*="link"] { 31 | opacity: 0.55; 32 | transition: opacity .25s ease-in-out; 33 | transition-delay: 20ms; 34 | } 35 | 36 | .view-header:not(:hover) a.view-action[aria-label*="Pin"] { 37 | opacity: 0.35; 38 | transition: opacity .25s ease-in-out; 39 | transition-delay: 40ms; 40 | } 41 | 42 | .view-header:not(:hover) a.view-action[aria-label*="Close"] { 43 | opacity: 0.1; 44 | transition: opacity .25s ease-in-out; 45 | transition-delay: 60ms; 46 | } 47 | 48 | .view-header:not(:hover) a.view-action[aria-label*="More"] { 49 | opacity: 0.1; 50 | transition: opacity .25s ease-in-out; 51 | transition-delay: 80ms; 52 | } 53 | 54 | /* hovered ie. on cursor entry to the header */ 55 | .view-header:hover a.view-action[aria-label*="Preview"], 56 | .view-header:hover a.view-action[aria-label*="Edit"] { 57 | opacity: 1; 58 | transition: opacity .25s ease-in-out; 59 | transition-delay: 0ms; 60 | } 61 | 62 | .view-header:hover a.view-action[aria-label*="link"] { 63 | opacity: 1; 64 | transition: opacity .25s ease-in-out; 65 | transition-delay: 20ms; 66 | } 67 | 68 | .view-header:hover a.view-action[aria-label*="Pin"] { 69 | opacity: 1; 70 | transition: opacity .25s ease-in-out; 71 | transition-delay: 40ms; 72 | } 73 | 74 | .view-header:hover a.view-action[aria-label*="Close"] { 75 | opacity: 1; 76 | transition: opacity .25s ease-in-out; 77 | transition-delay: 60ms; 78 | } 79 | 80 | .view-header:hover a.view-action[aria-label*="More"] { 81 | opacity: 1; 82 | transition: opacity .25s ease-in-out; 83 | transition-delay: 80ms; 84 | } 85 | ``` 86 | 87 | [Original Forum Post](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/250) -------------------------------------------------------------------------------- /content/snippets/list-obsidian-commands.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: List of Obsidian Commands 3 | date: 2021-05-15 4 | taxonomies: 5 | tags: 6 | - dataview 7 | kind: 8 | - plugins 9 | extra: 10 | author: Moonbase59 11 | --- 12 | 13 | I needed a list of currently enabled Obsidian Commands (those in the Command Palette, internal plus plugins). So I thought »Why not do it using Obsidian itself (and Dataview)?« 14 | 15 | ### Commands sorted by internal Command ID 16 | 17 | ```js 18 | const getNestedObject = (nestedObj, pathArr) => { 19 | return pathArr.reduce((obj, key) => 20 | (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj); 21 | } 22 | 23 | function getHotkey(arr) { 24 | return arr.hotkeys ? [[getNestedObject(arr.hotkeys, [0, 'modifiers'])], 25 | [getNestedObject(arr.hotkeys, [0, 'key'])]].flat(2).join('+').replace('Mod', 'Ctrl') : '–'; 26 | } 27 | 28 | let cmds = dv.array(Object.entries(app.commands.commands)) 29 | .sort(v => v[1].id, 'asc'); 30 | 31 | dv.paragraph(cmds.length + " commands currently enabled.

"); 32 | 33 | dv.table(["Command ID", "Name in current locale", "Hotkeys"], 34 | cmds.map(v => [ 35 | v[1].id, 36 | v[1].name, 37 | getHotkey(v[1]), 38 | ]) 39 | ); 40 | ``` 41 | 42 | 43 | Result: 44 | 45 | ![obsidian-dataview-command-list-by-id](https://forum.obsidian.md/uploads/default/optimized/2X/9/941d1ddfba27d5caab7bc258634ac95fb017525d_2_482x500.png) 46 | 47 | ### Commands sorted by assigned hotkey 48 | 49 | This I missed the most. Just to check if a planned hotkey combo is already taken … 50 | 51 | ```js 52 | const getNestedObject = (nestedObj, pathArr) => { 53 | return pathArr.reduce((obj, key) => 54 | (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj); 55 | } 56 | 57 | function getHotkey(arr) { 58 | return arr.hotkeys ? [[getNestedObject(arr.hotkeys, [0, 'modifiers'])], 59 | [getNestedObject(arr.hotkeys, [0, 'key'])]].flat(2).join('+').replace('Mod', 'Ctrl') : '–'; 60 | } 61 | 62 | let cmds = dv.array(Object.entries(app.commands.commands)) 63 | .where(v => getHotkey(v[1]) != '–') 64 | .sort(v => v[1].id, 'asc') 65 | .sort(v => getHotkey(v[1]), 'asc'); 66 | 67 | dv.paragraph(cmds.length + " commands with assigned hotkeys.

"); 68 | 69 | dv.table(["Command ID", "Name in current locale", "Hotkeys"], 70 | cmds.map(v => [ 71 | v[1].id, 72 | v[1].name, 73 | getHotkey(v[1]), 74 | ]) 75 | ); 76 | ``` 77 | 78 | 79 | Result: 80 | 81 | ![obsidian-dataview-command-list-by-hotkey](https://forum.obsidian.md/uploads/default/optimized/2X/8/86470033b38fd2b4ca5ec117606d210f2c4d349b_2_479x500.png) 82 | 83 | ### Notes 84 | 85 | 86 | I’m on Linux and this is good enough for me. I leave remapping MacOS keys and/or adding nice `` tags around the keys (but not the plus signs in between!) as an exercise for the reader. ![wink](https://forum.obsidian.md/images/emoji/apple/wink.png?v=9) 87 | 88 | Anyway, it’s a good check what we have, and could well be a starting point for the [Buttons](https://github.com/shabegom/buttons) and [Obsidian Leaflet 1](https://github.com/valentine195/obsidian-leaflet-plugin) plugins to maybe invoke commands _language-independently_, using their _ID_. Because now we know it an can make a list! 89 | 90 | (Bi- and multilingual people switch Obsidian’s language often, and it sucks that commands called up by their (locale-specific!) _name_ suddenly stop working.) 91 | 92 | [Original Forum Post](https://forum.obsidian.md/t/dataviewjs-snippet-showcase/17847/13) -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {%block title %}{{config.title}}{%endblock title%} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% if config.generate_feed %} 17 | 18 | {% endif %} 19 | 20 | 21 | 39 |
40 | {% block content %} {% endblock %} 41 |
42 | 48 | 49 | 50 | 51 | 52 | 84 | -------------------------------------------------------------------------------- /sass/styles.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --monospace: "Fira Code", monospace; 3 | --headline: "Publico Headline", -apple-system, "Helvetica","Arial"; 4 | --background: #FCFCFD; 5 | --background-highlight: white; 6 | } 7 | 8 | body,html { 9 | font-size: 16px; 10 | background: var(--background); 11 | width: 100vw; 12 | height: 100vh; 13 | font-family: -apple-system, "Helvetica","Arial"; 14 | } 15 | 16 | h1,h2,h3,h4,h5,h6 { 17 | font-family: var(--headline); 18 | } 19 | 20 | h1 { 21 | font-size: 1.602rem; 22 | } 23 | 24 | nav { 25 | display: flex; 26 | justify-content: space-evenly; 27 | align-items: baseline; 28 | transition: 300ms all ease-in-out; 29 | ul { 30 | display: flex; 31 | list-style-type: none; 32 | li { 33 | margin: 10px; 34 | font-family: var(--monospace); 35 | } 36 | } 37 | } 38 | 39 | main { 40 | margin: 20px; 41 | h2 { 42 | text-align: center; 43 | } 44 | } 45 | 46 | .card { 47 | width: 95vw; 48 | max-width: 640px; 49 | margin: 0 auto; 50 | padding-bottom: 80px; 51 | &.mini { 52 | background: var(--background-highlight); 53 | width: 30vw; 54 | border: 1px solid rgba(128,128,128,0.4); 55 | border-radius: 13px; 56 | transition: 300ms all ease-in-out; 57 | margin: auto; 58 | max-height: 40vh; 59 | overflow-y: hidden; 60 | padding-bottom: 5px; 61 | 62 | img,video { 63 | max-width: 300px; 64 | } 65 | } 66 | &:hover { 67 | border-width: 4px; 68 | } 69 | 70 | 71 | > * { 72 | margin: 5px; 73 | } 74 | a { 75 | text-decoration: none; 76 | color: inherit; 77 | } 78 | .content a { 79 | color: lightcoral; 80 | &:hover { 81 | color: coral; 82 | } 83 | } 84 | pre { 85 | overflow: scroll; 86 | padding: 10px; 87 | border-radius: 4px; 88 | } 89 | .top { 90 | display: flex; 91 | justify-content: space-between; 92 | } 93 | 94 | .tags { 95 | list-style: none; 96 | display: flex; 97 | font-family: var(--monospace); 98 | color: orange; 99 | * { 100 | margin: 5px; 101 | } 102 | } 103 | .kind { 104 | text-transform: uppercase; 105 | font-family: var(--monospace); 106 | background:#8fceff; 107 | color: black; 108 | border-radius: 4px; 109 | padding: 10px; 110 | height: min-content; 111 | transition: 300ms all ease-in-out; 112 | 113 | &:hover { 114 | color: #1a1a1a; 115 | } 116 | } 117 | 118 | img,video { 119 | max-width: 60vw; 120 | } 121 | } 122 | 123 | .snippets { 124 | display: flex; 125 | flex-wrap: wrap; 126 | list-style: none; 127 | > * { 128 | margin: 20px; 129 | } 130 | padding-bottom: 80px; 131 | } 132 | 133 | .mono { 134 | font-family: var(--monospace); 135 | } 136 | 137 | a.clear { 138 | text-decoration: none; 139 | color: inherit; 140 | } 141 | 142 | footer { 143 | position: fixed; 144 | bottom: 0; 145 | text-align: center; 146 | width: 100%; 147 | background: var(--background); 148 | } 149 | 150 | .resource { 151 | text-align: center; 152 | width: 100%; 153 | } 154 | 155 | @media screen and (max-width: 768px) { 156 | .snippets { 157 | flex-direction: column; 158 | width: 90vw; 159 | margin: 0; 160 | padding: 0; 161 | .card.mini { 162 | width: 80vw; 163 | margin: 0 auto; 164 | img,video { 165 | width: 150px; 166 | } 167 | } 168 | } 169 | 170 | nav { 171 | flex-direction: column; 172 | align-items: center; 173 | } 174 | } 175 | 176 | .copy-code-button { 177 | color: #272822; 178 | background-color: #FFF; 179 | border-color: #272822; 180 | border: 2px solid; 181 | border-radius: 3px 3px 0px 0px; 182 | 183 | /* right-align */ 184 | display: block; 185 | margin-left: auto; 186 | margin-right: 0; 187 | 188 | margin-bottom: -1rem; 189 | padding: 3px 8px; 190 | font-size: 0.8em; 191 | } 192 | 193 | .copy-code-button:hover { 194 | cursor: pointer; 195 | background-color: #F2F2F2; 196 | } 197 | 198 | .copy-code-button:focus { 199 | /* Avoid an ugly focus outline on click in Chrome, 200 | but darken the button for accessibility. 201 | See https://stackoverflow.com/a/25298082/1481479 */ 202 | background-color: #E6E6E6; 203 | outline: 0; 204 | } 205 | 206 | .copy-code-button:active { 207 | background-color: #D9D9D9; 208 | } 209 | 210 | @media (prefers-color-scheme: dark) { 211 | :root { 212 | --background: #1a1a1a; 213 | --background-highlight: black; 214 | } 215 | 216 | a { 217 | color: #8fceff; 218 | } 219 | } -------------------------------------------------------------------------------- /content/snippets/dataview-table-as-cards.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Dataview Table as Cards 3 | date: 2021-05-20 4 | taxonomies: 5 | tags: 6 | - css 7 | kind: 8 | - styling 9 | extra: 10 | author: yungbananapeel 11 | --- 12 | 13 | ![](https://cdn.discordapp.com/attachments/840286238928797736/845044771621699634/dataview_library.jpg) 14 | 15 | ```css 16 | /* READ ME */ 17 | /* 18 | This css has been built to be used with dataview tables, and assumes you are not using dataviewjs. But this can easily be adapted to list view. Because this css is not supported by a js backend, text and backgrounds will not autosize (i think so anyway, i haven't found a way. if you do share on discord @yungbananapeel#2624) 19 | 20 | I'm not that great as using css, so there is probably a lot of redundancies in the file. The Main thing to understand about using the css to manipulate the tables is the structure of a DV table. 21 | 22 | Any content about a page you want returned is delivered as a child element of a span, that is nested inside of a TD.The TD's are the individual containers that make up the columns of a row. if you want to change the structure of a table on top of this file, its important to remember all the relationships between the TR>TD>SPAN>CONTENT. 23 | 24 | An an example images and links are returned as & tags as children of a div, but strings are returned as the content of the span, not as content of a child element.like so: 25 | 26 | cool link 27 | picture 28 | 29 | YOUR TEXT HERE 30 | 31 | TABLE STRUCTURE 32 |
33 | 34 | 35 | 36 | 37 | 38 | EACH TR CORRESPONDS TO A SINGLE PAGE RETURNED FROM YOUR QUERY. 39 | 46 | 47 | 48 |
40 | EACH TD CORRESPONDS TO A COLUMN 41 | THEY ARE ORDERED TOP TO BOTTOM, IN ORDER FROM LEFT TO RIGHT 42 | 43 | THIS SPAN IS WHERE YOUR RETURNS INFO IS (links, images, text) 44 | 45 |
49 |
50 | */ 51 | /* COLORS */ 52 | .CardView { 53 | --Name-bg: red; 54 | -- 55 | } 56 | /* Hide Table Head */ 57 | .CardView thead{ 58 | display: none; 59 | line-height: 0; 60 | height: 0px; 61 | } 62 | CardView table { 63 | border-collapse: collapse; 64 | border-spacing: 0; 65 | width: 100%; 66 | } 67 | 68 | 69 | /* Table wide Changes */ 70 | /* .CardView tbody { 71 | display: flex; 72 | flex-direction: row; 73 | flex-wrap: wrap; 74 | } */ 75 | /* Turn all spans into flex boxes*/ 76 | .CardView span { 77 | display: flex; 78 | float: left; 79 | margin: 0; 80 | padding: 0; 81 | max-width: 350px; 82 | } 83 | /* Create a card Shape from the Table Row */ 84 | .CardView tr { 85 | display: block; 86 | text-align: justify; 87 | float: left; 88 | padding: 0; 89 | margin-right: 60px; 90 | height: 475px; 91 | width: 310px; 92 | background-color: rgb(36, 32, 32) !important; 93 | border: 5px solid rgb(0, 0, 0) !important; 94 | box-shadow: 10px 11px 19px -1px #070202; 95 | } 96 | 97 | .CardView td { 98 | display: block; 99 | min-height: 50px; 100 | padding: 15px; 101 | } 102 | /* First Column Box*/ 103 | .CardView td:first-child { 104 | min-height: 75px !important ; 105 | padding: auto; 106 | background-color: rgba(255, 255, 255, 0.863); 107 | border: 5px solid rgb(255, 255, 255); 108 | } 109 | /* First Column link */ 110 | .CardView td:first-child span a { 111 | text-overflow: ellipsis !important; 112 | word-wrap: break-word !important; 113 | text-overflow: ellipsis !important; 114 | display: block; 115 | line-height: 1em; 116 | max-height: 2em; 117 | font-size: 23px; 118 | font-weight: bold !important; 119 | color: rgb(207, 17, 17) !important; 120 | } 121 | 122 | /* Second Column */ 123 | /* column bg */ 124 | .CardView td:nth-child(2) { 125 | z-index: 2; 126 | background-color: rgb(226, 75, 75); 127 | width: 175px; 128 | display: block; 129 | float: left; 130 | line-height: 1em; 131 | max-height: 2em; 132 | } 133 | /* column link */ 134 | .CardView td:nth-child(2) a { 135 | color: rgb(206, 211, 189) !important; 136 | font-weight: bold !important; 137 | width: 60px; 138 | word-wrap: break-word; 139 | text-overflow: ellipsis !important; 140 | } 141 | 142 | /* third column */ 143 | .CardView td:nth-child(3) { 144 | max-height: 50px !important; 145 | color: rgb(255, 81, 81) !important; 146 | z-index: -1; 147 | width: 125px; 148 | line-height: 1em; 149 | max-height: 2em; 150 | display: block; 151 | float: right; 152 | background-color: rgb(250, 246, 0); 153 | } 154 | /* third column links */ 155 | .CardView td:nth-child(3) span a { 156 | color: rgb(255, 81, 81) !important; 157 | text-align: right; 158 | width: 100%; 159 | overflow: hidden; 160 | display: block; 161 | float: right; 162 | font-weight: bold !important; 163 | word-wrap: break-word; 164 | text-overflow: ellipsis !important; 165 | } 166 | /* third column strings */ 167 | .CardView td:nth-child(3) span{ 168 | color: rgb(255, 81, 81) !important; 169 | text-align: right; 170 | width: 100%; 171 | overflow: hidden; 172 | display: block; 173 | float: right; 174 | font-weight: bold !important; 175 | word-wrap: break-word; 176 | text-overflow: ellipsis !important; 177 | } 178 | 179 | /* Last Column Image */ 180 | .CardView td span img { 181 | display: block; 182 | width: 300px; 183 | height: 300px; 184 | object-fit: contain; 185 | margin: 0 auto; 186 | padding: 0; 187 | margin: 20px auto; 188 | } 189 | 190 | ``` -------------------------------------------------------------------------------- /static/search.js: -------------------------------------------------------------------------------- 1 | function debounce(func, wait) { 2 | var timeout; 3 | 4 | return function () { 5 | var context = this; 6 | var args = arguments; 7 | clearTimeout(timeout); 8 | 9 | timeout = setTimeout(function () { 10 | timeout = null; 11 | func.apply(context, args); 12 | }, wait); 13 | }; 14 | } 15 | 16 | // Taken from mdbook 17 | // The strategy is as follows: 18 | // First, assign a value to each word in the document: 19 | // Words that correspond to search terms (stemmer aware): 40 20 | // Normal words: 2 21 | // First word in a sentence: 8 22 | // Then use a sliding window with a constant number of words and count the 23 | // sum of the values of the words within the window. Then use the window that got the 24 | // maximum sum. If there are multiple maximas, then get the last one. 25 | // Enclose the terms in . 26 | function makeTeaser(body, terms) { 27 | var TERM_WEIGHT = 40; 28 | var NORMAL_WORD_WEIGHT = 2; 29 | var FIRST_WORD_WEIGHT = 8; 30 | var TEASER_MAX_WORDS = 30; 31 | 32 | var stemmedTerms = terms.map(function (w) { 33 | return elasticlunr.stemmer(w.toLowerCase()); 34 | }); 35 | var termFound = false; 36 | var index = 0; 37 | var weighted = []; // contains elements of ["word", weight, index_in_document] 38 | 39 | // split in sentences, then words 40 | var sentences = body.toLowerCase().split(". "); 41 | 42 | for (var i in sentences) { 43 | var words = sentences[i].split(" "); 44 | var value = FIRST_WORD_WEIGHT; 45 | 46 | for (var j in words) { 47 | var word = words[j]; 48 | 49 | if (word.length > 0) { 50 | for (var k in stemmedTerms) { 51 | if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) { 52 | value = TERM_WEIGHT; 53 | termFound = true; 54 | } 55 | } 56 | weighted.push([word, value, index]); 57 | value = NORMAL_WORD_WEIGHT; 58 | } 59 | 60 | index += word.length; 61 | index += 1; // ' ' or '.' if last word in sentence 62 | } 63 | 64 | index += 1; // because we split at a two-char boundary '. ' 65 | } 66 | 67 | if (weighted.length === 0) { 68 | return body; 69 | } 70 | 71 | var windowWeights = []; 72 | var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS); 73 | // We add a window with all the weights first 74 | var curSum = 0; 75 | for (var i = 0; i < windowSize; i++) { 76 | curSum += weighted[i][1]; 77 | } 78 | windowWeights.push(curSum); 79 | 80 | for (var i = 0; i < weighted.length - windowSize; i++) { 81 | curSum -= weighted[i][1]; 82 | curSum += weighted[i + windowSize][1]; 83 | windowWeights.push(curSum); 84 | } 85 | 86 | // If we didn't find the term, just pick the first window 87 | var maxSumIndex = 0; 88 | if (termFound) { 89 | var maxFound = 0; 90 | // backwards 91 | for (var i = windowWeights.length - 1; i >= 0; i--) { 92 | if (windowWeights[i] > maxFound) { 93 | maxFound = windowWeights[i]; 94 | maxSumIndex = i; 95 | } 96 | } 97 | } 98 | 99 | var teaser = []; 100 | var startIndex = weighted[maxSumIndex][2]; 101 | for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) { 102 | var word = weighted[i]; 103 | if (startIndex < word[2]) { 104 | // missing text from index to start of `word` 105 | teaser.push(body.substring(startIndex, word[2])); 106 | startIndex = word[2]; 107 | } 108 | 109 | // add around search terms 110 | if (word[1] === TERM_WEIGHT) { 111 | teaser.push(""); 112 | } 113 | startIndex = word[2] + word[0].length; 114 | teaser.push(body.substring(word[2], startIndex)); 115 | 116 | if (word[1] === TERM_WEIGHT) { 117 | teaser.push(""); 118 | } 119 | } 120 | teaser.push("…"); 121 | return teaser.join(""); 122 | } 123 | 124 | function formatSearchResultItem(item, terms) { 125 | return ( 126 | '
' + 127 | `${item.doc.title}` + 128 | `
${makeTeaser(item.doc.body, terms)}
` + 129 | "
" 130 | ); 131 | } 132 | 133 | function initSearch() { 134 | var $searchInput = document.getElementById("search"); 135 | var $searchResults = document.querySelector(".search-results"); 136 | var $searchResultsItems = document.querySelector(".search-results__items"); 137 | 138 | $searchInput.addEventListener("click", (e) => e.stopPropagation()); 139 | $searchResults.addEventListener("click", (e) => e.stopPropagation()); 140 | $searchResultsItems.addEventListener("click", (e) => e.stopPropagation()); 141 | 142 | var MAX_ITEMS = 10; 143 | 144 | var options = { 145 | bool: "AND", 146 | fields: { 147 | title: { boost: 2 }, 148 | body: { boost: 1 }, 149 | }, 150 | }; 151 | var currentTerm = ""; 152 | var index = elasticlunr.Index.load(window.searchIndex); 153 | 154 | $searchInput.addEventListener( 155 | "keyup", 156 | debounce(function () { 157 | var term = $searchInput.value.trim(); 158 | if (term === currentTerm || !index) { 159 | return; 160 | } 161 | $searchResults.style.display = term === "" ? "none" : "block"; 162 | $searchResultsItems.innerHTML = ""; 163 | if (term === "") { 164 | return; 165 | } 166 | 167 | var results = index.search(term, options); 168 | if (results.length === 0) { 169 | $searchResults.style.display = "none"; 170 | return; 171 | } 172 | 173 | currentTerm = term; 174 | for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) { 175 | var item = document.createElement("li"); 176 | item.innerHTML = formatSearchResultItem(results[i], term.split(" ")); 177 | $searchResultsItems.appendChild(item); 178 | } 179 | }, 150) 180 | ); 181 | } 182 | 183 | window.addEventListener("click", (e) => { 184 | var $searchInput = document.getElementById("search"); 185 | var $searchResults = document.querySelector(".search-results"); 186 | var $searchResultsItems = document.querySelector(".search-results__items"); 187 | $searchInput.value = ""; 188 | $searchResults.style.display = "none"; 189 | $searchResultsItems.innerHTML = ""; 190 | }); 191 | 192 | function whenAvailable(callback, names) { 193 | var interval = 10; // ms 194 | window.setTimeout(function () { 195 | if (names.every((name) => typeof window[name] !== "undefined")) { 196 | callback(); 197 | } else { 198 | window.setTimeout(arguments.callee, interval); 199 | } 200 | }, interval); 201 | } 202 | 203 | whenAvailable(() => { 204 | initSearch(); 205 | }, ["elasticlunr", "searchIndex"]); 206 | -------------------------------------------------------------------------------- /content/snippets/birthdays.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Upcoming Birthdays 3 | date: 2021-05-09 4 | taxonomies: 5 | tags: 6 | - dataview 7 | kind: 8 | - plugins 9 | extra: 10 | author: Moonbase59 11 | --- 12 | 13 | Here’s a rather robust and flexible list of upcoming birthdays that 14 | 15 | - shows **link**, **next birthday**, and **age** someone will turn to 16 | - has a configurabe **date range** (from today, for a “natural language” duration) 17 | - sorts by **next birthday** 18 | - uses **locale settings** from the language _Obsidian is set to_ 19 | - doesn’t choke when crossing the year boundary 20 | - has YAML **searchterm** configuration 21 | - has YAML “natural language” **duration** configuration; “odd” data like `duration: 0.5 years` will be auto-translated to `6 months` (or `6 Monate` in German) 22 | - has YAML **date format** configuration (yay!) 23 | - has a configurable **info line** above the table (can be disabled) 24 | 25 | ![obsidian-dataview-upcoming-birthdays](https://forum.obsidian.md/uploads/default/optimized/2X/4/4f70d33649d6c45a7ac9c86b3226b0cb3f021dc0_2_690x487.png) 26 | 27 | 28 | Upcoming birthdays with English settings, custom date format and info line 29 | 30 | **The technically-minded** may also find interesting: 31 | 32 | - utility functions that can be used for table data 33 | - custom function for “where” 34 | - comparator function for “sort” 35 | - easily translatable “info line” with parameters 36 | - how I need to _undo_ Dataview’s YAML pre-parsing of dates and durations 37 | 38 | ![obsidian-dataview-upcoming-birthdays-de](https://forum.obsidian.md/uploads/default/optimized/2X/5/5d6ccde0ae290500f38c930b2c91142f45f27304_2_690x483.png) 39 | 40 | 41 | Upcoming birthdays with German settings, custom date format and info line 42 | 43 | ## Requirements 44 | 45 | 46 | - _Dataview 0.3.3+_ 47 | - `moment.js` (comes with Obsidian) 48 | - Notes to be included must have a birthday as `YYYY-MM-DD` in the frontmatter: 49 | 50 | birthday: 1959-07-19 51 | 52 | 53 | - The note _using_ this script **must** have the parameters `searchterm` and a (more or less) “natural language” `duration` in the frontmatter: 54 | 55 | #searchterm: "#family or #friends" 56 | searchterm: '"People"' 57 | duration: 1 year 58 | 59 | 60 | - The note using this script **_can_** have an additional `dateformat` in the frontmatter: 61 | 62 | dateformat: "ddd, D MMMM YYYY" 63 | 64 | 65 | If left out or empty, it will default to `YYYY-MM-DD`. 66 | 67 | ## Code 68 | 69 | ### YAML frontmatter example 70 | 71 | ```yaml 72 | #searchterm: "#family or #friends" 73 | searchterm: '"People"' 74 | duration: 1 year 75 | dateformat: "ddd, D MMMM YYYY" 76 | ``` 77 | 78 | ### `dataviewjs` code 79 | 80 | This contains some utility functions that can be used in your table, like `nextBirthday()`, `turns()`. 81 | 82 | ```js 83 | var start = moment().startOf('day'); 84 | var end = moment(start).add(dv.current().duration); 85 | var dateformat = "YYYY-MM-DD"; 86 | if (dv.current().dateformat) { dateformat = dv.current().dateformat; } 87 | 88 | // info text above table, {0}=duration, {1}=start date, {2}=end date 89 | // parameters can be left out, or the string empty 90 | var infotext = "Upcoming birthdays for {0} from now ({1} – {2})

"; 91 | 92 | //====================================================================== 93 | 94 | function nextBirthday(birthday) { 95 | // Get person’s next birthday on or after "start" 96 | // returns a moment 97 | 98 | // need to "unparse" because DV has already converted YAML birthday to DateTime object 99 | // shouldn’t harm if already a string 100 | var bday = moment(birthday.toString()); 101 | var bdayNext = moment(bday).year(start.year()); 102 | if (bdayNext.isBefore(start, 'day')) { 103 | bdayNext.add(1, "year"); 104 | } 105 | return bdayNext; 106 | } 107 | 108 | function turns(birthday) { 109 | // Get the age in years a person will turn to on their next birthday 110 | 111 | // need to "unparse" because DV has already converted YAML birthday to DateTime object 112 | // shouldn’t harm if already a string 113 | var bday = moment(birthday.toString()); 114 | return nextBirthday(birthday).diff(bday, 'years'); 115 | } 116 | 117 | function showBirthday(birthday) { 118 | // Determine if this birthday is in the range to be shown 119 | // including the start date, excluding the end date 120 | // because that comes from a duration calculation 121 | // for use with "where", returns true or false 122 | 123 | if (birthday) { 124 | // need to "unparse" because DV has already converted YAML birthday to DateTime object 125 | // shouldn’t harm if already a string 126 | var bday = moment(birthday.toString()); 127 | var bdayNext = nextBirthday(birthday); 128 | if (bdayNext.isBetween(start, end, 'day', '[)')) { 129 | return true; 130 | } else { 131 | return false; 132 | } 133 | } else { 134 | return false; 135 | } 136 | } 137 | 138 | function sortByNextBirthday(a, b) { 139 | // comparator function for "sort" 140 | 141 | if (nextBirthday(a).isBefore(nextBirthday(b))) { 142 | return -1; 143 | } 144 | if (nextBirthday(a).isAfter(nextBirthday(b))) { 145 | return 1; 146 | } 147 | // they’re equal 148 | return 0; 149 | } 150 | 151 | 152 | //====================================================================== 153 | 154 | dv.paragraph(infotext.format(moment.duration(dv.current().duration.toString()).humanize(), start.format(dateformat), end.format(dateformat))); 155 | 156 | dv.table( 157 | ["Name", "Birthday", "Turns"], 158 | dv.pages(dv.current().searchterm) 159 | // use a function to see if this birthday is in range to be shown 160 | .where(p => showBirthday(p.birthday)) 161 | // use a comparator function to sort by next birthday 162 | .sort(p => p.birthday, 'asc', sortByNextBirthday) 163 | .map(p => [ 164 | p.file.link, 165 | p.birthday ? nextBirthday(p.birthday).format(dateformat) : '–', 166 | turns(p.birthday) 167 | ]) 168 | ); 169 | ``` 170 | 171 | ## Notes 172 | 173 | 174 | - Dataview actually _parses_ the cell content, so if you for example set the date format to `D. MMMM`, you’ll get large vertical spacing. This is because DV _thinks_ something like `17. May` must be an _ordered list item_ and parses it accordingly. Which in turn will ruin your vertical spacing. 175 | See [0.3.3: table item converts to ordered list, ruining vertical spacing · Issue #199 · blacksmithgu/obsidian-dataview · GitHub 1](https://github.com/blacksmithgu/obsidian-dataview/issues/199). 176 | 177 | - Using durations > 1 year (like `2 years`) _work_, but don’t make much sense. The table will only display a person’s _next_ birthday. So no duplicates. 178 | 179 | [Original Forum Post](https://forum.obsidian.md/t/dataviewjs-snippet-showcase/17847/6) -------------------------------------------------------------------------------- /content/snippets/people-nearby.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Show family members friends and places that are nearby 3 | date: 2021-05-08 4 | taxonomies: 5 | tags: 6 | - dataview 7 | kind: 8 | - plugins 9 | extra: 10 | author: Moonbase59 11 | --- 12 | 13 | I love location data, maps, and visualizing stuff. When I plan to travel or visit a friend or family member, I love to see “what’s near” in each person or location note. Automatically linking places and people together, so to say. 14 | 15 | ![](https://forum.obsidian.md/uploads/default/original/2X/c/cd1e190d4115a6935a5429fee51683d41cc34739.png) 16 | 17 | * If I visit a friend, I can check if there are other friends or places of interest nearby, and we could maybe visit them together. 18 | * I can check if other friends are near enough to do something together, maybe meet for a barbeque. 19 | * When sightseeing, I won’t miss nearby friends, business contacts, favourite restaurants or other sights anymore. 20 | 21 | ## Goals 22 | - Never miss anything nearby anymore. 23 | - Have this dataview available as a template so it can be in every person, business contact, and place-of-interest note and automatically show me what’s near this place. 24 | - No more people and location notes without location data (easily be copied from Google Maps or the like). 25 | 26 | ## Requirements 27 | 28 | - All people/location notes must have a 29 | 30 | ```yaml 31 | location: [lat, lon] 32 | ``` 33 | 34 | entry in the YAML frontmatter. (This syntax has something to do with YAML & JS data structure and easy parsing. The sequence [lat, lon] has been chosen for practical reasons: People are used to it and it can easily be copied from Google Maps and others.) 35 | - _Dataview 0.3.0+_ installed. 36 | - `moment.js` available (it currently is). 37 | - Distance units of **m**, **km**, **yd** and **mi** must be usable and easy to switch. 38 | - Distances must be calculated as correct straight-line distances, taking into account that Earth is not a perfect sphere but a rotational ellipsoid. 39 | - Distances must also be available as (approximate; for speed and offline use) driving distances. 40 | - Distances shall be shown with the unit appended but internally numeric, for easy calculation/comparison. 41 | - Numbers shall be formatted *according to the language currently set in Obsidian* (`4,096.1` vs `4.096,1`). The OS’s system setting shall only be used if all else fails. 42 | - Date & time strings must be easily formatable however I wish, defaulting to ISO-8601 (`2021-05-08T10:34:05+02:00`). 43 | - Very long note title links shall optionally be shortened in Dataview table views, using my [dataview-shorten-links.css snippet](https://forum.obsidian.md/t/how-to-achieve-css-code-snippets/8474/152). 44 | - Tags (from frontmatter only, a current Dataview restriction) shall be shown in one (comma- or blank-)separated string, not as a list. 45 | - The list shall be sorted by distance from “here” (i.e., this note). 46 | - The distance values shall be clickable and lead to the Google Maps Route Planner, destination already filled in, and start point taken from the current location. 47 | - Above the table, a text line shall show the currently set “nearby” radius as well as the selected unit of measurement (`within 100 km driving distance, within 50 mi straight-line distance`), so we later know what’s actually shown in the table. 48 | 49 | ## The Code 50 | 51 | ```js 52 | // Nearby Family Members, Friends and Places 53 | // 2021-05-15 - Matthias C. Hormann (Moonbase59) 54 | 55 | // set parameters (to be supplied via YAML frontmatter, eventually) 56 | // DV 0.3.3 interprets "500000 m" as a Luxon duration, 57 | // so we have to put nearby: '"500000 m"' and remove the ". 58 | let nearby = dv.current().nearby.replace(/['"]+/g, ''); 59 | let unit = nearby.split(' ')[1]; 60 | let radius = nearby.split(' ')[0]; 61 | let origin = dv.current().location; 62 | 63 | // search term as used in dv.pages() 64 | // use "#tags" or '"folder/subfolder"' for a folder 65 | let searchterm = dv.current().searchterm; 66 | 67 | //====================================================================== 68 | 69 | function getDistance(origin, destination, unit='m') { 70 | // return distance in selected unit (m,km,yd,mi) 71 | var factor = 1.0; 72 | switch (unit) { 73 | case 'm': 74 | factor = 1.0; 75 | break; 76 | case 'km': 77 | factor = 1000.0; 78 | break; 79 | case 'yd': 80 | factor = 0.9144; 81 | break; 82 | case 'mi': 83 | factor = 1609.344; 84 | break; 85 | default: 86 | factor = 1.0; 87 | console.warn("getDistance: Invalid unit '%s', using 'm'. Valid units are: m,km,yd,mi.",unit); 88 | } 89 | 90 | var lon1 = toRadian(origin[1]), 91 | lat1 = toRadian(origin[0]), 92 | lon2 = toRadian(destination[1]), 93 | lat2 = toRadian(destination[0]); 94 | 95 | var deltaLat = lat2 - lat1; 96 | var deltaLon = lon2 - lon1; 97 | 98 | var a = Math.pow(Math.sin(deltaLat/2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(deltaLon/2), 2); 99 | var c = 2 * Math.asin(Math.sqrt(a)); 100 | var EARTH_RADIUS = 6371000; // 6,371 km in metres 101 | return c * EARTH_RADIUS / factor; 102 | } 103 | 104 | function toRadian(degree) { 105 | return degree*Math.PI/180; 106 | } 107 | 108 | function getDrivingDistance(origin, destination, unit='m') { 109 | // PREDICTED, using a factor. 110 | // Much faster, and no need for Internet access. 111 | // The U.S. predict 1.417, based on statistical analysis. 112 | // For Germany, I’ve found 1.3 a good value (comparing w/ Google Maps "best route") 113 | var factor = 1.3; 114 | return getDistance(origin, destination, unit) * factor; 115 | } 116 | 117 | //====================================================================== 118 | 119 | // Show what we will display. 120 | dv.paragraph("List shows nearby places (within " + radius + " " + unit + " driving distance)."); 121 | dv.paragraph("

"); 122 | 123 | // get the pages 124 | let pages = dv.pages(searchterm) 125 | .where(p => p.location && 126 | // must be >0 so we don’t catch ourselves! 127 | getDrivingDistance(origin, p.location, unit) > 0.0 && 128 | getDrivingDistance(origin, p.location, unit) <= radius) 129 | .sort(p => getDistance(origin, p.location, unit)); 130 | 131 | // create table 132 | dv.table(["Name", "Tags", "Distance*"], 133 | pages.map(p => [ 134 | // The name 135 | p.file.link, 136 | // tags (show '–' if none defined) 137 | (p.file.etags ? p.file.etags.join(' ') : '–'), 138 | // straight-line distance 139 | /* 140 | getDistance(origin, p.location, unit) 141 | .toLocaleString(moment.locale(), {maximumFractionDigits: 1}) + " " + unit, 142 | */ 143 | // predicted driving distance and Google Maps Route Planner Link 144 | (getDrivingDistance(origin, p.location, unit) 145 | .toLocaleString(moment.locale(), {maximumFractionDigits: 1}) + " " + unit) 146 | .link('https://www.google.com/maps/dir/?api=1&dir_action=navigate&destination=' + p.location[0] + ',' + p.location[1]), 147 | ]) 148 | ); 149 | 150 | // show a small legend 151 | dv.paragraph("* Approximate driving distance; when clicked, opens a new Google Maps Route Planner window."); 152 | ``` 153 | 154 | [Original Forum Post](https://forum.obsidian.md/t/dataviewjs-snippet-showcase/17847/2) -------------------------------------------------------------------------------- /static/reset.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { 178 | /* 1 */ 179 | overflow: visible; 180 | } 181 | 182 | /** 183 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 184 | * 1. Remove the inheritance of text transform in Firefox. 185 | */ 186 | 187 | button, 188 | select { 189 | /* 1 */ 190 | text-transform: none; 191 | } 192 | 193 | /** 194 | * Correct the inability to style clickable types in iOS and Safari. 195 | */ 196 | 197 | button, 198 | [type="button"], 199 | [type="reset"], 200 | [type="submit"] { 201 | -webkit-appearance: button; 202 | } 203 | 204 | /** 205 | * Remove the inner border and padding in Firefox. 206 | */ 207 | 208 | button::-moz-focus-inner, 209 | [type="button"]::-moz-focus-inner, 210 | [type="reset"]::-moz-focus-inner, 211 | [type="submit"]::-moz-focus-inner { 212 | border-style: none; 213 | padding: 0; 214 | } 215 | 216 | /** 217 | * Restore the focus styles unset by the previous rule. 218 | */ 219 | 220 | button:-moz-focusring, 221 | [type="button"]:-moz-focusring, 222 | [type="reset"]:-moz-focusring, 223 | [type="submit"]:-moz-focusring { 224 | outline: 1px dotted ButtonText; 225 | } 226 | 227 | /** 228 | * Correct the padding in Firefox. 229 | */ 230 | 231 | fieldset { 232 | padding: 0.35em 0.75em 0.625em; 233 | } 234 | 235 | /** 236 | * 1. Correct the text wrapping in Edge and IE. 237 | * 2. Correct the color inheritance from `fieldset` elements in IE. 238 | * 3. Remove the padding so developers are not caught out when they zero out 239 | * `fieldset` elements in all browsers. 240 | */ 241 | 242 | legend { 243 | box-sizing: border-box; /* 1 */ 244 | color: inherit; /* 2 */ 245 | display: table; /* 1 */ 246 | max-width: 100%; /* 1 */ 247 | padding: 0; /* 3 */ 248 | white-space: normal; /* 1 */ 249 | } 250 | 251 | /** 252 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 253 | */ 254 | 255 | progress { 256 | vertical-align: baseline; 257 | } 258 | 259 | /** 260 | * Remove the default vertical scrollbar in IE 10+. 261 | */ 262 | 263 | textarea { 264 | overflow: auto; 265 | } 266 | 267 | /** 268 | * 1. Add the correct box sizing in IE 10. 269 | * 2. Remove the padding in IE 10. 270 | */ 271 | 272 | [type="checkbox"], 273 | [type="radio"] { 274 | box-sizing: border-box; /* 1 */ 275 | padding: 0; /* 2 */ 276 | } 277 | 278 | /** 279 | * Correct the cursor style of increment and decrement buttons in Chrome. 280 | */ 281 | 282 | [type="number"]::-webkit-inner-spin-button, 283 | [type="number"]::-webkit-outer-spin-button { 284 | height: auto; 285 | } 286 | 287 | /** 288 | * 1. Correct the odd appearance in Chrome and Safari. 289 | * 2. Correct the outline style in Safari. 290 | */ 291 | 292 | [type="search"] { 293 | -webkit-appearance: textfield; /* 1 */ 294 | outline-offset: -2px; /* 2 */ 295 | } 296 | 297 | /** 298 | * Remove the inner padding in Chrome and Safari on macOS. 299 | */ 300 | 301 | [type="search"]::-webkit-search-decoration { 302 | -webkit-appearance: none; 303 | } 304 | 305 | /** 306 | * 1. Correct the inability to style clickable types in iOS and Safari. 307 | * 2. Change font properties to `inherit` in Safari. 308 | */ 309 | 310 | ::-webkit-file-upload-button { 311 | -webkit-appearance: button; /* 1 */ 312 | font: inherit; /* 2 */ 313 | } 314 | 315 | /* Interactive 316 | ========================================================================== */ 317 | 318 | /* 319 | * Add the correct display in Edge, IE 10+, and Firefox. 320 | */ 321 | 322 | details { 323 | display: block; 324 | } 325 | 326 | /* 327 | * Add the correct display in all browsers. 328 | */ 329 | 330 | summary { 331 | display: list-item; 332 | } 333 | 334 | /* Misc 335 | ========================================================================== */ 336 | 337 | /** 338 | * Add the correct display in IE 10+. 339 | */ 340 | 341 | template { 342 | display: none; 343 | } 344 | 345 | /** 346 | * Add the correct display in IE 10. 347 | */ 348 | 349 | [hidden] { 350 | display: none; 351 | } 352 | --------------------------------------------------------------------------------