mirror of
https://github.com/Ellpeck/ObsidianCustomFrames.git
synced 2024-11-04 19:29:08 +01:00
Compare commits
No commits in common. "master" and "2.4.6" have entirely different histories.
21 changed files with 3245 additions and 1946 deletions
|
@ -4,6 +4,6 @@ root = true
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
|
|
14
README.md
14
README.md
|
@ -37,10 +37,6 @@ urlSuffix: #reminders
|
||||||
### 📱 On Obsidian Mobile
|
### 📱 On Obsidian Mobile
|
||||||
Unfortunately, Obsidian Mobile does not run on [Electron](https://www.electronjs.org/), which is what allows iframes and [webviews](https://www.electronjs.org/docs/latest/api/webview-tag) to be displayed with very few restrictions related to cookies, cross-origin resource sharing, and so on. This means that a lot of sites won't work there, especially ones that you have to log in to. However, when you create a frame, you can toggle the "Disable on Mobile" option to hide a Desktop-only frame in Obsidian mobile.
|
Unfortunately, Obsidian Mobile does not run on [Electron](https://www.electronjs.org/), which is what allows iframes and [webviews](https://www.electronjs.org/docs/latest/api/webview-tag) to be displayed with very few restrictions related to cookies, cross-origin resource sharing, and so on. This means that a lot of sites won't work there, especially ones that you have to log in to. However, when you create a frame, you can toggle the "Disable on Mobile" option to hide a Desktop-only frame in Obsidian mobile.
|
||||||
|
|
||||||
Need help using the plugin? Feel free to join the Discord server!
|
|
||||||
|
|
||||||
[![Join the Discord server](https://ellpeck.de/res/discord-wide.png)](https://link.ellpeck.de/discordweb)
|
|
||||||
|
|
||||||
## 📦 Presets
|
## 📦 Presets
|
||||||
By default, Custom Frames comes with a few presets that allow you to get new panes for popular sites up and running quickly.
|
By default, Custom Frames comes with a few presets that allow you to get new panes for popular sites up and running quickly.
|
||||||
- [Obsidian Forum](https://forum.obsidian.md/)
|
- [Obsidian Forum](https://forum.obsidian.md/)
|
||||||
|
@ -49,7 +45,6 @@ By default, Custom Frames comes with a few presets that allow you to get new pan
|
||||||
- [Todoist](https://todoist.com), optimized for a narrow (half-height) side panel by removing some buttons and slimming margins.
|
- [Todoist](https://todoist.com), optimized for a narrow (half-height) side panel by removing some buttons and slimming margins.
|
||||||
- [Notion](https://www.notion.so/) (it's recommended to close Notion's sidebar if used as a side pane)
|
- [Notion](https://www.notion.so/) (it's recommended to close Notion's sidebar if used as a side pane)
|
||||||
- [Twitter](https://twitter.com)
|
- [Twitter](https://twitter.com)
|
||||||
- [Readwise Daily Review](https://readwise.io/dailyreview)
|
|
||||||
|
|
||||||
If you create a frame that you think other people would like, don't hesitate to create a pull request with [a new preset](https://github.com/Ellpeck/ObsidianCustomFrames/blob/master/src/settings.ts#L5).
|
If you create a frame that you think other people would like, don't hesitate to create a pull request with [a new preset](https://github.com/Ellpeck/ObsidianCustomFrames/blob/master/src/settings.ts#L5).
|
||||||
|
|
||||||
|
@ -57,20 +52,19 @@ If you create a frame that you think other people would like, don't hesitate to
|
||||||
- ~~Allow setting a custom icon for each pane~~
|
- ~~Allow setting a custom icon for each pane~~
|
||||||
- ~~Allow displaying custom frames in Markdown code blocks~~
|
- ~~Allow displaying custom frames in Markdown code blocks~~
|
||||||
- ~~Add the ability to add a ribbon button for a frame that opens it in the main view~~
|
- ~~Add the ability to add a ribbon button for a frame that opens it in the main view~~
|
||||||
- Allow creating links outside of Obsidian that open in a custom frame
|
- Allow creating links that open in a custom frame rather than the browser
|
||||||
- Possibly allow executing custom JavaScript in iframes (though security implications still need to be explored)
|
- Possibly allow executing custom JavaScript in iframes (though security implications still need to be explored)
|
||||||
- Add a global setting that causes popups to be opened in a new Obsidian window rather than the default browser
|
- Add a global setting that causes popups to be opened in a new Obsidian window rather than the default browser
|
||||||
- Add more options to Markdown mode, like allowing for back and forward buttons
|
- Add more options to Markdown mode, like allowing for back and forward buttons
|
||||||
- Possibly allow extracting selected text into a note similar to how the Note composer plugin works, and potentially allow using a note template that includes the link to the site extracted from
|
|
||||||
|
|
||||||
## ⚠️ Known Issues
|
## ⚠️ Known Issues
|
||||||
There are a few known issues with Custom Frames. If you encounter any of these, please **don't** report it on the issue tracker.
|
There are a few known issues with Custom Frames. If you encounter any of these, please **don't** report it on the issue tracker.
|
||||||
- Popups and new tabs are currently opened in the default browser rather than the custom frame. You can find more info, including workarounds for logging in to certain sites, in [this issue](https://github.com/Ellpeck/ObsidianCustomFrames/issues/40).
|
- In Obsidian **0.14.2 and lower**, a lot of websites don't function properly in custom frames. This is due to these older versions not having features in place that allow for frames to have special, additional functionality related to cookies and headers.
|
||||||
- Some links refuse to open from within custom frames, especially before Obsidian 1.3.7. You can find more info in [this issue](https://github.com/Ellpeck/ObsidianCustomFrames/issues/76).
|
- In Obsidian **0.14.5 and lower**, when dragging or moving a pane, hovering the mouse over a custom frame will cause it to get stuck or behave unexpectedly.
|
||||||
|
|
||||||
## 🙏 Acknowledgements
|
## 🙏 Acknowledgements
|
||||||
Thanks to [lishid](https://github.com/lishid) for their help with making iframes work in Obsidian for a purpose like this. Also thanks to them for *motivating* me to turn Obsidian Keep into a more versatile plugin, which is how Custom Frames was born.
|
Thanks to [lishid](https://github.com/lishid) for their help with making iframes work in Obsidian for a purpose like this. Also thanks to them for *motivating* me to turn Obsidian Keep into a more versatile plugin, which is how Custom Frames was born.
|
||||||
|
|
||||||
If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!
|
If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!
|
||||||
|
|
||||||
[![Support me (if you want), via Patreon, Ko-fi or GitHub Sponsors](https://ellpeck.de/res/generalsupport-wide.png)](https://ellpeck.de/support)
|
[![Support me (if you want), via Patreon, Ko-fi or GitHub Sponsors](https://ellpeck.de/res/generalsupport.png)](https://ellpeck.de/support)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import esbuild from "esbuild";
|
import esbuild from "esbuild";
|
||||||
import process from "process";
|
import process from "process";
|
||||||
import builtins from 'builtin-modules';
|
import builtins from 'builtin-modules';
|
||||||
import {copy} from 'esbuild-plugin-copy';
|
import { copy } from 'esbuild-plugin-copy';
|
||||||
|
|
||||||
const banner = `/*
|
const banner = `/*
|
||||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"id": "obsidian-custom-frames",
|
"id": "obsidian-custom-frames",
|
||||||
"name": "Custom Frames",
|
"name": "Custom Frames",
|
||||||
"version": "2.4.7",
|
"version": "2.4.6",
|
||||||
"minAppVersion": "1.2.0",
|
"minAppVersion": "1.2.0",
|
||||||
"description": "A plugin that turns web apps into panes using iframes with custom styling. Also comes with presets for Google Keep, Todoist and more.",
|
"description": "A plugin that turns web apps into panes using iframes with custom styling. Also comes with presets for Google Keep, Todoist and more.",
|
||||||
"author": "Ellpeck",
|
"author": "Ellpeck",
|
||||||
"authorUrl": "https://ellpeck.de",
|
"authorUrl": "https://ellpeck.de",
|
||||||
"fundingUrl": "https://ellpeck.de/support",
|
|
||||||
"isDesktopOnly": false
|
"isDesktopOnly": false
|
||||||
}
|
}
|
||||||
|
|
183
package-lock.json
generated
183
package-lock.json
generated
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "obsidian-custom-frames",
|
"name": "obsidian-custom-frames",
|
||||||
"version": "2.4.7",
|
"version": "2.4.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-custom-frames",
|
"name": "obsidian-custom-frames",
|
||||||
"version": "2.4.7",
|
"version": "2.4.5",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.6",
|
"@types/node": "^16.11.6",
|
||||||
"builtin-modules": "^3.2.0",
|
"builtin-modules": "^3.2.0",
|
||||||
"electron": "^20.3.9",
|
"electron": "^13.6.2",
|
||||||
"esbuild": "0.14.0",
|
"esbuild": "0.14.0",
|
||||||
"esbuild-plugin-copy": "^1.3.0",
|
"esbuild-plugin-copy": "^1.3.0",
|
||||||
"obsidian": "latest",
|
"obsidian": "latest",
|
||||||
|
@ -146,16 +146,6 @@
|
||||||
"@types/estree": "*"
|
"@types/estree": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/yauzl": {
|
|
||||||
"version": "2.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
|
|
||||||
"integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-styles": {
|
"node_modules/ansi-styles": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
|
@ -208,6 +198,12 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-from": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/builtin-modules": {
|
"node_modules/builtin-modules": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
||||||
|
@ -308,6 +304,21 @@
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/concat-stream": {
|
||||||
|
"version": "1.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||||
|
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": [
|
||||||
|
"node >= 0.8"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^2.2.2",
|
||||||
|
"typedarray": "^0.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/config-chain": {
|
"node_modules/config-chain": {
|
||||||
"version": "1.1.13",
|
"version": "1.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
||||||
|
@ -319,6 +330,12 @@
|
||||||
"proto-list": "~1.2.1"
|
"proto-list": "~1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/core-util-is": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
@ -397,23 +414,29 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/electron": {
|
"node_modules/electron": {
|
||||||
"version": "20.3.12",
|
"version": "13.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/electron/-/electron-20.3.12.tgz",
|
"resolved": "https://registry.npmjs.org/electron/-/electron-13.6.9.tgz",
|
||||||
"integrity": "sha512-CuCZKhwdSXaUNIoEuPVZ25YH18zmox3wEM8Acwcy9tlpD8Jiuq3ji3RZ98eVWJalrpqbdE9LtTD/sLC86GIkLg==",
|
"integrity": "sha512-Es/sBy85NIuqsO9MW41PUCpwIkeinlTQ7g0ainfnmRAM2rmog3GBxVCaoV5dzEjwTF7TKG1Yr/E7Z3qHmlfWAg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/get": "^1.14.1",
|
"@electron/get": "^1.0.1",
|
||||||
"@types/node": "^16.11.26",
|
"@types/node": "^14.6.2",
|
||||||
"extract-zip": "^2.0.1"
|
"extract-zip": "^1.0.3"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"electron": "cli.js"
|
"electron": "cli.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.17.0"
|
"node": ">= 8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/electron/node_modules/@types/node": {
|
||||||
|
"version": "14.18.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz",
|
||||||
|
"integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/encodeurl": {
|
"node_modules/encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
|
@ -762,40 +785,35 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/extract-zip": {
|
"node_modules/extract-zip": {
|
||||||
"version": "2.0.1",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
|
||||||
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
"integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.1.1",
|
"concat-stream": "^1.6.2",
|
||||||
"get-stream": "^5.1.0",
|
"debug": "^2.6.9",
|
||||||
|
"mkdirp": "^0.5.4",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"extract-zip": "cli.js"
|
"extract-zip": "cli.js"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.17.0"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@types/yauzl": "^2.9.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/extract-zip/node_modules/get-stream": {
|
"node_modules/extract-zip/node_modules/debug": {
|
||||||
"version": "5.2.0",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pump": "^3.0.0"
|
"ms": "2.0.0"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/extract-zip/node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.2.12",
|
"version": "3.2.12",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
|
||||||
|
@ -1079,6 +1097,12 @@
|
||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/ini": {
|
"node_modules/ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||||
|
@ -1116,6 +1140,12 @@
|
||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/json-buffer": {
|
"node_modules/json-buffer": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
|
||||||
|
@ -1220,6 +1250,27 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mkdirp": {
|
||||||
|
"version": "0.5.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||||
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.6"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "bin/cmd.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/moment": {
|
"node_modules/moment": {
|
||||||
"version": "2.29.4",
|
"version": "2.29.4",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||||
|
@ -1346,6 +1397,12 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/progress": {
|
"node_modules/progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||||
|
@ -1392,6 +1449,21 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "2.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
|
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/responselike": {
|
"node_modules/responselike": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
|
||||||
|
@ -1452,6 +1524,12 @@
|
||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
|
@ -1500,6 +1578,15 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/style-mod": {
|
"node_modules/style-mod": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
|
||||||
|
@ -1581,6 +1668,12 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typedarray": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.4.4",
|
"version": "4.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
|
||||||
|
@ -1615,6 +1708,12 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/w3c-keyname": {
|
"node_modules/w3c-keyname": {
|
||||||
"version": "2.2.6",
|
"version": "2.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "obsidian-custom-frames",
|
"name": "obsidian-custom-frames",
|
||||||
"version": "2.4.7",
|
"version": "2.4.6",
|
||||||
"description": "An Obsidian plugin that turns web apps into panes using iframes with custom styling. Also comes with presets for Google Keep, Todoist and more.",
|
"description": "An Obsidian plugin that turns web apps into panes using iframes with custom styling. Also comes with presets for Google Keep, Todoist and more.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.6",
|
"@types/node": "^16.11.6",
|
||||||
"builtin-modules": "^3.2.0",
|
"builtin-modules": "^3.2.0",
|
||||||
"electron": "^20.3.9",
|
"electron": "^13.6.2",
|
||||||
"esbuild": "0.14.0",
|
"esbuild": "0.14.0",
|
||||||
"esbuild-plugin-copy": "^1.3.0",
|
"esbuild-plugin-copy": "^1.3.0",
|
||||||
"obsidian": "latest",
|
"obsidian": "latest",
|
||||||
|
|
|
@ -24,7 +24,6 @@ export class CustomFrame {
|
||||||
this.frame.addEventListener("dom-ready", () => {
|
this.frame.addEventListener("dom-ready", () => {
|
||||||
this.frame.setZoomFactor(this.data.zoomLevel);
|
this.frame.setZoomFactor(this.data.zoomLevel);
|
||||||
this.frame.insertCSS(this.data.customCss);
|
this.frame.insertCSS(this.data.customCss);
|
||||||
this.frame.executeJavaScript(this.data.customJs)
|
|
||||||
});
|
});
|
||||||
this.frame.addEventListener("destroyed", () => {
|
this.frame.addEventListener("destroyed", () => {
|
||||||
// recreate the webview if it was moved to a new window
|
// recreate the webview if it was moved to a new window
|
||||||
|
@ -36,7 +35,7 @@ export class CustomFrame {
|
||||||
} else {
|
} else {
|
||||||
this.frame = parent.doc.createElement("iframe");
|
this.frame = parent.doc.createElement("iframe");
|
||||||
parent.appendChild(this.frame);
|
parent.appendChild(this.frame);
|
||||||
this.frame.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation allow-downloads");
|
this.frame.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation");
|
||||||
this.frame.setAttribute("allow", "encrypted-media; fullscreen; oversized-images; picture-in-picture; sync-xhr; geolocation;");
|
this.frame.setAttribute("allow", "encrypted-media; fullscreen; oversized-images; picture-in-picture; sync-xhr; geolocation;");
|
||||||
style += `transform: scale(${this.data.zoomLevel}); transform-origin: 0 0;`;
|
style += `transform: scale(${this.data.zoomLevel}); transform-origin: 0 0;`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,7 @@ export class CustomFramesSettingTab extends PluginSettingTab {
|
||||||
display(): void {
|
display(): void {
|
||||||
this.containerEl.empty();
|
this.containerEl.empty();
|
||||||
this.containerEl.createEl("h2", { text: "Custom Frames Settings" });
|
this.containerEl.createEl("h2", { text: "Custom Frames Settings" });
|
||||||
this.containerEl.createEl("p", {
|
this.containerEl.createEl("p", { text: "Please note that Obsidian has to be restarted or reloaded for most of these settings to take effect.", cls: "mod-warning" });
|
||||||
text: "Please note that Obsidian has to be restarted or reloaded for most of these settings to take effect.",
|
|
||||||
cls: "mod-warning"
|
|
||||||
});
|
|
||||||
|
|
||||||
new Setting(this.containerEl)
|
new Setting(this.containerEl)
|
||||||
.setName("Frame Padding")
|
.setName("Frame Padding")
|
||||||
|
@ -149,22 +146,6 @@ export class CustomFramesSettingTab extends PluginSettingTab {
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
new Setting(content)
|
|
||||||
.setName("Additional JavaScript")
|
|
||||||
.setDesc(createFragment(f => {
|
|
||||||
f.createSpan({ text: "A snippet of additional JavaScript that should be applied to this frame." });
|
|
||||||
f.createEl("br");
|
|
||||||
f.createEl("em", { text: "Note that this is only applied on Desktop." });
|
|
||||||
}))
|
|
||||||
.addTextArea(t => {
|
|
||||||
t.inputEl.rows = 5;
|
|
||||||
t.inputEl.cols = 50;
|
|
||||||
t.setValue(frame.customJs);
|
|
||||||
t.onChange(async v => {
|
|
||||||
frame.customJs = v;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
new ButtonComponent(content)
|
new ButtonComponent(content)
|
||||||
.setButtonText("Remove Frame")
|
.setButtonText("Remove Frame")
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
|
@ -197,8 +178,7 @@ export class CustomFramesSettingTab extends PluginSettingTab {
|
||||||
openInCenter: false,
|
openInCenter: false,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: "",
|
customCss: ""
|
||||||
customJs: ""
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.plugin.settings.frames.push(presets[option]);
|
this.plugin.settings.frames.push(presets[option]);
|
||||||
|
@ -207,20 +187,14 @@ export class CustomFramesSettingTab extends PluginSettingTab {
|
||||||
this.display();
|
this.display();
|
||||||
});
|
});
|
||||||
|
|
||||||
let disclaimer = this.containerEl.createEl("p", { cls: "mod-warning" });
|
var disclaimer = this.containerEl.createEl("p", { cls: "mod-warning" });
|
||||||
disclaimer.createSpan({ text: "Please be advised that, when adding a site as a custom frame, you potentially expose personal information you enter to other plugins you have installed. For more information, see " });
|
disclaimer.createSpan({ text: "Please be advised that, when adding a site as a custom frame, you potentially expose personal information you enter to other plugins you have installed. For more information, see " });
|
||||||
disclaimer.createEl("a", {
|
disclaimer.createEl("a", { text: "this discussion", href: "https://github.com/Ellpeck/ObsidianCustomFrames/issues/54#issuecomment-1210879685", cls: "mod-warning" });
|
||||||
text: "this discussion",
|
|
||||||
href: "https://github.com/Ellpeck/ObsidianCustomFrames/issues/54#issuecomment-1210879685",
|
|
||||||
cls: "mod-warning"
|
|
||||||
});
|
|
||||||
disclaimer.createSpan({ text: "." });
|
disclaimer.createSpan({ text: "." });
|
||||||
|
|
||||||
this.containerEl.createEl("hr");
|
this.containerEl.createEl("hr");
|
||||||
this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" });
|
this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" });
|
||||||
this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }).createEl("img", {
|
this.containerEl.createEl("a", { href: "https://ellpeck.de/support" })
|
||||||
attr: { src: "https://ellpeck.de/res/generalsupport.png" },
|
.createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "custom-frames-support" });
|
||||||
cls: "custom-frames-support"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@ export const presets: Record<string, CustomFrameSettings> = {
|
||||||
openInCenter: true,
|
openInCenter: true,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: "",
|
customCss: ""
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"detexify": {
|
"detexify": {
|
||||||
url: "https://detexify.kirelabs.org/classify.html",
|
url: "https://detexify.kirelabs.org/classify.html",
|
||||||
|
@ -28,8 +27,7 @@ export const presets: Record<string, CustomFrameSettings> = {
|
||||||
#classify--info-area,
|
#classify--info-area,
|
||||||
.adsbygoogle {
|
.adsbygoogle {
|
||||||
display: none !important
|
display: none !important
|
||||||
}`,
|
}`
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
url: "https://calendar.google.com/calendar",
|
url: "https://calendar.google.com/calendar",
|
||||||
|
@ -40,15 +38,12 @@ export const presets: Record<string, CustomFrameSettings> = {
|
||||||
openInCenter: true,
|
openInCenter: true,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: `/* hide the menu bar "Calendar" text and remove minimum width */
|
customCss: `/* hide the menu bar, "Keep" text, and logo */
|
||||||
div[style*="min-width: 238px"] {
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child[class*=" "],
|
||||||
min-width: 0 !important;
|
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child,
|
||||||
padding-right: 0 !important;
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child > div:first-child {
|
||||||
}
|
display: none !important;
|
||||||
div[style*="min-width: 238px"] span[role*="heading"] {
|
}`
|
||||||
display: none !important;
|
|
||||||
}`,
|
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"keep": {
|
"keep": {
|
||||||
url: "https://keep.google.com",
|
url: "https://keep.google.com",
|
||||||
|
@ -59,17 +54,11 @@ div[style*="min-width: 238px"] span[role*="heading"] {
|
||||||
openInCenter: false,
|
openInCenter: false,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: `/* hide the menu bar, the "Keep" text and the Google Apps button */
|
customCss: `/* hide the menu bar and the "Keep" text */
|
||||||
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child,
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child,
|
||||||
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child > span,
|
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child > span {
|
||||||
html > body > div:first-child > header:first-child > div:nth-child(2) > div:first-child > div:first-child,
|
|
||||||
html > body > div:first-child > header:first-child > div:nth-child(2) > div:nth-child(3) > div:first-child > div:first-child > div:first-child {
|
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}`
|
||||||
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child {
|
|
||||||
cursor: default;
|
|
||||||
}`,
|
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"todoist": {
|
"todoist": {
|
||||||
url: "https://todoist.com",
|
url: "https://todoist.com",
|
||||||
|
@ -96,8 +85,7 @@ html > body > div:first-child > header:first-child > div > div:first-child > div
|
||||||
|
|
||||||
.undo_toast {
|
.undo_toast {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
}`,
|
}`
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"notion": {
|
"notion": {
|
||||||
url: "https://www.notion.so/",
|
url: "https://www.notion.so/",
|
||||||
|
@ -108,8 +96,7 @@ html > body > div:first-child > header:first-child > div > div:first-child > div
|
||||||
openInCenter: true,
|
openInCenter: true,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: "",
|
customCss: ""
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"twitter": {
|
"twitter": {
|
||||||
url: "https://twitter.com",
|
url: "https://twitter.com",
|
||||||
|
@ -120,8 +107,7 @@ html > body > div:first-child > header:first-child > div > div:first-child > div
|
||||||
openInCenter: false,
|
openInCenter: false,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: "",
|
customCss: ""
|
||||||
customJs: ""
|
|
||||||
},
|
},
|
||||||
"tasks": {
|
"tasks": {
|
||||||
url: "https://tasks.google.com/embed/?origin=https://calendar.google.com&fullWidth=1",
|
url: "https://tasks.google.com/embed/?origin=https://calendar.google.com&fullWidth=1",
|
||||||
|
@ -132,21 +118,8 @@ html > body > div:first-child > header:first-child > div > div:first-child > div
|
||||||
openInCenter: false,
|
openInCenter: false,
|
||||||
zoomLevel: 1,
|
zoomLevel: 1,
|
||||||
forceIframe: false,
|
forceIframe: false,
|
||||||
customCss: "",
|
customCss: ""
|
||||||
customJs: ""
|
}
|
||||||
},
|
|
||||||
"readwise-daily-review": {
|
|
||||||
"url": "https://readwise.io/dailyreview",
|
|
||||||
"displayName": "Readwise Daily Review",
|
|
||||||
"icon": "highlighter",
|
|
||||||
"hideOnMobile": true,
|
|
||||||
"addRibbonIcon": false,
|
|
||||||
"openInCenter": false,
|
|
||||||
"zoomLevel": 1,
|
|
||||||
"forceIframe": false,
|
|
||||||
"customCss": ".fixed-nav {\n display: none !important;\n}",
|
|
||||||
"customJs": ""
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface CustomFramesSettings {
|
export interface CustomFramesSettings {
|
||||||
|
@ -164,7 +137,6 @@ export interface CustomFrameSettings {
|
||||||
zoomLevel: number;
|
zoomLevel: number;
|
||||||
forceIframe: boolean;
|
forceIframe: boolean;
|
||||||
customCss: string;
|
customCss: string;
|
||||||
customJs: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIcon(settings: CustomFrameSettings) {
|
export function getIcon(settings: CustomFrameSettings) {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
||||||
!data.json
|
|
|
@ -20,7 +20,7 @@
|
||||||
"openInCenter": false,
|
"openInCenter": false,
|
||||||
"zoomLevel": 1,
|
"zoomLevel": 1,
|
||||||
"forceIframe": false,
|
"forceIframe": false,
|
||||||
"customCss": "/* hide the menu bar, the \"Keep\" text and the Google Apps button */\nhtml > body > div:nth-child(2) > div:nth-child(2) > div:first-child, \nhtml > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child > span, \nhtml > body > div:first-child > header:first-child > div:nth-child(2) > div:first-child > div:first-child, \nhtml > body > div:first-child > header:first-child > div:nth-child(2) > div:nth-child(3) > div:first-child > div:first-child > div:first-child { \n\tdisplay: none !important; \n}\nhtml > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child {\n\tcursor: default; \n}"
|
"customCss": "/* hide the menu bar and the \"Keep\" text */\nhtml > body > div:nth-child(2) > div:nth-child(2) > div:first-child, \nhtml > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child > span { \n\tdisplay: none !important; \n}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://calendar.google.com/calendar",
|
"url": "https://calendar.google.com/calendar",
|
||||||
|
|
592
test-vault/.obsidian/plugins/obsidian-custom-frames/main
vendored
Normal file
592
test-vault/.obsidian/plugins/obsidian-custom-frames/main
vendored
Normal file
|
@ -0,0 +1,592 @@
|
||||||
|
/*
|
||||||
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||||
|
if you want to view the source, please visit the github repository of this plugin
|
||||||
|
*/
|
||||||
|
var __create = Object.create;
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
||||||
|
var __export = (target, all) => {
|
||||||
|
__markAsModule(target);
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __reExport = (target, module2, desc) => {
|
||||||
|
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
||||||
|
for (let key of __getOwnPropNames(module2))
|
||||||
|
if (!__hasOwnProp.call(target, key) && key !== "default")
|
||||||
|
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
var __toModule = (module2) => {
|
||||||
|
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
||||||
|
};
|
||||||
|
var __async = (__this, __arguments, generator) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var fulfilled = (value) => {
|
||||||
|
try {
|
||||||
|
step(generator.next(value));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var rejected = (value) => {
|
||||||
|
try {
|
||||||
|
step(generator.throw(value));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
||||||
|
step((generator = generator.apply(__this, __arguments)).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/main.ts
|
||||||
|
__export(exports, {
|
||||||
|
default: () => CustomFramesPlugin
|
||||||
|
});
|
||||||
|
var import_obsidian4 = __toModule(require("obsidian"));
|
||||||
|
|
||||||
|
// src/frame.ts
|
||||||
|
var import_obsidian = __toModule(require("obsidian"));
|
||||||
|
|
||||||
|
// src/settings.ts
|
||||||
|
var defaultSettings = {
|
||||||
|
frames: [],
|
||||||
|
padding: 5
|
||||||
|
};
|
||||||
|
var presets = {
|
||||||
|
"obsidian": {
|
||||||
|
url: "https://forum.obsidian.md/",
|
||||||
|
displayName: "Obsidian Forum",
|
||||||
|
icon: "edit",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: true,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
},
|
||||||
|
"detexify": {
|
||||||
|
url: "https://detexify.kirelabs.org/classify.html",
|
||||||
|
displayName: "Detexify",
|
||||||
|
icon: "type",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 0.95,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide info clutter and ad banner */
|
||||||
|
#classify--info-area,
|
||||||
|
.adsbygoogle {
|
||||||
|
display: none !important
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"calendar": {
|
||||||
|
url: "https://calendar.google.com/calendar",
|
||||||
|
displayName: "Google Calendar",
|
||||||
|
icon: "calendar",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: true,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide the menu bar, "Keep" text, and logo */
|
||||||
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child[class*=" "],
|
||||||
|
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child,
|
||||||
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child > div:first-child {
|
||||||
|
display: none !important;
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"keep": {
|
||||||
|
url: "https://keep.google.com",
|
||||||
|
displayName: "Google Keep",
|
||||||
|
icon: "files",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide the menu bar and the "Keep" text */
|
||||||
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child,
|
||||||
|
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child > span {
|
||||||
|
display: none !important;
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"todoist": {
|
||||||
|
url: "https://todoist.com",
|
||||||
|
displayName: "Todoist",
|
||||||
|
icon: "list-checks",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide the help, home, search, and productivity overview buttons, create extra space, and prevent toast pop-up from acting weird */
|
||||||
|
[aria-label="Go to Home view"], #quick_find, [aria-label="Productivity"], [aria-label="Help & Feedback"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view_content {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view_header {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.undo_toast {
|
||||||
|
width: 95%;
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"notion": {
|
||||||
|
url: "https://www.notion.so/",
|
||||||
|
displayName: "Notion",
|
||||||
|
icon: "box",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: true,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
url: "https://twitter.com",
|
||||||
|
displayName: "Twitter",
|
||||||
|
icon: "twitter",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
},
|
||||||
|
"tasks": {
|
||||||
|
url: "https://tasks.google.com/embed/?origin=https://calendar.google.com&fullWidth=1",
|
||||||
|
displayName: "Google Tasks",
|
||||||
|
icon: "list-checks",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getIcon(settings) {
|
||||||
|
return settings.icon ? `lucide-${settings.icon}` : "documents";
|
||||||
|
}
|
||||||
|
function getId(settings) {
|
||||||
|
return settings.displayName.toLowerCase().replace(/\s/g, "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/frame.ts
|
||||||
|
var CustomFrame = class {
|
||||||
|
constructor(settings, data) {
|
||||||
|
this.settings = settings;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
create(parent, additionalStyle = void 0, urlSuffix = void 0) {
|
||||||
|
let style = `padding: ${this.settings.padding}px;`;
|
||||||
|
if (additionalStyle)
|
||||||
|
style += additionalStyle;
|
||||||
|
if (import_obsidian.Platform.isDesktopApp && !this.data.forceIframe) {
|
||||||
|
let frameDoc = parent.doc;
|
||||||
|
this.frame = frameDoc.createElement("webview");
|
||||||
|
parent.appendChild(this.frame);
|
||||||
|
this.frame.setAttribute("allowpopups", "");
|
||||||
|
this.frame.addEventListener("dom-ready", () => {
|
||||||
|
this.frame.setZoomFactor(this.data.zoomLevel);
|
||||||
|
this.frame.insertCSS(this.data.customCss);
|
||||||
|
});
|
||||||
|
this.frame.addEventListener("destroyed", () => {
|
||||||
|
if (frameDoc != parent.doc) {
|
||||||
|
this.frame.detach();
|
||||||
|
this.create(parent, additionalStyle, urlSuffix);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.frame = parent.doc.createElement("iframe");
|
||||||
|
parent.appendChild(this.frame);
|
||||||
|
this.frame.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation");
|
||||||
|
this.frame.setAttribute("allow", "encrypted-media; fullscreen; oversized-images; picture-in-picture; sync-xhr; geolocation;");
|
||||||
|
style += `transform: scale(${this.data.zoomLevel}); transform-origin: 0 0;`;
|
||||||
|
}
|
||||||
|
this.frame.addClass("custom-frames-frame");
|
||||||
|
this.frame.addClass(`custom-frames-${getId(this.data)}`);
|
||||||
|
this.frame.setAttribute("style", style);
|
||||||
|
let src = this.data.url;
|
||||||
|
if (urlSuffix) {
|
||||||
|
if (!urlSuffix.startsWith("/"))
|
||||||
|
src += "/";
|
||||||
|
src += urlSuffix;
|
||||||
|
}
|
||||||
|
this.frame.setAttribute("src", src);
|
||||||
|
}
|
||||||
|
refresh() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.location.reload();
|
||||||
|
} else {
|
||||||
|
this.frame.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.open(this.data.url);
|
||||||
|
} else {
|
||||||
|
this.frame.loadURL(this.data.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goBack() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.history.back();
|
||||||
|
} else {
|
||||||
|
this.frame.goBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goForward() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.history.forward();
|
||||||
|
} else {
|
||||||
|
this.frame.goForward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toggleDevTools() {
|
||||||
|
if (!(this.frame instanceof HTMLIFrameElement)) {
|
||||||
|
if (!this.frame.isDevToolsOpened()) {
|
||||||
|
this.frame.openDevTools();
|
||||||
|
} else {
|
||||||
|
this.frame.closeDevTools();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getCurrentUrl() {
|
||||||
|
return this.frame instanceof HTMLIFrameElement ? this.frame.contentWindow.location.href : this.frame.getURL();
|
||||||
|
}
|
||||||
|
focus() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.focus();
|
||||||
|
} else {
|
||||||
|
this.frame.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/settings-tab.ts
|
||||||
|
var import_obsidian2 = __toModule(require("obsidian"));
|
||||||
|
var CustomFramesSettingTab = class extends import_obsidian2.PluginSettingTab {
|
||||||
|
constructor(app, plugin) {
|
||||||
|
super(app, plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
display() {
|
||||||
|
this.containerEl.empty();
|
||||||
|
this.containerEl.createEl("h2", { text: "Custom Frames Settings" });
|
||||||
|
this.containerEl.createEl("p", { text: "Please note that Obsidian has to be restarted or reloaded for most of these settings to take effect.", cls: "mod-warning" });
|
||||||
|
new import_obsidian2.Setting(this.containerEl).setName("Frame Padding").setDesc("The padding that should be left around the inside of custom frame panes, in pixels.").addText((t) => {
|
||||||
|
t.inputEl.type = "number";
|
||||||
|
t.setValue(String(this.plugin.settings.padding));
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
this.plugin.settings.padding = v.length ? Number(v) : defaultSettings.padding;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
for (let frame of this.plugin.settings.frames) {
|
||||||
|
let heading = this.containerEl.createEl("h3", { text: frame.displayName || "Unnamed Frame" });
|
||||||
|
let toggle = new import_obsidian2.ButtonComponent(this.containerEl).setButtonText("Show Settings").setClass("custom-frames-show").onClick(() => __async(this, null, function* () {
|
||||||
|
content.hidden = !content.hidden;
|
||||||
|
toggle.setButtonText(content.hidden ? "Show Settings" : "Hide Settings");
|
||||||
|
}));
|
||||||
|
let content = this.containerEl.createDiv();
|
||||||
|
content.hidden = true;
|
||||||
|
new import_obsidian2.Setting(content).setName("Display Name").setDesc("The display name that this frame should have.").addText((t) => {
|
||||||
|
t.setValue(frame.displayName);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.displayName = v;
|
||||||
|
heading.setText(frame.displayName || "Unnamed Frame");
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Icon").setDesc(createFragment((f) => {
|
||||||
|
f.createSpan({ text: "The icon that this frame's pane should have. The names of any " });
|
||||||
|
f.createEl("a", { text: "Lucide icons", href: "https://lucide.dev/" });
|
||||||
|
f.createSpan({ text: " can be used." });
|
||||||
|
})).addText((t) => {
|
||||||
|
t.setValue(frame.icon);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.icon = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("URL").setDesc("The URL that should be opened in this frame.").addText((t) => {
|
||||||
|
t.setValue(frame.url);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.url = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Disable on Mobile").setDesc("Custom Frames is a lot more restricted on mobile devices and doesn't allow for the same types of content to be displayed. If a frame doesn't work as expected on mobile, it can be disabled.").addToggle((t) => {
|
||||||
|
t.setValue(frame.hideOnMobile);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.hideOnMobile = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Add Ribbon Icon").setDesc("Whether a button to open this frame should be added to the ribbon.").addToggle((t) => {
|
||||||
|
t.setValue(frame.addRibbonIcon);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.addRibbonIcon = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Open in Center").setDesc("Whether this frame should be opened in the unpinned center editor rather than one of the panes on the side. This is useful for sites that don't work well in a narrow view, or sites that don't require a note to be open when viewed.").addToggle((t) => {
|
||||||
|
t.setValue(frame.openInCenter);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.openInCenter = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Force iframe").setDesc(createFragment((f) => {
|
||||||
|
f.createSpan({ text: "Whether this frame should use iframes on desktop as opposed to Electron webviews." });
|
||||||
|
f.createEl("br");
|
||||||
|
f.createEl("em", { text: "Only enable this setting if the frame is causing issues or frequent crashes. This setting causes all Desktop-only settings to be ignored." });
|
||||||
|
})).addToggle((t) => {
|
||||||
|
t.setValue(frame.forceIframe);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.forceIframe = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Page Zoom").setDesc("The zoom that this frame's page should be displayed with, as a percentage.").addText((t) => {
|
||||||
|
t.inputEl.type = "number";
|
||||||
|
t.setValue(String(frame.zoomLevel * 100));
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.zoomLevel = v.length ? Number(v) / 100 : 1;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Additional CSS").setDesc(createFragment((f) => {
|
||||||
|
f.createSpan({ text: "A snippet of additional CSS that should be applied to this frame." });
|
||||||
|
f.createEl("br");
|
||||||
|
f.createEl("em", { text: "Note that this is only applied on Desktop." });
|
||||||
|
})).addTextArea((t) => {
|
||||||
|
t.inputEl.rows = 5;
|
||||||
|
t.inputEl.cols = 50;
|
||||||
|
t.setValue(frame.customCss);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.customCss = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.ButtonComponent(content).setButtonText("Remove Frame").onClick(() => __async(this, null, function* () {
|
||||||
|
this.plugin.settings.frames.remove(frame);
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
this.display();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.containerEl.createEl("hr");
|
||||||
|
this.containerEl.createEl("p", { text: `Create a new frame, either from a preset shipped with the plugin, or a custom one that you can edit yourself. Each frame's pane can be opened using the "Custom Frames: Open" command.` });
|
||||||
|
let addDiv = this.containerEl.createDiv();
|
||||||
|
let dropdown = new import_obsidian2.DropdownComponent(addDiv);
|
||||||
|
dropdown.addOption("new", "Custom");
|
||||||
|
for (let key of Object.keys(presets))
|
||||||
|
dropdown.addOption(key, presets[key].displayName);
|
||||||
|
new import_obsidian2.ButtonComponent(addDiv).setButtonText("Add Frame").setClass("custom-frames-add").onClick(() => __async(this, null, function* () {
|
||||||
|
let option = dropdown.getValue();
|
||||||
|
if (option == "new") {
|
||||||
|
this.plugin.settings.frames.push({
|
||||||
|
url: "",
|
||||||
|
displayName: "New Frame",
|
||||||
|
icon: "",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.plugin.settings.frames.push(presets[option]);
|
||||||
|
}
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
this.display();
|
||||||
|
}));
|
||||||
|
var disclaimer = this.containerEl.createEl("p", { cls: "mod-warning" });
|
||||||
|
disclaimer.createSpan({ text: "Please be advised that, when adding a site as a custom frame, you potentially expose personal information you enter to other plugins you have installed. For more information, see " });
|
||||||
|
disclaimer.createEl("a", { text: "this discussion", href: "https://github.com/Ellpeck/ObsidianCustomFrames/issues/54#issuecomment-1210879685", cls: "mod-warning" });
|
||||||
|
disclaimer.createSpan({ text: "." });
|
||||||
|
this.containerEl.createEl("hr");
|
||||||
|
this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" });
|
||||||
|
this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }).createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "custom-frames-support" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/view.ts
|
||||||
|
var import_obsidian3 = __toModule(require("obsidian"));
|
||||||
|
var _CustomFrameView = class extends import_obsidian3.ItemView {
|
||||||
|
constructor(leaf, settings, data, name) {
|
||||||
|
super(leaf);
|
||||||
|
this.data = data;
|
||||||
|
this.name = name;
|
||||||
|
this.frame = new CustomFrame(settings, data);
|
||||||
|
this.navigation = data.openInCenter;
|
||||||
|
for (let action of _CustomFrameView.actions)
|
||||||
|
this.addAction(action.icon, action.name, () => action.action(this));
|
||||||
|
}
|
||||||
|
onload() {
|
||||||
|
this.contentEl.empty();
|
||||||
|
this.contentEl.addClass("custom-frames-view");
|
||||||
|
this.frame.create(this.contentEl);
|
||||||
|
}
|
||||||
|
onPaneMenu(menu, source) {
|
||||||
|
super.onPaneMenu(menu, source);
|
||||||
|
for (let action of _CustomFrameView.actions) {
|
||||||
|
menu.addItem((i) => {
|
||||||
|
i.setTitle(action.name);
|
||||||
|
i.setIcon(action.icon);
|
||||||
|
i.onClick(() => action.action(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getViewType() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
getDisplayText() {
|
||||||
|
return this.data.displayName;
|
||||||
|
}
|
||||||
|
getIcon() {
|
||||||
|
return getIcon(this.data);
|
||||||
|
}
|
||||||
|
focus() {
|
||||||
|
this.frame.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var CustomFrameView = _CustomFrameView;
|
||||||
|
CustomFrameView.actions = [
|
||||||
|
{
|
||||||
|
name: "Return to original page",
|
||||||
|
icon: "home",
|
||||||
|
action: (v) => v.frame.return()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Open dev tools",
|
||||||
|
icon: "binary",
|
||||||
|
action: (v) => v.frame.toggleDevTools()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Copy link",
|
||||||
|
icon: "link",
|
||||||
|
action: (v) => navigator.clipboard.writeText(v.frame.getCurrentUrl())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Open in browser",
|
||||||
|
icon: "globe",
|
||||||
|
action: (v) => open(v.frame.getCurrentUrl())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Refresh",
|
||||||
|
icon: "refresh-cw",
|
||||||
|
action: (v) => v.frame.refresh()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Go back",
|
||||||
|
icon: "arrow-left",
|
||||||
|
action: (v) => v.frame.goBack()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Go forward",
|
||||||
|
icon: "arrow-right",
|
||||||
|
action: (v) => v.frame.goForward()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// src/main.ts
|
||||||
|
var CustomFramesPlugin = class extends import_obsidian4.Plugin {
|
||||||
|
onload() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
yield this.loadSettings();
|
||||||
|
for (let frame of this.settings.frames) {
|
||||||
|
if (!frame.url || !frame.displayName)
|
||||||
|
continue;
|
||||||
|
let name = `custom-frames-${getId(frame)}`;
|
||||||
|
if (import_obsidian4.Platform.isMobileApp && frame.hideOnMobile) {
|
||||||
|
console.log(`Skipping frame ${name} which is hidden on mobile`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log(`Registering frame ${name} for URL ${frame.url}`);
|
||||||
|
this.registerView(name, (l) => new CustomFrameView(l, this.settings, frame, name));
|
||||||
|
this.addCommand({
|
||||||
|
id: `open-${name}`,
|
||||||
|
name: `Open ${frame.displayName}`,
|
||||||
|
callback: () => this.openLeaf(name, frame.openInCenter, false)
|
||||||
|
});
|
||||||
|
if (frame.addRibbonIcon)
|
||||||
|
this.addRibbonIcon(getIcon(frame), `Open ${frame.displayName}`, (e) => this.openLeaf(name, frame.openInCenter, import_obsidian4.Platform.isMacOS ? e.metaKey : e.ctrlKey));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Couldn't register frame ${name}, is there already one with the same name?`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addSettingTab(new CustomFramesSettingTab(this.app, this));
|
||||||
|
this.registerMarkdownCodeBlockProcessor("custom-frames", (s, e) => {
|
||||||
|
e.empty();
|
||||||
|
e.addClass("custom-frames-view-file");
|
||||||
|
let frameMatch = /frame:([^\n]+)/gi.exec(s);
|
||||||
|
let frameName = frameMatch && frameMatch[1].trim();
|
||||||
|
if (!frameName) {
|
||||||
|
e.createSpan({ text: "Couldn't parse frame name" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = this.settings.frames.find((f) => f.displayName == frameName);
|
||||||
|
if (!data) {
|
||||||
|
e.createSpan({ text: `Couldn't find a frame with name ${frameName}` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (import_obsidian4.Platform.isMobileApp && data.hideOnMobile) {
|
||||||
|
e.createSpan({ text: `${frameName} is hidden on mobile` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let styleMatch = /style:([^\n]+)/gi.exec(s);
|
||||||
|
let style = styleMatch && styleMatch[1].trim();
|
||||||
|
style || (style = "height: 600px;");
|
||||||
|
let urlSuffixMatch = /urlsuffix:([^\n]+)/gi.exec(s);
|
||||||
|
let urlSuffix = urlSuffixMatch && urlSuffixMatch[1].trim();
|
||||||
|
urlSuffix || (urlSuffix = "");
|
||||||
|
let frame = new CustomFrame(this.settings, data);
|
||||||
|
frame.create(e, style, urlSuffix);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
loadSettings() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
this.settings = Object.assign({}, defaultSettings, yield this.loadData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
saveSettings() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
yield this.saveData(this.settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
openLeaf(name, center, split) {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
let leaf;
|
||||||
|
if (center) {
|
||||||
|
leaf = this.app.workspace.getLeaf(split);
|
||||||
|
yield leaf.setViewState({ type: name, active: true });
|
||||||
|
} else {
|
||||||
|
if (!this.app.workspace.getLeavesOfType(name).length)
|
||||||
|
yield this.app.workspace.getRightLeaf(false).setViewState({ type: name, active: true });
|
||||||
|
leaf = this.app.workspace.getLeavesOfType(name)[0];
|
||||||
|
this.app.workspace.revealLeaf(leaf);
|
||||||
|
}
|
||||||
|
if (leaf.view instanceof CustomFrameView)
|
||||||
|
leaf.view.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
592
test-vault/.obsidian/plugins/obsidian-custom-frames/main.js
vendored
Normal file
592
test-vault/.obsidian/plugins/obsidian-custom-frames/main.js
vendored
Normal file
|
@ -0,0 +1,592 @@
|
||||||
|
/*
|
||||||
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||||
|
if you want to view the source, please visit the github repository of this plugin
|
||||||
|
*/
|
||||||
|
var __create = Object.create;
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
||||||
|
var __export = (target, all) => {
|
||||||
|
__markAsModule(target);
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __reExport = (target, module2, desc) => {
|
||||||
|
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
||||||
|
for (let key of __getOwnPropNames(module2))
|
||||||
|
if (!__hasOwnProp.call(target, key) && key !== "default")
|
||||||
|
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
var __toModule = (module2) => {
|
||||||
|
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
||||||
|
};
|
||||||
|
var __async = (__this, __arguments, generator) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var fulfilled = (value) => {
|
||||||
|
try {
|
||||||
|
step(generator.next(value));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var rejected = (value) => {
|
||||||
|
try {
|
||||||
|
step(generator.throw(value));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
||||||
|
step((generator = generator.apply(__this, __arguments)).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/main.ts
|
||||||
|
__export(exports, {
|
||||||
|
default: () => CustomFramesPlugin
|
||||||
|
});
|
||||||
|
var import_obsidian4 = __toModule(require("obsidian"));
|
||||||
|
|
||||||
|
// src/frame.ts
|
||||||
|
var import_obsidian = __toModule(require("obsidian"));
|
||||||
|
|
||||||
|
// src/settings.ts
|
||||||
|
var defaultSettings = {
|
||||||
|
frames: [],
|
||||||
|
padding: 5
|
||||||
|
};
|
||||||
|
var presets = {
|
||||||
|
"obsidian": {
|
||||||
|
url: "https://forum.obsidian.md/",
|
||||||
|
displayName: "Obsidian Forum",
|
||||||
|
icon: "edit",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: true,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
},
|
||||||
|
"detexify": {
|
||||||
|
url: "https://detexify.kirelabs.org/classify.html",
|
||||||
|
displayName: "Detexify",
|
||||||
|
icon: "type",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 0.95,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide info clutter and ad banner */
|
||||||
|
#classify--info-area,
|
||||||
|
.adsbygoogle {
|
||||||
|
display: none !important
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"calendar": {
|
||||||
|
url: "https://calendar.google.com/calendar",
|
||||||
|
displayName: "Google Calendar",
|
||||||
|
icon: "calendar",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: true,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide the menu bar, "Keep" text, and logo */
|
||||||
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child[class*=" "],
|
||||||
|
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child,
|
||||||
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child > div:first-child {
|
||||||
|
display: none !important;
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"keep": {
|
||||||
|
url: "https://keep.google.com",
|
||||||
|
displayName: "Google Keep",
|
||||||
|
icon: "files",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide the menu bar and the "Keep" text */
|
||||||
|
html > body > div:nth-child(2) > div:nth-child(2) > div:first-child,
|
||||||
|
html > body > div:first-child > header:first-child > div > div:first-child > div > div:first-child > a:first-child > span {
|
||||||
|
display: none !important;
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"todoist": {
|
||||||
|
url: "https://todoist.com",
|
||||||
|
displayName: "Todoist",
|
||||||
|
icon: "list-checks",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: `/* hide the help, home, search, and productivity overview buttons, create extra space, and prevent toast pop-up from acting weird */
|
||||||
|
[aria-label="Go to Home view"], #quick_find, [aria-label="Productivity"], [aria-label="Help & Feedback"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view_content {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view_header {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.undo_toast {
|
||||||
|
width: 95%;
|
||||||
|
}`
|
||||||
|
},
|
||||||
|
"notion": {
|
||||||
|
url: "https://www.notion.so/",
|
||||||
|
displayName: "Notion",
|
||||||
|
icon: "box",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: true,
|
||||||
|
openInCenter: true,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
url: "https://twitter.com",
|
||||||
|
displayName: "Twitter",
|
||||||
|
icon: "twitter",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
},
|
||||||
|
"tasks": {
|
||||||
|
url: "https://tasks.google.com/embed/?origin=https://calendar.google.com&fullWidth=1",
|
||||||
|
displayName: "Google Tasks",
|
||||||
|
icon: "list-checks",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getIcon(settings) {
|
||||||
|
return settings.icon ? `lucide-${settings.icon}` : "documents";
|
||||||
|
}
|
||||||
|
function getId(settings) {
|
||||||
|
return settings.displayName.toLowerCase().replace(/\s/g, "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/frame.ts
|
||||||
|
var CustomFrame = class {
|
||||||
|
constructor(settings, data) {
|
||||||
|
this.settings = settings;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
create(parent, additionalStyle = void 0, urlSuffix = void 0) {
|
||||||
|
let style = `padding: ${this.settings.padding}px;`;
|
||||||
|
if (additionalStyle)
|
||||||
|
style += additionalStyle;
|
||||||
|
if (import_obsidian.Platform.isDesktopApp && !this.data.forceIframe) {
|
||||||
|
let frameDoc = parent.doc;
|
||||||
|
this.frame = frameDoc.createElement("webview");
|
||||||
|
parent.appendChild(this.frame);
|
||||||
|
this.frame.setAttribute("allowpopups", "");
|
||||||
|
this.frame.addEventListener("dom-ready", () => {
|
||||||
|
this.frame.setZoomFactor(this.data.zoomLevel);
|
||||||
|
this.frame.insertCSS(this.data.customCss);
|
||||||
|
});
|
||||||
|
this.frame.addEventListener("destroyed", () => {
|
||||||
|
if (frameDoc != parent.doc) {
|
||||||
|
this.frame.detach();
|
||||||
|
this.create(parent, additionalStyle, urlSuffix);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.frame = parent.doc.createElement("iframe");
|
||||||
|
parent.appendChild(this.frame);
|
||||||
|
this.frame.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation");
|
||||||
|
this.frame.setAttribute("allow", "encrypted-media; fullscreen; oversized-images; picture-in-picture; sync-xhr; geolocation;");
|
||||||
|
style += `transform: scale(${this.data.zoomLevel}); transform-origin: 0 0;`;
|
||||||
|
}
|
||||||
|
this.frame.addClass("custom-frames-frame");
|
||||||
|
this.frame.addClass(`custom-frames-${getId(this.data)}`);
|
||||||
|
this.frame.setAttribute("style", style);
|
||||||
|
let src = this.data.url;
|
||||||
|
if (urlSuffix) {
|
||||||
|
if (!urlSuffix.startsWith("/"))
|
||||||
|
src += "/";
|
||||||
|
src += urlSuffix;
|
||||||
|
}
|
||||||
|
this.frame.setAttribute("src", src);
|
||||||
|
}
|
||||||
|
refresh() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.location.reload();
|
||||||
|
} else {
|
||||||
|
this.frame.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.open(this.data.url);
|
||||||
|
} else {
|
||||||
|
this.frame.loadURL(this.data.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goBack() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.history.back();
|
||||||
|
} else {
|
||||||
|
this.frame.goBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goForward() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.history.forward();
|
||||||
|
} else {
|
||||||
|
this.frame.goForward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toggleDevTools() {
|
||||||
|
if (!(this.frame instanceof HTMLIFrameElement)) {
|
||||||
|
if (!this.frame.isDevToolsOpened()) {
|
||||||
|
this.frame.openDevTools();
|
||||||
|
} else {
|
||||||
|
this.frame.closeDevTools();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getCurrentUrl() {
|
||||||
|
return this.frame instanceof HTMLIFrameElement ? this.frame.contentWindow.location.href : this.frame.getURL();
|
||||||
|
}
|
||||||
|
focus() {
|
||||||
|
if (this.frame instanceof HTMLIFrameElement) {
|
||||||
|
this.frame.contentWindow.focus();
|
||||||
|
} else {
|
||||||
|
this.frame.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/settings-tab.ts
|
||||||
|
var import_obsidian2 = __toModule(require("obsidian"));
|
||||||
|
var CustomFramesSettingTab = class extends import_obsidian2.PluginSettingTab {
|
||||||
|
constructor(app, plugin) {
|
||||||
|
super(app, plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
display() {
|
||||||
|
this.containerEl.empty();
|
||||||
|
this.containerEl.createEl("h2", { text: "Custom Frames Settings" });
|
||||||
|
this.containerEl.createEl("p", { text: "Please note that Obsidian has to be restarted or reloaded for most of these settings to take effect.", cls: "mod-warning" });
|
||||||
|
new import_obsidian2.Setting(this.containerEl).setName("Frame Padding").setDesc("The padding that should be left around the inside of custom frame panes, in pixels.").addText((t) => {
|
||||||
|
t.inputEl.type = "number";
|
||||||
|
t.setValue(String(this.plugin.settings.padding));
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
this.plugin.settings.padding = v.length ? Number(v) : defaultSettings.padding;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
for (let frame of this.plugin.settings.frames) {
|
||||||
|
let heading = this.containerEl.createEl("h3", { text: frame.displayName || "Unnamed Frame" });
|
||||||
|
let toggle = new import_obsidian2.ButtonComponent(this.containerEl).setButtonText("Show Settings").setClass("custom-frames-show").onClick(() => __async(this, null, function* () {
|
||||||
|
content.hidden = !content.hidden;
|
||||||
|
toggle.setButtonText(content.hidden ? "Show Settings" : "Hide Settings");
|
||||||
|
}));
|
||||||
|
let content = this.containerEl.createDiv();
|
||||||
|
content.hidden = true;
|
||||||
|
new import_obsidian2.Setting(content).setName("Display Name").setDesc("The display name that this frame should have.").addText((t) => {
|
||||||
|
t.setValue(frame.displayName);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.displayName = v;
|
||||||
|
heading.setText(frame.displayName || "Unnamed Frame");
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Icon").setDesc(createFragment((f) => {
|
||||||
|
f.createSpan({ text: "The icon that this frame's pane should have. The names of any " });
|
||||||
|
f.createEl("a", { text: "Lucide icons", href: "https://lucide.dev/" });
|
||||||
|
f.createSpan({ text: " can be used." });
|
||||||
|
})).addText((t) => {
|
||||||
|
t.setValue(frame.icon);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.icon = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("URL").setDesc("The URL that should be opened in this frame.").addText((t) => {
|
||||||
|
t.setValue(frame.url);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.url = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Disable on Mobile").setDesc("Custom Frames is a lot more restricted on mobile devices and doesn't allow for the same types of content to be displayed. If a frame doesn't work as expected on mobile, it can be disabled.").addToggle((t) => {
|
||||||
|
t.setValue(frame.hideOnMobile);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.hideOnMobile = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Add Ribbon Icon").setDesc("Whether a button to open this frame should be added to the ribbon.").addToggle((t) => {
|
||||||
|
t.setValue(frame.addRibbonIcon);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.addRibbonIcon = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Open in Center").setDesc("Whether this frame should be opened in the unpinned center editor rather than one of the panes on the side. This is useful for sites that don't work well in a narrow view, or sites that don't require a note to be open when viewed.").addToggle((t) => {
|
||||||
|
t.setValue(frame.openInCenter);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.openInCenter = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Force iframe").setDesc(createFragment((f) => {
|
||||||
|
f.createSpan({ text: "Whether this frame should use iframes on desktop as opposed to Electron webviews." });
|
||||||
|
f.createEl("br");
|
||||||
|
f.createEl("em", { text: "Only enable this setting if the frame is causing issues or frequent crashes. This setting causes all Desktop-only settings to be ignored." });
|
||||||
|
})).addToggle((t) => {
|
||||||
|
t.setValue(frame.forceIframe);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.forceIframe = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Page Zoom").setDesc("The zoom that this frame's page should be displayed with, as a percentage.").addText((t) => {
|
||||||
|
t.inputEl.type = "number";
|
||||||
|
t.setValue(String(frame.zoomLevel * 100));
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.zoomLevel = v.length ? Number(v) / 100 : 1;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.Setting(content).setName("Additional CSS").setDesc(createFragment((f) => {
|
||||||
|
f.createSpan({ text: "A snippet of additional CSS that should be applied to this frame." });
|
||||||
|
f.createEl("br");
|
||||||
|
f.createEl("em", { text: "Note that this is only applied on Desktop." });
|
||||||
|
})).addTextArea((t) => {
|
||||||
|
t.inputEl.rows = 5;
|
||||||
|
t.inputEl.cols = 50;
|
||||||
|
t.setValue(frame.customCss);
|
||||||
|
t.onChange((v) => __async(this, null, function* () {
|
||||||
|
frame.customCss = v;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
new import_obsidian2.ButtonComponent(content).setButtonText("Remove Frame").onClick(() => __async(this, null, function* () {
|
||||||
|
this.plugin.settings.frames.remove(frame);
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
this.display();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.containerEl.createEl("hr");
|
||||||
|
this.containerEl.createEl("p", { text: `Create a new frame, either from a preset shipped with the plugin, or a custom one that you can edit yourself. Each frame's pane can be opened using the "Custom Frames: Open" command.` });
|
||||||
|
let addDiv = this.containerEl.createDiv();
|
||||||
|
let dropdown = new import_obsidian2.DropdownComponent(addDiv);
|
||||||
|
dropdown.addOption("new", "Custom");
|
||||||
|
for (let key of Object.keys(presets))
|
||||||
|
dropdown.addOption(key, presets[key].displayName);
|
||||||
|
new import_obsidian2.ButtonComponent(addDiv).setButtonText("Add Frame").setClass("custom-frames-add").onClick(() => __async(this, null, function* () {
|
||||||
|
let option = dropdown.getValue();
|
||||||
|
if (option == "new") {
|
||||||
|
this.plugin.settings.frames.push({
|
||||||
|
url: "",
|
||||||
|
displayName: "New Frame",
|
||||||
|
icon: "",
|
||||||
|
hideOnMobile: true,
|
||||||
|
addRibbonIcon: false,
|
||||||
|
openInCenter: false,
|
||||||
|
zoomLevel: 1,
|
||||||
|
forceIframe: false,
|
||||||
|
customCss: ""
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.plugin.settings.frames.push(presets[option]);
|
||||||
|
}
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
this.display();
|
||||||
|
}));
|
||||||
|
var disclaimer = this.containerEl.createEl("p", { cls: "mod-warning" });
|
||||||
|
disclaimer.createSpan({ text: "Please be advised that, when adding a site as a custom frame, you potentially expose personal information you enter to other plugins you have installed. For more information, see " });
|
||||||
|
disclaimer.createEl("a", { text: "this discussion", href: "https://github.com/Ellpeck/ObsidianCustomFrames/issues/54#issuecomment-1210879685", cls: "mod-warning" });
|
||||||
|
disclaimer.createSpan({ text: "." });
|
||||||
|
this.containerEl.createEl("hr");
|
||||||
|
this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" });
|
||||||
|
this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }).createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "custom-frames-support" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/view.ts
|
||||||
|
var import_obsidian3 = __toModule(require("obsidian"));
|
||||||
|
var _CustomFrameView = class extends import_obsidian3.ItemView {
|
||||||
|
constructor(leaf, settings, data, name) {
|
||||||
|
super(leaf);
|
||||||
|
this.data = data;
|
||||||
|
this.name = name;
|
||||||
|
this.frame = new CustomFrame(settings, data);
|
||||||
|
this.navigation = data.openInCenter;
|
||||||
|
for (let action of _CustomFrameView.actions)
|
||||||
|
this.addAction(action.icon, action.name, () => action.action(this));
|
||||||
|
}
|
||||||
|
onload() {
|
||||||
|
this.contentEl.empty();
|
||||||
|
this.contentEl.addClass("custom-frames-view");
|
||||||
|
this.frame.create(this.contentEl);
|
||||||
|
}
|
||||||
|
onPaneMenu(menu, source) {
|
||||||
|
super.onPaneMenu(menu, source);
|
||||||
|
for (let action of _CustomFrameView.actions) {
|
||||||
|
menu.addItem((i) => {
|
||||||
|
i.setTitle(action.name);
|
||||||
|
i.setIcon(action.icon);
|
||||||
|
i.onClick(() => action.action(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getViewType() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
getDisplayText() {
|
||||||
|
return this.data.displayName;
|
||||||
|
}
|
||||||
|
getIcon() {
|
||||||
|
return getIcon(this.data);
|
||||||
|
}
|
||||||
|
focus() {
|
||||||
|
this.frame.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var CustomFrameView = _CustomFrameView;
|
||||||
|
CustomFrameView.actions = [
|
||||||
|
{
|
||||||
|
name: "Return to original page",
|
||||||
|
icon: "home",
|
||||||
|
action: (v) => v.frame.return()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Open dev tools",
|
||||||
|
icon: "binary",
|
||||||
|
action: (v) => v.frame.toggleDevTools()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Copy link",
|
||||||
|
icon: "link",
|
||||||
|
action: (v) => navigator.clipboard.writeText(v.frame.getCurrentUrl())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Open in browser",
|
||||||
|
icon: "globe",
|
||||||
|
action: (v) => open(v.frame.getCurrentUrl())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Refresh",
|
||||||
|
icon: "refresh-cw",
|
||||||
|
action: (v) => v.frame.refresh()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Go back",
|
||||||
|
icon: "arrow-left",
|
||||||
|
action: (v) => v.frame.goBack()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Go forward",
|
||||||
|
icon: "arrow-right",
|
||||||
|
action: (v) => v.frame.goForward()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// src/main.ts
|
||||||
|
var CustomFramesPlugin = class extends import_obsidian4.Plugin {
|
||||||
|
onload() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
yield this.loadSettings();
|
||||||
|
for (let frame of this.settings.frames) {
|
||||||
|
if (!frame.url || !frame.displayName)
|
||||||
|
continue;
|
||||||
|
let name = `custom-frames-${getId(frame)}`;
|
||||||
|
if (import_obsidian4.Platform.isMobileApp && frame.hideOnMobile) {
|
||||||
|
console.log(`Skipping frame ${name} which is hidden on mobile`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log(`Registering frame ${name} for URL ${frame.url}`);
|
||||||
|
this.registerView(name, (l) => new CustomFrameView(l, this.settings, frame, name));
|
||||||
|
this.addCommand({
|
||||||
|
id: `open-${name}`,
|
||||||
|
name: `Open ${frame.displayName}`,
|
||||||
|
callback: () => this.openLeaf(name, frame.openInCenter, false)
|
||||||
|
});
|
||||||
|
if (frame.addRibbonIcon)
|
||||||
|
this.addRibbonIcon(getIcon(frame), `Open ${frame.displayName}`, (e) => this.openLeaf(name, frame.openInCenter, import_obsidian4.Platform.isMacOS ? e.metaKey : e.ctrlKey));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Couldn't register frame ${name}, is there already one with the same name?`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addSettingTab(new CustomFramesSettingTab(this.app, this));
|
||||||
|
this.registerMarkdownCodeBlockProcessor("custom-frames", (s, e) => {
|
||||||
|
e.empty();
|
||||||
|
e.addClass("custom-frames-view-file");
|
||||||
|
let frameMatch = /frame:([^\n]+)/gi.exec(s);
|
||||||
|
let frameName = frameMatch && frameMatch[1].trim();
|
||||||
|
if (!frameName) {
|
||||||
|
e.createSpan({ text: "Couldn't parse frame name" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = this.settings.frames.find((f) => f.displayName == frameName);
|
||||||
|
if (!data) {
|
||||||
|
e.createSpan({ text: `Couldn't find a frame with name ${frameName}` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (import_obsidian4.Platform.isMobileApp && data.hideOnMobile) {
|
||||||
|
e.createSpan({ text: `${frameName} is hidden on mobile` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let styleMatch = /style:([^\n]+)/gi.exec(s);
|
||||||
|
let style = styleMatch && styleMatch[1].trim();
|
||||||
|
style || (style = "height: 600px;");
|
||||||
|
let urlSuffixMatch = /urlsuffix:([^\n]+)/gi.exec(s);
|
||||||
|
let urlSuffix = urlSuffixMatch && urlSuffixMatch[1].trim();
|
||||||
|
urlSuffix || (urlSuffix = "");
|
||||||
|
let frame = new CustomFrame(this.settings, data);
|
||||||
|
frame.create(e, style, urlSuffix);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
loadSettings() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
this.settings = Object.assign({}, defaultSettings, yield this.loadData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
saveSettings() {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
yield this.saveData(this.settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
openLeaf(name, center, split) {
|
||||||
|
return __async(this, null, function* () {
|
||||||
|
let leaf;
|
||||||
|
if (center) {
|
||||||
|
leaf = this.app.workspace.getLeaf(split);
|
||||||
|
yield leaf.setViewState({ type: name, active: true });
|
||||||
|
} else {
|
||||||
|
if (!this.app.workspace.getLeavesOfType(name).length)
|
||||||
|
yield this.app.workspace.getRightLeaf(false).setViewState({ type: name, active: true });
|
||||||
|
leaf = this.app.workspace.getLeavesOfType(name)[0];
|
||||||
|
this.app.workspace.revealLeaf(leaf);
|
||||||
|
}
|
||||||
|
if (leaf.view instanceof CustomFrameView)
|
||||||
|
leaf.view.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
10
test-vault/.obsidian/plugins/obsidian-custom-frames/manifest
vendored
Normal file
10
test-vault/.obsidian/plugins/obsidian-custom-frames/manifest
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"id": "obsidian-custom-frames",
|
||||||
|
"name": "Custom Frames",
|
||||||
|
"version": "2.4.6",
|
||||||
|
"minAppVersion": "1.2.0",
|
||||||
|
"description": "A plugin that turns web apps into panes using iframes with custom styling. Also comes with presets for Google Keep, Todoist and more.",
|
||||||
|
"author": "Ellpeck",
|
||||||
|
"authorUrl": "https://ellpeck.de",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
10
test-vault/.obsidian/plugins/obsidian-custom-frames/manifest.json
vendored
Normal file
10
test-vault/.obsidian/plugins/obsidian-custom-frames/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"id": "obsidian-custom-frames",
|
||||||
|
"name": "Custom Frames",
|
||||||
|
"version": "2.4.6",
|
||||||
|
"minAppVersion": "1.2.0",
|
||||||
|
"description": "A plugin that turns web apps into panes using iframes with custom styling. Also comes with presets for Google Keep, Todoist and more.",
|
||||||
|
"author": "Ellpeck",
|
||||||
|
"authorUrl": "https://ellpeck.de",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
31
test-vault/.obsidian/plugins/obsidian-custom-frames/styles
vendored
Normal file
31
test-vault/.obsidian/plugins/obsidian-custom-frames/styles
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
.custom-frames-view {
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-view-file {
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-frame {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
background-color: white;
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-add {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-show {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-support {
|
||||||
|
max-width: 50%;
|
||||||
|
width: 400px;
|
||||||
|
height: auto;
|
||||||
|
}
|
31
test-vault/.obsidian/plugins/obsidian-custom-frames/styles.css
vendored
Normal file
31
test-vault/.obsidian/plugins/obsidian-custom-frames/styles.css
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
.custom-frames-view {
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-view-file {
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-frame {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
background-color: white;
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-add {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-show {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-frames-support {
|
||||||
|
max-width: 50%;
|
||||||
|
width: 400px;
|
||||||
|
height: auto;
|
||||||
|
}
|
|
@ -12,6 +12,5 @@
|
||||||
"2.4.3": "0.15.5",
|
"2.4.3": "0.15.5",
|
||||||
"2.4.4": "0.16.0",
|
"2.4.4": "0.16.0",
|
||||||
"2.4.5": "1.1.0",
|
"2.4.5": "1.1.0",
|
||||||
"2.4.6": "1.2.0",
|
"2.4.6": "1.2.0"
|
||||||
"2.4.7": "1.2.0"
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue