This commit is contained in:
Ell 2023-05-22 19:37:17 +02:00
parent 51b03d7bfc
commit ab10797f39
11 changed files with 1866 additions and 1956 deletions

View file

@ -4,6 +4,6 @@ root = true
[*] [*]
charset = utf-8 charset = utf-8
insert_final_newline = true insert_final_newline = true
indent_style = tab indent_style = space
indent_size = 4 indent_size = 4
tab_width = 4 tab_width = 4

View file

@ -13,7 +13,7 @@ To use this plugin, simply go into its settings and add a new frame, either from
### 🪟 Pane Mode ### 🪟 Pane Mode
To open a Custom Frame as a pane, you can use the "Custom Frames: Open" command. To open a Custom Frame as a pane, you can use the "Custom Frames: Open" command.
There are also plenty of settings to customize your frame further, including adding custom CSS to the site, adding a ribbon icon, displaying the frame in the center of the editor, and more. There are also plenty of settings to customize your frame further, including adding custom CSS to the site, adding a ribbon icon, displaying the frame in the center of the editor, and more.
### 🗒️ Markdown Mode ### 🗒️ Markdown Mode
You can also display your custom frames in your Markdown documents. Custom Frames adds a special code block syntax that transforms the code block into a custom frame in Live Preview and Reading mode. Your code block should look like this: You can also display your custom frames in your Markdown documents. Custom Frames adds a special code block syntax that transforms the code block into a custom frame in Live Preview and Reading mode. Your code block should look like this:
@ -23,7 +23,7 @@ frame: YOUR FRAME'S NAME
``` ```
~~~ ~~~
Optionally, you can also pass custom style settings to the embed, which allows you to change things like the embed's height, as well as an additional suffix that will be appended to the frame's regular URL, which can be useful for things like displaying a specific note in Google Keep. Optionally, you can also pass custom style settings to the embed, which allows you to change things like the embed's height, as well as an additional suffix that will be appended to the frame's regular URL, which can be useful for things like displaying a specific note in Google Keep.
Here's an example using the [Google Keep preset](#-presets): Here's an example using the [Google Keep preset](#-presets):
~~~ ~~~
@ -42,7 +42,7 @@ By default, Custom Frames comes with a few presets that allow you to get new pan
- [Obsidian Forum](https://forum.obsidian.md/) - [Obsidian Forum](https://forum.obsidian.md/)
- [Google Keep](https://keep.google.com), optimized for a narrow pane on the side - [Google Keep](https://keep.google.com), optimized for a narrow pane on the side
- [Google Calendar](https://calendar.google.com/calendar/u/0/r/day), optimized by removing some buttons. Close side panel with top-left button. - [Google Calendar](https://calendar.google.com/calendar/u/0/r/day), optimized by removing some buttons. Close side panel with top-left button.
- [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)
@ -60,7 +60,7 @@ If you create a frame that you think other people would like, don't hesitate to
## ⚠️ 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.
- 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. - 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.
- 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. - 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.

View file

@ -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
@ -11,50 +11,50 @@ if you want to view the source, please visit the github repository of this plugi
const prod = (process.argv[2] === 'production'); const prod = (process.argv[2] === 'production');
esbuild.build({ esbuild.build({
banner: { banner: {
js: banner, js: banner,
}, },
entryPoints: ['src/main.ts'], entryPoints: ['src/main.ts'],
bundle: true, bundle: true,
external: [ external: [
'obsidian', 'obsidian',
'electron', 'electron',
'@codemirror/autocomplete', '@codemirror/autocomplete',
'@codemirror/closebrackets', '@codemirror/closebrackets',
'@codemirror/collab', '@codemirror/collab',
'@codemirror/commands', '@codemirror/commands',
'@codemirror/comment', '@codemirror/comment',
'@codemirror/fold', '@codemirror/fold',
'@codemirror/gutter', '@codemirror/gutter',
'@codemirror/highlight', '@codemirror/highlight',
'@codemirror/history', '@codemirror/history',
'@codemirror/language', '@codemirror/language',
'@codemirror/lint', '@codemirror/lint',
'@codemirror/matchbrackets', '@codemirror/matchbrackets',
'@codemirror/panel', '@codemirror/panel',
'@codemirror/rangeset', '@codemirror/rangeset',
'@codemirror/rectangular-selection', '@codemirror/rectangular-selection',
'@codemirror/search', '@codemirror/search',
'@codemirror/state', '@codemirror/state',
'@codemirror/stream-parser', '@codemirror/stream-parser',
'@codemirror/text', '@codemirror/text',
'@codemirror/tooltip', '@codemirror/tooltip',
'@codemirror/view', '@codemirror/view',
...builtins ...builtins
], ],
plugins: [ plugins: [
copy({ copy({
assets: [{ assets: [{
from: ["./manifest.json", "./main.js", "./styles.css"], from: ["./manifest.json", "./main.js", "./styles.css"],
to: ["./test-vault/.obsidian/plugins/obsidian-custom-frames/."] to: ["./test-vault/.obsidian/plugins/obsidian-custom-frames/."]
}] }]
}), }),
], ],
format: 'cjs', format: 'cjs',
watch: !prod, watch: !prod,
target: 'es2016', target: 'es2016',
logLevel: "info", logLevel: "info",
sourcemap: prod ? false : 'inline', sourcemap: prod ? false : 'inline',
treeShaking: true, treeShaking: true,
outfile: 'main.js', outfile: 'main.js',
}).catch(() => process.exit(1)); }).catch(() => process.exit(1));

View file

@ -1,10 +1,10 @@
{ {
"id": "obsidian-custom-frames", "id": "obsidian-custom-frames",
"name": "Custom Frames", "name": "Custom Frames",
"version": "2.4.6", "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",
"isDesktopOnly": false "isDesktopOnly": false
} }

3393
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,24 +1,24 @@
{ {
"name": "obsidian-custom-frames", "name": "obsidian-custom-frames",
"version": "2.4.6", "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": {
"dev": "node esbuild.config.mjs", "dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json" "version": "node version-bump.mjs && git add manifest.json versions.json"
}, },
"keywords": [], "keywords": [],
"author": "Ellpeck", "author": "Ellpeck",
"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": "^13.6.2", "electron": "^20.3.9",
"esbuild": "0.14.0", "esbuild": "0.14.0",
"esbuild-plugin-copy": "^1.3.0", "esbuild-plugin-copy": "^1.3.0",
"obsidian": "latest", "obsidian": "latest",
"tslib": "2.3.1", "tslib": "2.3.1",
"typescript": "4.4.4" "typescript": "4.4.4"
} }
} }

View file

@ -6,92 +6,92 @@ import { CustomFrameView } from "./view";
export default class CustomFramesPlugin extends Plugin { export default class CustomFramesPlugin extends Plugin {
settings: CustomFramesSettings; settings: CustomFramesSettings;
async onload(): Promise<void> { async onload(): Promise<void> {
await this.loadSettings(); await this.loadSettings();
for (let frame of this.settings.frames) { for (let frame of this.settings.frames) {
if (!frame.url || !frame.displayName) if (!frame.url || !frame.displayName)
continue; continue;
let name = `custom-frames-${getId(frame)}`; let name = `custom-frames-${getId(frame)}`;
if (Platform.isMobileApp && frame.hideOnMobile) { if (Platform.isMobileApp && frame.hideOnMobile) {
console.log(`Skipping frame ${name} which is hidden on mobile`); console.log(`Skipping frame ${name} which is hidden on mobile`);
continue; continue;
} }
try { try {
console.log(`Registering frame ${name} for URL ${frame.url}`); console.log(`Registering frame ${name} for URL ${frame.url}`);
this.registerView(name, l => new CustomFrameView(l, this.settings, frame, name)); this.registerView(name, l => new CustomFrameView(l, this.settings, frame, name));
this.addCommand({ this.addCommand({
id: `open-${name}`, id: `open-${name}`,
name: `Open ${frame.displayName}`, name: `Open ${frame.displayName}`,
callback: () => this.openLeaf(name, frame.openInCenter, false), callback: () => this.openLeaf(name, frame.openInCenter, false),
}); });
if (frame.addRibbonIcon) if (frame.addRibbonIcon)
this.addRibbonIcon(getIcon(frame), `Open ${frame.displayName}`, this.addRibbonIcon(getIcon(frame), `Open ${frame.displayName}`,
e => this.openLeaf(name, frame.openInCenter, Platform.isMacOS ? e.metaKey : e.ctrlKey)); e => this.openLeaf(name, frame.openInCenter, Platform.isMacOS ? e.metaKey : e.ctrlKey));
} catch { } catch {
console.error(`Couldn't register frame ${name}, is there already one with the same name?`); console.error(`Couldn't register frame ${name}, is there already one with the same name?`);
} }
} }
this.addSettingTab(new CustomFramesSettingTab(this.app, this)); this.addSettingTab(new CustomFramesSettingTab(this.app, this));
this.registerMarkdownCodeBlockProcessor("custom-frames", (s, e) => { this.registerMarkdownCodeBlockProcessor("custom-frames", (s, e) => {
e.empty(); e.empty();
e.addClass("custom-frames-view-file"); e.addClass("custom-frames-view-file");
let frameMatch = /frame:([^\n]+)/gi.exec(s); let frameMatch = /frame:([^\n]+)/gi.exec(s);
let frameName = frameMatch && frameMatch[1].trim(); let frameName = frameMatch && frameMatch[1].trim();
if (!frameName) { if (!frameName) {
e.createSpan({ text: "Couldn't parse frame name" }); e.createSpan({ text: "Couldn't parse frame name" });
return; return;
} }
let data = this.settings.frames.find(f => f.displayName == frameName); let data = this.settings.frames.find(f => f.displayName == frameName);
if (!data) { if (!data) {
e.createSpan({ text: `Couldn't find a frame with name ${frameName}` }); e.createSpan({ text: `Couldn't find a frame with name ${frameName}` });
return; return;
} }
if (Platform.isMobileApp && data.hideOnMobile) { if (Platform.isMobileApp && data.hideOnMobile) {
e.createSpan({ text: `${frameName} is hidden on mobile` }); e.createSpan({ text: `${frameName} is hidden on mobile` });
return; return;
} }
let styleMatch = /style:([^\n]+)/gi.exec(s); let styleMatch = /style:([^\n]+)/gi.exec(s);
let style = styleMatch && styleMatch[1].trim(); let style = styleMatch && styleMatch[1].trim();
style ||= "height: 600px;"; style ||= "height: 600px;";
let urlSuffixMatch = /urlsuffix:([^\n]+)/gi.exec(s); let urlSuffixMatch = /urlsuffix:([^\n]+)/gi.exec(s);
let urlSuffix = urlSuffixMatch && urlSuffixMatch[1].trim(); let urlSuffix = urlSuffixMatch && urlSuffixMatch[1].trim();
urlSuffix ||= ""; urlSuffix ||= "";
let frame = new CustomFrame(this.settings, data); let frame = new CustomFrame(this.settings, data);
frame.create(e, style, urlSuffix); frame.create(e, style, urlSuffix);
}); });
} }
async loadSettings() { async loadSettings() {
this.settings = Object.assign({}, defaultSettings, await this.loadData()); this.settings = Object.assign({}, defaultSettings, await this.loadData());
} }
async saveSettings() { async saveSettings() {
await this.saveData(this.settings); await this.saveData(this.settings);
} }
private async openLeaf(name: string, center: boolean, split: boolean): Promise<void> { private async openLeaf(name: string, center: boolean, split: boolean): Promise<void> {
let leaf: WorkspaceLeaf; let leaf: WorkspaceLeaf;
if (center) { if (center) {
leaf = this.app.workspace.getLeaf(split); leaf = this.app.workspace.getLeaf(split);
await leaf.setViewState({ type: name, active: true }); await leaf.setViewState({ type: name, active: true });
} else { } else {
if (!this.app.workspace.getLeavesOfType(name).length) if (!this.app.workspace.getLeavesOfType(name).length)
await this.app.workspace.getRightLeaf(false).setViewState({ type: name, active: true }); await this.app.workspace.getRightLeaf(false).setViewState({ type: name, active: true });
leaf = this.app.workspace.getLeavesOfType(name)[0]; leaf = this.app.workspace.getLeavesOfType(name)[0];
this.app.workspace.revealLeaf(leaf); this.app.workspace.revealLeaf(leaf);
} }
if (leaf.view instanceof CustomFrameView) if (leaf.view instanceof CustomFrameView)
leaf.view.focus(); leaf.view.focus();
} }
} }

View file

@ -14,7 +14,10 @@ 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", { text: "Please note that Obsidian has to be restarted or reloaded for most of these settings to take effect.", cls: "mod-warning" }); 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 Setting(this.containerEl) new Setting(this.containerEl)
.setName("Frame Padding") .setName("Frame Padding")
@ -187,14 +190,20 @@ export class CustomFramesSettingTab extends PluginSettingTab {
this.display(); this.display();
}); });
var disclaimer = this.containerEl.createEl("p", { cls: "mod-warning" }); let 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", { text: "this discussion", href: "https://github.com/Ellpeck/ObsidianCustomFrames/issues/54#issuecomment-1210879685", cls: "mod-warning" }); disclaimer.createEl("a", {
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" }) this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }).createEl("img", {
.createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "custom-frames-support" }); attr: { src: "https://ellpeck.de/res/generalsupport.png" },
cls: "custom-frames-support"
});
} }
} }

