silverbullet/web/cm_plugins/iframe_widget.ts

83 lines
2.4 KiB
TypeScript
Raw Permalink Normal View History

2024-08-02 23:14:40 +08:00
import type {
CodeWidgetCallback,
WidgetContent,
} from "../../plug-api/types.ts";
import { WidgetType } from "@codemirror/view";
import type { Client } from "../client.ts";
import { createWidgetSandboxIFrame } from "../components/widget_sandbox_iframe.ts";
export class IFrameWidget extends WidgetType {
iframe?: HTMLIFrameElement;
constructor(
readonly from: number,
readonly to: number,
readonly client: Client,
readonly bodyText: string,
readonly codeWidgetCallback: CodeWidgetCallback,
) {
super();
}
toDOM(): HTMLElement {
const from = this.from;
const iframe = createWidgetSandboxIFrame(
this.client,
this.bodyText,
2024-01-24 21:44:39 +08:00
this.codeWidgetCallback(this.bodyText, this.client.currentPage),
(message) => {
switch (message.type) {
case "blur":
this.client.editorView.dispatch({
selection: { anchor: from },
});
this.client.focus();
break;
case "reload":
2024-01-24 21:44:39 +08:00
this.codeWidgetCallback(this.bodyText, this.client.currentPage)
.then(
(widgetContent: WidgetContent | null) => {
if (widgetContent === null) {
iframe.contentWindow!.postMessage({
type: "html",
html: "",
theme:
document.getElementsByTagName("html")[0].dataset.theme,
});
} else {
iframe.contentWindow!.postMessage({
type: "html",
html: widgetContent.html,
script: widgetContent.script,
theme:
document.getElementsByTagName("html")[0].dataset.theme,
});
}
},
);
break;
}
},
);
const estimatedHeight = this.estimatedHeight;
iframe.height = `${estimatedHeight}px`;
return iframe;
}
2024-10-10 18:52:28 +08:00
override get estimatedHeight(): number {
const cachedHeight = this.client.getCachedWidgetHeight(this.bodyText);
2024-01-02 19:48:18 +08:00
// console.log("Calling estimated height", this.bodyText, cachedHeight);
return cachedHeight > 0 ? cachedHeight : 150;
}
2024-10-10 18:52:28 +08:00
override eq(other: WidgetType): boolean {
return (
other instanceof IFrameWidget &&
other.bodyText === this.bodyText
);
}
}