Skip to content

Commit 9ed060e

Browse files
committed
add post embed processor
1 parent 1a3a831 commit 9ed060e

6 files changed

Lines changed: 992 additions & 1 deletion

File tree

bun.lock

Lines changed: 9 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@atcute/oauth-browser-client": "^3.0.0",
3636
"@atcute/pckt": "^0.1.5",
3737
"@atcute/standard-site": "^1.0.0",
38+
"bluesky-post-embed": "^1.0.6",
3839
"obsidian": "latest",
3940
"remark-parse": "^11.0.0",
4041
"remark-stringify": "^11.0.0",

src/lib.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
import { Record } from "@atcute/atproto/types/repo/listRecords";
22

3-
export { getRecord, deleteRecord, putRecord} from "./lib/atproto";
3+
export { getRecord, deleteRecord, putRecord } from "./lib/atproto";
4+
5+
export const BSKY_POST_RE = /https:\/\/bsky\.app\/profile\/([^/?#]+)\/post\/([A-Za-z0-9]+)/;
6+
7+
export function bskyPostATUri(url: string): string | null {
8+
const match = url.match(BSKY_POST_RE);
9+
if (!match) return null;
10+
11+
const [, handleOrDid, rkey] = match;
12+
if (!handleOrDid || !rkey) return null;
13+
14+
return `at://${handleOrDid}/app.bsky.feed.post/${rkey}`;
15+
}
416

517
export {
618
getSembleCollections,

src/main.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { StandardFeedView, VIEW_ATMOSPHERE_STANDARD_FEED } from "views/standardf
66
import { ATClient } from "lib/client";
77
import { Clipper } from "lib/clipper";
88
import { registerIcons } from "./icons";
9+
import { BlueskyPostProcessor } from "./postprocessor";
910

1011
export default class AtmospherePlugin extends Plugin {
1112
settings: AtProtoSettings = DEFAULT_SETTINGS;
@@ -15,6 +16,7 @@ export default class AtmospherePlugin extends Plugin {
1516
async onload() {
1617
registerIcons();
1718
await this.loadSettings();
19+
1820
this.client = new ATClient();
1921
this.clipper = new Clipper(this);
2022

@@ -34,6 +36,9 @@ export default class AtmospherePlugin extends Plugin {
3436
}
3537
});
3638

39+
const bskyProcessor = new BlueskyPostProcessor();
40+
this.registerMarkdownPostProcessor((el, ctx) => bskyProcessor.process(el, ctx));
41+
3742
this.registerView(VIEW_TYPE_ATMOSPHERE_BOOKMARKS, (leaf) => {
3843
return new BookmarksView(leaf, this);
3944
});

src/postprocessor.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Component, MarkdownPostProcessorContext, setIcon } from "obsidian";
2+
import { BSKY_POST_RE, bskyPostATUri } from "lib";
3+
4+
5+
export class BlueskyPostProcessor extends Component {
6+
7+
async process(el: HTMLElement, _ctx: MarkdownPostProcessorContext) {
8+
9+
if (!customElements.get("bluesky-post")) {
10+
import("bluesky-post-embed");
11+
}
12+
13+
const links = el.findAll("a").filter(link => {
14+
const href = link.getAttribute("href") ?? "";
15+
return BSKY_POST_RE.test(href);
16+
});
17+
18+
if (links.length === 0) return;
19+
20+
for (const link of links) {
21+
const atUri = bskyPostATUri(link.getAttribute("href") ?? "");
22+
if (!atUri) continue;
23+
24+
this.attachToggle(link, atUri);
25+
}
26+
}
27+
28+
private attachToggle(link: HTMLElement, uri: string) {
29+
const embedId = `bsky-embed-${uri.replace(/[:\/]/g, "-")}`;
30+
31+
const btn = document.createElement("button");
32+
btn.setAttribute("aria-label", "Toggle post embed");
33+
btn.addClass("bsky-embed-toggle");
34+
setIcon(btn, "message-circle");
35+
36+
link.insertAdjacentElement("afterend", btn);
37+
38+
btn.addEventListener("click", () => {
39+
const existing = document.getElementById(embedId);
40+
if (existing) {
41+
existing.remove();
42+
setIcon(btn, "message-circle");
43+
return;
44+
}
45+
46+
const embedEl = document.createElement("bluesky-post") as HTMLElement;
47+
embedEl.id = embedId;
48+
embedEl.setAttribute("src", uri);
49+
embedEl.setAttribute("allow-unauthenticated", "");
50+
embedEl.addClass("bsky-post-embed-wrapper");
51+
52+
btn.insertAdjacentElement("afterend", embedEl);
53+
setIcon(btn, "x");
54+
});
55+
}
56+
}

0 commit comments

Comments
 (0)