Added support for twitter and simplify codepen's code.

This commit is contained in:
GnoxNahte 2024-03-05 23:12:54 +08:00
parent 529c6c2b77
commit 04513c920e
5 changed files with 145 additions and 33 deletions

View file

@ -1,25 +1,23 @@
import { PluginSettings } from "main";
import { EmbedBase } from "./embedBase";
export class CodepenEmbed implements EmbedBase {
export class CodepenEmbed extends EmbedBase {
name = "CodePen";
regex = new RegExp(/https:\/\/codepen\.io\/(\w+)\/(?:pen)\/(\w+)/);
regex = new RegExp(/https:\/\/codepen\.io\/(\w+)\/pen\/(\w+)(\?.*)?/);
createEmbed(link: string, container: HTMLElement, settings: Readonly<PluginSettings>): HTMLElement {
const iframe = createEl("iframe", {parent: container});
createEmbed(url: string, settings: Readonly<PluginSettings>): HTMLElement {
const regexMatch = url.match(this.regex);
// Shouldn't happen since got test before. But in case
if (regexMatch === null)
return this.onErrorCreatingEmbed();
let url = link;
if (link.contains("?"))
url = link.substring(0, link.indexOf("?"));
if (link.contains("/pen/"))
url = url.replace("/pen/", "/embed/");
// Creating the iframe
const iframe = createEl("iframe");
iframe.src = url + "?default-tab=result&editable=true";
// iframe.href = url + "?default-tab=result&editable=true";
iframe.textContent = "Codepen";
container.appendChild(iframe);
container.classList.add("codepen");
iframe.src = `https://codepen.io/${regexMatch[1]}/embed/${regexMatch[2]}?default-tab=result&editable=true`;
iframe.classList.add("auto-embed", "codepen-embed");
return iframe;
}
}
}

View file

@ -1,13 +1,25 @@
import { PluginSettings } from "main";
export interface EmbedBase {
export abstract class EmbedBase {
readonly name: string;
// To identify if the anchor link matches the embed type
readonly regex: RegExp;
createEmbed(
link: string,
container: HTMLElement,
settings: Readonly<PluginSettings>,
): HTMLElement;
abstract createEmbed(
link: string,
settings: Readonly<PluginSettings>,
): HTMLElement;
onload?(): void;
onunload?(): void;
onErrorCreatingEmbed(): HTMLElement {
const errorMsg = "Error with codepen url";
const error = createEl("p");
error.setText(errorMsg);
console.log(errorMsg);
return error;
}
}

79
embeds/twitter.ts Normal file
View file

@ -0,0 +1,79 @@
import { PluginSettings } from "main";
import { EmbedBase } from "./embedBase";
export class TwitterEmbed extends EmbedBase {
name = "Twitter";
regex = new RegExp(/https:\/\/(?:x|twitter)\.com\/\w+\/status\/(\w+)/);
onload(): void {
window.addEventListener("message", this.listenForTwitterResize);
}
createEmbed(url: string, settings: Readonly<PluginSettings>): HTMLElement {
const regexMatch = url.match(this.regex);
// Shouldn't happen since got test before. But in case
if (regexMatch === null)
return this.onErrorCreatingEmbed();
// Creating the iframe
const iframe = createEl("iframe");
const postId = regexMatch[1];
url = "https://platform.twitter.com/embed/Tweet.html?dnt=true&theme=dark&id=" + postId;
iframe.src = url;
iframe.id += "twitter-" + postId;
iframe.classList.add("auto-embed", "twitter-embed");
iframe.sandbox.add("allow-forms", "allow-presentation", "allow-same-origin", "allow-scripts", "allow-modals", "allow-popups");
iframe.setAttribute("scrolling", "no");
iframe.setAttribute("allowfullscreen", "");
return iframe;
}
onunload() : void {
window.removeEventListener("message", this.listenForTwitterResize);
}
listenForTwitterResize(e: MessageEvent) {
console.log("Origin: " + e.origin);
console.log("Data: " + e.data);
if (e.origin !== "https://platform.twitter.com")
return;
// Twitter Params format:
/*
twttr.embed {
id: string,
jsonrpc: "2.0",
method: string,
params[]:
{
width: number;
height: number;
data: {
tweet_id: string;
};
}
}
*/
// To visualise the data:
// console.log(e.data);
// Only continue if the method is for resizing
if (e.data["twttr.embed"]["method"] !== "twttr.private.resize")
return;
const params = e.data["twttr.embed"]["params"][0];
const iframe = document.getElementById("twitter-" + params["data"]["tweet_id"]) as HTMLIFrameElement;
console.log("Tweet-id: " + params["data"]["tweet_id"]);
if (iframe === null)
return;
iframe.style.height = params["height"] + "px";
iframe.style.width = params["width"] + "px";
}
}

21
main.ts
View file

@ -1,6 +1,8 @@
import { CodepenEmbed } from 'embeds/codepen';
import { TwitterEmbed } from 'embeds/twitter';
import { EmbedBase } from 'embeds/embedBase';
import { Plugin } from 'obsidian';
import { YouTubeEmbed } from 'embeds/youtube';
// Remember to rename these classes and interfaces!
@ -16,24 +18,33 @@ export default class MyPlugin extends Plugin {
settings: PluginSettings;
embedSources: EmbedBase[] = [
new CodepenEmbed(),
new TwitterEmbed(),
new YouTubeEmbed(),
]
async onload() {
console.log('loading plugin!!')
console.log('loading plugin');
await this.loadSettings();
this.embedSources.forEach(source => {
source.onload?.();
});
this.registerMarkdownPostProcessor((el, ctx) => {
console.log("Registering markdown")
const anchors = el.querySelectorAll('a.external-link') as NodeListOf<HTMLAnchorElement>;
anchors.forEach((anchor) => {
console.log("Testing: " + anchor.text);
this.handleAnchor(anchor);
})
})
}
onunload() {
console.log('unloading plugin')
console.log('unloading plugin');
this.embedSources.forEach(source => {
source.onunload?.();
});
}
async loadSettings() {
@ -69,10 +80,8 @@ export default class MyPlugin extends Plugin {
}
private createEmbed(embedSource: EmbedBase, link: string) {
const container = createDiv({cls: "embed-container"});
const embed = embedSource.createEmbed(link, container, this.settings);
const embed = embedSource.createEmbed(link, this.settings);
return embed;
return container;
}
private insertEmbed(a: HTMLAnchorElement, container: HTMLElement) {

View file

@ -6,19 +6,33 @@ available in the app when your plugin is enabled.
If your plugin does not need CSS, delete this file.
*/
iframe {
width: 100%;
min-height: 500px;
iframe.auto-embed {
max-width: 100%;
/* min-height: 500px; */
}
iframe.small {
iframe.small.auto-embed {
min-height: 300px;
}
iframe.large {
iframe.large.auto-embed {
min-height: 1000px;
}
iframe.largest {
iframe.largest.auto-embed {
min-height: calc(100vh - 100px);
}
.auto-embed.twitter-embed {
width: 600px;
height: 350px;
min-height: unset;
}
.auto-embed.youtube-embed {
/* width: 560px;
height: 315px; */
width: 100%;
aspect-ratio: 1.7777;
}