Skip to content

Commit 6f003ee

Browse files
authored
use oembed-parse to get the iframe from the source (Youtube, Soundcloud etc) WIP (#34)
* feat(oembed): use oembed parse to get the iframe * test(oembed): add test to getIframe * feat(oembed): compute aspect ratio * feat(input): add contextual menu * feat(readme): update doc * feat(version): bump to 0.4.0
1 parent f4cb2f0 commit 6f003ee

21 files changed

+257
-116
lines changed

README.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
# Obsidian Plugin: Convert a URL (e.g. YouTube) into an iframe (preview)
2-
**Transform a YouTube URL into a YouTube preview.**
2+
**Transform any URL into a preview.**
33

4-
![Demo](images/demo-url-to-preview-3.gif)
4+
![Demo](images/demo-url-to-preview-0.4.0.gif)
55

6-
Transform a selected URL to an embed view if the website allows it. It offers the possibilitiy to resize the preview.
6+
1. Select an url
7+
2. right click on it (or use the command `Convert to Url Preview`)
8+
3. Click on `Url to Preview/Iframe`.
9+
![contextual menu](images/contextual-menu.png)
710

8-
The default hotkey is `cmd + shift + i`.
11+
12+
The default hotkey is `cmd + alt + i`.
913

1014

1115
# Installation
1216
Support for 3rd party plugins is enabled in settings (Obsidian > Settings > Third Party plugin > Safe mode - OFF)
1317
To install this plugin, download zip archive from GitHub releases page. Extract the archive into <vault>/.obsidian/plugins.
1418

15-
# Future improvement
16-
- Find a way to detect when the website doesn't allow cross origins.
17-
- Support more websites.
18-
1919
# Change log
2020

21+
## 0.4.0
22+
- Instead of doing a custom mapping to embed for YouTube, we now rely on the OEmbed standard. Thanks to https://www.npmjs.com/package/oembed-parser
23+
- This allows to preserve the timestamp on Youtube and to get default size for many websites.
24+
- Add contextual menu (right click on a link) ![contextual menu](images/contextual-menu.png)
25+
26+
2127
## 0.3.0
2228
- Simplify the output when using a recent Obsidian download, by leveraging `aspect-ratio` css.
2329

images/contextual-menu.png

29.9 KB
Loading
3.93 MB
Loading

images/demo-url-to-preview-3.gif

-11.6 MB
Binary file not shown.

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "convert-url-to-iframe",
33
"name": "Convert url to preview (iframe)",
4-
"version": "0.3.0",
4+
"version": "0.4.0",
55
"description": "Convert an url (ex, youtube) into an iframe (preview)",
66
"author": "Hachez Floran",
77
"authorUrl": "https://github.com/FHachez",

package-lock.json

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "obsidian-convert-url-to-iframe",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "Convert an url (ex, youtube) into an iframe (preview)",
55
"main": "main.js",
66
"scripts": {
@@ -12,6 +12,8 @@
1212
"author": "",
1313
"license": "MIT",
1414
"devDependencies": {
15+
"@types/dompurify": "^2.3.2",
16+
"@types/jsdom": "^16.2.14",
1517
"@types/node": "^14.14.2",
1618
"@typescript-eslint/eslint-plugin": "^5.2.0",
1719
"@typescript-eslint/parser": "^5.2.0",
@@ -25,5 +27,9 @@
2527
"ts-jest": "^26.4.3",
2628
"tslib": "^2.0.3",
2729
"typescript": "^4.1.0"
30+
},
31+
"dependencies": {
32+
"dompurify": "^2.3.4",
33+
"oembed-parser": "^2.0.0"
2834
}
2935
}

src/components/resizable_iframe_container.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { defaultHeight } from "src/constant";
22
import { AspectRatioType } from "src/types/aspect-ratio";
3-
import { swapRatio } from "src/utils/ratio_swapper";
3+
import { addAspectRatio, swapRatio } from "src/utils/ratio.utils";
44

55
export interface IResizableIframeContainerOutput {
66
iframeContainer: HTMLElement,
@@ -10,18 +10,20 @@ export interface IResizableIframeContainerOutput {
1010
}
1111

1212

13-
export function createIframeContainerEl(contentEl: HTMLElement, url: string): IResizableIframeContainerOutput{
13+
export function createIframeContainerEl(contentEl: HTMLElement, iframeHtml: string): IResizableIframeContainerOutput{
1414
// Container to keep a min height for the iframe to keep the content visible
1515
const iframeContainer = contentEl.createEl('div');
1616
iframeContainer.className = "iframe__container space-y"
1717

1818
// Inline styling to make sure that the created iframe will keep the style even without the plugin
19-
const iframe = iframeContainer.createEl('iframe');
20-
iframe.src = url;
21-
iframe.allow = "fullscreen"
22-
iframe.style.height = '100%';
23-
iframe.style.width = '100%';
24-
iframe.style.setProperty('aspect-ratio', '16/9');
19+
const fragment = document.createElement('template');
20+
fragment.innerHTML = iframeHtml;
21+
22+
const iframe = fragment.content.firstChild as HTMLIFrameElement;
23+
iframeContainer.appendChild(iframe);
24+
25+
console.log(iframe.outerHTML)
26+
addAspectRatio(iframe);
2527

2628
const resetToDefaultWidth= () => {
2729
iframe.style.width = '100%';
@@ -30,6 +32,7 @@ export function createIframeContainerEl(contentEl: HTMLElement, url: string): IR
3032

3133
resetToDefaultWidth();
3234

35+
console.log(iframeHtml, iframe)
3336

3437
return {
3538
iframeContainer,
@@ -108,4 +111,4 @@ export function createIframeContainerElLegacy(contentEl: HTMLElement, url: strin
108111
iframeContainer.style.height = ratioContainer.offsetHeight + 'px';
109112
},
110113
};
111-
}
114+
}

src/configure_iframe_modal.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import { doesSupportAspectRatio } from './constant';
66

77

88
export class ConfigureIframeModal extends Modal {
9-
url: string;
9+
iframeHtml: string;
1010
editor: any;
1111

12-
constructor(app: App, url: string, editor: any) {
12+
constructor(app: App, iframeHtml: string, editor: any) {
1313
super(app);
14-
this.url = url;
14+
this.iframeHtml = iframeHtml;
1515
this.editor = editor;
1616

1717
// Allow the modal to grow in width
@@ -33,7 +33,7 @@ export class ConfigureIframeModal extends Modal {
3333

3434
// Electron < 12 doesn't support the aspect ratio. We need to use a fancy div container with a padding bottom
3535
const { iframeContainer, outputHtml, resetToDefaultWidth, updateAspectRatio } = doesSupportAspectRatio ?
36-
createIframeContainerEl(contentEl, this.url) : createIframeContainerElLegacy(contentEl, this.url);
36+
createIframeContainerEl(contentEl, this.iframeHtml) : createIframeContainerElLegacy(contentEl, this.iframeHtml);
3737
const widthCheckbox = createShouldUseDefaultWidthButton(container, resetToDefaultWidth);
3838
const aspectRatioInput = createAspectRatioInput(container ,updateAspectRatio);
3939

src/constant.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ declare namespace process {
99
export const defaultHeight = "100px"
1010

1111
const electronMajorVersion = process.versions?.electron?.split('.')[0]
12-
export const doesSupportAspectRatio = +(electronMajorVersion) >= 12;
12+
export const doesSupportAspectRatio = +(electronMajorVersion) >= 12;

0 commit comments

Comments
 (0)