Initial commit: Vault setup with .gitignore
29
.gitignore
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Device-specific layout (safe to ignore across machines)
|
||||
.obsidian/workspace.json
|
||||
.obsidian/workspace-mobile.json
|
||||
|
||||
# Obsidian plugin cache or temp files
|
||||
.obsidian/plugins/**/data.json
|
||||
.obsidian/plugins/**/cache.json
|
||||
.obsidian/plugins/**/.cache/
|
||||
.obsidian/plugins/**/__pycache__/
|
||||
|
||||
# OS and editor temp files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
*.log
|
||||
*.swp
|
||||
*.swo
|
||||
*.bak
|
||||
*.tmp
|
||||
~$*
|
||||
|
||||
# VS Code folders (optional)
|
||||
.vscode/
|
||||
.vscode-insiders/
|
||||
|
||||
# Node modules (if you build plugins)
|
||||
node_modules/
|
||||
dist/
|
||||
|
13
.obsidian/app.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"promptDelete": false,
|
||||
"readableLineLength": false,
|
||||
"trashOption": "none",
|
||||
"alwaysUpdateLinks": true,
|
||||
"newFileLocation": "folder",
|
||||
"newFileFolderPath": "00 Inbox",
|
||||
"showUnsupportedFiles": true,
|
||||
"showInlineTitle": false,
|
||||
"livePreview": false,
|
||||
"showIndentGuide": false,
|
||||
"showLineNumber": true
|
||||
}
|
9
.obsidian/appearance.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"translucency": false,
|
||||
"cssTheme": "AnuPpuccin",
|
||||
"enabledCssSnippets": [
|
||||
"extended-colorschemes",
|
||||
"custom-background",
|
||||
"S - Checkboxes"
|
||||
]
|
||||
}
|
3
.obsidian/backlink.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"backlinkInDocument": true
|
||||
}
|
5
.obsidian/canvas.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"snapToObjects": true,
|
||||
"snapToGrid": true,
|
||||
"newFileLocation": "current"
|
||||
}
|
17
.obsidian/community-plugins.json
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
[
|
||||
"obsidian-style-settings",
|
||||
"obsidian-markdown-formatting-assistant-plugin",
|
||||
"obsidian-icon-folder",
|
||||
"editing-toolbar",
|
||||
"url-into-selection",
|
||||
"obsidian-auto-link-title",
|
||||
"obsidian-footnotes",
|
||||
"obsidian-link-embed",
|
||||
"link-favicon",
|
||||
"obsidian-admonition",
|
||||
"dataview",
|
||||
"templater-obsidian",
|
||||
"periodic-notes",
|
||||
"calendar",
|
||||
"obsidian-amazingmarvin-plugin"
|
||||
]
|
31
.obsidian/core-plugins.json
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"file-explorer": true,
|
||||
"global-search": true,
|
||||
"switcher": true,
|
||||
"graph": false,
|
||||
"backlink": true,
|
||||
"canvas": true,
|
||||
"outgoing-link": true,
|
||||
"tag-pane": true,
|
||||
"properties": false,
|
||||
"page-preview": true,
|
||||
"daily-notes": false,
|
||||
"templates": true,
|
||||
"note-composer": true,
|
||||
"command-palette": true,
|
||||
"slash-command": true,
|
||||
"editor-status": true,
|
||||
"bookmarks": false,
|
||||
"markdown-importer": false,
|
||||
"zk-prefixer": false,
|
||||
"random-note": false,
|
||||
"outline": false,
|
||||
"word-count": true,
|
||||
"slides": false,
|
||||
"audio-recorder": false,
|
||||
"workspaces": true,
|
||||
"file-recovery": true,
|
||||
"publish": false,
|
||||
"sync": false,
|
||||
"webviewer": true
|
||||
}
|
5
.obsidian/daily-notes.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"format": "",
|
||||
"folder": "",
|
||||
"template": ""
|
||||
}
|
22
.obsidian/graph.json
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"collapse-filter": true,
|
||||
"search": "",
|
||||
"showTags": false,
|
||||
"showAttachments": false,
|
||||
"hideUnresolved": false,
|
||||
"showOrphans": true,
|
||||
"collapse-color-groups": true,
|
||||
"colorGroups": [],
|
||||
"collapse-display": true,
|
||||
"showArrow": false,
|
||||
"textFadeMultiplier": 0,
|
||||
"nodeSizeMultiplier": 1,
|
||||
"lineSizeMultiplier": 1,
|
||||
"collapse-forces": true,
|
||||
"centerStrength": 0.518713248970312,
|
||||
"repelStrength": 10,
|
||||
"linkStrength": 1,
|
||||
"linkDistance": 250,
|
||||
"scale": 1,
|
||||
"close": true
|
||||
}
|
18
.obsidian/hotkeys.json
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"obsidian-footnotes:insert-named-footnote": [
|
||||
{
|
||||
"modifiers": [
|
||||
"Alt"
|
||||
],
|
||||
"key": "-"
|
||||
}
|
||||
],
|
||||
"obsidian-footnotes:insert-autonumbered-footnote": [
|
||||
{
|
||||
"modifiers": [
|
||||
"Alt"
|
||||
],
|
||||
"key": "0"
|
||||
}
|
||||
]
|
||||
}
|
BIN
.obsidian/icons/boxicons.zip
vendored
Normal file
1
.obsidian/icons/boxicons/BxBookmarks.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="currentColor"><path d="M14 5H6c-1.103 0-2 .897-2 2v16l6-3.601L16 23V7c0-1.103-.897-2-2-2zm0 14.467-4-2.399-4 2.399V7h8v12.467z"></path><path d="M18 1h-8c-1.103 0-2 .897-2 2h8c1.103 0 2 .897 2 2v10.443l2 2.489V3c0-1.103-.897-2-2-2z"></path></svg>
|
After Width: | Height: | Size: 338 B |
1
.obsidian/icons/boxicons/BxlPython.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="currentColor"><path d="M9.585 11.692h4.328s2.432.039 2.432-2.35V5.391S16.714 3 11.936 3C7.362 3 7.647 4.983 7.647 4.983l.006 2.055h4.363v.617H5.92s-2.927-.332-2.927 4.282 2.555 4.45 2.555 4.45h1.524v-2.141s-.083-2.554 2.513-2.554zm-.056-5.74a.784.784 0 1 1 0-1.57.784.784 0 1 1 0 1.57z"></path><path d="M18.452 7.532h-1.524v2.141s.083 2.554-2.513 2.554h-4.328s-2.432-.04-2.432 2.35v3.951s-.369 2.391 4.409 2.391c4.573 0 4.288-1.983 4.288-1.983l-.006-2.054h-4.363v-.617h6.097s2.927.332 2.927-4.282-2.555-4.451-2.555-4.451zm-3.981 10.436a.784.784 0 1 1 0 1.57.784.784 0 1 1 0-1.57z"></path></svg>
|
After Width: | Height: | Size: 687 B |
BIN
.obsidian/icons/coolicons.zip
vendored
Normal file
1
.obsidian/icons/coolicons/Archive.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="16px" height="16px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="File / Archive"><path id="Vector" d="M6.60035 9H17.4003M6.60035 9C6.04029 9 5.75957 9 5.54566 9.10899C5.3575 9.20487 5.20463 9.35774 5.10875 9.5459C4.99976 9.75981 4.99976 10.04 4.99976 10.6001V15.8001C4.99976 16.9202 4.99976 17.4804 5.21775 17.9082C5.40949 18.2845 5.71523 18.5905 6.09156 18.7822C6.51896 19 7.07875 19 8.19667 19H15.8025C16.9204 19 17.4794 19 17.9068 18.7822C18.2831 18.5905 18.5902 18.2844 18.782 17.9081C18.9998 17.4807 18.9998 16.9216 18.9998 15.8037V10.591C18.9998 10.037 18.9998 9.75865 18.8914 9.5459C18.7955 9.35774 18.6419 9.20487 18.4538 9.10899C18.2398 9 17.9604 9 17.4003 9M6.60035 9H4.97507C4.12597 9 3.70168 9 3.4607 8.85156C3.13911 8.65347 2.95678 8.29079 2.98902 7.91447C3.0132 7.63223 3.26593 7.29089 3.77222 6.60739C3.91866 6.40971 3.99189 6.31084 4.08152 6.23535C4.20104 6.1347 4.34286 6.06322 4.49488 6.02709C4.60889 6 4.73126 6 4.9773 6H19.0217C19.2677 6 19.3904 6 19.5044 6.02709C19.6564 6.06322 19.7982 6.1347 19.9177 6.23535C20.0074 6.31084 20.0809 6.40924 20.2273 6.60693C20.7336 7.29042 20.9867 7.63218 21.0109 7.91442C21.0432 8.29074 20.8602 8.65347 20.5386 8.85156C20.2976 9 19.8723 9 19.0232 9H17.4003M9.99976 14H13.9998" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
.obsidian/icons/coolicons/DesktopTower.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="16px" height="16px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="System / Desktop_Tower"><path id="Vector" d="M10 20H7M18 17H16M13.0002 9H6.2002C5.08009 9 4.51962 9 4.0918 9.21799C3.71547 9.40973 3.40973 9.71547 3.21799 10.0918C3 10.5196 3 11.0801 3 12.2002V13.8002C3 14.9203 3 15.4796 3.21799 15.9074C3.40973 16.2837 3.71547 16.5905 4.0918 16.7822C4.5192 17 5.07899 17 6.19691 17H13.0001M13.0002 9L13 16.8002C13 16.8689 13 16.9354 13.0001 17M13.0002 9L13 7.2002C13 6.08009 13 5.51962 13.218 5.0918C13.4097 4.71547 13.7155 4.40973 14.0918 4.21799C14.5196 4 15.0801 4 16.2002 4H17.8002C18.9203 4 19.4796 4 19.9074 4.21799C20.2837 4.40973 20.5905 4.71547 20.7822 5.0918C21 5.5192 21 6.07899 21 7.19691V16.8031C21 17.921 21 18.48 20.7822 18.9074C20.5905 19.2837 20.2837 19.5905 19.9074 19.7822C19.48 20 18.921 20 17.8031 20H16.1969C15.079 20 14.5192 20 14.0918 19.7822C13.7155 19.5905 13.4097 19.2837 13.218 18.9074C13.0134 18.5058 13.0008 17.9884 13.0001 17M17.002 7V7.002L17 7.00195V7H17.002Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
.obsidian/icons/feather-icons.zip
vendored
Normal file
1
.obsidian/icons/feather-icons/Book.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>
|
After Width: | Height: | Size: 320 B |
1
.obsidian/icons/feather-icons/Inbox.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline><path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path></svg>
|
After Width: | Height: | Size: 379 B |
1
.obsidian/icons/feather-icons/Video.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="23 7 16 12 23 17 23 7"></polygon><rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect></svg>
|
After Width: | Height: | Size: 303 B |
BIN
.obsidian/icons/font-awesome-brands.zip
vendored
Normal file
1
.obsidian/icons/font-awesome-brands/Aws.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" fill="currentColor" width="16px" height="16px"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M180.41 203.01c-.72 22.65 10.6 32.68 10.88 39.05a8.164 8.164 0 0 1-4.1 6.27l-12.8 8.96a10.66 10.66 0 0 1-5.63 1.92c-.43-.02-8.19 1.83-20.48-25.61a78.608 78.608 0 0 1-62.61 29.45c-16.28.89-60.4-9.24-58.13-56.21-1.59-38.28 34.06-62.06 70.93-60.05 7.1.02 21.6.37 46.99 6.27v-15.62c2.69-26.46-14.7-46.99-44.81-43.91-2.4.01-19.4-.5-45.84 10.11-7.36 3.38-8.3 2.82-10.75 2.82-7.41 0-4.36-21.48-2.94-24.2 5.21-6.4 35.86-18.35 65.94-18.18a76.857 76.857 0 0 1 55.69 17.28 70.285 70.285 0 0 1 17.67 52.36l-.01 69.29zM93.99 235.4c32.43-.47 46.16-19.97 49.29-30.47 2.46-10.05 2.05-16.41 2.05-27.4-9.67-2.32-23.59-4.85-39.56-4.87-15.15-1.14-42.82 5.63-41.74 32.26-1.24 16.79 11.12 31.4 29.96 30.48zm170.92 23.05c-7.86.72-11.52-4.86-12.68-10.37l-49.8-164.65c-.97-2.78-1.61-5.65-1.92-8.58a4.61 4.61 0 0 1 3.86-5.25c.24-.04-2.13 0 22.25 0 8.78-.88 11.64 6.03 12.55 10.37l35.72 140.83 33.16-140.83c.53-3.22 2.94-11.07 12.8-10.24h17.16c2.17-.18 11.11-.5 12.68 10.37l33.42 142.63L420.98 80.1c.48-2.18 2.72-11.37 12.68-10.37h19.72c.85-.13 6.15-.81 5.25 8.58-.43 1.85 3.41-10.66-52.75 169.9-1.15 5.51-4.82 11.09-12.68 10.37h-18.69c-10.94 1.15-12.51-9.66-12.68-10.75L328.67 110.7l-32.78 136.99c-.16 1.09-1.73 11.9-12.68 10.75h-18.3zm273.48 5.63c-5.88.01-33.92-.3-57.36-12.29a12.802 12.802 0 0 1-7.81-11.91v-10.75c0-8.45 6.2-6.9 8.83-5.89 10.04 4.06 16.48 7.14 28.81 9.6 36.65 7.53 52.77-2.3 56.72-4.48 13.15-7.81 14.19-25.68 5.25-34.95-10.48-8.79-15.48-9.12-53.13-21-4.64-1.29-43.7-13.61-43.79-52.36-.61-28.24 25.05-56.18 69.52-55.95 12.67-.01 46.43 4.13 55.57 15.62 1.35 2.09 2.02 4.55 1.92 7.04v10.11c0 4.44-1.62 6.66-4.87 6.66-7.71-.86-21.39-11.17-49.16-10.75-6.89-.36-39.89.91-38.41 24.97-.43 18.96 26.61 26.07 29.7 26.89 36.46 10.97 48.65 12.79 63.12 29.58 17.14 22.25 7.9 48.3 4.35 55.44-19.08 37.49-68.42 34.44-69.26 34.42zm40.2 104.86c-70.03 51.72-171.69 79.25-258.49 79.25A469.127 469.127 0 0 1 2.83 327.46c-6.53-5.89-.77-13.96 7.17-9.47a637.37 637.37 0 0 0 316.88 84.12 630.22 630.22 0 0 0 241.59-49.55c11.78-5 21.77 7.8 10.12 16.38zm29.19-33.29c-8.96-11.52-59.28-5.38-81.81-2.69-6.79.77-7.94-5.12-1.79-9.47 40.07-28.17 105.88-20.1 113.44-10.63 7.55 9.47-2.05 75.41-39.56 106.91-5.76 4.87-11.27 2.3-8.71-4.1 8.44-21.25 27.39-68.49 18.43-80.02z"></path></svg>
|
After Width: | Height: | Size: 2.5 KiB |
BIN
.obsidian/icons/font-awesome-regular.zip
vendored
Normal file
BIN
.obsidian/icons/font-awesome-solid.zip
vendored
Normal file
1
.obsidian/icons/font-awesome-solid/Gears.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" fill="currentColor" width="16px" height="16px"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M308.5 135.3c7.1-6.3 9.9-16.2 6.2-25c-2.3-5.3-4.8-10.5-7.6-15.5L304 89.4c-3-5-6.3-9.9-9.8-14.6c-5.7-7.6-15.7-10.1-24.7-7.1l-28.2 9.3c-10.7-8.8-23-16-36.2-20.9L199 27.1c-1.9-9.3-9.1-16.7-18.5-17.8C173.9 8.4 167.2 8 160.4 8h-.7c-6.8 0-13.5 .4-20.1 1.2c-9.4 1.1-16.6 8.6-18.5 17.8L115 56.1c-13.3 5-25.5 12.1-36.2 20.9L50.5 67.8c-9-3-19-.5-24.7 7.1c-3.5 4.7-6.8 9.6-9.9 14.6l-3 5.3c-2.8 5-5.3 10.2-7.6 15.6c-3.7 8.7-.9 18.6 6.2 25l22.2 19.8C32.6 161.9 32 168.9 32 176s.6 14.1 1.7 20.9L11.5 216.7c-7.1 6.3-9.9 16.2-6.2 25c2.3 5.3 4.8 10.5 7.6 15.6l3 5.2c3 5.1 6.3 9.9 9.9 14.6c5.7 7.6 15.7 10.1 24.7 7.1l28.2-9.3c10.7 8.8 23 16 36.2 20.9l6.1 29.1c1.9 9.3 9.1 16.7 18.5 17.8c6.7 .8 13.5 1.2 20.4 1.2s13.7-.4 20.4-1.2c9.4-1.1 16.6-8.6 18.5-17.8l6.1-29.1c13.3-5 25.5-12.1 36.2-20.9l28.2 9.3c9 3 19 .5 24.7-7.1c3.5-4.7 6.8-9.5 9.8-14.6l3.1-5.4c2.8-5 5.3-10.2 7.6-15.5c3.7-8.7 .9-18.6-6.2-25l-22.2-19.8c1.1-6.8 1.7-13.8 1.7-20.9s-.6-14.1-1.7-20.9l22.2-19.8zM112 176a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zM504.7 500.5c6.3 7.1 16.2 9.9 25 6.2c5.3-2.3 10.5-4.8 15.5-7.6l5.4-3.1c5-3 9.9-6.3 14.6-9.8c7.6-5.7 10.1-15.7 7.1-24.7l-9.3-28.2c8.8-10.7 16-23 20.9-36.2l29.1-6.1c9.3-1.9 16.7-9.1 17.8-18.5c.8-6.7 1.2-13.5 1.2-20.4s-.4-13.7-1.2-20.4c-1.1-9.4-8.6-16.6-17.8-18.5L583.9 307c-5-13.3-12.1-25.5-20.9-36.2l9.3-28.2c3-9 .5-19-7.1-24.7c-4.7-3.5-9.6-6.8-14.6-9.9l-5.3-3c-5-2.8-10.2-5.3-15.6-7.6c-8.7-3.7-18.6-.9-25 6.2l-19.8 22.2c-6.8-1.1-13.8-1.7-20.9-1.7s-14.1 .6-20.9 1.7l-19.8-22.2c-6.3-7.1-16.2-9.9-25-6.2c-5.3 2.3-10.5 4.8-15.6 7.6l-5.2 3c-5.1 3-9.9 6.3-14.6 9.9c-7.6 5.7-10.1 15.7-7.1 24.7l9.3 28.2c-8.8 10.7-16 23-20.9 36.2L315.1 313c-9.3 1.9-16.7 9.1-17.8 18.5c-.8 6.7-1.2 13.5-1.2 20.4s.4 13.7 1.2 20.4c1.1 9.4 8.6 16.6 17.8 18.5l29.1 6.1c5 13.3 12.1 25.5 20.9 36.2l-9.3 28.2c-3 9-.5 19 7.1 24.7c4.7 3.5 9.5 6.8 14.6 9.8l5.4 3.1c5 2.8 10.2 5.3 15.5 7.6c8.7 3.7 18.6 .9 25-6.2l19.8-22.2c6.8 1.1 13.8 1.7 20.9 1.7s14.1-.6 20.9-1.7l19.8 22.2zM464 304a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"></path></svg>
|
After Width: | Height: | Size: 2.3 KiB |
1
.obsidian/icons/font-awesome-solid/Inbox.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" width="16px" height="16px"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M121 32C91.6 32 66 52 58.9 80.5L1.9 308.4C.6 313.5 0 318.7 0 323.9V416c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V323.9c0-5.2-.6-10.4-1.9-15.5l-57-227.9C446 52 420.4 32 391 32H121zm0 64H391l48 192H387.8c-12.1 0-23.2 6.8-28.6 17.7l-14.3 28.6c-5.4 10.8-16.5 17.7-28.6 17.7H195.8c-12.1 0-23.2-6.8-28.6-17.7l-14.3-28.6c-5.4-10.8-16.5-17.7-28.6-17.7H73L121 96z"></path></svg>
|
After Width: | Height: | Size: 702 B |
BIN
.obsidian/icons/icon-brew.zip
vendored
Normal file
BIN
.obsidian/icons/lucide-icons.zip
vendored
Normal file
1
.obsidian/icons/lucide-icons/BookCopy.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 16V4a2 2 0 0 1 2-2h11"></path><path d="M5 14H4a2 2 0 1 0 0 4h1"></path><path d="M22 18H11a2 2 0 1 0 0 4h11V6H11a2 2 0 0 0-2 2v12"></path></svg>
|
After Width: | Height: | Size: 340 B |
1
.obsidian/icons/lucide-icons/BrainCircuit.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"></path><path d="M9 13a4.5 4.5 0 0 0 3-4"></path><path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"></path><path d="M3.477 10.896a4 4 0 0 1 .585-.396"></path><path d="M6 18a4 4 0 0 1-1.967-.516"></path><path d="M12 13h4"></path><path d="M12 18h6a2 2 0 0 1 2 2v1"></path><path d="M12 8h8"></path><path d="M16 8V5a2 2 0 0 1 2-2"></path><circle cx="16" cy="13" r=".5"></circle><circle cx="18" cy="3" r=".5"></circle><circle cx="20" cy="21" r=".5"></circle><circle cx="20" cy="8" r=".5"></circle></svg>
|
After Width: | Height: | Size: 769 B |
1
.obsidian/icons/lucide-icons/Code.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>
|
After Width: | Height: | Size: 282 B |
1
.obsidian/icons/lucide-icons/FileSpreadsheet.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"></path><path d="M14 2v4a2 2 0 0 0 2 2h4"></path><path d="M8 13h2"></path><path d="M14 13h2"></path><path d="M8 17h2"></path><path d="M14 17h2"></path></svg>
|
After Width: | Height: | Size: 410 B |
1
.obsidian/icons/lucide-icons/LibraryBig.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="18" x="3" y="3" rx="1"></rect><path d="M7 3v18"></path><path d="M20.4 18.9c.2.5-.1 1.1-.6 1.3l-1.9.7c-.5.2-1.1-.1-1.3-.6L11.1 5.1c-.2-.5.1-1.1.6-1.3l1.9-.7c.5-.2 1.1.1 1.3.6Z"></path></svg>
|
After Width: | Height: | Size: 398 B |
1
.obsidian/icons/lucide-icons/ShieldCheck.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"></path><path d="m9 12 2 2 4-4"></path></svg>
|
After Width: | Height: | Size: 402 B |
1
.obsidian/icons/lucide-icons/Tags.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 5 6.3 6.3a2.4 2.4 0 0 1 0 3.4L17 19"></path><path d="M9.586 5.586A2 2 0 0 0 8.172 5H3a1 1 0 0 0-1 1v5.172a2 2 0 0 0 .586 1.414L8.29 18.29a2.426 2.426 0 0 0 3.42 0l3.58-3.58a2.426 2.426 0 0 0 0-3.42z"></path><circle cx="6.5" cy="9.5" r=".5" fill="currentColor"></circle></svg>
|
After Width: | Height: | Size: 473 B |
1
.obsidian/icons/lucide-icons/WholeWord.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="7" cy="12" r="3"></circle><path d="M10 9v6"></path><circle cx="17" cy="12" r="3"></circle><path d="M14 7v8"></path><path d="M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1"></path></svg>
|
After Width: | Height: | Size: 378 B |
1
.obsidian/icons/lucide-icons/Wrench.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path></svg>
|
After Width: | Height: | Size: 361 B |
BIN
.obsidian/icons/octicons.zip
vendored
Normal file
1
.obsidian/icons/octicons/Gear16.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z"></path></svg>
|
After Width: | Height: | Size: 2.4 KiB |
1
.obsidian/icons/octicons/Terminal16.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 16 16" fill="currentColor"><path d="M0 2.75C0 1.784.784 1 1.75 1h12.5c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 14.25 15H1.75A1.75 1.75 0 0 1 0 13.25Zm1.75-.25a.25.25 0 0 0-.25.25v10.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V2.75a.25.25 0 0 0-.25-.25ZM7.25 8a.749.749 0 0 1-.22.53l-2.25 2.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L5.44 8 3.72 6.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.25 2.25c.141.14.22.331.22.53Zm1.5 1.5h3a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1 0-1.5Z"></path></svg>
|
After Width: | Height: | Size: 597 B |
BIN
.obsidian/icons/remix-icons.zip
vendored
Normal file
1
.obsidian/icons/remix-icons/AdminFill.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><path d="M12 14V22H4C4 17.5817 7.58172 14 12 14ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM21 17H22V22H14V17H15V16C15 14.3431 16.3431 13 18 13C19.6569 13 21 14.3431 21 16V17ZM19 17V16C19 15.4477 18.5523 15 18 15C17.4477 15 17 15.4477 17 16V17H19Z"></path></svg>
|
After Width: | Height: | Size: 425 B |
1
.obsidian/icons/remix-icons/AdminLine.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><path d="M12 14V16C8.68629 16 6 18.6863 6 22H4C4 17.5817 7.58172 14 12 14ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM12 11C14.21 11 16 9.21 16 7C16 4.79 14.21 3 12 3C9.79 3 8 4.79 8 7C8 9.21 9.79 11 12 11ZM21 17H22V22H14V17H15V16C15 14.3431 16.3431 13 18 13C19.6569 13 21 14.3431 21 16V17ZM19 17V16C19 15.4477 18.5523 15 18 15C17.4477 15 17 15.4477 17 16V17H19Z"></path></svg>
|
After Width: | Height: | Size: 540 B |
1
.obsidian/icons/remix-icons/ArticleLine.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><path d="M20 22H4C3.44772 22 3 21.5523 3 21V3C3 2.44772 3.44772 2 4 2H20C20.5523 2 21 2.44772 21 3V21C21 21.5523 20.5523 22 20 22ZM19 20V4H5V20H19ZM7 6H11V10H7V6ZM7 12H17V14H7V12ZM7 16H17V18H7V16ZM13 7H17V9H13V7Z"></path></svg>
|
After Width: | Height: | Size: 334 B |
1
.obsidian/icons/remix-icons/InboxUnarchiveLine.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><path d="M20 3L22 7V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V7.00353L4 3H20ZM20 9H4V19H20V9ZM12 10L16 14H13V18H11V14H8L12 10ZM18.764 5H5.236L4.237 7H19.764L18.764 5Z"></path></svg>
|
After Width: | Height: | Size: 305 B |
BIN
.obsidian/icons/rpg-awesome.zip
vendored
Normal file
1
.obsidian/icons/rpg-awesome/Gears.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 613 613" enable-background="new 0 0 613 613" xml:space="preserve" fill="currentColor"><path d="M576.368,231.834l-32.985,57.427c-20.128-8.609-41.599-14.639-64.05-17.609v-66.345h-64.222v66.301 c-21.864,2.842-42.826,8.555-62.514,16.731l-32.425-56.506l-43.044,24.212l-17.76-24.862c5.859-8.141,10.483-17.303,13.554-27.254 l64.799-7.091l-6.381-64.857l-62.004,6.13c-4.842-11.121-11.779-21.221-20.393-29.727l24.768-55.321l-59.008-26.408h-0.004 L190.172,81.44c-12.573-1.042-24.854,0.457-36.3,4.089l-34.6-48.439L66.645,75.536l35.612,49.859 c-5.99,9.506-10.364,20.226-12.689,31.839l-62.562,6.847l6.38,64.854l66.115-7.235c4.678,8.461,10.631,16.176,17.642,22.857 L89.172,307.03l59.01,26.408l28.199-62.988c9.712,0.632,19.236-0.243,28.318-2.444l40.754,55.825l37.916-27.701l13.955,24.095 c-17.581,13.427-33.316,29.153-46.766,46.727l-58.833-33.895l-30.715,55.847l57.507,33.407 c-8.446,20.236-14.304,41.816-17.144,64.325H134.48v64.224h67.177c1.986,14.402,5.24,28.376,9.612,41.885h202.403c0,0,0,0,0,0h0 c-28.598-12.855-48.524-41.57-48.524-74.959c0-45.381,36.787-82.166,82.166-82.166s82.166,36.785,82.166,82.166 c0,33.387-19.926,62.104-48.525,74.959h0c0,0,0,0,0,0H590.33v0v-30.018v-11.867v-64.224v-14.66v-73.997v-61.431v-20.943v-76.091 L576.368,231.834z M185.724,232.535c-29.018,1.771-53.98-20.313-55.751-49.33c-1.771-29.017,20.321-53.976,49.339-55.747 s53.981,20.317,55.751,49.334C236.835,205.809,214.743,230.764,185.724,232.535z"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
1
.obsidian/icons/rpg-awesome/LightningBolt.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 612 612" enable-background="new 0 0 612 612" xml:space="preserve" fill="currentColor"><g transform="matrix(15 0 0 15 -5924 -6649.4327)"></g><g transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)"><path stroke="#000000" stroke-miterlimit="10" d="M492.417,955.35h38.25v-62.156l38.25,90.844h-38.25v62.156L492.417,955.35z"></path></g></svg>
|
After Width: | Height: | Size: 506 B |
BIN
.obsidian/icons/simple-icons.zip
vendored
Normal file
1
.obsidian/icons/simple-icons/Bookstack.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16px" height="16px"><path d="M.3013 17.6146c-.1299-.3387-.5228-1.5119-.1337-2.4314l9.8273 5.6738a.329.329 0 0 0 .3299 0L24 12.9616v2.3542l-13.8401 7.9906-9.8586-5.6918zM.1911 8.9628c-.2882.8769.0149 2.0581.1236 2.4261l9.8452 5.6841L24 9.0823V6.7275L10.3248 14.623a.329.329 0 0 1-.3299 0L.1911 8.9628zm13.1698-1.9361c-.1819.1113-.4394.0015-.4852-.2064l-.2805-1.1336-2.1254-.1752a.33.33 0 0 1-.1378-.6145l5.5782-3.2207-1.7021-.9826L.6979 8.4935l9.462 5.463 13.5104-7.8004-4.401-2.5407-5.9084 3.4113zm-.1821-1.7286.2321.938 5.1984-3.0014-2.0395-1.1775-4.994 2.8834 1.3099.108a.3302.3302 0 0 1 .2931.2495zM24 9.845l-13.6752 7.8954a.329.329 0 0 1-.3299 0L.1678 12.0667c-.3891.919.003 2.0914.1332 2.4311l9.8589 5.692L24 12.1993V9.845z"></path></svg>
|
After Width: | Height: | Size: 841 B |
1
.obsidian/icons/simple-icons/Googleclassroom.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16px" height="16px"><path d="M1.6367 1.6367C.7322 1.6367 0 2.369 0 3.2734v17.4532c0 .9045.7322 1.6367 1.6367 1.6367h20.7266c.9045 0 1.6367-.7322 1.6367-1.6367V3.2734c0-.9045-.7322-1.6367-1.6367-1.6367H1.6367zm.545 2.1817h19.6367v16.3632h-2.7266v-1.0898h-4.9102v1.0898h-12V3.8184zM12 8.1816c-.9046 0-1.6367.7322-1.6367 1.6368 0 .9045.7321 1.6367 1.6367 1.6367.9046 0 1.6367-.7322 1.6367-1.6367 0-.9046-.7321-1.6368-1.6367-1.6368zm-4.3633 1.9102c-.6773 0-1.2285.5493-1.2285 1.2266 0 .6772.5512 1.2265 1.2285 1.2265.6773 0 1.2266-.5493 1.2266-1.2265 0-.6773-.5493-1.2266-1.2266-1.2266zm8.7266 0c-.6773 0-1.2266.5493-1.2266 1.2266 0 .6772.5493 1.2265 1.2266 1.2265.6773 0 1.2285-.5493 1.2285-1.2265 0-.6773-.5512-1.2266-1.2285-1.2266zM12 12.5449c-1.179 0-2.4128.4012-3.1484 1.0059-.384-.1198-.8043-.1875-1.2149-.1875-1.3136 0-2.7285.695-2.7285 1.5586v.8965h14.1836v-.8965c0-.8637-1.4149-1.5586-2.7285-1.5586-.4106 0-.831.0677-1.2149.1875-.7356-.6047-1.9694-1.0059-3.1484-1.0059Z"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
1
.obsidian/icons/simple-icons/Python.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16px" height="16px"><path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
1
.obsidian/icons/simple-icons/Wordpress.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16px" height="16px"><path d="M21.469 6.825c.84 1.537 1.318 3.3 1.318 5.175 0 3.979-2.156 7.456-5.363 9.325l3.295-9.527c.615-1.54.82-2.771.82-3.864 0-.405-.026-.78-.07-1.11m-7.981.105c.647-.03 1.232-.105 1.232-.105.582-.075.514-.93-.067-.899 0 0-1.755.135-2.88.135-1.064 0-2.85-.15-2.85-.15-.585-.03-.661.855-.075.885 0 0 .54.061 1.125.09l1.68 4.605-2.37 7.08L5.354 6.9c.649-.03 1.234-.1 1.234-.1.585-.075.516-.93-.065-.896 0 0-1.746.138-2.874.138-.2 0-.438-.008-.69-.015C4.911 3.15 8.235 1.215 12 1.215c2.809 0 5.365 1.072 7.286 2.833-.046-.003-.091-.009-.141-.009-1.06 0-1.812.923-1.812 1.914 0 .89.513 1.643 1.06 2.531.411.72.89 1.643.89 2.977 0 .915-.354 1.994-.821 3.479l-1.075 3.585-3.9-11.61.001.014zM12 22.784c-1.059 0-2.081-.153-3.048-.437l3.237-9.406 3.315 9.087c.024.053.05.101.078.149-1.12.393-2.325.609-3.582.609M1.211 12c0-1.564.336-3.05.935-4.39L7.29 21.709C3.694 19.96 1.212 16.271 1.211 12M12 0C5.385 0 0 5.385 0 12s5.385 12 12 12 12-5.385 12-12S18.615 0 12 0"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
.obsidian/icons/tabler-icons.zip
vendored
Normal file
1
.obsidian/icons/tabler-icons/Books.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-books"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 4m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v14a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path><path d="M9 4m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v14a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path><path d="M5 8h4"></path><path d="M9 16h4"></path><path d="M13.803 4.56l2.184 -.53c.562 -.135 1.133 .19 1.282 .732l3.695 13.418a1.02 1.02 0 0 1 -.634 1.219l-.133 .041l-2.184 .53c-.562 .135 -1.133 -.19 -1.282 -.732l-3.695 -13.418a1.02 1.02 0 0 1 .634 -1.219l.133 -.041z"></path><path d="M14 9l4 -1"></path><path d="M16 16l3.923 -.98"></path></svg>
|
After Width: | Height: | Size: 841 B |
1
.obsidian/icons/tabler-icons/Checks.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-checks"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7 12l5 5l10 -10"></path><path d="M2 12l5 5m5 -5l5 -5"></path></svg>
|
After Width: | Height: | Size: 384 B |
1
.obsidian/icons/tabler-icons/CloudPlus.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-cloud-plus"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 18.004h-5.343c-2.572 -.004 -4.657 -2.011 -4.657 -4.487c0 -2.475 2.085 -4.482 4.657 -4.482c.393 -1.762 1.794 -3.2 3.675 -3.773c1.88 -.572 3.956 -.193 5.444 1c1.488 1.19 2.162 3.007 1.77 4.769h.99a3.46 3.46 0 0 1 3.085 1.9"></path><path d="M16 19h6"></path><path d="M19 16v6"></path></svg>
|
After Width: | Height: | Size: 611 B |
1
.obsidian/icons/tabler-icons/Code.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-code"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7 8l-4 4l4 4"></path><path d="M17 8l4 4l-4 4"></path><path d="M14 4l-4 16"></path></svg>
|
After Width: | Height: | Size: 403 B |
1
.obsidian/icons/tabler-icons/Logs.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-logs"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 12h.01"></path><path d="M4 6h.01"></path><path d="M4 18h.01"></path><path d="M8 18h2"></path><path d="M8 12h2"></path><path d="M8 6h2"></path><path d="M14 6h6"></path><path d="M14 12h6"></path><path d="M14 18h6"></path></svg>
|
After Width: | Height: | Size: 542 B |
1
.obsidian/icons/tabler-icons/Network.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-network"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M6 9a6 6 0 1 0 12 0a6 6 0 0 0 -12 0"></path><path d="M12 3c1.333 .333 2 2.333 2 6s-.667 5.667 -2 6"></path><path d="M12 3c-1.333 .333 -2 2.333 -2 6s.667 5.667 2 6"></path><path d="M6 9h12"></path><path d="M3 20h7"></path><path d="M14 20h7"></path><path d="M10 20a2 2 0 1 0 4 0a2 2 0 0 0 -4 0"></path><path d="M12 15v3"></path></svg>
|
After Width: | Height: | Size: 649 B |
1
.obsidian/icons/tabler-icons/Notes.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-notes"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 3m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z"></path><path d="M9 7l6 0"></path><path d="M9 11l6 0"></path><path d="M9 15l4 0"></path></svg>
|
After Width: | Height: | Size: 489 B |
1
.obsidian/icons/tabler-icons/Protocol.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-protocol"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M15 6l-7 12"></path><path d="M20 6l-7 12"></path><path d="M5 14v.015"></path><path d="M5 10.015v.015"></path></svg>
|
After Width: | Height: | Size: 433 B |
1
.obsidian/icons/tabler-icons/Template.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-template"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 4m0 1a1 1 0 0 1 1 -1h14a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-14a1 1 0 0 1 -1 -1z"></path><path d="M4 12m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v6a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path><path d="M14 12l6 0"></path><path d="M14 16l6 0"></path><path d="M14 20l6 0"></path></svg>
|
After Width: | Height: | Size: 590 B |
4459
.obsidian/plugins/calendar/main.js
vendored
Normal file
10
.obsidian/plugins/calendar/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "calendar",
|
||||
"name": "Calendar",
|
||||
"description": "Calendar view of your daily notes",
|
||||
"version": "1.5.10",
|
||||
"author": "Liam Cain",
|
||||
"authorUrl": "https://github.com/liamcain/",
|
||||
"isDesktopOnly": false,
|
||||
"minAppVersion": "0.9.11"
|
||||
}
|
20876
.obsidian/plugins/dataview/main.js
vendored
Normal file
11
.obsidian/plugins/dataview/manifest.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"id": "dataview",
|
||||
"name": "Dataview",
|
||||
"version": "0.5.68",
|
||||
"minAppVersion": "0.13.11",
|
||||
"description": "Complex data views for the data-obsessed.",
|
||||
"author": "Michael Brenan <blacksmithgu@gmail.com>",
|
||||
"authorUrl": "https://github.com/blacksmithgu",
|
||||
"helpUrl": "https://blacksmithgu.github.io/obsidian-dataview/",
|
||||
"isDesktopOnly": false
|
||||
}
|
141
.obsidian/plugins/dataview/styles.css
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
.block-language-dataview {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/** Table Views **/
|
||||
/*****************/
|
||||
|
||||
/* List View Default Styling; rendered internally as a table. */
|
||||
.table-view-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table-view-table > thead > tr, .table-view-table > tbody > tr {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.table-view-table > tbody > tr:hover {
|
||||
background-color: var(--table-row-background-hover);
|
||||
}
|
||||
|
||||
.table-view-table > thead > tr > th {
|
||||
font-weight: 700;
|
||||
font-size: larger;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: solid;
|
||||
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.table-view-table > tbody > tr > td {
|
||||
text-align: left;
|
||||
border: none;
|
||||
font-weight: 400;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.table-view-table ul, .table-view-table ol {
|
||||
margin-block-start: 0.2em !important;
|
||||
margin-block-end: 0.2em !important;
|
||||
}
|
||||
|
||||
/** Rendered value styling for any view. */
|
||||
.dataview-result-list-root-ul {
|
||||
padding: 0em !important;
|
||||
margin: 0em !important;
|
||||
}
|
||||
|
||||
.dataview-result-list-ul {
|
||||
margin-block-start: 0.2em !important;
|
||||
margin-block-end: 0.2em !important;
|
||||
}
|
||||
|
||||
/** Generic grouping styling. */
|
||||
.dataview.result-group {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/** Inline Fields **/
|
||||
/*******************/
|
||||
|
||||
.dataview.inline-field-key {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-family: var(--font-monospace);
|
||||
background-color: var(--background-primary-alt);
|
||||
color: var(--nav-item-color-selected);
|
||||
}
|
||||
|
||||
.dataview.inline-field-value {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-family: var(--font-monospace);
|
||||
background-color: var(--background-secondary-alt);
|
||||
color: var(--nav-item-color-selected);
|
||||
}
|
||||
|
||||
.dataview.inline-field-standalone-value {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-family: var(--font-monospace);
|
||||
background-color: var(--background-secondary-alt);
|
||||
color: var(--nav-item-color-selected);
|
||||
}
|
||||
|
||||
/***************/
|
||||
/** Task View **/
|
||||
/***************/
|
||||
|
||||
.dataview.task-list-item, .dataview.task-list-basic-item {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
.dataview.task-list-item:hover, .dataview.task-list-basic-item:hover {
|
||||
background-color: var(--text-selection);
|
||||
box-shadow: -40px 0 0 var(--text-selection);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/** Error Views **/
|
||||
/*****************/
|
||||
|
||||
div.dataview-error-box {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 4px dashed var(--background-secondary);
|
||||
}
|
||||
|
||||
.dataview-error-message {
|
||||
color: var(--text-muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/** Additional Metadata **/
|
||||
/*************************/
|
||||
|
||||
.dataview.small-text {
|
||||
font-size: smaller;
|
||||
color: var(--text-muted);
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.dataview.small-text::before {
|
||||
content: "(";
|
||||
}
|
||||
|
||||
.dataview.small-text::after {
|
||||
content: ")";
|
||||
}
|
12
.obsidian/plugins/editing-toolbar/main.js
vendored
Normal file
10
.obsidian/plugins/editing-toolbar/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "editing-toolbar",
|
||||
"name": "Editing Toolbar",
|
||||
"version": "3.1.16",
|
||||
"minAppVersion": "0.14.0",
|
||||
"description": "The Obsidian Editing Toolbar is modified from cmenu, which provides more powerful customization settings and has many built-in editing commands to be a MS Word-like toolbar editing experience.",
|
||||
"author": "Cuman",
|
||||
"authorUrl": "https://github.com/cumany/obsidian-editing-toolbar",
|
||||
"isDesktopOnly": false
|
||||
}
|
1332
.obsidian/plugins/editing-toolbar/styles.css
vendored
Normal file
12
.obsidian/plugins/link-favicon/main.js
vendored
Normal file
10
.obsidian/plugins/link-favicon/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "link-favicon",
|
||||
"name": "Link Favicons",
|
||||
"version": "1.8.4",
|
||||
"minAppVersion": "1.3.0",
|
||||
"description": "See the favicon for a linked website. ",
|
||||
"author": "Johannes Theiner",
|
||||
"authorUrl": "https://github.com/joethei",
|
||||
"isDesktopOnly": false
|
||||
}
|
7
.obsidian/plugins/link-favicon/styles.css
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
https://github.com/joethei/obisidian-link-favicon
|
||||
*/
|
||||
|
||||
.link-favicon{cursor:pointer!important;image-rendering:-webkit-optimize-contrast;margin-bottom:.3em;margin-left:.1em;margin-right:.1em;max-height:1em;vertical-align:bottom}.link-favicon-preview{font-size:50px;text-align:center}.link-favicon-preview img{height:50px}.link-favicon[data-color-inversion=true][data-is-readable-a-a=false]{filter:hue-rotate(180deg) invert(1)}.link-favicon-scrollable-content{height:60vh;overflow:auto}
|
513
.obsidian/plugins/obsidian-admonition/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-admonition/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-admonition",
|
||||
"name": "Admonition",
|
||||
"version": "10.3.2",
|
||||
"minAppVersion": "1.1.0",
|
||||
"description": "Enhanced callouts for Obsidian.md",
|
||||
"author": "Jeremy Valentine",
|
||||
"authorUrl": "",
|
||||
"isDesktopOnly": false
|
||||
}
|
1
.obsidian/plugins/obsidian-admonition/octicons.json
vendored
Normal file
1
.obsidian/plugins/obsidian-admonition/rpg.json
vendored
Normal file
1
.obsidian/plugins/obsidian-admonition/styles.css
vendored
Normal file
11348
.obsidian/plugins/obsidian-amazingmarvin-plugin/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-amazingmarvin-plugin/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-amazingmarvin-plugin",
|
||||
"name": "Amazing Marvin",
|
||||
"version": "0.3.1",
|
||||
"minAppVersion": "0.9.12",
|
||||
"description": "This is a plugin for Obsidian (https://obsidian.md) for Amazing Marvin (https://app.amazingmarvin.com/)",
|
||||
"author": "Shirayuki Nekomata",
|
||||
"authorUrl": "https://github.com/ikuyarihS",
|
||||
"isDesktopOnly": false
|
||||
}
|
59
.obsidian/plugins/obsidian-amazingmarvin-plugin/styles.css
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
.amazing-marvin-container {
|
||||
padding-left: 3%;
|
||||
}
|
||||
.modal-button-container .button,
|
||||
.amazing-marvin-container .button-group .button {
|
||||
display: inline-flex;
|
||||
border: 1px solid;
|
||||
padding: 1%;
|
||||
}
|
||||
.modal-button-container .icon,
|
||||
.amazing-marvin-container .button-group .icon {
|
||||
fill: var(--text-normal);
|
||||
margin-right: 5px;
|
||||
}
|
||||
.amazing-marvin-container .button-group .span {
|
||||
font-style: italic;
|
||||
font-size: small;
|
||||
margin-left: 2%;
|
||||
}
|
||||
|
||||
.workspace-leaf-content .amazing-marvin-container {
|
||||
user-select: text !important;
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
.amazing-marvin-title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.amazing-marvin-title-container .amazing-marvin-label {
|
||||
user-select: none !important;
|
||||
font-size: 75%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 7px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.amazing-marvin-list::before,
|
||||
.amazing-marvin-list-item::before {
|
||||
content: None !important;
|
||||
}
|
||||
|
||||
.amazing-marvin-error-display {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.amazing-marvin-title-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.amazing-marvin-setting-header {
|
||||
padding-bottom: 3%;
|
||||
}
|
||||
|
||||
.amazing-marvin-setting-footer {
|
||||
text-align: center;
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
}
|
771
.obsidian/plugins/obsidian-auto-link-title/main.js
vendored
Normal file
|
@ -0,0 +1,771 @@
|
|||
/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
||||
if you want to view the source visit the plugins github repository
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var obsidian = require('obsidian');
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
function __awaiter(thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
}
|
||||
|
||||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
||||
var e = new Error(message);
|
||||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
||||
};
|
||||
|
||||
const DEFAULT_SETTINGS = {
|
||||
regex: /^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$/i,
|
||||
lineRegex: /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi,
|
||||
linkRegex: /^\[([^\[\]]*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)$/i,
|
||||
linkLineRegex: /\[([^\[\]]*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)/gi,
|
||||
imageRegex: /\.(gif|jpe?g|tiff?|png|webp|bmp|tga|psd|ai)$/i,
|
||||
enhanceDefaultPaste: true,
|
||||
shouldPreserveSelectionAsTitle: false,
|
||||
enhanceDropEvents: true,
|
||||
websiteBlacklist: "",
|
||||
maximumTitleLength: 0,
|
||||
useNewScraper: false,
|
||||
linkPreviewApiKey: "",
|
||||
useBetterPasteId: false,
|
||||
};
|
||||
class AutoLinkTitleSettingTab extends obsidian.PluginSettingTab {
|
||||
constructor(app, plugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
display() {
|
||||
let { containerEl } = this;
|
||||
containerEl.empty();
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Enhance Default Paste")
|
||||
.setDesc("Fetch the link title when pasting a link in the editor with the default paste command")
|
||||
.addToggle((val) => val
|
||||
.setValue(this.plugin.settings.enhanceDefaultPaste)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
console.log(value);
|
||||
this.plugin.settings.enhanceDefaultPaste = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Enhance Drop Events")
|
||||
.setDesc("Fetch the link title when drag and dropping a link from another program")
|
||||
.addToggle((val) => val
|
||||
.setValue(this.plugin.settings.enhanceDropEvents)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
console.log(value);
|
||||
this.plugin.settings.enhanceDropEvents = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Maximum title length")
|
||||
.setDesc("Set the maximum length of the title. Set to 0 to disable.")
|
||||
.addText((val) => val
|
||||
.setValue(this.plugin.settings.maximumTitleLength.toString(10))
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
const titleLength = Number(value);
|
||||
this.plugin.settings.maximumTitleLength =
|
||||
isNaN(titleLength) || titleLength < 0 ? 0 : titleLength;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Preserve selection as title")
|
||||
.setDesc("Whether to prefer selected text as title over fetched title when pasting")
|
||||
.addToggle((val) => val
|
||||
.setValue(this.plugin.settings.shouldPreserveSelectionAsTitle)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
console.log(value);
|
||||
this.plugin.settings.shouldPreserveSelectionAsTitle = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Website Blacklist")
|
||||
.setDesc("List of strings (comma separated) that disable autocompleting website titles. Can be URLs or arbitrary text.")
|
||||
.addTextArea((val) => val
|
||||
.setValue(this.plugin.settings.websiteBlacklist)
|
||||
.setPlaceholder("localhost, tiktok.com")
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
this.plugin.settings.websiteBlacklist = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Use New Scraper")
|
||||
.setDesc("Use experimental new scraper, seems to work well on desktop but not mobile.")
|
||||
.addToggle((val) => val
|
||||
.setValue(this.plugin.settings.useNewScraper)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
console.log(value);
|
||||
this.plugin.settings.useNewScraper = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Use Better Fetching Placeholder")
|
||||
.setDesc("Use a more readable placeholder when fetching the title of a link.")
|
||||
.addToggle((val) => val
|
||||
.setValue(this.plugin.settings.useBetterPasteId)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
console.log(value);
|
||||
this.plugin.settings.useBetterPasteId = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("LinkPreview API Key")
|
||||
.setDesc("API key for the LinkPreview.net service. Get one at https://my.linkpreview.net/access_keys")
|
||||
.addText((text) => text
|
||||
.setValue(this.plugin.settings.linkPreviewApiKey || "")
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
const trimmedValue = value.trim();
|
||||
if (trimmedValue.length > 0 && trimmedValue.length !== 32) {
|
||||
new obsidian.Notice("LinkPreview API key must be 32 characters long");
|
||||
this.plugin.settings.linkPreviewApiKey = "";
|
||||
}
|
||||
else {
|
||||
this.plugin.settings.linkPreviewApiKey = trimmedValue;
|
||||
}
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
class CheckIf {
|
||||
static isMarkdownLinkAlready(editor) {
|
||||
let cursor = editor.getCursor();
|
||||
// Check if the characters before the url are ]( to indicate a markdown link
|
||||
var titleEnd = editor.getRange({ ch: cursor.ch - 2, line: cursor.line }, { ch: cursor.ch, line: cursor.line });
|
||||
return titleEnd == "](";
|
||||
}
|
||||
static isAfterQuote(editor) {
|
||||
let cursor = editor.getCursor();
|
||||
// Check if the characters before the url are " or ' to indicate we want the url directly
|
||||
// This is common in elements like <a href="linkhere"></a>
|
||||
var beforeChar = editor.getRange({ ch: cursor.ch - 1, line: cursor.line }, { ch: cursor.ch, line: cursor.line });
|
||||
return beforeChar == "\"" || beforeChar == "'";
|
||||
}
|
||||
static isUrl(text) {
|
||||
let urlRegex = new RegExp(DEFAULT_SETTINGS.regex);
|
||||
return urlRegex.test(text);
|
||||
}
|
||||
static isImage(text) {
|
||||
let imageRegex = new RegExp(DEFAULT_SETTINGS.imageRegex);
|
||||
return imageRegex.test(text);
|
||||
}
|
||||
static isLinkedUrl(text) {
|
||||
let urlRegex = new RegExp(DEFAULT_SETTINGS.linkRegex);
|
||||
return urlRegex.test(text);
|
||||
}
|
||||
}
|
||||
|
||||
class EditorExtensions {
|
||||
static getSelectedText(editor) {
|
||||
if (!editor.somethingSelected()) {
|
||||
let wordBoundaries = this.getWordBoundaries(editor);
|
||||
editor.setSelection(wordBoundaries.start, wordBoundaries.end);
|
||||
}
|
||||
return editor.getSelection();
|
||||
}
|
||||
static cursorWithinBoundaries(cursor, match) {
|
||||
let startIndex = match.index;
|
||||
let endIndex = match.index + match[0].length;
|
||||
return startIndex <= cursor.ch && cursor.ch <= endIndex;
|
||||
}
|
||||
static getWordBoundaries(editor) {
|
||||
let cursor = editor.getCursor();
|
||||
// If its a normal URL token this is not a markdown link
|
||||
// In this case we can simply overwrite the link boundaries as-is
|
||||
let lineText = editor.getLine(cursor.line);
|
||||
// First check if we're in a link
|
||||
let linksInLine = lineText.matchAll(DEFAULT_SETTINGS.linkLineRegex);
|
||||
for (let match of linksInLine) {
|
||||
if (this.cursorWithinBoundaries(cursor, match)) {
|
||||
return {
|
||||
start: { line: cursor.line, ch: match.index },
|
||||
end: { line: cursor.line, ch: match.index + match[0].length },
|
||||
};
|
||||
}
|
||||
}
|
||||
// If not, check if we're in just a standard ol' URL.
|
||||
let urlsInLine = lineText.matchAll(DEFAULT_SETTINGS.lineRegex);
|
||||
for (let match of urlsInLine) {
|
||||
if (this.cursorWithinBoundaries(cursor, match)) {
|
||||
return {
|
||||
start: { line: cursor.line, ch: match.index },
|
||||
end: { line: cursor.line, ch: match.index + match[0].length },
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
start: cursor,
|
||||
end: cursor,
|
||||
};
|
||||
}
|
||||
static getEditorPositionFromIndex(content, index) {
|
||||
let substr = content.substr(0, index);
|
||||
let l = 0;
|
||||
let offset = -1;
|
||||
let r = -1;
|
||||
for (; (r = substr.indexOf("\n", r + 1)) !== -1; l++, offset = r)
|
||||
;
|
||||
offset += 1;
|
||||
let ch = content.substr(offset, index - offset).length;
|
||||
return { line: l, ch: ch };
|
||||
}
|
||||
}
|
||||
|
||||
function blank$1(text) {
|
||||
return text === undefined || text === null || text === '';
|
||||
}
|
||||
function notBlank$1(text) {
|
||||
return !blank$1(text);
|
||||
}
|
||||
function scrape(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const response = yield obsidian.requestUrl(url);
|
||||
if (!response.headers['content-type'].includes('text/html'))
|
||||
return getUrlFinalSegment$1(url);
|
||||
const html = response.text;
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
const title = doc.querySelector('title');
|
||||
if (blank$1(title === null || title === void 0 ? void 0 : title.innerText)) {
|
||||
// If site is javascript based and has a no-title attribute when unloaded, use it.
|
||||
var noTitle = title === null || title === void 0 ? void 0 : title.getAttr('no-title');
|
||||
if (notBlank$1(noTitle)) {
|
||||
return noTitle;
|
||||
}
|
||||
// Otherwise if the site has no title/requires javascript simply return Title Unknown
|
||||
return url;
|
||||
}
|
||||
return title.innerText;
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
return '';
|
||||
}
|
||||
});
|
||||
}
|
||||
function getUrlFinalSegment$1(url) {
|
||||
try {
|
||||
const segments = new URL(url).pathname.split('/');
|
||||
const last = segments.pop() || segments.pop(); // Handle potential trailing slash
|
||||
return last;
|
||||
}
|
||||
catch (_) {
|
||||
return 'File';
|
||||
}
|
||||
}
|
||||
function getPageTitle$1(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!(url.startsWith('http') || url.startsWith('https'))) {
|
||||
url = 'https://' + url;
|
||||
}
|
||||
return scrape(url);
|
||||
});
|
||||
}
|
||||
|
||||
const electronPkg = require("electron");
|
||||
function blank(text) {
|
||||
return text === undefined || text === null || text === "";
|
||||
}
|
||||
function notBlank(text) {
|
||||
return !blank(text);
|
||||
}
|
||||
// async wrapper to load a url and settle on load finish or fail
|
||||
function load(window, url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.webContents.on("did-finish-load", (event) => resolve(event));
|
||||
window.webContents.on("did-fail-load", (event) => reject(event));
|
||||
window.loadURL(url);
|
||||
});
|
||||
});
|
||||
}
|
||||
function electronGetPageTitle(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { remote } = electronPkg;
|
||||
const { BrowserWindow } = remote;
|
||||
try {
|
||||
const window = new BrowserWindow({
|
||||
width: 1000,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: true,
|
||||
images: false,
|
||||
},
|
||||
show: false,
|
||||
});
|
||||
window.webContents.setAudioMuted(true);
|
||||
window.webContents.on("will-navigate", (event, newUrl) => {
|
||||
event.preventDefault();
|
||||
window.loadURL(newUrl);
|
||||
});
|
||||
yield load(window, url);
|
||||
try {
|
||||
const title = window.webContents.getTitle();
|
||||
window.destroy();
|
||||
if (notBlank(title)) {
|
||||
return title;
|
||||
}
|
||||
else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
window.destroy();
|
||||
return url;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
function nonElectronGetPageTitle(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const html = yield obsidian.request({ url });
|
||||
const doc = new DOMParser().parseFromString(html, "text/html");
|
||||
const title = doc.querySelectorAll("title")[0];
|
||||
if (title == null || blank(title === null || title === void 0 ? void 0 : title.innerText)) {
|
||||
// If site is javascript based and has a no-title attribute when unloaded, use it.
|
||||
var noTitle = title === null || title === void 0 ? void 0 : title.getAttr("no-title");
|
||||
if (notBlank(noTitle)) {
|
||||
return noTitle;
|
||||
}
|
||||
// Otherwise if the site has no title/requires javascript simply return Title Unknown
|
||||
return url;
|
||||
}
|
||||
return title.innerText;
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
function getUrlFinalSegment(url) {
|
||||
try {
|
||||
const segments = new URL(url).pathname.split('/');
|
||||
const last = segments.pop() || segments.pop(); // Handle potential trailing slash
|
||||
return last;
|
||||
}
|
||||
catch (_) {
|
||||
return "File";
|
||||
}
|
||||
}
|
||||
function tryGetFileType(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const response = yield fetch(url, { method: "HEAD" });
|
||||
// Ensure site returns an ok status code before scraping
|
||||
if (!response.ok) {
|
||||
return "Site Unreachable";
|
||||
}
|
||||
// Ensure site is an actual HTML page and not a pdf or 3 gigabyte video file.
|
||||
let contentType = response.headers.get("content-type");
|
||||
if (!contentType.includes("text/html")) {
|
||||
return getUrlFinalSegment(url);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (err) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
function getPageTitle(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// If we're on Desktop use the Electron scraper
|
||||
if (!(url.startsWith("http") || url.startsWith("https"))) {
|
||||
url = "https://" + url;
|
||||
}
|
||||
// Try to do a HEAD request to see if the site is reachable and if it's an HTML page
|
||||
// If we error out due to CORS, we'll just try to scrape the page anyway.
|
||||
let fileType = yield tryGetFileType(url);
|
||||
if (fileType) {
|
||||
return fileType;
|
||||
}
|
||||
if (electronPkg != null) {
|
||||
return electronGetPageTitle(url);
|
||||
}
|
||||
else {
|
||||
return nonElectronGetPageTitle(url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class AutoLinkTitle extends obsidian.Plugin {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.shortTitle = (title) => {
|
||||
if (this.settings.maximumTitleLength === 0) {
|
||||
return title;
|
||||
}
|
||||
if (title.length < this.settings.maximumTitleLength + 3) {
|
||||
return title;
|
||||
}
|
||||
const shortenedTitle = `${title.slice(0, this.settings.maximumTitleLength)}...`;
|
||||
return shortenedTitle;
|
||||
};
|
||||
}
|
||||
onload() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
console.log("loading obsidian-auto-link-title");
|
||||
yield this.loadSettings();
|
||||
this.blacklist = this.settings.websiteBlacklist
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
// Listen to paste event
|
||||
this.pasteFunction = this.pasteUrlWithTitle.bind(this);
|
||||
// Listen to drop event
|
||||
this.dropFunction = this.dropUrlWithTitle.bind(this);
|
||||
this.addCommand({
|
||||
id: "auto-link-title-paste",
|
||||
name: "Paste URL and auto fetch title",
|
||||
editorCallback: (editor) => this.manualPasteUrlWithTitle(editor),
|
||||
hotkeys: [],
|
||||
});
|
||||
this.addCommand({
|
||||
id: "auto-link-title-normal-paste",
|
||||
name: "Normal paste (no fetching behavior)",
|
||||
editorCallback: (editor) => this.normalPaste(editor),
|
||||
hotkeys: [
|
||||
{
|
||||
modifiers: ["Mod", "Shift"],
|
||||
key: "v",
|
||||
},
|
||||
],
|
||||
});
|
||||
this.registerEvent(this.app.workspace.on("editor-paste", this.pasteFunction));
|
||||
this.registerEvent(this.app.workspace.on("editor-drop", this.dropFunction));
|
||||
this.addCommand({
|
||||
id: "enhance-url-with-title",
|
||||
name: "Enhance existing URL with link and title",
|
||||
editorCallback: (editor) => this.addTitleToLink(editor),
|
||||
hotkeys: [
|
||||
{
|
||||
modifiers: ["Mod", "Shift"],
|
||||
key: "e",
|
||||
},
|
||||
],
|
||||
});
|
||||
this.addSettingTab(new AutoLinkTitleSettingTab(this.app, this));
|
||||
});
|
||||
}
|
||||
addTitleToLink(editor) {
|
||||
// Only attempt fetch if online
|
||||
if (!navigator.onLine)
|
||||
return;
|
||||
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||
// If the cursor is on a raw html link, convert to a markdown link and fetch title
|
||||
if (CheckIf.isUrl(selectedText)) {
|
||||
this.convertUrlToTitledLink(editor, selectedText);
|
||||
}
|
||||
// If the cursor is on the URL part of a markdown link, fetch title and replace existing link title
|
||||
else if (CheckIf.isLinkedUrl(selectedText)) {
|
||||
const link = this.getUrlFromLink(selectedText);
|
||||
this.convertUrlToTitledLink(editor, link);
|
||||
}
|
||||
}
|
||||
normalPaste(editor) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let clipboardText = yield navigator.clipboard.readText();
|
||||
if (clipboardText === null || clipboardText === "")
|
||||
return;
|
||||
editor.replaceSelection(clipboardText);
|
||||
});
|
||||
}
|
||||
// Simulate standard paste but using editor.replaceSelection with clipboard text since we can't seem to dispatch a paste event.
|
||||
manualPasteUrlWithTitle(editor) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const clipboardText = yield navigator.clipboard.readText();
|
||||
// Only attempt fetch if online
|
||||
if (!navigator.onLine) {
|
||||
editor.replaceSelection(clipboardText);
|
||||
return;
|
||||
}
|
||||
if (clipboardText == null || clipboardText == "")
|
||||
return;
|
||||
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
||||
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
||||
// to fetch the title is a waste of bandwidth.
|
||||
if (!CheckIf.isUrl(clipboardText) || CheckIf.isImage(clipboardText)) {
|
||||
editor.replaceSelection(clipboardText);
|
||||
return;
|
||||
}
|
||||
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
||||
// as the user has already probably put a meaningful title, also it would lead to the title
|
||||
// being inside the link.
|
||||
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
||||
editor.replaceSelection(clipboardText);
|
||||
return;
|
||||
}
|
||||
// If url is pasted over selected text and setting is enabled, no need to fetch title,
|
||||
// just insert a link
|
||||
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||
if (selectedText && this.settings.shouldPreserveSelectionAsTitle) {
|
||||
editor.replaceSelection(`[${selectedText}](${clipboardText})`);
|
||||
return;
|
||||
}
|
||||
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
||||
this.convertUrlToTitledLink(editor, clipboardText);
|
||||
return;
|
||||
});
|
||||
}
|
||||
pasteUrlWithTitle(clipboard, editor) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!this.settings.enhanceDefaultPaste) {
|
||||
return;
|
||||
}
|
||||
if (clipboard.defaultPrevented)
|
||||
return;
|
||||
// Only attempt fetch if online
|
||||
if (!navigator.onLine)
|
||||
return;
|
||||
let clipboardText = clipboard.clipboardData.getData("text/plain");
|
||||
if (clipboardText === null || clipboardText === "")
|
||||
return;
|
||||
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
||||
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
||||
// to fetch the title is a waste of bandwidth.
|
||||
if (!CheckIf.isUrl(clipboardText) || CheckIf.isImage(clipboardText)) {
|
||||
return;
|
||||
}
|
||||
// We've decided to handle the paste, stop propagation to the default handler.
|
||||
clipboard.stopPropagation();
|
||||
clipboard.preventDefault();
|
||||
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
||||
// as the user has already probably put a meaningful title, also it would lead to the title
|
||||
// being inside the link.
|
||||
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
||||
editor.replaceSelection(clipboardText);
|
||||
return;
|
||||
}
|
||||
// If url is pasted over selected text and setting is enabled, no need to fetch title,
|
||||
// just insert a link
|
||||
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||
if (selectedText && this.settings.shouldPreserveSelectionAsTitle) {
|
||||
editor.replaceSelection(`[${selectedText}](${clipboardText})`);
|
||||
return;
|
||||
}
|
||||
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
||||
this.convertUrlToTitledLink(editor, clipboardText);
|
||||
return;
|
||||
});
|
||||
}
|
||||
dropUrlWithTitle(dropEvent, editor) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!this.settings.enhanceDropEvents) {
|
||||
return;
|
||||
}
|
||||
if (dropEvent.defaultPrevented)
|
||||
return;
|
||||
// Only attempt fetch if online
|
||||
if (!navigator.onLine)
|
||||
return;
|
||||
let dropText = dropEvent.dataTransfer.getData("text/plain");
|
||||
if (dropText === null || dropText === "")
|
||||
return;
|
||||
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
||||
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
||||
// to fetch the title is a waste of bandwidth.
|
||||
if (!CheckIf.isUrl(dropText) || CheckIf.isImage(dropText)) {
|
||||
return;
|
||||
}
|
||||
// We've decided to handle the paste, stop propagation to the default handler.
|
||||
dropEvent.stopPropagation();
|
||||
dropEvent.preventDefault();
|
||||
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
||||
// as the user has already probably put a meaningful title, also it would lead to the title
|
||||
// being inside the link.
|
||||
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
||||
editor.replaceSelection(dropText);
|
||||
return;
|
||||
}
|
||||
// If url is pasted over selected text and setting is enabled, no need to fetch title,
|
||||
// just insert a link
|
||||
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||
if (selectedText && this.settings.shouldPreserveSelectionAsTitle) {
|
||||
editor.replaceSelection(`[${selectedText}](${dropText})`);
|
||||
return;
|
||||
}
|
||||
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
||||
this.convertUrlToTitledLink(editor, dropText);
|
||||
return;
|
||||
});
|
||||
}
|
||||
isBlacklisted(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.loadSettings();
|
||||
this.blacklist = this.settings.websiteBlacklist
|
||||
.split(/,|\n/)
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
return this.blacklist.some((site) => url.includes(site));
|
||||
});
|
||||
}
|
||||
convertUrlToTitledLink(editor, url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (yield this.isBlacklisted(url)) {
|
||||
let domain = new URL(url).hostname;
|
||||
editor.replaceSelection(`[${domain}](${url})`);
|
||||
return;
|
||||
}
|
||||
// Generate a unique id for find/replace operations for the title.
|
||||
const pasteId = this.getPasteId();
|
||||
// Instantly paste so you don't wonder if paste is broken
|
||||
editor.replaceSelection(`[${pasteId}](${url})`);
|
||||
// Fetch title from site, replace Fetching Title with actual title
|
||||
const title = yield this.fetchUrlTitle(url);
|
||||
const escapedTitle = this.escapeMarkdown(title);
|
||||
const shortenedTitle = this.shortTitle(escapedTitle);
|
||||
const text = editor.getValue();
|
||||
const start = text.indexOf(pasteId);
|
||||
if (start < 0) {
|
||||
console.log(`Unable to find text "${pasteId}" in current editor, bailing out; link ${url}`);
|
||||
}
|
||||
else {
|
||||
const end = start + pasteId.length;
|
||||
const startPos = EditorExtensions.getEditorPositionFromIndex(text, start);
|
||||
const endPos = EditorExtensions.getEditorPositionFromIndex(text, end);
|
||||
editor.replaceRange(shortenedTitle, startPos, endPos);
|
||||
}
|
||||
});
|
||||
}
|
||||
escapeMarkdown(text) {
|
||||
var unescaped = text.replace(/\\(\*|_|`|~|\\|\[|\])/g, "$1"); // unescape any "backslashed" character
|
||||
var escaped = unescaped.replace(/(\*|_|`|<|>|~|\\|\[|\])/g, "\\$1"); // escape *, _, `, ~, \, [, ], <, and >
|
||||
var escaped = unescaped.replace(/(\*|_|`|\||<|>|~|\\|\[|\])/g, "\\$1"); // escape *, _, `, ~, \, |, [, ], <, and >
|
||||
return escaped;
|
||||
}
|
||||
fetchUrlTitleViaLinkPreview(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (this.settings.linkPreviewApiKey.length !== 32) {
|
||||
console.error("LinkPreview API key is not 32 characters long, please check your settings");
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
const apiEndpoint = `https://api.linkpreview.net/?q=${encodeURIComponent(url)}`;
|
||||
const response = yield fetch(apiEndpoint, {
|
||||
headers: {
|
||||
"X-Linkpreview-Api-Key": this.settings.linkPreviewApiKey,
|
||||
},
|
||||
});
|
||||
const data = yield response.json();
|
||||
return data.title;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
fetchUrlTitle(url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
let title = "";
|
||||
title = yield this.fetchUrlTitleViaLinkPreview(url);
|
||||
console.log(`Title via Link Preview: ${title}`);
|
||||
if (title === "") {
|
||||
console.log("Title via Link Preview failed, falling back to scraper");
|
||||
if (this.settings.useNewScraper) {
|
||||
console.log("Using new scraper");
|
||||
title = yield getPageTitle$1(url);
|
||||
}
|
||||
else {
|
||||
console.log("Using old scraper");
|
||||
title = yield getPageTitle(url);
|
||||
}
|
||||
}
|
||||
console.log(`Title: ${title}`);
|
||||
title =
|
||||
title.replace(/(\r\n|\n|\r)/gm, "").trim() ||
|
||||
"Title Unavailable | Site Unreachable";
|
||||
return title;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
return "Error fetching title";
|
||||
}
|
||||
});
|
||||
}
|
||||
getUrlFromLink(link) {
|
||||
let urlRegex = new RegExp(DEFAULT_SETTINGS.linkRegex);
|
||||
return urlRegex.exec(link)[2];
|
||||
}
|
||||
getPasteId() {
|
||||
var base = "Fetching Title";
|
||||
if (this.settings.useBetterPasteId) {
|
||||
return this.getBetterPasteId(base);
|
||||
}
|
||||
else {
|
||||
return `${base}#${this.createBlockHash()}`;
|
||||
}
|
||||
}
|
||||
getBetterPasteId(base) {
|
||||
// After every character, add 0, 1 or 2 invisible characters
|
||||
// so that to the user it looks just like the base string.
|
||||
// The number of combinations is 3^14 = 4782969
|
||||
let result = "";
|
||||
var invisibleCharacter = "\u200B";
|
||||
var maxInvisibleCharacters = 2;
|
||||
for (var i = 0; i < base.length; i++) {
|
||||
var count = Math.floor(Math.random() * (maxInvisibleCharacters + 1));
|
||||
result += base.charAt(i) + invisibleCharacter.repeat(count);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Custom hashid by @shabegom
|
||||
createBlockHash() {
|
||||
let result = "";
|
||||
var characters = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
onunload() {
|
||||
console.log("unloading obsidian-auto-link-title");
|
||||
}
|
||||
loadSettings() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
||||
});
|
||||
}
|
||||
saveSettings() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.saveData(this.settings);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AutoLinkTitle;
|
||||
|
||||
|
||||
/* nosourcemap */
|
10
.obsidian/plugins/obsidian-auto-link-title/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-auto-link-title",
|
||||
"name": "Auto Link Title",
|
||||
"version": "1.5.5",
|
||||
"minAppVersion": "0.12.17",
|
||||
"description": "This plugin automatically fetches the titles of links from the web",
|
||||
"author": "Matt Furden",
|
||||
"authorUrl": "https://github.com/zolrath",
|
||||
"isDesktopOnly": false
|
||||
}
|
1
.obsidian/plugins/obsidian-auto-link-title/styles.css
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/* no styles */
|
489
.obsidian/plugins/obsidian-footnotes/main.js
vendored
Normal file
|
@ -0,0 +1,489 @@
|
|||
'use strict';
|
||||
|
||||
var obsidian = require('obsidian');
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
function __awaiter(thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS = {
|
||||
enableAutoSuggest: true,
|
||||
enableFootnoteSectionHeading: false,
|
||||
FootnoteSectionHeading: "Footnotes",
|
||||
};
|
||||
class FootnotePluginSettingTab extends obsidian.PluginSettingTab {
|
||||
constructor(app, plugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
display() {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
containerEl.createEl("h2", {
|
||||
text: "Footnote Shortcut",
|
||||
});
|
||||
const mainDesc = containerEl.createEl('p');
|
||||
mainDesc.appendText('Need help? Check the ');
|
||||
mainDesc.appendChild(createEl('a', {
|
||||
text: "README",
|
||||
href: "https://github.com/MichaBrugger/obsidian-footnotes",
|
||||
}));
|
||||
mainDesc.appendText('!');
|
||||
containerEl.createEl('br');
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Enable Footnote Autosuggest")
|
||||
.setDesc("Suggests existing footnotes when entering named footnotes.")
|
||||
.addToggle((toggle) => toggle
|
||||
.setValue(this.plugin.settings.enableAutoSuggest)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
this.plugin.settings.enableAutoSuggest = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
containerEl.createEl("h3", {
|
||||
text: "Footnotes Section Behavior",
|
||||
});
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Enable Footnote Section Heading")
|
||||
.setDesc("Automatically adds a heading separating footnotes at the bottom of the note from the rest of the text.")
|
||||
.addToggle((toggle) => toggle
|
||||
.setValue(this.plugin.settings.enableFootnoteSectionHeading)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
this.plugin.settings.enableFootnoteSectionHeading = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Footnote Section Heading")
|
||||
.setDesc("Heading to place above footnotes section (Supports Markdown formatting). Heading will be H1 size.")
|
||||
.addText((text) => text
|
||||
.setPlaceholder("Heading is Empty")
|
||||
.setValue(this.plugin.settings.FootnoteSectionHeading)
|
||||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||
this.plugin.settings.FootnoteSectionHeading = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
var AllMarkers = /\[\^([^\[\]]+)\](?!:)/dg;
|
||||
var AllNumberedMarkers = /\[\^(\d+)\]/gi;
|
||||
var AllDetailsNameOnly = /\[\^([^\[\]]+)\]:/g;
|
||||
var DetailInLine = /\[\^([^\[\]]+)\]:/;
|
||||
var ExtractNameFromFootnote = /(\[\^)([^\[\]]+)(?=\])/;
|
||||
function listExistingFootnoteDetails(doc) {
|
||||
let FootnoteDetailList = [];
|
||||
//search each line for footnote details and add to list
|
||||
for (let i = 0; i < doc.lineCount(); i++) {
|
||||
let theLine = doc.getLine(i);
|
||||
let lineMatch = theLine.match(AllDetailsNameOnly);
|
||||
if (lineMatch) {
|
||||
let temp = lineMatch[0];
|
||||
temp = temp.replace("[^", "");
|
||||
temp = temp.replace("]:", "");
|
||||
FootnoteDetailList.push(temp);
|
||||
}
|
||||
}
|
||||
if (FootnoteDetailList.length > 0) {
|
||||
return FootnoteDetailList;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function listExistingFootnoteMarkersAndLocations(doc) {
|
||||
let markerEntry;
|
||||
let FootnoteMarkerInfo = [];
|
||||
//search each line for footnote markers
|
||||
//for each, add their name, line number, and start index to FootnoteMarkerInfo
|
||||
for (let i = 0; i < doc.lineCount(); i++) {
|
||||
let theLine = doc.getLine(i);
|
||||
let lineMatch;
|
||||
while ((lineMatch = AllMarkers.exec(theLine)) != null) {
|
||||
markerEntry = {
|
||||
footnote: lineMatch[0],
|
||||
lineNum: i,
|
||||
startIndex: lineMatch.index
|
||||
};
|
||||
FootnoteMarkerInfo.push(markerEntry);
|
||||
}
|
||||
}
|
||||
return FootnoteMarkerInfo;
|
||||
}
|
||||
function shouldJumpFromDetailToMarker(lineText, cursorPosition, doc) {
|
||||
// check if we're in a footnote detail line ("[^1]: footnote")
|
||||
// if so, jump cursor back to the footnote in the text
|
||||
let match = lineText.match(DetailInLine);
|
||||
if (match) {
|
||||
let s = match[0];
|
||||
let index = s.replace("[^", "");
|
||||
index = index.replace("]:", "");
|
||||
let footnote = s.replace(":", "");
|
||||
let returnLineIndex = cursorPosition.line;
|
||||
// find the FIRST OCCURENCE where this footnote exists in the text
|
||||
for (let i = 0; i < doc.lineCount(); i++) {
|
||||
let scanLine = doc.getLine(i);
|
||||
if (scanLine.contains(footnote)) {
|
||||
let cursorLocationIndex = scanLine.indexOf(footnote);
|
||||
returnLineIndex = i;
|
||||
doc.setCursor({
|
||||
line: returnLineIndex,
|
||||
ch: cursorLocationIndex + footnote.length,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function shouldJumpFromMarkerToDetail(lineText, cursorPosition, doc) {
|
||||
// Jump cursor TO detail marker
|
||||
// does this line have a footnote marker?
|
||||
// does the cursor overlap with one of them?
|
||||
// if so, which one?
|
||||
// find this footnote marker's detail line
|
||||
// place cursor there
|
||||
let markerTarget = null;
|
||||
let FootnoteMarkerInfo = listExistingFootnoteMarkersAndLocations(doc);
|
||||
let currentLine = cursorPosition.line;
|
||||
let footnotesOnLine = FootnoteMarkerInfo.filter((markerEntry) => markerEntry.lineNum === currentLine);
|
||||
if (footnotesOnLine != null) {
|
||||
for (let i = 0; i <= footnotesOnLine.length - 1; i++) {
|
||||
if (footnotesOnLine[i].footnote !== null) {
|
||||
let marker = footnotesOnLine[i].footnote;
|
||||
let indexOfMarkerInLine = footnotesOnLine[i].startIndex;
|
||||
if (cursorPosition.ch >= indexOfMarkerInLine &&
|
||||
cursorPosition.ch <= indexOfMarkerInLine + marker.length) {
|
||||
markerTarget = marker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (markerTarget !== null) {
|
||||
// extract name
|
||||
let match = markerTarget.match(ExtractNameFromFootnote);
|
||||
if (match) {
|
||||
let footnoteName = match[2];
|
||||
// find the first line with this detail marker name in it.
|
||||
for (let i = 0; i < doc.lineCount(); i++) {
|
||||
let theLine = doc.getLine(i);
|
||||
let lineMatch = theLine.match(DetailInLine);
|
||||
if (lineMatch) {
|
||||
// compare to the index
|
||||
let nameMatch = lineMatch[1];
|
||||
if (nameMatch == footnoteName) {
|
||||
doc.setCursor({ line: i, ch: lineMatch[0].length + 1 });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function addFootnoteSectionHeader(plugin) {
|
||||
//check if 'Enable Footnote Section Heading' is true
|
||||
//if so, return the "Footnote Section Heading"
|
||||
// else, return ""
|
||||
if (plugin.settings.enableFootnoteSectionHeading == true) {
|
||||
let returnHeading = `\n# ${plugin.settings.FootnoteSectionHeading}`;
|
||||
return returnHeading;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
//FUNCTIONS FOR AUTONUMBERED FOOTNOTES
|
||||
function insertAutonumFootnote(plugin) {
|
||||
const mdView = app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
if (!mdView)
|
||||
return false;
|
||||
if (mdView.editor == undefined)
|
||||
return false;
|
||||
const doc = mdView.editor;
|
||||
const cursorPosition = doc.getCursor();
|
||||
const lineText = doc.getLine(cursorPosition.line);
|
||||
const markdownText = mdView.data;
|
||||
if (shouldJumpFromDetailToMarker(lineText, cursorPosition, doc))
|
||||
return;
|
||||
if (shouldJumpFromMarkerToDetail(lineText, cursorPosition, doc))
|
||||
return;
|
||||
return shouldCreateAutonumFootnote(lineText, cursorPosition, plugin, doc, markdownText);
|
||||
}
|
||||
function shouldCreateAutonumFootnote(lineText, cursorPosition, plugin, doc, markdownText) {
|
||||
// create new footnote with the next numerical index
|
||||
let matches = markdownText.match(AllNumberedMarkers);
|
||||
let currentMax = 1;
|
||||
if (matches != null) {
|
||||
for (let i = 0; i <= matches.length - 1; i++) {
|
||||
let match = matches[i];
|
||||
match = match.replace("[^", "");
|
||||
match = match.replace("]", "");
|
||||
let matchNumber = Number(match);
|
||||
if (matchNumber + 1 > currentMax) {
|
||||
currentMax = matchNumber + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
let footNoteId = currentMax;
|
||||
let footnoteMarker = `[^${footNoteId}]`;
|
||||
let linePart1 = lineText.substr(0, cursorPosition.ch);
|
||||
let linePart2 = lineText.substr(cursorPosition.ch);
|
||||
let newLine = linePart1 + footnoteMarker + linePart2;
|
||||
doc.replaceRange(newLine, { line: cursorPosition.line, ch: 0 }, { line: cursorPosition.line, ch: lineText.length });
|
||||
let lastLineIndex = doc.lastLine();
|
||||
let lastLine = doc.getLine(lastLineIndex);
|
||||
while (lastLineIndex > 0) {
|
||||
lastLine = doc.getLine(lastLineIndex);
|
||||
if (lastLine.length > 0) {
|
||||
doc.replaceRange("", { line: lastLineIndex, ch: 0 }, { line: doc.lastLine(), ch: 0 });
|
||||
break;
|
||||
}
|
||||
lastLineIndex--;
|
||||
}
|
||||
let footnoteDetail = `\n[^${footNoteId}]: `;
|
||||
let list = listExistingFootnoteDetails(doc);
|
||||
if (list === null && currentMax == 1) {
|
||||
footnoteDetail = "\n" + footnoteDetail;
|
||||
let Heading = addFootnoteSectionHeader(plugin);
|
||||
doc.setLine(doc.lastLine(), lastLine + Heading + footnoteDetail);
|
||||
doc.setCursor(doc.lastLine() - 1, footnoteDetail.length - 1);
|
||||
}
|
||||
else {
|
||||
doc.setLine(doc.lastLine(), lastLine + footnoteDetail);
|
||||
doc.setCursor(doc.lastLine(), footnoteDetail.length - 1);
|
||||
}
|
||||
}
|
||||
//FUNCTIONS FOR NAMED FOOTNOTES
|
||||
function insertNamedFootnote(plugin) {
|
||||
const mdView = app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
if (!mdView)
|
||||
return false;
|
||||
if (mdView.editor == undefined)
|
||||
return false;
|
||||
const doc = mdView.editor;
|
||||
const cursorPosition = doc.getCursor();
|
||||
const lineText = doc.getLine(cursorPosition.line);
|
||||
mdView.data;
|
||||
if (shouldJumpFromDetailToMarker(lineText, cursorPosition, doc))
|
||||
return;
|
||||
if (shouldJumpFromMarkerToDetail(lineText, cursorPosition, doc))
|
||||
return;
|
||||
if (shouldCreateMatchingFootnoteDetail(lineText, cursorPosition, plugin, doc))
|
||||
return;
|
||||
return shouldCreateFootnoteMarker(lineText, cursorPosition, doc);
|
||||
}
|
||||
function shouldCreateMatchingFootnoteDetail(lineText, cursorPosition, plugin, doc) {
|
||||
// Create matching footnote detail for footnote marker
|
||||
// does this line have a footnote marker?
|
||||
// does the cursor overlap with one of them?
|
||||
// if so, which one?
|
||||
// does this footnote marker have a detail line?
|
||||
// if not, create it and place cursor there
|
||||
let reOnlyMarkersMatches = lineText.match(AllMarkers);
|
||||
let markerTarget = null;
|
||||
if (reOnlyMarkersMatches) {
|
||||
for (let i = 0; i <= reOnlyMarkersMatches.length; i++) {
|
||||
let marker = reOnlyMarkersMatches[i];
|
||||
if (marker != undefined) {
|
||||
let indexOfMarkerInLine = lineText.indexOf(marker);
|
||||
if (cursorPosition.ch >= indexOfMarkerInLine &&
|
||||
cursorPosition.ch <= indexOfMarkerInLine + marker.length) {
|
||||
markerTarget = marker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (markerTarget != null) {
|
||||
//extract footnote
|
||||
let match = markerTarget.match(ExtractNameFromFootnote);
|
||||
//find if this footnote exists by listing existing footnote details
|
||||
if (match) {
|
||||
let footnoteId = match[2];
|
||||
let list = listExistingFootnoteDetails(doc);
|
||||
// Check if the list is empty OR if the list doesn't include current footnote
|
||||
// if so, add detail for the current footnote
|
||||
if (list === null || !list.includes(footnoteId)) {
|
||||
let lastLineIndex = doc.lastLine();
|
||||
let lastLine = doc.getLine(lastLineIndex);
|
||||
while (lastLineIndex > 0) {
|
||||
lastLine = doc.getLine(lastLineIndex);
|
||||
if (lastLine.length > 0) {
|
||||
doc.replaceRange("", { line: lastLineIndex, ch: 0 }, { line: doc.lastLine(), ch: 0 });
|
||||
break;
|
||||
}
|
||||
lastLineIndex--;
|
||||
}
|
||||
let footnoteDetail = `\n[^${footnoteId}]: `;
|
||||
if (list === null || list.length < 1) {
|
||||
footnoteDetail = "\n" + footnoteDetail;
|
||||
let Heading = addFootnoteSectionHeader(plugin);
|
||||
doc.setLine(doc.lastLine(), lastLine + Heading + footnoteDetail);
|
||||
doc.setCursor(doc.lastLine() - 1, footnoteDetail.length - 1);
|
||||
}
|
||||
else {
|
||||
doc.setLine(doc.lastLine(), lastLine + footnoteDetail);
|
||||
doc.setCursor(doc.lastLine(), footnoteDetail.length - 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
function shouldCreateFootnoteMarker(lineText, cursorPosition, doc, markdownText) {
|
||||
//create empty footnote marker for name input
|
||||
let emptyMarker = `[^]`;
|
||||
doc.replaceRange(emptyMarker, doc.getCursor());
|
||||
//move cursor in between [^ and ]
|
||||
doc.setCursor(cursorPosition.line, cursorPosition.ch + 2);
|
||||
//open footnotePicker popup
|
||||
}
|
||||
|
||||
class Autocomplete extends obsidian.EditorSuggest {
|
||||
constructor(plugin) {
|
||||
super(plugin.app);
|
||||
this.Footnote_Detail_Names_And_Text = /\[\^([^\[\]]+)\]:(.+(?:\n(?:(?!\[\^[^\[\]]+\]:).)+)*)/g;
|
||||
this.getSuggestions = (context) => {
|
||||
const { query } = context;
|
||||
const mdView = app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
const doc = mdView.editor;
|
||||
const matches = this.Extract_Footnote_Detail_Names_And_Text(doc);
|
||||
const filteredResults = matches.filter((entry) => entry[1].includes(query));
|
||||
return filteredResults;
|
||||
};
|
||||
this.plugin = plugin;
|
||||
}
|
||||
onTrigger(cursorPosition, doc, file) {
|
||||
if (this.plugin.settings.enableAutoSuggest) {
|
||||
const mdView = app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
const lineText = doc.getLine(cursorPosition.line);
|
||||
mdView.data;
|
||||
let reOnlyMarkersMatches = lineText.match(AllMarkers);
|
||||
let markerTarget = null;
|
||||
let indexOfMarkerInLine = null;
|
||||
if (reOnlyMarkersMatches) {
|
||||
for (let i = 0; i <= reOnlyMarkersMatches.length; i++) {
|
||||
let marker = reOnlyMarkersMatches[i];
|
||||
if (marker != undefined) {
|
||||
indexOfMarkerInLine = lineText.indexOf(marker);
|
||||
if (cursorPosition.ch >= indexOfMarkerInLine &&
|
||||
cursorPosition.ch <= indexOfMarkerInLine + marker.length) {
|
||||
markerTarget = marker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (markerTarget != null) {
|
||||
//extract footnote
|
||||
let match = markerTarget.match(ExtractNameFromFootnote);
|
||||
//find if this footnote exists by listing existing footnote details
|
||||
if (match) {
|
||||
let footnoteId = match[2];
|
||||
if (footnoteId !== undefined) {
|
||||
this.latestTriggerInfo = {
|
||||
end: cursorPosition,
|
||||
start: {
|
||||
ch: indexOfMarkerInLine + 2,
|
||||
line: cursorPosition.line
|
||||
},
|
||||
query: footnoteId
|
||||
};
|
||||
return this.latestTriggerInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Extract_Footnote_Detail_Names_And_Text(doc) {
|
||||
//search each line for footnote details and add to list
|
||||
//save the footnote detail name as capture group 1
|
||||
//save the footnote detail text as capture group 2
|
||||
let docText = doc.getValue();
|
||||
const matches = Array.from(docText.matchAll(this.Footnote_Detail_Names_And_Text));
|
||||
return matches;
|
||||
}
|
||||
renderSuggestion(value, el) {
|
||||
el.createEl("b", { text: value[1] });
|
||||
el.createEl("br");
|
||||
el.createEl("p", { text: value[2] });
|
||||
}
|
||||
selectSuggestion(value, evt) {
|
||||
const { context, plugin } = this;
|
||||
if (!context)
|
||||
return;
|
||||
const mdView = app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
mdView.editor;
|
||||
const field = value[1];
|
||||
const replacement = `${field}`;
|
||||
context.editor.replaceRange(replacement, this.latestTriggerInfo.start, this.latestTriggerInfo.end);
|
||||
}
|
||||
}
|
||||
|
||||
//Add chevron-up-square icon from lucide for mobile toolbar (temporary until Obsidian updates to Lucide v0.130.0)
|
||||
obsidian.addIcon("chevron-up-square", `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-up-square"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><polyline points="8,14 12,10 16,14"></polyline></svg>`);
|
||||
class FootnotePlugin extends obsidian.Plugin {
|
||||
onload() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.loadSettings();
|
||||
this.registerEditorSuggest(new Autocomplete(this));
|
||||
this.addCommand({
|
||||
id: "insert-autonumbered-footnote",
|
||||
name: "Insert / Navigate Auto-Numbered Footnote",
|
||||
icon: "plus-square",
|
||||
checkCallback: (checking) => {
|
||||
if (checking)
|
||||
return !!this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
insertAutonumFootnote(this);
|
||||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: "insert-named-footnote",
|
||||
name: "Insert / Navigate Named Footnote",
|
||||
icon: "chevron-up-square",
|
||||
checkCallback: (checking) => {
|
||||
if (checking)
|
||||
return !!this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
||||
insertNamedFootnote(this);
|
||||
}
|
||||
});
|
||||
this.addSettingTab(new FootnotePluginSettingTab(this.app, this));
|
||||
});
|
||||
}
|
||||
loadSettings() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
||||
});
|
||||
}
|
||||
saveSettings() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.saveData(this.settings);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FootnotePlugin;
|
||||
|
||||
|
||||
/* nosourcemap */
|
10
.obsidian/plugins/obsidian-footnotes/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-footnotes",
|
||||
"name": "Footnote Shortcut",
|
||||
"version": "0.1.3",
|
||||
"minAppVersion": "0.12.0",
|
||||
"description": "Insert and write footnotes faster",
|
||||
"author": "Alexis Rondeau, Micha Brugger, Jason Qin",
|
||||
"authorUrl": "https://publish.obsidian.md/alexisrondeau",
|
||||
"isDesktopOnly": false
|
||||
}
|
7158
.obsidian/plugins/obsidian-icon-folder/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-icon-folder/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-icon-folder",
|
||||
"name": "Iconize",
|
||||
"version": "2.14.7",
|
||||
"minAppVersion": "0.9.12",
|
||||
"description": "Add icons to anything you desire in Obsidian, including files, folders, and text.",
|
||||
"author": "Florian Woelki",
|
||||
"authorUrl": "https://florianwoelki.com/",
|
||||
"isDesktopOnly": false
|
||||
}
|
120
.obsidian/plugins/obsidian-icon-folder/styles.css
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
.iconize-inline-title-wrapper {
|
||||
width: var(--line-width);
|
||||
max-width: var(--max-width);
|
||||
margin-inline: var(--content-margin);
|
||||
}
|
||||
|
||||
.iconize-title-icon {
|
||||
max-width: var(--max-width);
|
||||
margin-right: var(--size-4-2);
|
||||
}
|
||||
|
||||
.iconize-icon-in-link {
|
||||
transform: translateY(20%);
|
||||
margin-right: var(--size-2-2);
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.iconize-icon {
|
||||
border: 1px solid transparent;
|
||||
margin: 0px 4px 0px 0px;
|
||||
display: flex;
|
||||
align-self: center;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
.nav-folder-title,
|
||||
.nav-file-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.iconize-setting input[type='color'] {
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.iconize-modal.prompt-results {
|
||||
margin: 0;
|
||||
overflow-y: auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.prompt .iconize-subheadline {
|
||||
margin-top: 12px;
|
||||
font-size: 12px;
|
||||
color: gray;
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 6;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.iconize-modal.prompt-results {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
.prompt .iconize-subheadline {
|
||||
grid-column-end: 4;
|
||||
}
|
||||
}
|
||||
|
||||
.iconize-modal.prompt-results .suggestion-item {
|
||||
cursor: pointer;
|
||||
white-space: pre-wrap;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
flex-direction: column-reverse;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
padding: 16px 8px;
|
||||
line-break: auto;
|
||||
word-break: break-word;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.iconize-modal.prompt-results .suggestion-item.suggestion-item__center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.iconize-icon-preview {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.iconize-icon-preview img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.iconize-icon-preview svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: currentColor;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.iconize-dragover {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.iconize-dragover-el {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: var(--text-normal);
|
||||
background-color: var(--background-secondary-alt);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Custom rule modal. */
|
||||
.iconize-custom-modal .modal-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.iconize-custom-modal .modal-content input {
|
||||
width: 100%;
|
||||
margin-right: 0.5rem;
|
||||
}
|
1932
.obsidian/plugins/obsidian-link-embed/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-link-embed/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-link-embed",
|
||||
"name": "Link Embed",
|
||||
"version": "2.5.5",
|
||||
"minAppVersion": "0.12.0",
|
||||
"description": "Instantly turn plain links in your notes into beautiful, Notion-style rich link previews. The plugin automatically fetches page metadata (title, description, favicon & image) and renders it as an elegant, card-styled embed—so your vault stays informative and visually appealing with zero extra effort.",
|
||||
"author": "SErAphLi",
|
||||
"authorUrl": "https://github.com/Seraphli",
|
||||
"isDesktopOnly": false
|
||||
}
|
336
.obsidian/plugins/obsidian-link-embed/styles.css
vendored
Normal file
|
@ -0,0 +1,336 @@
|
|||
.w {
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: none transparent;
|
||||
text-align: left;
|
||||
}
|
||||
.em > a,
|
||||
.tc > a,
|
||||
.th > a {
|
||||
background-color: transparent;
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
.em > a,
|
||||
.tc > a,
|
||||
.th > a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
.w {
|
||||
line-height: 1.4;
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
|
||||
Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
color: inherit;
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.t,
|
||||
.w,
|
||||
.wf {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
@supports (-webkit-overflow-scrolling: touch) {
|
||||
.w {
|
||||
max-width: 100vw;
|
||||
}
|
||||
}
|
||||
.wc,
|
||||
.wt {
|
||||
overflow: hidden;
|
||||
}
|
||||
._sm {
|
||||
background: inherit;
|
||||
}
|
||||
._lc .wf {
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
||||
._lc .wt {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.wt {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
@media (min-width: 360px) {
|
||||
.wt {
|
||||
padding: 12px 15px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
.wt {
|
||||
padding: 16px 20px;
|
||||
}
|
||||
}
|
||||
._lc._sm:not(.xd) .wc {
|
||||
min-width: 100px;
|
||||
width: 100px;
|
||||
min-height: 100px;
|
||||
}
|
||||
._lc._sm:not(.xd) .wc._wi {
|
||||
max-width: min(50%, 200px);
|
||||
}
|
||||
@media (min-width: 360px) {
|
||||
._lc._sm:not(.xd) .wc {
|
||||
min-width: 110px;
|
||||
width: 110px;
|
||||
min-height: 110px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 360px) {
|
||||
._lc._sm:not(.xd) .wc._wi {
|
||||
max-width: min(50%, 220px);
|
||||
}
|
||||
}
|
||||
@media (min-width: 460px) {
|
||||
._lc._sm:not(.xd) .wc {
|
||||
min-width: 140px;
|
||||
width: 140px;
|
||||
min-height: 140px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 460px) {
|
||||
._lc._sm:not(.xd) .wc._wi {
|
||||
max-width: min(50%, 280px);
|
||||
}
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
._lc._sm:not(.xd) .wc {
|
||||
min-width: 160px;
|
||||
width: 160px;
|
||||
min-height: 160px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
._lc._sm:not(.xd) .wc._wi {
|
||||
max-width: min(50%, 320px);
|
||||
}
|
||||
}
|
||||
@supports (-moz-appearance: meterbar) and (all: initial) {
|
||||
._lc .wc {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-align: stretch;
|
||||
align-items: stretch;
|
||||
-ms-flex-line-pack: stretch;
|
||||
align-content: stretch;
|
||||
}
|
||||
}
|
||||
@media (max-width: 459px) {
|
||||
._lc .twt {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (min-width: 460px) {
|
||||
._lc .twd {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
._lc._ts .th {
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
._lc._ts._lh14 .th {
|
||||
max-height: 1.4em;
|
||||
}
|
||||
._lc._ts .td {
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
._lc._ts._lh14 .td {
|
||||
max-height: 2.8em;
|
||||
}
|
||||
@media (min-width: 460px) {
|
||||
._lc._ts .th {
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
._lc._ts._lh14 .th {
|
||||
max-height: 1.4em;
|
||||
}
|
||||
._lc._ts .td {
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
._lc._ts._lh14 .td {
|
||||
max-height: 4.2em;
|
||||
}
|
||||
}
|
||||
.t {
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
.td,
|
||||
.th {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
}
|
||||
@supports (display: -webkit-box) {
|
||||
.td,
|
||||
.th {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.td {
|
||||
vertical-align: inherit;
|
||||
}
|
||||
.tf,
|
||||
.th {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.td {
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
._od .tf:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.tf {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.tc {
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@media (min-width: 460px) {
|
||||
.td {
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
}
|
||||
._ffsa {
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
|
||||
Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
._fwn {
|
||||
font-weight: 400;
|
||||
}
|
||||
._fwb {
|
||||
font-weight: 700;
|
||||
}
|
||||
._fsn {
|
||||
font-style: normal;
|
||||
}
|
||||
._lh14 {
|
||||
line-height: 1.4;
|
||||
}
|
||||
._f0,
|
||||
._f1m {
|
||||
font-size: 12px;
|
||||
}
|
||||
._f1p {
|
||||
font-size: 13px;
|
||||
}
|
||||
@media (min-width: 360px) {
|
||||
._f0 {
|
||||
font-size: 13px;
|
||||
}
|
||||
._f1p {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 460px) {
|
||||
._f1m {
|
||||
font-size: 13px;
|
||||
}
|
||||
._f0 {
|
||||
font-size: 14px;
|
||||
}
|
||||
._f1p {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
._f1m {
|
||||
font-size: 14px;
|
||||
}
|
||||
._f0 {
|
||||
font-size: 15px;
|
||||
}
|
||||
._f1p {
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
.e {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
@supports (-moz-appearance: meterbar) and (all: initial) {
|
||||
._lc .e {
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
._lc:not(._ap) .e {
|
||||
height: 100%;
|
||||
}
|
||||
.em {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.c {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.c {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: no-repeat center;
|
||||
background-size: cover;
|
||||
}
|
||||
.c {
|
||||
z-index: 20;
|
||||
}
|
||||
.w {
|
||||
background-color: inherit;
|
||||
}
|
||||
.t {
|
||||
line-height: 1.4;
|
||||
color: inherit;
|
||||
}
|
||||
.th {
|
||||
color: inherit;
|
||||
}
|
||||
.tf {
|
||||
color: #999;
|
||||
}
|
||||
.tw {
|
||||
color: #999;
|
||||
}
|
||||
.thl {
|
||||
font-weight: 600;
|
||||
}
|
||||
.embed {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius-s);
|
||||
box-shadow: rgba(0, 0, 0, 0.06) 0px 1px 3px;
|
||||
}
|
5132
.obsidian/plugins/obsidian-markdown-formatting-assistant-plugin/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-markdown-formatting-assistant-plugin/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-markdown-formatting-assistant-plugin",
|
||||
"name": "Markdown Formatting Assistant",
|
||||
"version": "0.4.1",
|
||||
"minAppVersion": "0.15.6",
|
||||
"description": "This Plugin provides a simple Editor for Markdown, HTML and Colors and in addition a command interface. The command interface facilitate a faster workflow.",
|
||||
"author": "Reocin",
|
||||
"authorUrl": "https://github.com/Reocin/obsidian-markdown-formatting-assistant-plugin",
|
||||
"isDesktopOnly": false
|
||||
}
|
62
.obsidian/plugins/obsidian-markdown-formatting-assistant-plugin/styles.css
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Sets all the text color to red! */
|
||||
.nav-action-button {
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
padding: 0px;
|
||||
margin: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.nav-action-text-button {
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
margin: 4px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
border: 1px solid;
|
||||
}
|
||||
.nav-action-text-button.is-active {
|
||||
background-color: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
.nav-action-text-button.is-active:hover {
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
.nav-action-text-button:hover {
|
||||
color: var(--text-accent);
|
||||
}
|
||||
|
||||
.color-icon {
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
min-width: 16px;
|
||||
max-width: 16px;
|
||||
height: 16px;
|
||||
min-height: 16px;
|
||||
max-height: 16px;
|
||||
margin: 3px;
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.command-list-view-row {
|
||||
display: flex;
|
||||
}
|
||||
.command-list-view-container {
|
||||
min-width: 60px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.command-list-view-icon {
|
||||
height: 24px;
|
||||
max-height: 24px;
|
||||
border: 1px solid gray;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.command-list-view-text {
|
||||
padding-left: 12px;
|
||||
color: #c7254e;
|
||||
}
|
165
.obsidian/plugins/obsidian-style-settings/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-style-settings/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-style-settings",
|
||||
"name": "Style Settings",
|
||||
"version": "1.0.9",
|
||||
"minAppVersion": "0.11.5",
|
||||
"description": "Offers controls for adjusting theme, plugin, and snippet CSS variables.",
|
||||
"author": "mgmeyers",
|
||||
"authorUrl": "https://github.com/mgmeyers/obsidian-style-settings",
|
||||
"isDesktopOnly": false
|
||||
}
|