View file

@ -1,31 +1,31 @@
.custom-frames-view { .custom-frames-view {
padding: 0 !important; padding: 0 !important;
overflow: hidden !important; overflow: hidden !important;
} }
.custom-frames-view-file { .custom-frames-view-file {
padding: 0; padding: 0;
overflow: auto; overflow: auto;
} }
.custom-frames-frame { .custom-frames-frame {
width: 100%; width: 100%;
height: 100%; height: 100%;
border: none; border: none;
background-color: white; background-color: white;
background-clip: content-box; background-clip: content-box;
} }
.custom-frames-add { .custom-frames-add {
margin-left: 10px; margin-left: 10px;
} }
.custom-frames-show { .custom-frames-show {
margin-bottom: 18px; margin-bottom: 18px;
} }
.custom-frames-support { .custom-frames-support {
max-width: 50%; max-width: 50%;
width: 400px; width: 400px;
height: auto; height: auto;
} }

View file

@ -1,23 +1,23 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"inlineSourceMap": true, "inlineSourceMap": true,
"inlineSources": true, "inlineSources": true,
"module": "ESNext", "module": "ESNext",
"target": "ES6", "target": "ES6",
"allowJs": true, "allowJs": true,
"noImplicitAny": true, "noImplicitAny": true,
"moduleResolution": "node", "moduleResolution": "node",
"importHelpers": true, "importHelpers": true,
"isolatedModules": true, "isolatedModules": true,
"lib": [ "lib": [
"DOM", "DOM",
"ES5", "ES5",
"ES6", "ES6",
"ES7" "ES7"
]
},
"include": [
"**/*.ts"
] ]
},
"include": [
"**/*.ts"
]
} }

View file

@ -1,16 +1,16 @@
{ {
"2.0.0": "0.13.33", "2.0.0": "0.13.33",
"2.0.1": "0.13.33", "2.0.1": "0.13.33",
"2.1.0": "0.13.33", "2.1.0": "0.13.33",
"2.2.0": "0.14.3", "2.2.0": "0.14.3",
"2.2.1": "0.14.3", "2.2.1": "0.14.3",
"2.2.2": "0.14.3", "2.2.2": "0.14.3",
"2.3.0": "0.14.5", "2.3.0": "0.14.5",
"2.4.0": "0.14.5", "2.4.0": "0.14.5",
"2.4.1": "0.14.5", "2.4.1": "0.14.5",
"2.4.2": "0.14.5", "2.4.2": "0.14.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"
} }