[issue]
196 | | | | |
197 | | | | └─⫸ Reference issue id (optional)
198 | │ │ │
199 | │ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
200 | │ │
201 | │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
202 | │ elements|forms|http|language-service|localize|platform-browser|
203 | │ platform-browser-dynamic|platform-server|router|service-worker|
204 | │ upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve|
205 | │ devtools....
206 | │
207 | └─⫸ Commit Type: build|ci|doc|docs|feat|fix|perf|refactor|test
208 | website|chore|style|type|revert|deprecate
209 | ```
210 |
211 |
212 |
213 | ### Commiting
214 | If you are pushing a commit which addresses a submitted issue, reference your issue at the end of the commit message. You may also optionally add the major issue to the end of your commit body.
215 |
216 | References should be on their own line, following the word `Ref` or `Refs`
217 |
218 | ```
219 | Title: fix(core): fix error message displayed to users. [#22]
220 | Description: The description of your commit
221 |
222 | Ref: #22, #34, #37
223 | ```
224 |
225 |
226 |
227 |
228 |
229 | ### ESLint & Prettier
230 | The following allows you to configure ESLint and Prettier.
231 |
232 |
233 |
234 | #### Packages
235 | We use the following packages for linting and prettier.
236 |
237 |
238 |
239 | | Package | Repo File | Description |
240 | | --- | --- | --- |
241 | | [typescript-eslint](https://npmjs.com/package/typescript-eslint) | [package.json](./package.json) | Tooling which enables you to use TypeScript with ESLint |
242 | | [eslint-plugin-prettier](https://npmjs.com/package/eslint-plugin-prettier) | [package.json](./package.json) | Runs Prettier as an ESLint rule and reports differences as individual ESLint issues. |
243 | | [@typescript-eslint/parser](https://npmjs.com/package/@typescript-eslint/parser) | [package.json](./package.json) | An ESLint parser which leverages TypeScript ESTree to allow for ESLint to lint TypeScript source code. |
244 | | [@typescript-eslint/eslint-plugin](https://npmjs.com/package/@typescript-eslint/eslint-plugin) | [package.json](./package.json) | An ESLint plugin which provides lint rules for TypeScript codebases. |
245 | | [@stylistic/eslint-plugin-js](https://npmjs.com/package/@stylistic/eslint-plugin-js) | [package.json](./package.json) | JavaScript stylistic rules for ESLint, migrated from eslint core. |
246 | | [@stylistic/eslint-plugin-ts](https://npmjs.com/package/@stylistic/eslint-plugin-ts) | [package.json](./package.json) | TypeScript stylistic rules for ESLint, migrated from typescript-eslint. |
247 | | [@stylistic/eslint-plugin-plus](https://npmjs.com/package/@stylistic/eslint-plugin-plus) | [package.json](./package.json) | Supplementary rules introduced by ESLint Stylistic. |
248 | | [prettier](https://npmjs.com/package/prettier) | [package.json](./package.json) | Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary. |
249 |
250 |
251 |
252 | You can add the following to your `package.json` file:
253 | ```yml
254 | "devDependencies": {
255 | "eslint-plugin-prettier": "^5.1.3",
256 | "typescript-eslint": "^7.14.0",
257 | "@typescript-eslint/parser": "^7.16.0",
258 | "@typescript-eslint/eslint-plugin": "^7.16.0",
259 | "@stylistic/eslint-plugin-js": "^2.3.0",
260 | "@stylistic/eslint-plugin-ts": "^2.3.0",
261 | "@stylistic/eslint-plugin-plus": "^2.3.0",
262 | "prettier": "^3.2.5"
263 | },
264 | ```
265 |
266 |
267 |
268 | #### Configs
269 | Within the root folder of the repo, there are several configuration files which you should be using within the project. These files dictate how prettier and eslint will behave and what is acceptable / not acceptable.
270 |
271 |
272 |
273 | Pick the config file below depending on which version of ESLint you are using. The v8 and older `.eslint` may not be there if we have migrated over to an Eslint v9 flat config file:
274 |
275 |
276 |
277 | ##### ESLint >= v9 Config
278 | - [eslint.config.mjs](https://github.com/aetherinox/obsidian-dataview-snippets/blob/main/eslint.config.mjs)
279 | - [eslint.config.js](https://github.com/aetherinox/obsidian-dataview-snippets/blob/main/eslint.config.js)
280 |
281 | https://github.com/Aetherinox/obsidian-dataview-snippets/blob/9e4aa53c1268d8852d3a0ab3980cb25adf239e99/eslint.config.js#L1-L151
282 |
283 |
284 |
285 | ##### ESLint < v9 Config
286 | - [.eslintrc](https://github.com/aetherinox/obsidian-dataview-snippets/blob/main/.eslintrc)
287 |
288 |
289 |
290 | ##### Prettier
291 | - [.prettierrc](https://github.com/aetherinox/obsidian-dataview-snippets/blob/main/.prettierrc)
292 |
293 | ```yml
294 | printWidth: 120,
295 | tabWidth: 4,
296 | useTabs: false,
297 | semi: false,
298 | singleQuote: true,
299 | quoteProps: 'preserve',
300 | jsxSingleQuote: true,
301 | trailingComma: 'none',
302 | bracketSpacing: true,
303 | bracketSameLine: false,
304 | arrowParens: 'always',
305 | proseWrap: 'preserve',
306 | htmlWhitespaceSensitivity: 'ignore',
307 | endOfLine: 'auto',
308 | embeddedLanguageFormatting: 'auto',
309 | singleAttributePerLine: false,
310 | experimentalTernaries: false
311 | ```
312 |
313 |
314 |
315 | When submitting your pull request, these linting and style rules will be verified with all of your files. If you did not follow these rules; the linter tests on your pull request will fail; and you'll be expected to correct these issues before your submission will be transferred over for human review.
316 |
317 |
318 |
319 | ### Commenting
320 |
321 | Comment your code. If someone else comes along, they should be able to do a quick glance and have an idea of what is going on. Plus it helps novice readers to better understand the process.
322 |
323 | You may use block style commenting, or single lines:
324 |
325 | ```javascript
326 | /*
327 | make platform writable
328 | */
329 |
330 | Object.defineProperty(process, 'platform', {
331 | value: platform,
332 | writable: true
333 | });
334 |
335 | afterEach(() => {
336 | process.platform = platform;
337 | process.env.OSTYPE = OSTYPE;
338 | });
339 |
340 | /*
341 | tests to decide if the end-user is running on Darwin or another platform.
342 | */
343 |
344 | test(`Return true if platform is Darwin`, () => {
345 | process.platform = 'darwin';
346 | expect(bIsDarwin()).toBe(true);
347 | });
348 |
349 | test(`Return false if platform is not Darwin`, () => {
350 | process.platform = 'linux';
351 | expect(bIsDarwin()).toBe(false);
352 | });
353 | ```
354 |
355 |
356 |
357 | ### Casing
358 |
359 | When writing your code, ensure you stick to `camelCase`
360 |
361 | ```javascript
362 | let myVar = 'one';
363 | let secondVar = 'two';
364 | ```
365 |
366 |
367 |
368 | ### Indentation Style
369 | For files that are not controlled by prettier or eslint; you should be using the `Allman Style`. This style puts the brace associated with a control statement on the next line, indented. Statements within the braces are indented to the same level as the braces.
370 |
371 |
372 |
373 | ```javascript
374 | return {
375 | status: "failure",
376 | user:
377 | {
378 | id: "1aaa35aa-fb3a-62ae-ffec-a14g7fc401ac",
379 | label: "Test String",
380 | }
381 | };
382 | ```
383 |
384 |
385 |
386 | ### Spaces Instead Of Tabs
387 | When writing your code, set your IDE to utilize **spaces**, with a configured size of `4 characters`. If this project utilizes ESLint, you should find the file `.editorconfig` in the root directory of the repo which defines how the file should be formatted. Load that file into programs such as Visual Studio Code.
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 | **[`^ back to top ^`](#about)**
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 | [general-npmjs-uri]: https://npmjs.com
407 | [general-nodejs-uri]: https://nodejs.org
408 | [general-npmtrends-uri]: http://npmtrends.com/obsidian-dataview-snippets
409 |
410 |
411 | [github-version-img]: https://img.shields.io/github/v/tag/Aetherinox/obsidian-dataview-snippets?logo=GitHub&label=Version&color=ba5225
412 | [github-version-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases
413 |
414 |
415 | [npm-version-img]: https://img.shields.io/npm/v/obsidian-dataview-snippets?logo=npm&label=Version&color=ba5225
416 | [npm-version-uri]: https://npmjs.com/package/obsidian-dataview-snippets
417 |
418 |
419 | [pypi-version-img]: https://img.shields.io/pypi/v/obsidian-dataview-snippets-plugin
420 | [pypi-version-uri]: https://pypi.org/project/obsidian-dataview-snippets-plugin/
421 |
422 |
423 | [license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0
424 | [license-mit-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/blob/main/LICENSE
425 |
426 |
427 | [github-downloads-img]: https://img.shields.io/github/downloads/Aetherinox/obsidian-dataview-snippets/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892
428 | [github-downloads-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases
429 |
430 |
431 | [npmjs-downloads-img]: https://img.shields.io/npm/dw/%40aetherinox%2Fmkdocs-link-embeds?logo=npm&&label=Downloads&color=376892
432 | [npmjs-downloads-uri]: https://npmjs.com/package/obsidian-dataview-snippets
433 |
434 |
435 | [github-size-img]: https://img.shields.io/github/repo-size/Aetherinox/obsidian-dataview-snippets?logo=github&label=Size&color=59702a
436 | [github-size-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases
437 |
438 |
439 | [npmjs-size-img]: https://img.shields.io/npm/unpacked-size/obsidian-dataview-snippets/latest?logo=npm&label=Size&color=59702a
440 | [npmjs-size-uri]: https://npmjs.com/package/obsidian-dataview-snippets
441 |
442 |
443 | [codecov-coverage-img]: https://img.shields.io/codecov/c/github/Aetherinox/obsidian-dataview-snippets?token=MPAVASGIOG&logo=codecov&logoColor=FFFFFF&label=Coverage&color=354b9e
444 | [codecov-coverage-uri]: https://codecov.io/github/Aetherinox/obsidian-dataview-snippets
445 |
446 |
447 | [contribs-all-img]: https://img.shields.io/github/all-contributors/Aetherinox/obsidian-dataview-snippets?logo=contributorcovenant&color=de1f6f&label=contributors
448 | [contribs-all-uri]: https://github.com/all-contributors/all-contributors
449 |
450 |
451 | [github-build-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
452 | [github-build-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/release.yml
453 |
454 |
455 | [github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
456 | [github-build-pypi-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/pypi-release.yml
457 |
458 |
459 | [github-tests-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/npm-tests.yml?logo=github&label=Tests&color=2c6488
460 | [github-tests-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/npm-tests.yml
461 |
462 |
463 | [github-commit-img]: https://img.shields.io/github/last-commit/Aetherinox/obsidian-dataview-snippets?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131
464 | [github-commit-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/commits/main/
465 |
466 |
467 | [btn-github-submit-img]: https://img.shields.io/badge/submit%20new%20issue-de1f5c?style=for-the-badge&logo=github&logoColor=FFFFFF
468 | [btn-github-submit-uri]: https://github.com/aetherinox/obsidian-dataview-snippets/issues
469 |
470 |
471 |
472 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Aetherinox
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Dataview Snippets
3 |
⭕ Obsidian Snippet Collection ⭕
4 |
5 |
6 |
7 |
A collection of dataview scripts which can be utilized within your Obsidian.md notes to perform various tasks and display data.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | [![Version][github-version-img]][github-version-uri]
18 | [![Build Status][github-build-img]][github-build-uri]
19 | [![Downloads][github-downloads-img]][github-downloads-uri]
20 | [![Size][github-size-img]][github-size-img]
21 | [![Last Commit][github-commit-img]][github-commit-img]
22 | [![Contributors][contribs-all-img]](#contributors-)
23 |
24 |
25 |
26 |
27 |
28 |
29 | ---
30 |
31 |
32 |
33 | - [About](#about)
34 | - [Snippets](#snippets)
35 | - [Table of Contents: Version 1](#table-of-contents-version-1)
36 | - [Table of Contents: Version 2](#table-of-contents-version-2)
37 | - [Subfolder Data](#subfolder-data)
38 | - [Bad Links: Version 1](#bad-links-version-1)
39 | - [Tag Cloud: Version 1](#tag-cloud-version-1)
40 | - [Tag Cloud: Version 2](#tag-cloud-version-2)
41 | - [Page Cloud: Version 1](#page-cloud-version-1)
42 | - [Alphabetized List: Version 1](#alphabetized-list-version-1)
43 | - [Contributors ✨](#contributors-)
44 |
45 |
46 |
47 | ---
48 |
49 |
50 |
51 | ## About
52 | This repo originally started a single **Table of Contents** script which displays at the top of your obsidian note. However, numerous other scripts have been added since then.
53 |
54 | The snippets in this repo require you to download and install the following:
55 | - [Obsidian.md](obsidian.md/)
56 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
57 |
58 |
59 |
60 | ---
61 |
62 |
63 |
64 | ## Snippets
65 | The following snippets are available in this repo
66 |
67 |
68 |
69 | ### Table of Contents: Version 1
70 |
71 | 
72 |
73 | The `Table of Contents: Version 1` snippet displays a table of contents. It compiles a list of all your folder's current subpages and pulls the headers from each page to display in a simple and neat list.
74 |
75 |
76 |
77 | For this version, you will need to create a new **Folder Note** using the [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes), and then paste the provided code at the top of the new folder note.
78 |
79 |
80 |
81 | This version requires you to install the following:
82 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
83 | - [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)
84 |
85 |
86 |
87 |
88 |
89 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%201)
90 |
91 |
92 |
93 |
94 |
95 | ---
96 |
97 |
98 |
99 | ### Table of Contents: Version 2
100 |
101 | 
102 |
103 | The `Table of Contents: Version 2` snippet displays a table of contents. It compiles a list of all your folder's current subpages and pulls the headers from each page to display in a simple and neat list.
104 |
105 |
106 |
107 | To use this snippet, paste the provided table of contents code at the top of a regular Obsidian note. It will fetch all of the headers which exist on that same page and display them in an unordered list at the top.
108 |
109 |
110 |
111 | This version requires you to install the following:
112 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
113 |
114 |
115 |
116 |
117 |
118 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%202)
119 |
120 |
121 |
122 |
123 |
124 | ---
125 |
126 |
127 |
128 | ### Subfolder Data
129 |
130 | 
131 |
132 | The `Subfolder Data` snippet displays a table of contents listing based on a specified subfolder. This is useful if you want to pull a list of headers which exist on a page that is not associated to the current folder you are working in.
133 |
134 | The other snippets above also support subpages, but this one is a bit more customized for subfolder management.
135 |
136 |
137 |
138 | This version **requires** you to install the following:
139 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
140 |
141 | The following plugins are **optional**:
142 | - [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)
143 |
144 |
145 |
146 |
147 |
148 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Subfolder%20Data)
149 |
150 |
151 |
152 |
153 |
154 | ---
155 |
156 |
157 |
158 | ### Bad Links: Version 1
159 |
160 | 
161 |
162 | The `Bad Links: Version 1` snippet displays a list of internal links within your vault that lead nowhere (are broken).
163 |
164 | To fix these, you can delete the link on the associated page, or you can click each item in the list and create a new page. Once the link has been fixed, it will be removed from the list.
165 |
166 |
167 |
168 | This version **requires** you to install the following:
169 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
170 |
171 |
172 |
173 |
174 |
175 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Bad%20Links%201)
176 |
177 |
178 |
179 |
180 |
181 | ---
182 |
183 |
184 |
185 | ### Tag Cloud: Version 1
186 |
187 | 
188 |
189 | The `Tag Cloud: Version 1` snippet fetches a list of tags associated to your vault and displays them in a series of columns.
190 |
191 | Each tag can be clicked on, which will open the Search interface and display all other pages associated to the selected tag.
192 |
193 | The functionality of `Version 1` and `Version 2` are the same. Both just have difference appearances.
194 |
195 |
196 |
197 |
198 | This version **requires** you to install the following:
199 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
200 |
201 |
202 |
203 |
204 |
205 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Tag%20Cloud%201)
206 |
207 |
208 |
209 |
210 |
211 | ---
212 |
213 |
214 |
215 | ### Tag Cloud: Version 2
216 |
217 | 
218 |
219 | The `Tag Cloud: Version 2` snippet fetches a list of tags associated to your vault and displays them in a series of columns.
220 |
221 | Each tag can be clicked on, which will open the Search interface and display all other pages associated to the selected tag.
222 |
223 | The functionality of `Version 1` and `Version 2` are the same. Both just have difference appearances.
224 |
225 |
226 |
227 | This version **requires** you to install the following:
228 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
229 |
230 |
231 |
232 |
233 |
234 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Tag%20Cloud%202)
235 |
236 |
237 |
238 |
239 |
240 | ---
241 |
242 |
243 |
244 | ### Page Cloud: Version 1
245 |
246 | 
247 |
248 | The `Page Cloud: Version 1` snippet fetches a list of pages within your vault and displays them in a cloud structure.
249 |
250 | Each page can be clicked on which will re-direct you to that particular page. Page titles also support the frontmatter values:
251 | - name
252 | - title
253 | - alias
254 |
255 | The functionality of `Version 1` and `Version 2` are the same. Both just have difference appearances.
256 |
257 |
258 |
259 | This version **requires** you to install the following:
260 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
261 |
262 |
263 |
264 |
265 |
266 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Page%20Cloud%201)
267 |
268 |
269 |
270 |
271 |
272 | ---
273 |
274 |
275 |
276 | ### Alphabetized List: Version 1
277 |
278 | 
279 |
280 | The `Alphabetized List: Version 1` snippet fetches a list of pages within your vault and displays them in a alphabetized list.
281 |
282 | Each page can be clicked on which will re-direct you to that particular page. Page titles also support the frontmatter values:
283 | - name
284 | - title
285 | - alias
286 |
287 |
288 |
289 | This version **requires** you to install the following:
290 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
291 |
292 |
293 |
294 |
295 |
296 | [](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Alphabetized%20List%201)
297 |
298 |
299 |
300 |
301 |
302 | ---
303 |
304 |
305 |
306 | ## Contributors ✨
307 | We are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:
308 |
309 | - [Pull Request Procedure](.github/PULL_REQUEST_TEMPLATE.md)
310 | - [Contributor Policy](CONTRIBUTING.md)
311 |
312 |
313 |
314 | Want to help but can't write code?
315 | - Review [active questions by our community](https://github.com/Aetherinox/obsidian-dataview-snippets/labels/help%20wanted) and answer the ones you know.
316 |
317 |
318 |
319 | The following people have helped get this project going:
320 |
321 |
322 |
323 |
324 |
325 |
326 | [![Contributors][contribs-all-img]](#contributors-)
327 |
328 |
329 |
330 |
331 |
332 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 | [general-npmjs-uri]: https://npmjs.com
352 | [general-nodejs-uri]: https://nodejs.org
353 | [general-npmtrends-uri]: http://npmtrends.com/obsidian-dataview-snippets
354 |
355 |
356 | [github-version-img]: https://img.shields.io/github/v/tag/Aetherinox/obsidian-dataview-snippets?logo=GitHub&label=Version&color=ba5225
357 | [github-version-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases
358 |
359 |
360 | [npm-version-img]: https://img.shields.io/npm/v/obsidian-dataview-snippets?logo=npm&label=Version&color=ba5225
361 | [npm-version-uri]: https://npmjs.com/package/obsidian-dataview-snippets
362 |
363 |
364 | [pypi-version-img]: https://img.shields.io/pypi/v/obsidian-dataview-snippets-plugin
365 | [pypi-version-uri]: https://pypi.org/project/obsidian-dataview-snippets-plugin/
366 |
367 |
368 | [license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0
369 | [license-mit-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/blob/main/LICENSE
370 |
371 |
372 | [github-downloads-img]: https://img.shields.io/github/downloads/Aetherinox/obsidian-dataview-snippets/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892
373 | [github-downloads-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases
374 |
375 |
376 | [npmjs-downloads-img]: https://img.shields.io/npm/dw/%40aetherinox%2Fmkdocs-link-embeds?logo=npm&&label=Downloads&color=376892
377 | [npmjs-downloads-uri]: https://npmjs.com/package/obsidian-dataview-snippets
378 |
379 |
380 | [github-size-img]: https://img.shields.io/github/repo-size/Aetherinox/obsidian-dataview-snippets?logo=github&label=Size&color=59702a
381 | [github-size-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases
382 |
383 |
384 | [npmjs-size-img]: https://img.shields.io/npm/unpacked-size/obsidian-dataview-snippets/latest?logo=npm&label=Size&color=59702a
385 | [npmjs-size-uri]: https://npmjs.com/package/obsidian-dataview-snippets
386 |
387 |
388 | [codecov-coverage-img]: https://img.shields.io/codecov/c/github/Aetherinox/obsidian-dataview-snippets?token=MPAVASGIOG&logo=codecov&logoColor=FFFFFF&label=Coverage&color=354b9e
389 | [codecov-coverage-uri]: https://codecov.io/github/Aetherinox/obsidian-dataview-snippets
390 |
391 |
392 | [contribs-all-img]: https://img.shields.io/github/all-contributors/Aetherinox/obsidian-dataview-snippets?logo=contributorcovenant&color=de1f6f&label=contributors
393 | [contribs-all-uri]: https://github.com/all-contributors/all-contributors
394 |
395 |
396 | [github-build-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
397 | [github-build-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/release.yml
398 |
399 |
400 | [github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30
401 | [github-build-pypi-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/pypi-release.yml
402 |
403 |
404 | [github-tests-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/npm-tests.yml?logo=github&label=Tests&color=2c6488
405 | [github-tests-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/npm-tests.yml
406 |
407 |
408 | [github-commit-img]: https://img.shields.io/github/last-commit/Aetherinox/obsidian-dataview-snippets?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131
409 | [github-commit-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/commits/main/
410 |
411 |
412 |
413 |
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/example_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/example_2.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/example_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/example_3.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/example_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/example_4.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/example_5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/example_5.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 1/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Alphabetized List 1/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Alphabetized List 2/code.txt:
--------------------------------------------------------------------------------
1 | dv.container.className += ' atx-alv1-dataview'
2 |
3 | var html = "";
4 | let arrAlphabet = [];
5 | let arrPages = dv.pages( "" )
6 | .forEach( p =>
7 | {
8 | const file = p.file
9 | const file_path = file.path;
10 | const file_name = file.name;
11 | const file_label = file.frontmatter.name || file.frontmatter.title || file.frontmatter.alias || file_name;
12 |
13 | const letter = file_label.charAt( 0 ).toUpperCase( );
14 | let index = arrAlphabet.findIndex( ( item ) => item.name === letter );
15 |
16 | if ( index === -1 )
17 | arrAlphabet.push( { name: letter, pages: [ { name: file_name, label: file_label, path: file_path } ] } );
18 | else
19 | {
20 | var item = arrAlphabet.find( item => item.name == letter );
21 | let arr = item.pages;
22 |
23 | arr.push( { name: file_name, label: file_label, path: file_path } );
24 | }
25 |
26 | arrAlphabet.sort( ( a, b ) => a.name.localeCompare( b.name ) )
27 | });
28 |
29 | const ulAlphabet = dv.el( 'ul', '', { container: dv.container } );
30 |
31 | dv.list(
32 | dv.array( arrAlphabet )
33 | .forEach( obj =>
34 | {
35 | const arrPages = obj.pages;
36 | const liAlphabet = dv.el( 'li', obj.name, { container: ulAlphabet } );
37 | const ulPages = dv.el( 'ul', '', { container: liAlphabet });
38 |
39 | Promise.all( arrPages.map( async ( pages ) =>
40 | {
41 | const page_path = pages.path;
42 | const page_name = pages.name;
43 | const page_label = pages.label;
44 |
45 | const file_link = dv.fileLink( page_path, false, page_label );
46 |
47 | dv.el( 'li', file_link, { container: ulPages } );
48 |
49 | }
50 | ));
51 | })
52 | )
53 |
54 | const divClose = dv.el( 'div', html, { container: dv.container, cls: 'atx-alv1-close' } );
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/example_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/example_1.png
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/example_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/example_2.gif
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/example_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/example_3.gif
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/example_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/example_4.gif
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/example_5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/example_5.gif
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/Bad Links 1/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Bad Links 1/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Page Cloud 1/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Page Cloud 1/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/Page Cloud 1/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Page Cloud 1/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/Page Cloud 1/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Page Cloud 1/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/Page Cloud 1/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Page Cloud 1/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Page Cloud 1/images/install_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Page Cloud 1/images/install_4.gif
--------------------------------------------------------------------------------
/Snippets/Subfolder Data/README.md:
--------------------------------------------------------------------------------
1 | # Obsidian: Subfolder Data
2 | This snippet requires a copy of [Obsidian.md](obsidian.md/)
3 |
4 | This snippet requires the [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview).
5 |
6 |
7 |
8 | ## About
9 | The `Subfolder Data` snippet displays a table of contents listing based on a specified subfolder. This is useful if you want to pull a list of headers which exist on a page that is not associated to the current folder you are working in.
10 |
11 |
12 |
13 | At the time of writing this script, I am using the following:
14 |
15 | | Software | Version |
16 | | --- | --- |
17 | | [Obsidian.md](https://obsidian.md/) |  |
18 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) |  |
19 | | [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) |  |
20 |
21 |
22 |
23 | ### Previews
24 | The following are preview images of what the snippet will do and appear like:
25 |
26 |
27 |
28 | 
29 |
30 |
31 |
32 |
33 |
34 | ---
35 |
36 |
37 |
38 | ## Usage
39 |
40 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
41 | - Install [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) *(if wanting to use notes*)
42 | - Copy the code below and paste it in a note.
43 |
44 |
45 |
46 | ````shell
47 | ```dataviewjs
48 | /*
49 | Table of Contents Script > Version 3
50 |
51 | This version allows for pulling subfolder notes to
52 | another table of contents page.
53 |
54 | Excludes any subfolder table of contents pages
55 | labeled FOLDERNAME/FOLDERNAME.md
56 |
57 | Change "General" to the subpage you are wanting to target
58 | */
59 |
60 | const path_sub = "General"
61 |
62 | let count = 0;
63 | const path_base = dv.current().file.path
64 | const path_targ = path_base.substr(0, path_base.lastIndexOf("/"));
65 | const path_fnote_excl = path_sub + ".md"
66 | const filter_page = '"' + path_targ + "/" + path_sub + '"';
67 | const filter_folder = path_targ + "/" + path_sub;
68 |
69 | let p = dv.pages(filter_page)
70 | .where(p => p.file.name != dv.current().file.name) // Filter out the current page
71 | .where(p => p.file.folder == filter_folder) // Filter out folders
72 | .where(p => !p.file.path.endsWith(path_fnote_excl) ) // Filter folder note index
73 | .sort(p => p.file.path)
74 | .forEach(p =>
75 | {
76 | dv.header(4, p.file.name); // display page name as header
77 | const cache = this.app.metadataCache.getCache(p.file.path);
78 |
79 | if (cache)
80 | {
81 | const headings = cache.headings; // get headings from cache
82 |
83 | if (headings)
84 | {
85 | const houtput = headings.slice(1) // exclude the first heading
86 | .filter(h => h.level <= 6)
87 | .map(h =>
88 | {
89 | var file_head = h.heading
90 | var header_skip = file_head.replace(/ /g,"_").toLowerCase();
91 | if (header_skip === "table_of_contents" || header_skip === "toc")
92 | {
93 | return ""
94 | }
95 |
96 | count++;
97 |
98 | // Determine indentation based on heading level
99 | let indent = " ".repeat(h.level);
100 | var file_name = p.file.name;
101 |
102 | // remove backticks and tag symbols
103 | var file_head = file_head.replace(/`/g, '');
104 | var file_head = file_head.replace(/#/g, '');
105 | var file_title = h.heading.split('#')[0];
106 |
107 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]";
108 |
109 | if ( h.level == 1 )
110 | return indent + "- " + objLink + "";
111 | else if ( h.level == 2 )
112 | return indent + " - " + objLink + "";
113 | else if ( h.level == 3 )
114 | return indent + " - " + objLink + "";
115 | else if ( h.level == 4 )
116 | return indent + " - " + objLink + "";
117 | else if ( h.level == 5 )
118 | return indent + " - " + objLink + "";
119 | else if ( h.level == 6 )
120 | return indent + " - " + objLink + "";
121 | else
122 | return indent + "- " + objLink;
123 | })
124 | .join("\n")
125 |
126 | dv.el("div", houtput);
127 | dv.el("div", "
");
128 | }
129 | }
130 | });
131 |
132 | /*
133 | display NO RESULTS
134 | */
135 |
136 | if (count === 0)
137 | {
138 | const rootNode = dv.el("div", "No results", { cls: "toc_results_none" });
139 | rootNode.setAttribute("style", "text-align:center;");
140 | }
141 | ```
142 | ````
143 |
144 |
145 |
146 | Ensure you change the path to the **subfolder** you want to target:
147 |
148 | ```javascript
149 | const path_sub = "General"
150 | ```
151 |
152 |
153 |
154 | In the screenshot example, I changed it `Plugins` because the Plugins folder is a subfolder of what I wanted to target and build a table of contents from. You can use an entirely different path to whatever folder you want to generate a list of headers from.
155 |
156 | ```javascript
157 | const path_sub = "Plugins"
158 | ```
159 |
160 |
161 |
162 | Next, you need to add some custom CSS.
163 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below).
164 |
165 | Click the mini folder icon to open your **Obsidian Snippets folder**.
166 |
167 |
168 |
169 | 
170 |
171 |
172 |
173 | Create a new file named whatever (`toc.css` in our example).
174 |
175 | Copy the code below and paste it into the new `toc.css` file which should be in `YourVaultName/.obsidian/snippets/toc.css`
176 |
177 |
178 |
179 | 
180 |
181 |
182 |
183 | ```css
184 | /*
185 | Snippet: Table of Contents
186 | */
187 |
188 | /*
189 | toc > header 2
190 | */
191 |
192 | .toc_h2 a
193 | {
194 | color: #7fa8f5 !important;
195 | font-size: 10pt;
196 | font-weight: lighter;
197 | line-height: 20px;
198 | }
199 |
200 | /*
201 | toc > header 3
202 | */
203 |
204 | .toc_h3 a
205 | {
206 | color: #f85289 !important;
207 | font-size: 9pt;
208 | font-weight: lighter;
209 | line-height: 20px;
210 | }
211 |
212 | /*
213 | toc > header 4, 5, 6
214 | */
215 |
216 | .toc_h4 a, .toc_h5 a, .toc_h6 a
217 | {
218 | color: #969696 !important;
219 | font-size: 8pt;
220 | font-weight: normal;
221 | line-height: 20px;
222 | }
223 |
224 | /*
225 | toc > bad links > path
226 | */
227 |
228 | .toc_badpaths_path, .toc_badpaths_path a
229 | {
230 | color: #adadad !important;
231 | font-size: 8pt;
232 | font-weight: normal;
233 | line-height: 20px;
234 | }
235 |
236 | /*
237 | toc > no results
238 | */
239 |
240 | .toc_results_none
241 | {
242 | text-align: center;
243 | font-size: 12pt;
244 | }
245 | ```
246 |
247 |
248 |
249 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `toc.css`.
250 |
251 | 
252 |
253 |
254 |
255 | You should see a table of contents which is populated with the headings of your subfolders.
--------------------------------------------------------------------------------
/Snippets/Subfolder Data/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Subfolder Data/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/Subfolder Data/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Subfolder Data/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/Subfolder Data/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Subfolder Data/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/Subfolder Data/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Subfolder Data/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Subfolder Data/snippet-version3:
--------------------------------------------------------------------------------
1 | ```dataviewjs
2 | /*
3 | Table of Contents Script > Version 3
4 |
5 | This version allows for pulling subfolder notes to
6 | another table of contents page.
7 |
8 | Excludes any subfolder table of contents pages
9 | labeled FOLDERNAME/FOLDERNAME.md
10 |
11 | change "General" to the subpage you are wanting to target
12 | */
13 |
14 | const path_sub = "General"
15 |
16 | let count = 0;
17 | const path_base = dv.current().file.path
18 | const path_targ = path_base.substr(0, path_base.lastIndexOf("/"));
19 | const path_fnote_excl = path_sub + ".md"
20 | const filter_page = '"' + path_targ + "/" + path_sub + '"';
21 | const filter_folder = path_targ + "/" + path_sub;
22 |
23 | let p = dv.pages(filter_page)
24 | .where(p => p.file.name != dv.current().file.name) // Filter out the current page
25 | .where(p => p.file.folder == filter_folder) // Filter out folders
26 | .where(p => !p.file.path.endsWith(path_fnote_excl) ) // Filter folder note index
27 | .sort(p => p.file.path)
28 | .forEach(p =>
29 | {
30 | dv.header(4, p.file.name); // display page name as header
31 | const cache = this.app.metadataCache.getCache(p.file.path);
32 |
33 | if (cache)
34 | {
35 | const headings = cache.headings; // get headings from cache
36 |
37 | if (headings)
38 | {
39 | const houtput = headings.slice(1) // exclude the first heading
40 | .filter(h => h.level <= 6)
41 | .map(h =>
42 | {
43 | count++;
44 |
45 | // Determine indentation based on heading level
46 | let indent = " ".repeat(h.level);
47 | var file_name = p.file.name;
48 |
49 | // remove backticks and tag symbols
50 | var file_head = h.heading
51 | var file_head = file_head.replace(/`/g, '');
52 | var file_head = file_head.replace(/#/g, '');
53 | var file_title = h.heading.split('#')[0];
54 |
55 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]";
56 |
57 | if ( h.level == 1 )
58 | return indent + "- " + objLink + "";
59 | else if ( h.level == 2 )
60 | return indent + " - " + objLink + "";
61 | else if ( h.level == 3 )
62 | return indent + " - " + objLink + "";
63 | else if ( h.level == 4 )
64 | return indent + " - " + objLink + "";
65 | else if ( h.level == 5 )
66 | return indent + " - " + objLink + "";
67 | else if ( h.level == 6 )
68 | return indent + " - " + objLink + "";
69 | else
70 | return indent + "- " + objLink;
71 | })
72 | .join("\n")
73 |
74 | dv.el("div", houtput);
75 | dv.el("div", "
");
76 | }
77 | }
78 | });
79 |
80 | /*
81 | display NO RESULTS
82 | */
83 |
84 | if (count === 0)
85 | {
86 | const rootNode = dv.el("div", "No results", { cls: "toc-results-none" });
87 | rootNode.setAttribute("style", "text-align:center;");
88 | }
89 | ```
--------------------------------------------------------------------------------
/Snippets/TOC Version 1/README.md:
--------------------------------------------------------------------------------
1 |
2 |
📃 Table of Contents: Version 1 📃
3 |
4 |
A dataview script which displays a table of contents. It compiles a list of all your folder's current subpages and pulls the headers from each page to display in a simple and neat list.
5 |
6 |
7 |
8 |
9 |
10 | > [!NOTE]
11 | > Need a table of contents snippet which does **not** require the [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)?
12 | >
13 | > Click here to install [Table of Contents: Version 2](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%202)
14 |
15 |
16 |
17 | ## About
18 |
19 | This snippet requires you to have:
20 | - [Obsidian.md](obsidian.md/)
21 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
22 | - [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)
23 |
24 |
25 |
26 | The code for this version should be pasted inside a **Folder Note**. It will fetch all of the files that exist inside that folder.
27 |
28 |
29 |
30 | At the time of writing this script, I am using the following:
31 |
32 | | Software | Version |
33 | | --- | --- |
34 | | [Obsidian.md](https://obsidian.md/) |  |
35 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) |  |
36 | | [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) |  |
37 |
38 |
39 |
40 | ### Previews
41 | The following are preview images of what the snippet will do and appear like:
42 |
43 |
44 |
45 | 
46 |
47 |
48 |
49 |
50 |
51 | ---
52 |
53 |
54 |
55 | ## Usage
56 |
57 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
58 | - Install [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)
59 | - Right-click on a folder, select `Folder Note Commands` and select `Create Folder Note`
60 | - Copy the code below and paste in Obsidian folder note:
61 |
62 |
63 |
64 | ````javascript
65 | ```dataviewjs
66 |
67 | /*
68 | Table of Contents Script > Version 1
69 |
70 | This version requires the plugins:
71 | https://github.com/LostPaul/obsidian-folder-notes
72 | https://github.com/blacksmithgu/obsidian-dataview
73 |
74 | Create a new folder, right-click, and create folder note.
75 | Click inside the folder note and paste the code below.
76 |
77 | Inside that folder, place the files you want the table of
78 | contents to display. Make sure each file contains headers.
79 | */
80 |
81 | let count = 0;
82 | const path_base = dv.current().file.path
83 | const path_targ = path_base.substr(0, path_base.lastIndexOf("/"));
84 | const path_sub = ""
85 |
86 | const filter_page = '"' + path_targ + "" + path_sub + '"';
87 | const filter_folder = path_targ + path_sub;
88 |
89 | let p = dv.pages(filter_page)
90 | .where(p => p.file.name != dv.current().file.name) // Filter out the current page
91 | .where(p => p.file.folder == filter_folder) // Filter out folders
92 | .sort(p => p.file.path)
93 | .forEach(p =>
94 | {
95 | dv.header(4, p.file.name); // display page name as header
96 | const cache = this.app.metadataCache.getCache(p.file.path);
97 |
98 | if (cache)
99 | {
100 | const headings = cache.headings; // get headings from cache
101 |
102 | if ( typeof headings === 'undefined') {
103 | dv.el("div", '⭕ No Subheaders Found', { cls: "toc_results_none_subheader" });
104 | dv.el("div", "
");
105 | return;
106 | }
107 |
108 | if (headings)
109 | {
110 | const houtput = headings.slice(0) // exclude the first heading
111 | .filter(h => h.level <= 6)
112 | .map(h =>
113 | {
114 | let file_head = h.heading
115 | const header_skip = file_head.replace(/ /g,"_").toLowerCase();
116 | if (header_skip === "table_of_contents" || header_skip === "toc")
117 | {
118 | return ""
119 | }
120 |
121 | count++;
122 |
123 | // Determine indentation based on heading level
124 | let indent = " ".repeat(h.level);
125 | const file_name = p.file.name;
126 |
127 | // remove backticks and tag symbols
128 | file_head = file_head.replace(/`/g, '');
129 | file_head = file_head.replace(/#/g, '');
130 | const file_title = h.heading.split('#')[0];
131 |
132 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]";
133 |
134 | if ( h.level == 1 )
135 | return indent + "- " + objLink + "";
136 | else if ( h.level == 2 )
137 | return indent + " - " + objLink + "";
138 | else if ( h.level == 3 )
139 | return indent + " - " + objLink + "";
140 | else if ( h.level == 4 )
141 | return indent + " - " + objLink + "";
142 | else if ( h.level == 5 )
143 | return indent + " - " + objLink + "";
144 | else if ( h.level == 6 )
145 | return indent + " - " + objLink + "";
146 | else
147 | return 'No Result'
148 | })
149 | .join("\n")
150 |
151 | dv.el("div", houtput);
152 | dv.el("div", "
");
153 | }
154 | }
155 | });
156 |
157 | /*
158 | display NO RESULTS
159 | */
160 |
161 | if (count === 0)
162 | {
163 | const rootNode = dv.el("div", "No results", { cls: "toc_results_none" });
164 | rootNode.setAttribute("style", "text-align:center;");
165 | }
166 | ```
167 | ````
168 |
169 |
170 |
171 | If you want to target a subfolder / path, you can modify the variable `path_sub`. If you leave it blank, it will target the folder you paste the code in.
172 |
173 | ```javascript
174 | const path_sub = "Path/To/Subfolder"
175 | ```
176 |
177 |
178 |
179 | Next, you need to add some custom CSS.
180 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below).
181 |
182 | Click the mini folder icon to open your **Obsidian Snippets folder**.
183 |
184 |
185 |
186 | 
187 |
188 |
189 |
190 | Create a new file named whatever (`toc.css` in our example).
191 |
192 | Copy the code below and paste it into the new `toc.css` file which should be in `YourVaultName/.obsidian/snippets/toc.css`
193 |
194 |
195 |
196 | 
197 |
198 |
199 |
200 | ```css
201 | /*
202 | Snippet: Table of Contents
203 | */
204 |
205 | /*
206 | header 2
207 | */
208 |
209 | .toc_h2 a
210 | {
211 | color: #7fa8f5 !important;
212 | font-size: 10pt;
213 | font-weight: lighter;
214 | line-height: 20px;
215 | }
216 |
217 | /*
218 | header 3
219 | */
220 |
221 | .toc_h3 a
222 | {
223 | color: #f85289 !important;
224 | font-size: 9pt;
225 | font-weight: lighter;
226 | line-height: 20px;
227 | }
228 |
229 | /*
230 | header 4, 5, 6
231 | */
232 |
233 | .toc_h4 a, .toc_h5 a, .toc_h6 a
234 | {
235 | color: #969696 !important;
236 | font-size: 8pt;
237 | font-weight: normal;
238 | line-height: 20px;
239 | }
240 |
241 | /*
242 | bad links > path
243 | */
244 |
245 | .toc_badpaths_path, .toc_badpaths_path a
246 | {
247 | color: #adadad !important;
248 | font-size: 8pt;
249 | font-weight: normal;
250 | line-height: 20px;
251 | }
252 |
253 | /*
254 | no results > total
255 | */
256 |
257 | .toc_results_none
258 | {
259 | text-align: center;
260 | font-size: 12pt;
261 | }
262 |
263 | /*
264 | no results > subheader
265 | */
266 |
267 | .toc_results_none_subheader
268 | {
269 | padding-left: 12px;
270 | font-size: 10pt;
271 | }
272 | ```
273 |
274 |
275 |
276 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `toc.css`.
277 |
278 | 
279 |
280 |
281 |
282 | You should see a table of contents which is populated with the headings of your subfolders.
283 |
284 |
285 |
286 | ---
287 |
288 |
289 |
290 | ## Customization
291 | ### How to make page title above the each list appear bigger
292 | In your code, locate
293 | ```javascript
294 | dv.header(4, p.file.name);
295 | ```
296 |
297 | The `4` stands for `H4` or header 4. To make the text bigger, change that number to `3 or lower`. Overall, it accepts any number between `1 - 6`, with 1 being the biggest and 6 being the smallest text size.
298 |
299 |
300 |
301 |
302 | ### Make each page title not display as a listed item
303 | Locate the code toward the top:
304 | ```javascript
305 | dv.header(4, p.file.name);
306 | ```
307 | and replace it with:
308 | ```javascript
309 | dv.el("div", p.file.name);
310 | ```
311 |
312 | This will force each page title to display in a `div` and not as header object.
313 |
314 |
315 |
316 |
317 | ### My list is cutting off the first header of each page
318 | Locate the following code:
319 | ```javascript
320 | const houtput = headings.slice(1)
321 | ```
322 |
323 | The number `1` represents how many headers on the page that should be excluded from the first going from the top down. If you enter the number `0`, then no headers will be filtered out / all will show in the list. If you enter `3`, then the first three headers of each page will not appear in the table of contents list.
324 |
325 | To disable any headers from being excluded in the list, change the code above to the following:
326 | ```javascript
327 | const houtput = headings.slice(0)
328 | ```
329 |
330 |
331 |
332 |
333 | ### Exclude certain headers from appearing in the list
334 | Much like the example above which allows you to filter from from the top, you can also filter exactly which headers display in the list with the following code:
335 | ```javascript
336 | .filter(h => h.level <= 6)
337 | ```
338 |
339 | The number `6` represents which headers will be included in the list. If you change the value to a `4`, that means any sections of your page with headers 5 or 6 will not show.
340 | ```
341 | ##### This is H5
342 | ###### This is H6
343 | ```
344 |
345 |
346 |
347 |
348 | ### Making the gap between each list smaller/bigger
349 | You need to modify the following:
350 | ```javascript
351 | dv.el("div", "
");
352 | ```
353 | Each `
` is a line break. The more breaks you add, the larger the gap between each list. Remove each break to make the gap smaller.
354 |
355 |
356 |
--------------------------------------------------------------------------------
/Snippets/TOC Version 1/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 1/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/TOC Version 1/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 1/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/TOC Version 1/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 1/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/TOC Version 1/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 1/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/TOC Version 2/README.md:
--------------------------------------------------------------------------------
1 |
2 |
📃 Table of Contents: Version 2 📃
3 |
4 |
A dataview script which displays a table of contents. The code within this page should be pasted at the top of your Obsidian note which contains headers and subheaders. It will populate a list of all the headers and show them in a list.
5 |
6 |
7 |
8 |
9 |
10 | > [!NOTE]
11 | > Want a table of contents which is compatible with the [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)?
12 | >
13 | > Click here to install [Table of Contents: Version 1](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%201)
14 |
15 |
16 |
17 | ## About
18 |
19 | This snippet requires you to have:
20 | - [Obsidian.md](obsidian.md/)
21 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
22 |
23 |
24 |
25 | The code for this version should be pasted at the top of a note. It will fetch all of the headers that exist on that page and display them in an unordered list at the top.
26 |
27 |
28 |
29 | At the time of writing this script, I am using the following:
30 |
31 | | Software | Version |
32 | | --- | --- |
33 | | [Obsidian.md](https://obsidian.md/) |  |
34 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) |  |
35 |
36 |
37 |
38 | ### Previews
39 | The following are preview images of what the snippet will do and appear like:
40 |
41 |
42 |
43 | 
44 |
45 |
46 |
47 |
48 |
49 | ---
50 |
51 |
52 |
53 | ## Usage
54 |
55 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
56 | - Copy the code below and paste it at the top of a note you want to display a list of headers for:
57 |
58 |
59 |
60 | ````javascript
61 | ```dataviewjs
62 |
63 | /*
64 | Table of Contents Script > Version 2
65 |
66 | Should be pasted at the top of the page to outline
67 | all of the headers you want to list on the same page
68 |
69 | For this script, "path_sub" should not be edited.
70 | */
71 |
72 | let count = 0;
73 | const path_base = dv.current().file.path
74 | const path_targ = path_base.substr(0, path_base.lastIndexOf(".md"));
75 | const path_sub = ""
76 |
77 | const filter_page = '"' + path_targ + "" + path_sub + '"';
78 | const filter_folder = path_targ + path_sub;
79 |
80 | let p = dv.pages(filter_page)
81 | .sort(p => p.file.path)
82 | .forEach(p =>
83 | {
84 | // dv.header(4, p.file.name); // display page name as header
85 | const cache = this.app.metadataCache.getCache(p.file.path);
86 |
87 | if (cache)
88 | {
89 | const headings = cache.headings; // get headings from cache
90 |
91 | if (headings)
92 | {
93 | const houtput = headings.slice(0) // exclude the first heading
94 | .filter(h => h.level <= 6)
95 | .map(h =>
96 | {
97 | let file_head = h.heading
98 | const header_skip = file_head.replace(/ /g,"_").toLowerCase();
99 | if (header_skip === "table_of_contents" || header_skip === "toc")
100 | {
101 | return ""
102 | }
103 |
104 | count++;
105 |
106 | // Determine indentation based on heading level
107 | let indent = " ".repeat(h.level);
108 | const file_name = p.file.name;
109 |
110 | // remove backticks and tag symbols
111 | file_head = file_head.replace(/`/g, '');
112 | file_head = file_head.replace(/#/g, '');
113 | const file_title = h.heading.split('#')[0];
114 |
115 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]";
116 |
117 | if ( h.level == 1 )
118 | return indent + "- " + objLink + "";
119 | else if ( h.level == 2 )
120 | return indent + " - " + objLink + "";
121 | else if ( h.level == 3 )
122 | return indent + " - " + objLink + "";
123 | else if ( h.level == 4 )
124 | return indent + " - " + objLink + "";
125 | else if ( h.level == 5 )
126 | return indent + " - " + objLink + "";
127 | else if ( h.level == 6 )
128 | return indent + " - " + objLink + "";
129 | else
130 | return indent + "- " + objLink;
131 | })
132 | .join("\n")
133 |
134 | dv.el("div", houtput);
135 | dv.el("div", "
");
136 | }
137 | }
138 | });
139 |
140 | /*
141 | display NO RESULTS
142 | */
143 |
144 | if (count === 0)
145 | {
146 | const rootNode = dv.el("div", "No results", { cls: "toc_results_none" });
147 | rootNode.setAttribute("style", "text-align:center;");
148 | }
149 | ```
150 | ````
151 |
152 |
153 |
154 | If you want to target a subfolder / path, you can modify the variable `path_sub`. If you leave it blank, it will target the folder you paste the code in.
155 |
156 | ```javascript
157 | const path_sub = "Path/To/Subfolder"
158 | ```
159 |
160 |
161 |
162 | Next, you need to add some custom CSS.
163 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below).
164 |
165 | Click the mini folder icon to open your **Obsidian Snippets folder**.
166 |
167 |
168 |
169 | 
170 |
171 |
172 |
173 | Create a new file named whatever (`toc.css` in our example).
174 |
175 | Copy the code below and paste it into the new `toc.css` file which should be in `YourVaultName/.obsidian/snippets/toc.css`
176 |
177 |
178 |
179 | 
180 |
181 |
182 |
183 | ```css
184 | /*
185 | Snippet: Table of Contents > v2
186 | */
187 |
188 | /*
189 | toc > header 2
190 | */
191 |
192 | .toc_h2 a
193 | {
194 | color: #7fa8f5 !important;
195 | font-size: 10pt;
196 | font-weight: lighter;
197 | line-height: 20px;
198 | }
199 |
200 | /*
201 | toc > header 3
202 | */
203 |
204 | .toc_h3 a
205 | {
206 | color: #f85289 !important;
207 | font-size: 9pt;
208 | font-weight: lighter;
209 | line-height: 20px;
210 | }
211 |
212 | /*
213 | toc > header 4, 5, 6
214 | */
215 |
216 | .toc_h4 a, .toc_h5 a, .toc_h6 a
217 | {
218 | color: #969696 !important;
219 | font-size: 8pt;
220 | font-weight: normal;
221 | line-height: 20px;
222 | }
223 |
224 | /*
225 | toc > bad links > path
226 | */
227 |
228 | .toc_badpaths_path, .toc_badpaths_path a
229 | {
230 | color: #adadad !important;
231 | font-size: 8pt;
232 | font-weight: normal;
233 | line-height: 20px;
234 | }
235 |
236 | /*
237 | toc > no results
238 | */
239 |
240 | .toc_results_none
241 | {
242 | text-align: center;
243 | font-size: 12pt;
244 | }
245 | ```
246 |
247 |
248 |
249 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `toc.css`.
250 |
251 | 
252 |
253 |
254 |
255 | You should see a table of contents which is populated with the headings of your subfolders.
256 |
257 |
258 |
259 | ---
260 |
261 |
262 |
263 | ## Customization
264 | ### How to make page title above the each list appear bigger
265 | In your code, locate
266 | ```javascript
267 | dv.header(4, p.file.name);
268 | ```
269 |
270 | The `4` stands for `H4` or header 4. To make the text bigger, change that number to `3 or lower`. Overall, it accepts any number between `1 - 6`, with 1 being the biggest and 6 being the smallest text size.
271 |
272 |
273 |
274 |
275 | ### Make each page title not display as a listed item
276 | Locate the code toward the top:
277 | ```javascript
278 | dv.header(4, p.file.name);
279 | ```
280 | and replace it with:
281 | ```javascript
282 | dv.el("div", p.file.name);
283 | ```
284 |
285 | This will force each page title to display in a `div` and not as header object.
286 |
287 |
288 |
289 |
290 | ### My list is cutting off the first header of each page
291 | Locate the following code:
292 | ```javascript
293 | const houtput = headings.slice(1)
294 | ```
295 |
296 | The number `1` represents how many headers on the page that should be excluded from the first going from the top down. If you enter the number `0`, then no headers will be filtered out / all will show in the list. If you enter `3`, then the first three headers of each page will not appear in the table of contents list.
297 |
298 | To disable any headers from being excluded in the list, change the code above to the following:
299 | ```javascript
300 | const houtput = headings.slice(0)
301 | ```
302 |
303 |
304 |
305 |
306 | ### Exclude certain headers from appearing in the list
307 | Much like the example above which allows you to filter from from the top, you can also filter exactly which headers display in the list with the following code:
308 | ```javascript
309 | .filter(h => h.level <= 6)
310 | ```
311 |
312 | The number `6` represents which headers will be included in the list. If you change the value to a `4`, that means any sections of your page with headers 5 or 6 will not show.
313 | ```
314 | ##### This is H5
315 | ###### This is H6
316 | ```
317 |
318 |
319 |
320 |
321 | ### Making the gap between each list smaller/bigger
322 | You need to modify the following:
323 | ```javascript
324 | dv.el("div", "
");
325 | ```
326 | Each `
` is a line break. The more breaks you add, the larger the gap between each list. Remove each break to make the gap smaller.
327 |
328 |
329 |
--------------------------------------------------------------------------------
/Snippets/TOC Version 2/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 2/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/TOC Version 2/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 2/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/TOC Version 2/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 2/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/TOC Version 2/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/TOC Version 2/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 1/README.md:
--------------------------------------------------------------------------------
1 | # Obsidian: Tag Cloud : Version 1
2 | This snippet requires a copy of [Obsidian.md](obsidian.md/)
3 |
4 | This snippet requires the [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview).
5 |
6 |
7 |
8 | ## About
9 | The `Tag Cloud` snippet will fetch a list of your vault's current tags and display them in a colorful list.
10 |
11 |
12 |
13 | At the time of writing this script, I am using the following:
14 |
15 | | Software | Version |
16 | | --- | --- |
17 | | [Obsidian.md](https://obsidian.md/) |  |
18 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) |  |
19 |
20 |
21 |
22 | > [!WARNING] WARNING - Using Special Characters In Tags
23 | > Obsidian currently doesn't support using periods within tags. If you have any tags that contain a period, your tag list may not render.
24 | >
25 | > ex: `#my.tag`
26 |
27 |
28 |
29 | ### Previews
30 | The following are preview images of what the snippet will do and appear like:
31 |
32 |
33 |
34 | 
35 |
36 |
37 |
38 | ---
39 |
40 |
41 |
42 | ## Usage
43 |
44 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview)
45 | - Copy the code below and paste it in a note.
46 |
47 |
48 |
49 | ````shell
50 | ```dataviewjs
51 | /*
52 | Snippet: Tag Cloud - Version 1
53 |
54 | This snippet requires the Dataview Plugin
55 | https://github.com/blacksmithgu/obsidian-dataview
56 |
57 | View settings at:
58 | https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Tag%20Cloud%201
59 | */
60 |
61 | /*
62 | Settings
63 | */
64 |
65 | const QueryStr = `""`;
66 | const QueryFiles = dv.pages( QueryStr );
67 |
68 | const bRandomColor = true;
69 | const sortOption = 1;
70 | const weightBacklinks = 0.1;
71 | const weightWordCount = 0.05;
72 | const minFontSize = 12;
73 | const maxFontSize = 36;
74 | const tagsFilter = [ "#tag1", "#tag2" ];
75 | const arrColors = [];
76 |
77 | dv.container.className += ' atx-tcv1-dataview'
78 |
79 | /*
80 | Generate 40 colors
81 | */
82 |
83 | for ( let i = 0; i < 40; i++ )
84 | {
85 |
86 | let R = Math.floor( ( Math.random( ) * 100 ) + 100 );
87 | let G = Math.floor( ( Math.random( ) * 100 ) + 100 );
88 | let B = Math.floor( ( Math.random( ) * 100 ) + 100 );
89 |
90 | let rgb = ( R << 16 ) + ( G << 8 ) + B;
91 | let itemColor = `#${rgb.toString( 16 )}`;
92 |
93 | arrColors.push( itemColor );
94 | }
95 |
96 | /*
97 | Get all backlinks
98 | */
99 |
100 | async function QueryBacklinks( q )
101 | {
102 | const file = q.split( '/' ).pop( ).split( "." ).slice( 0, -1 ).join( "." );
103 | return dv.query(
104 | `
105 | LIST
106 | FROM [[${file}]] AND ${QueryStr}
107 | SORT file.name DESC
108 | `
109 | );
110 | }
111 |
112 | /*
113 | Get number of words in each file
114 | */
115 |
116 | async function QueryWordcount( q )
117 | {
118 | const fs = require( 'fs' );
119 | const path = require( 'path' );
120 | const text = fs.readFileSync( path.join( app.vault.adapter.basePath, q ), 'utf-8' );
121 | const pattern = /---[\s\S]*?---|```[\s\S]*?```|\$[\s\S]*?\$|\$\$[\s\S]*?\$\$/g;
122 | const cleanedText = text.replace( pattern, '' );
123 | const matchText = cleanedText.match( /\S+/g );
124 |
125 | if ( !matchText )
126 | return 0;
127 |
128 | return matchText.length;
129 | }
130 |
131 | /*
132 | Calculate font text size which is determined by number of backlinks
133 | and number of words available.
134 | */
135 |
136 | function Generate_FontSize( backlinks, wordCount )
137 | {
138 | const calcFontSize = Math.sqrt( ( backlinks * weightBacklinks ) + ( wordCount * weightWordCount ) ) * 2.5;
139 | return Math.round( ( calcFontSize / 100 ) * ( maxFontSize - minFontSize ) + minFontSize );
140 | }
141 |
142 | /*
143 | Generate font color
144 | */
145 |
146 | function Generate_Color( tagName, tagInfo )
147 | {
148 | if ( tagName == null ) { return "#FFFFFF"; }
149 |
150 | let cntColors = Object.keys( arrColors ).length;
151 | const tagWords = tagName.split(/\W+/g);
152 | const colorIndex = Math.floor( Math.random( ) * cntColors );
153 | const colorID = dv.pages( tagName ).length;
154 |
155 | if ( bRandomColor === true )
156 | return arrColors[ Object.keys( arrColors )[ colorIndex ] ];
157 |
158 | return arrColors[ Object.keys( arrColors )[ colorID ] ];
159 | }
160 |
161 | /*
162 | Sort > DESC / ASC
163 |
164 | alphabetize array results
165 | */
166 |
167 | function Sort_DESC( arr )
168 | {
169 | arr.sort( ( a, b ) => a.id.localeCompare( b.id ) )
170 | return arr;
171 | }
172 |
173 | function Sort_ASC( arr )
174 | {
175 | arr.sort( ( a, b ) => b.id.localeCompare( a.id ) )
176 | return arr;
177 | }
178 |
179 | /*
180 | Sort > Shuffle
181 |
182 | randomized array results
183 | */
184 |
185 | function Sort_Shuffle( arr )
186 | {
187 | for ( let i = arr.length - 1; i > 0; i-- )
188 | {
189 | const j = Math.floor( Math.random( ) * ( i + 1 ) );
190 | [ arr[ i ], arr[ j ] ] = [ arr[ j ], arr[ i ] ];
191 | }
192 |
193 | return arr;
194 | }
195 |
196 | /*
197 | Create Cloud
198 | */
199 |
200 | const CreateTagCloud = async ( ) =>
201 | {
202 | const tags = new Map( );
203 | const files = new Map( );
204 |
205 | /*
206 | Add all .md files to the tags map with their backlinks and word count
207 | */
208 |
209 | Promise.all( QueryFiles.map( async ( f ) =>
210 | {
211 | const file = f.file
212 | const blq = QueryBacklinks( file.path )
213 | const wcq = QueryWordcount( file.path )
214 |
215 | if ( file.tags )
216 | {
217 | await Promise.all( file.tags.map( async ( tag ) =>
218 | {
219 | if ( !tags.has( tag ) )
220 | tags.set( tag, { backlinks: 0, wordCount: 0 } );
221 |
222 | const tagInfo = tags.get( tag );
223 | const res = await blq;
224 |
225 | tagInfo.backlinks += res.value.values.length;
226 |
227 | const wc = await wcq;
228 | tagInfo.wordCount += wc;
229 | } ) );
230 | }
231 |
232 | for ( let i = 0; i < tagsFilter.length; i++ )
233 | {
234 | if ( tags.has( tagsFilter[ i ] ) )
235 | tags.delete( tagsFilter[ i ] );
236 | }
237 |
238 | const fileInfo = { backlinks: 0, wordCount: 0 };
239 | const res = await blq;
240 | fileInfo.backlinks = res.value.values.length;
241 | const wc = await wcq;
242 | fileInfo.wordCount = wc;
243 |
244 | files.set( file, fileInfo );
245 |
246 | })).then( ( ) =>
247 | {
248 | const data = []
249 |
250 | /*
251 | Calculate font size and font color.
252 | */
253 |
254 | let count = 0;
255 | tags.forEach( ( tagInfo, tagName ) =>
256 | {
257 | count++;
258 | const fontSize = Generate_FontSize( tagInfo.backlinks, tagInfo.wordCount );
259 | const color = Generate_Color( tagName, tagInfo );
260 | const length = dv.pages( tagName ).length;
261 |
262 | data.push( { name: `\\${tagName}`, id: tagName, length: length, fontSize, color } );
263 | });
264 |
265 | /*
266 | No tags found
267 | */
268 |
269 | if (count === 0)
270 | {
271 | const rootNode = dv.el("div", "🔖 No Tags Found", { cls: "atx-tcv1-results_none" });
272 | rootNode.setAttribute("style", "text-align:center;");
273 | return ``;
274 | }
275 |
276 | /*
277 | Sorting functions
278 | */
279 |
280 | const sortOptions =
281 | {
282 | 1: 'Sort_DESC',
283 | 2: 'Sort_ASC',
284 | 3: 'Sort_Shuffle',
285 | };
286 |
287 | let funcSort = sortOptions[ sortOption ]
288 |
289 | if ( funcSort === undefined )
290 | funcSort = sortOptions[ 1 ]
291 |
292 | /*
293 | Return results
294 | */
295 |
296 | return eval( funcSort )( data ).map( ( tag ) =>
297 | {
298 | return ``;
299 | } ).join( "" );
300 | } ).then( res => dv.paragraph( res ) )
301 | .catch( error =>
302 | {
303 | console.error( "Error: " + error );
304 | } );
305 | }
306 |
307 | CreateTagCloud( )
308 | ```
309 | ````
310 |
311 |
312 |
313 | #### Minified Version
314 | This version only formats the settings. All other formatting and comments are removed.
315 |
316 |
317 |
318 | ````shell
319 | ```dataviewjs
320 | const QueryStr = `""`;
321 | const QueryFiles = dv.pages( QueryStr );
322 |
323 | const bRandomColor = true;
324 | const sortOption = 1;
325 | const weightBacklinks = 0.1;
326 | const weightWordCount = 0.05;
327 | const minFontSize = 12;
328 | const maxFontSize = 36;
329 | const tagsFilter = [ "#tag1", "#tag2" ];
330 |
331 | const arrColors=[];dv.container.className+=" atx-tcv1-dataview";for(let t=0;t<40;t++){let t=Math.floor(100*Math.random()+100),o=Math.floor(100*Math.random()+100),e=Math.floor(100*Math.random()+100),a=(t<<16)+(o<<8)+e,n=`#${a.toString(16)}`;arrColors.push(n)}async function QueryBacklinks(t){const o=t.split("/").pop().split(".").slice(0,-1).join(".");return dv.query(`\n LIST\n FROM [[${o}]] AND ${QueryStr}\n SORT file.name DESC\n `)}async function QueryWordcount(t){const o=require("fs"),e=require("path"),a=o.readFileSync(e.join(app.vault.adapter.basePath,t),"utf-8").replace(/---[\s\S]*?---|```[\s\S]*?```|\$[\s\S]*?\$|\$\$[\s\S]*?\$\$/g,"").match(/\S+/g);return a?a.length:0}function Generate_FontSize(t,o){const e=2.5*Math.sqrt(t*weightBacklinks+o*weightWordCount);return Math.round(e/100*(maxFontSize-minFontSize)+minFontSize)}function Generate_Color(t,o){if(null==t)return"#FFFFFF";let e=Object.keys(arrColors).length;t.split(/\W+/g);const a=Math.floor(Math.random()*e),n=dv.pages(t).length;return!0===bRandomColor?arrColors[Object.keys(arrColors)[a]]:arrColors[Object.keys(arrColors)[n]]}function Sort_DESC(t){return t.sort(((t,o)=>t.id.localeCompare(o.id))),t}function Sort_ASC(t){return t.sort(((t,o)=>o.id.localeCompare(t.id))),t}function Sort_Shuffle(t){for(let o=t.length-1;o>0;o--){const e=Math.floor(Math.random()*(o+1));[t[o],t[e]]=[t[e],t[o]]}return t}const CreateTagCloud=async()=>{const tags=new Map,files=new Map;Promise.all(QueryFiles.map((async t=>{const o=t.file,e=QueryBacklinks(o.path),a=QueryWordcount(o.path);o.tags&&await Promise.all(o.tags.map((async t=>{tags.has(t)||tags.set(t,{backlinks:0,wordCount:0});const o=tags.get(t),n=await e;o.backlinks+=n.value.values.length;const r=await a;o.wordCount+=r})));for(let t=0;t{const data=[];let count=0;if(tags.forEach(((t,o)=>{count++;const e=Generate_FontSize(t.backlinks,t.wordCount),a=Generate_Color(o,t),n=dv.pages(o).length;data.push({name:`\\${o}`,id:o,length:n,fontSize:e,color:a})})),0===count){const t=dv.el("div","🔖 No Tags Found",{cls:"atx-tcv1-results_none"});return t.setAttribute("style","text-align:center;"),""}const sortOptions={1:"Sort_DESC",2:"Sort_ASC",3:"Sort_Shuffle"};let funcSort=sortOptions[sortOption];return void 0===funcSort&&(funcSort=sortOptions[1]),eval(funcSort)(data).map((t=>``)).join("")})).then((t=>dv.paragraph(t))).catch((t=>{console.error("Error: "+t)}))};CreateTagCloud();
332 | ```
333 | ````
334 |
335 |
336 |
337 |
338 |
339 | **[`^ back to top ^`](#table-of-contents-)**
340 |
341 |
342 |
343 |
344 |
345 | ---
346 |
347 |
348 |
349 | Next, you need to add some custom CSS.
350 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below).
351 |
352 | Click the mini folder icon to open your **Obsidian Snippets folder**.
353 |
354 |
355 |
356 | 
357 |
358 |
359 |
360 | Create a new file named whatever (`tag_cloud_v1.css` in our example).
361 |
362 | Copy the code below and paste it into the new `tag_cloud_v1.css` file which should be in `YourVaultName/.obsidian/snippets/tag_cloud_v1.css`
363 |
364 |
365 |
366 | 
367 |
368 |
369 |
370 | ```css
371 | /*
372 | Snippet: Tag Cloud - Version 1
373 | */
374 |
375 | /*
376 | animation: glow
377 | */
378 |
379 | @keyframes anim_glow
380 | {
381 | from
382 | {
383 | text-shadow: 0 0 110px #6f00ff, 0 0 120px #0084ff, 0 0 130px #e60073, 0 0 140px #e60073, 0 0 150px #e60073, 0 0 160px #e60073, 0 0 170px #e60073;
384 | }
385 | to
386 | {
387 | text-shadow: 0 0 20px #6f00ff, 0 0 30px #ff4da6, 0 0 40px #ff4da6, 0 0 50px #ff4da6, 0 0 60px #ff4da6, 0 0 70px #ff4da6, 0 0 80px #ff4da6;
388 | }
389 | }
390 |
391 | /*
392 | animation: pulse
393 | */
394 |
395 | @keyframes pulse
396 | {
397 | 0%
398 | {
399 | transform: scale(0.85);
400 | box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.7);
401 | }
402 |
403 | 70%
404 | {
405 | transform: scale(1);
406 | box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);
407 | }
408 |
409 | 100%
410 | {
411 | transform: scale(0.85);
412 | box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
413 | }
414 | }
415 |
416 | /*
417 | Dataview parent div
418 | */
419 |
420 | .atx-tcv1-dataview
421 | {
422 | padding-left: var( --atx-tcv2-general-container-padding );
423 | padding-right: var( --atx-tcv2-general-container-padding );
424 | padding-top: 20px;
425 | padding-bottom: 20px;
426 | }
427 |
428 | /*
429 | Tag Cloud > Item
430 | */
431 |
432 | .cloudtags-v1-item
433 | {
434 | margin-top: 5px;
435 | margin-bottom: 5px;
436 | margin-left: 7px;
437 | margin-right: 7px;
438 | padding-left: 7px;
439 | padding-right: 7px;
440 | padding-top: 4px;
441 | padding-bottom: 4px;
442 | background-color: #252525;
443 | border: 1px solid #353535 !important;
444 | border-radius: 6px;
445 | display: inline-block;
446 | font-weight: bold;
447 | position: relative;
448 | }
449 |
450 | .cloudtags-v1-item:hover
451 | {
452 | opacity: 1;
453 | background: #810d3d;
454 | border: 1px solid #dd2a74 !important;
455 | cursor: pointer;
456 | animation-name: pulse, anim_glow;
457 | animation-duration: 2s, 1s;
458 | animation-timing-function: ease, ease-in-out;
459 | animation-iteration-count: infinite, infinite;
460 | animation-direction: normal, alternate;
461 | }
462 |
463 | .cloudtags-v1-item:hover a
464 | {
465 | color: #FFF !important;
466 | background: none;
467 | }
468 |
469 | /*
470 | Tag Cloud > Links
471 | */
472 |
473 | a.cloudtags-v1-link
474 | {
475 | line-height: 30px;
476 | vertical-align: middle;
477 | text-decoration: none;
478 | }
479 |
480 | /*
481 | Tag Cloud > Length
482 | */
483 |
484 | .tagcloud-v1-length
485 | {
486 | border-radius: 50%;
487 | width: 18px;
488 | height: 18px;
489 | background: #424242;
490 | color: #FFF;
491 | text-align: center;
492 | font: 8px sans-serif;
493 | position: absolute;
494 | vertical-align: middle;
495 | margin: auto 0;
496 | left: 3%;
497 | top: -5px;
498 | transform: translateX(-50%);
499 | line-height: 19px;
500 | }
501 |
502 | /*
503 | Tag Cloud > No results
504 | */
505 |
506 | .atx-tcv1-results_none
507 | {
508 | text-align: center;
509 | font-size: 14pt;
510 | }
511 |
512 | .atx-tcv1-results_none_subheader
513 | {
514 | padding-left: 12px;
515 | font-size: 10pt;
516 | }
517 | ```
518 |
519 |
520 |
521 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `tag_cloud_v1.css`.
522 |
523 | 
524 |
525 |
526 |
527 | You should see a list of tags associated to your vault.
528 |
529 |
530 |
531 | ---
532 |
533 |
534 |
535 | ## Customization
536 | The section below explains how to customize this snippet.
537 |
538 |
539 |
540 | ### Filtering Folders, Pages & Tags
541 | This snippet allows you to filter out folders, pages and tags which will not be included in your list of generated tags that appear in your cloud. The syntax is the same as normal Dataview queries.
542 |
543 | To filter out folders or pages, edit the following:
544 |
545 | ```javascript
546 | const QueryStr = `""`;
547 | ```
548 |
549 |
550 |
551 | #### Exclude Folders
552 |
553 | To filter out or exclude the folder `"My Personal Stuff"`, and all notes in that folder; use the following:
554 |
555 | ```javascript
556 | const QueryStr = `-"My Personal Stuff"`;
557 | ```
558 |
559 | The folder name **must** be enclosed in quotation marks `"`.
560 |
561 |
562 |
563 | The `-` character represents an `exclude`, and must be used OUTSIDE the quotation marks.
564 |
565 |
566 |
567 | To exclude multiple folders, add `AND` between each folder.
568 |
569 | ```javascript
570 | const QueryStr = `-"My Personal Stuff" AND `-"Another Folder"`;
571 | ```
572 |
573 |
574 |
575 |
576 | #### Exclude Page
577 | To filter out a specific file or page, it is similar to the above, except you must provide the full path to the page, including the folder.
578 |
579 |
580 |
581 | For example, if you have a folder named `Personal Stuff`, and a page inside called `My Pin Codes`, you can exclude it using:
582 |
583 | ```javascript
584 | const QueryStr = `-"Personal Stuff/My PIN Codes"`;
585 | ```
586 |
587 |
588 |
589 |
590 | #### Exclude Tags
591 | To filter out specific tags, this is done slightly different than the other options above. You can prevent certain tags from appearing in your cloud by modifying the following property:
592 |
593 |
594 |
595 | ```javascript
596 | const tagsFilter = [ "#tag1", "#tag2" ];
597 | ```
598 |
599 |
600 |
601 | Ensure you use the structure provided. Each tag must be wrapped in quotation marks `"`, with a comma `,` separating each one.
602 |
603 |
604 |
605 |
606 | ### Change Sorting
607 | This snippet allows for three ways of sorting tags:
608 | 1. Alphabetically (Descending A-Z)
609 | 2. Alphabetically (Ascending Z-A)
610 | 3. Random / Shuffle
611 |
612 |
613 |
614 | To change the sorting, edit the property:
615 |
616 | ```javascript
617 | const sortOption = 1;
618 | ```
619 |
620 |
621 |
622 |
623 | ### Random Tag Colors
624 | Tags can either be assigned random colors, or colors can be assigned depending on how many times that tag has been called.
625 |
626 |
627 |
628 | To change this, edit the property:
629 |
630 | ```javascript
631 | const bRandomColor = true;
632 | ```
633 |
634 |
635 |
636 |
637 | ### Font Size
638 | The font size of a tag is determined by two things:
639 | 1. Number of times a tag is used
640 | 2. Number of words associated to a tag.
641 |
642 |
643 |
644 | To limit the font sizes that are used, edit the two properties below:
645 |
646 | ```javascript
647 | const minFontSize = 12;
648 | const maxFontSize = 32;
649 | ```
650 |
651 |
652 |
653 |
654 | ### Font Weight
655 | The font weight of a tag is determined by two things:
656 | 1. Number of times a tag is used
657 | 2. Number of words associated to a tag.
658 |
659 |
660 |
661 | To limit the font weight sizes used, edit the two properties below. The lower the value, the thinner the tag. Higher numbers will display more bold text. This setting also plays a role in the [Font Size](#font-size)
662 |
663 | ```javascript
664 | const weightBacklinks = 0.1;
665 | const weightWordCount = 0.3;
666 | ```
667 |
668 |
669 |
670 |
671 | ### Cloud Colors
672 | As of `v1.3.0`, this snippet auto generates the colors that will be used for each tag listed in the cloud. The color generation code will keep the color tones in the **pastel** range, and will exclude darker colors since the background box color is dark.
673 |
674 |
675 |
676 | To modify the color range, edit the following code:
677 |
678 | ```javascript
679 | let R = Math.floor( ( Math.random( ) * 100 ) + 100 );
680 | let G = Math.floor( ( Math.random( ) * 100 ) + 100 );
681 | let B = Math.floor( ( Math.random( ) * 100 ) + 100 );
682 | ```
683 |
684 |
685 |
686 | For brighter colors, increase `100`. Don't exceed `255`.
687 |
688 | For darker colors, decrease `100`. Don't go below `0`.
689 |
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 1/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 1/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 1/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 1/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 1/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 1/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 1/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 1/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 2/images/example_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 2/images/example_1.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 2/images/install_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 2/images/install_1.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 2/images/install_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 2/images/install_2.png
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 2/images/install_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 2/images/install_3.gif
--------------------------------------------------------------------------------
/Snippets/Tag Cloud 2/images/install_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/8db4ac9a0753363a7140c0af35cdeb0128b15ee3/Snippets/Tag Cloud 2/images/install_4.gif
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | const tsParser = require('@typescript-eslint/parser');
2 | const js = require('@eslint/js');
3 | const globals = require('globals');
4 | const ts = require('@typescript-eslint/eslint-plugin');
5 | const eslintConfigPrettier = require('eslint-config-prettier');
6 | const prettier = require('eslint-plugin-prettier');
7 | const stylisticJs = require('@stylistic/eslint-plugin-js');
8 | const stylisticTs = require('@stylistic/eslint-plugin-ts');
9 | const stylisticPlus = require('@stylistic/eslint-plugin-plus')
10 |
11 | module.exports = [
12 | {
13 | files: [
14 | '**/*.ts',
15 | './src/**/*.ts',
16 | './test/**/*.ts'
17 | ],
18 | plugins: {
19 | '@typescript-eslint': ts,
20 | 'prettier': prettier,
21 | '@stylistic/js': stylisticJs,
22 | '@stylistic/ts': stylisticTs,
23 | '@stylistic/plus': stylisticPlus
24 | },
25 | languageOptions: {
26 | parser: tsParser,
27 | globals: {
28 | ...globals.browser,
29 | },
30 | parserOptions: {
31 | project: ['tsconfig.json'],
32 | },
33 | },
34 | rules: {
35 | ...js.configs.recommended.rules,
36 | ...ts.configs['stylistic-type-checked'].rules,
37 | // eslint/js rules
38 | 'indent': [1, 4],
39 | 'space-before-function-paren': 0,
40 | 'prefer-const': 1,
41 | 'comma-dangle': 0,
42 | 'keyword-spacing': ['error', { before: true, after: true }],
43 | 'comma-spacing': ['error', { before: false, after: true }],
44 | 'indent': 0,
45 | 'prefer-spread': 1,
46 | 'eqeqeq': ['error', 'smart'],
47 | 'no-unexpected-multiline': 0,
48 | 'no-prototype-builtins': 0,
49 | 'no-useless-escape': 1,
50 | 'no-mixed-operators': 1,
51 | 'no-control-regex': 0,
52 | 'no-console': 2,
53 | 'no-var': 2,
54 | 'no-undef': 0,
55 | 'no-redeclare': 'error',
56 | 'no-unused-vars': [
57 | 'error',
58 | {
59 | 'argsIgnorePattern': '^_',
60 | 'varsIgnorePattern': '^_',
61 | 'ignoreRestSiblings': true
62 | }
63 | ],
64 |
65 | '@stylistic/js/no-multi-spaces': [ 0, { ignoreEOLComments: true } ],
66 | '@stylistic/js/arrow-spacing': [ 'error', { before: true, after: true } ],
67 | '@stylistic/js/arrow-parens': [ 'error', 'always' ],
68 |
69 | '@stylistic/js/block-spacing': [ 'error', 'always' ],
70 | '@stylistic/ts/block-spacing': [ 'error', 'always' ],
71 |
72 | '@stylistic/js/brace-style': [ 'error', 'allman', { allowSingleLine: true } ],
73 | '@stylistic/ts/brace-style': [ 'error', 'allman', { allowSingleLine: true } ],
74 |
75 | '@stylistic/js/comma-dangle': [ 'error', 'never' ],
76 | '@stylistic/ts/comma-dangle': [ 'error', 'never' ],
77 |
78 | '@stylistic/js/comma-spacing': [ 'error', { before: false, after: true }],
79 | '@stylistic/ts/comma-spacing': [ 'error', { before: false, after: true }],
80 |
81 | '@stylistic/js/keyword-spacing': [ 'error', {
82 | before: true,
83 | after: true,
84 | 'overrides':
85 | {
86 | return: { before: true, after: true },
87 | throw: { before: true, after: true },
88 | case: { before: true, after: true },
89 | as: { before: true, after: true },
90 | if: { before: true, after: true },
91 | for: { before: true, after: true },
92 | while: { before: true, after: true },
93 | static: { before: true, after: true }
94 | },
95 | }],
96 |
97 | '@stylistic/ts/keyword-spacing': ['error', {
98 | before: true,
99 | after: true,
100 | 'overrides':
101 | {
102 | return: { before: true, after: true },
103 | throw: { before: true, after: true },
104 | case: { before: true, after: true },
105 | as: { before: true, after: true },
106 | if: { before: true, after: true },
107 | for: { before: true, after: true },
108 | while: { before: true, after: true },
109 | static: { before: true, after: true }
110 | },
111 | }],
112 |
113 | '@stylistic/js/computed-property-spacing': ['error', 'always'],
114 | '@stylistic/js/eol-last': ['error', 'always'],
115 | '@stylistic/js/jsx-quotes': ['error', 'prefer-single'],
116 | '@stylistic/js/linebreak-style': ['error', 'unix'],
117 | '@stylistic/js/no-mixed-spaces-and-tabs': ['error'],
118 | '@stylistic/js/no-tabs': ['error'],
119 | '@stylistic/js/no-trailing-spaces': ['error', { 'skipBlankLines': true, 'ignoreComments': true }],
120 | '@stylistic/js/no-whitespace-before-property': ['error'],
121 |
122 | '@stylistic/js/object-curly-spacing': ['error', 'always'],
123 | '@stylistic/ts/object-curly-spacing': ['error', 'always'],
124 |
125 | '@stylistic/js/quote-props': ['error', 'as-needed'],
126 | '@stylistic/ts/quote-props': ['error', 'as-needed'],
127 |
128 | '@stylistic/js/quotes': ['error', 'single', { 'allowTemplateLiterals': true }],
129 | '@stylistic/ts/quotes': ['error', 'single', { 'allowTemplateLiterals': true }],
130 |
131 | '@stylistic/js/semi': ['error', 'never'],
132 | '@stylistic/ts/semi': ['error', 'never'],
133 |
134 | '@stylistic/js/space-in-parens': ['error', 'always'],
135 |
136 | '@stylistic/js/space-infix-ops': ['error'],
137 | '@stylistic/ts/space-infix-ops': ['error'],
138 |
139 | '@stylistic/js/spaced-comment': ['error', 'always'],
140 | '@stylistic/js/template-curly-spacing': ['error', 'always'],
141 | '@stylistic/js/template-tag-spacing': ['error', 'always'],
142 | '@stylistic/js/wrap-iife': [2, "inside", { functionPrototypeMethods: true }],
143 |
144 | '@stylistic/plus/type-named-tuple-spacing': ["error"],
145 | '@stylistic/plus/type-generic-spacing': ["error"],
146 |
147 | // 'prettier/prettier': ['error'],
148 | // @typescript-eslint rules
149 | '@typescript-eslint/prefer-nullish-coalescing': 'off' // require `strictNullChecks`
150 | },
151 | }];
152 |
--------------------------------------------------------------------------------
/obs.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /* eslint-disable @typescript-eslint/no-var-requires */
3 |
4 | /*
5 | build obs by running
6 | npm run build
7 |
8 | guid and uuid will be automatically generated and placed
9 | inside .env file which will then be read by the github workflow
10 | build script.
11 | */
12 |
13 | /*
14 | This script handles the following:
15 | - read package.json
16 | - create .env file
17 | - return uuid, guid, version
18 |
19 | can be called with the following external commands:
20 | - node obs.js returns version of obs
21 | - node obs.js generate generates uuid / guid and shows all env vars in console
22 | - node obs.js uuid returns obs uuid
23 | - node obs.js guid returns obs guid
24 | - node obs.js versiom returns version of obs
25 |
26 | can be called with the following obs commands:
27 | - npm run obs
28 | - npm run obs:generate
29 | - npm run env-obs
30 | - npm run env-uuid
31 | - npm run env-guid
32 | - npm run env-version
33 | */
34 |
35 | const fs = require('fs');
36 | const { v5: uuid } = require('uuid');
37 |
38 | /*
39 | * declrations > package.json
40 | */
41 |
42 | const { version, repository } = JSON.parse(fs.readFileSync('package.json'));
43 | const args = process.argv.slice(2, process.argv.length);
44 | const action = args[0];
45 | // const a = args[ 1 ];
46 | // const b = args[ 2 ];
47 |
48 | if (action === 'guid') {
49 | console.log(`${process.env.GUID}`);
50 | } else if (action === 'setup') {
51 | fs.writeFileSync('.env', '', (err) => {
52 | if (err) {
53 | console.error(err);
54 | } else {
55 | console.log(`Wrote to .env successfully`);
56 | }
57 | });
58 | } else if (action === 'generate') {
59 | const buildGuid = uuid(`${repository.url}`, uuid.URL);
60 | const buildUuid = uuid(version, buildGuid);
61 |
62 | const ids = `
63 | VERSION=${version}
64 | GUID=${buildGuid}
65 | UUID=${buildUuid}
66 | `;
67 |
68 | console.log(version);
69 | console.log(buildGuid);
70 | console.log(buildUuid);
71 |
72 | fs.writeFileSync('.env', ids, (err) => {
73 | if (err) {
74 | console.error(`Could not write env vars: ${err}`);
75 | } else {
76 | console.log(`Wrote env vars to .env`);
77 | }
78 | });
79 | } else if (action === 'uuid') {
80 | console.log(`${process.env.UUID}`);
81 | } else {
82 | console.log(version);
83 | }
84 |
85 | process.exit(0);
86 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@aetherinox/obsidian-dataview-snippets",
3 | "version": "1.4.3",
4 | "description": "A collection of Obsidian.md scripts to be used in combination with the dataview plugin.",
5 | "homepage": "https://github.com/Aetherinox/obsidian-dataview-snippets",
6 | "author": "Aetherinox ",
7 | "license": "MIT",
8 | "contributors": [
9 | {
10 | "name": "Aetherinox",
11 | "email": "118329232+Aetherinox@users.noreply.github.com",
12 | "url": "https://github.com/Aetherinox"
13 | },
14 | {
15 | "name": "EuropaServ",
16 | "email": "161414668+EuropaServ@users.noreply.github.com",
17 | "url": "https://github.com/EuropaServ"
18 | }
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/Aetherinox/obsidian-dataview-snippets.git"
23 | },
24 | "bugs": {
25 | "url": "https://github.com/Aetherinox/obsidian-dataview-snippets/issues"
26 | },
27 | "build": {
28 | "appId": "com.obsidian.dataview.snippets.id"
29 | },
30 | "funding": [
31 | {
32 | "type": "individual",
33 | "url": "https://buymeacoffee.com/aetherinox"
34 | }
35 | ],
36 | "keywords": [
37 | "obsidian",
38 | "dataview",
39 | "folder_notes",
40 | "snippets",
41 | "scripts",
42 | "notes"
43 | ],
44 | "scripts": {
45 | "pretest": "npm run lint",
46 | "lint": "eslint src/**/*.ts",
47 | "lint:fix": "eslint --fix src/**/*.ts",
48 | "pretty": "prettier . --check",
49 | "pretty:fix": "prettier . --write",
50 | "pretty:ignore": "prettier . --write --ignore-unknown",
51 | "obs": "node obs.js",
52 | "contrib:add": "all-contributors add",
53 | "contrib:generate": "all-contributors generate",
54 | "root": "node obs.js",
55 | "root:generate": "node obs.js generate",
56 | "env:obs": "npx --quiet env-cmd --no-override node obs.js",
57 | "env:uuid": "npx --quiet env-cmd --no-override node obs.js uuid",
58 | "env:guid": "npx --quiet env-cmd --no-override node obs.js guid",
59 | "env:version": "node -p require('./package.json').version;"
60 | },
61 | "devDependencies": {
62 | "eslint-plugin-prettier": "^5.2.1",
63 | "typescript-eslint": "^7.14.0",
64 | "@typescript-eslint/parser": "^7.16.0",
65 | "@typescript-eslint/eslint-plugin": "^7.16.0",
66 | "@stylistic/eslint-plugin-js": "^2.3.0",
67 | "@stylistic/eslint-plugin-ts": "^2.3.0",
68 | "@stylistic/eslint-plugin-plus": "^2.3.0",
69 | "prettier": "^3.2.5",
70 | "@rollup/plugin-commonjs": "^26.0.1",
71 | "@rollup/plugin-image": "^3.0.3",
72 | "@rollup/plugin-node-resolve": "^15.2.3",
73 | "@rollup/plugin-replace": "^5.0.7",
74 | "@rollup/plugin-terser": "^0.4.4",
75 | "@rollup/plugin-typescript": "^11.1.6",
76 | "rollup-plugin-license": "^3.5.2",
77 | "@types/semver": "^7.5.8",
78 | "@types/uuid": "^10.0.0",
79 | "obsidian": "^1.7.2",
80 | "rollup": "^4.24.0",
81 | "semver": "^7.6.3",
82 | "uuid": "^10.0.0",
83 | "all-contributors-cli": "^6.26.1"
84 | }
85 | }
86 |
--------------------------------------------------------------------------------