Skip to content

Instantly share code, notes, and snippets.

@brianrodri
Last active May 30, 2024 11:55
Show Gist options
  • Save brianrodri/b95ee3d7972f24700dd77769e8a3823c to your computer and use it in GitHub Desktop.
Save brianrodri/b95ee3d7972f24700dd77769e8a3823c to your computer and use it in GitHub Desktop.
import { Component, MarkdownView, Plugin, TFile, WorkspaceLeaf } from "obsidian";
import { render, unmountComponentAtNode } from "preact/compat";
export default class MyPlugin extends Plugin {
private components: PreactComponent[] = [];
public override onload() {
this.app.workspace.onLayoutReady(() => {
this.loadAllComponents();
this.registerEvent(
this.app.workspace.on("layout-change", () => {
// This feels hacky and like the wrong approach.
this.unloadAllComponents();
this.loadAllComponents();
}),
);
});
}
public override onunload() {
this.unloadAllComponents();
}
private loadAllComponents() {
this.app.workspace.iterateAllLeaves((leaf: WorkspaceLeaf) => {
const { view } = leaf;
if (view instanceof MarkdownView && view.file !== null) {
// TODO: How do I call `.removeChild()` if I've visited this leaf before?
if (view.getMode() === "preview") {
const component = new PreactComponent(view.containerEl, view.file);
view.addChild(component);
this.components.push(component);
}
}
});
}
private unloadAllComponents() {
this.components.forEach((component) => component.unload());
this.components = [];
}
}
class PreactComponent extends Component {
public constructor(
private readonly container: HTMLElement,
private readonly file: TFile,
private readonly className = "ROOT-ELEMENT-CLASS",
private readonly classes = [className, "markdown-preview-sizer"],
private readonly positionSelector = ".markdown-reading-view > .markdown-preview-view",
) {
super();
console.log(this.file.path);
}
public override onload() {
const rootElement = this.ensureRootElement();
const position = this.container.querySelector(this.positionSelector);
if (position) {
position.prepend(rootElement);
render(<>Hello World!</>, rootElement);
console.log("preact mounted");
}
}
public override onunload() {
const rootElement = this.container.querySelector(`.${this.className}`);
if (rootElement) {
unmountComponentAtNode(rootElement);
rootElement.remove();
console.log("preact unmounted");
}
}
private ensureRootElement() {
return this.container.querySelector(`.${this.className}`) ?? this.container.createDiv({ cls: this.classes });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment