Skip to content

Commit ff7ffcb

Browse files
committed
add profile embed
1 parent e57c6e5 commit ff7ffcb

8 files changed

Lines changed: 274 additions & 27 deletions

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
@@ -36,6 +36,7 @@
3636
"@atcute/pckt": "^0.1.5",
3737
"@atcute/standard-site": "^1.0.0",
3838
"bluesky-post-embed": "^1.0.6",
39+
"bluesky-profile-card-embed": "^1.0.1",
3940
"obsidian": "latest",
4041
"remark-parse": "^11.0.0",
4142
"remark-stringify": "^11.0.0",

src/commands/publishDocument.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ async function buildDocumentRecord(plugin: AtmospherePlugin, file: TFile): Promi
145145

146146
let richContent: PubLeafletContent.Main | BlogPcktContent.Main | null = null;
147147
if (pub?.url.contains("leaflet.pub")) {
148-
richContent = markdownToLeafletContent(resolved)
148+
richContent = await markdownToLeafletContent(resolved)
149149
} else if (pub?.url.contains("pckt.blog")) {
150150
richContent = markdownToPcktContent(resolved)
151151
}

src/lib/markdown/wikilinks.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import type { App } from "obsidian";
33
// Matches [[Note]], [[Note|Alias]], [[Note#Heading]], [[Note#Heading|Alias]]
44
const WIKILINK_RE = /\[\[([^\]|#]+)(?:#([^\]|]+))?(?:\|([^\]]+))?\]\]/g;
55

6-
function titleToSlug(title: string): string {
7-
return title
8-
.toLowerCase()
9-
.trim()
10-
.replace(/\s+/g, "-")
11-
.replace(/[^a-z0-9-]/g, "");
12-
}
6+
// function titleToSlug(title: string): string {
7+
// return title
8+
// .toLowerCase()
9+
// .trim()
10+
// .replace(/\s+/g, "-")
11+
// .replace(/[^a-z0-9-]/g, "");
12+
// }
1313

1414
/**
1515
* Resolves Obsidian wikilinks to standard markdown links.

src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +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";
9+
import { BskyEmbedProcessor } from "./postprocessor";
1010

1111
export default class AtmospherePlugin extends Plugin {
1212
settings: AtProtoSettings = DEFAULT_SETTINGS;
@@ -36,7 +36,7 @@ export default class AtmospherePlugin extends Plugin {
3636
}
3737
});
3838

39-
const bskyProcessor = new BlueskyPostProcessor();
39+
const bskyProcessor = new BskyEmbedProcessor();
4040
this.registerMarkdownPostProcessor((el, ctx) => bskyProcessor.process(el, ctx));
4141

4242
this.registerView(VIEW_TYPE_ATMOSPHERE_BOOKMARKS, (leaf) => {

src/postprocessor.ts

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,37 @@
11
import { Component, MarkdownPostProcessorContext, setIcon } from "obsidian";
2-
import { BSKY_POST_RE, bskyPostATUri } from "./util";
2+
import { BSKY_POST_RE, BSKY_PROFILE_RE, bskyPostATUri, bskyProfileActor } from "./util";
33

4-
5-
export class BlueskyPostProcessor extends Component {
4+
export class BskyEmbedProcessor extends Component {
65

76
async process(el: HTMLElement, _ctx: MarkdownPostProcessorContext) {
8-
97
if (!customElements.get("bluesky-post")) {
10-
import("bluesky-post-embed");
8+
await import("bluesky-post-embed");
9+
}
10+
if (!customElements.get("bluesky-profile-card")) {
11+
await import("bluesky-profile-card-embed");
1112
}
1213

1314
const links = el.findAll("a").filter(link => {
1415
const href = link.getAttribute("href") ?? "";
15-
return BSKY_POST_RE.test(href);
16+
return BSKY_POST_RE.test(href) || BSKY_PROFILE_RE.test(href);
1617
});
1718

1819
if (links.length === 0) return;
1920

2021
for (const link of links) {
21-
const atUri = bskyPostATUri(link.getAttribute("href") ?? "");
22-
if (!atUri) continue;
23-
24-
this.attachToggle(link, atUri);
22+
const postUri = bskyPostATUri(link.getAttribute("href") ?? "");
23+
if (postUri) {
24+
this.attachToggle(link, postUri);
25+
return;
26+
}
27+
const actor = bskyProfileActor(link.getAttribute("href") ?? "");
28+
if (actor) {
29+
this.attachToggle(link, undefined, actor);
30+
}
2531
}
2632
}
2733

28-
private attachToggle(link: HTMLElement, uri: string) {
29-
const embedId = `bsky-embed-${uri.replace(/[:\/]/g, "-")}`;
30-
34+
private attachToggle(link: HTMLElement, uri?: string, actor?: string) {
3135
const btn = document.createElement("button");
3236
btn.setAttribute("aria-label", "Toggle post embed");
3337
btn.addClass("bsky-embed-toggle");
@@ -36,18 +40,32 @@ export class BlueskyPostProcessor extends Component {
3640
link.insertAdjacentElement("afterend", btn);
3741

3842
btn.addEventListener("click", () => {
43+
let embedId = "";
44+
if (uri) {
45+
embedId = `bsky-post-embed-${uri.replace(/[:/]/g, "-")}`;
46+
} else if (actor) {
47+
embedId = `bsky-profile-${actor.replace(/[:/]/g, "-")}`;
48+
} else {
49+
return;
50+
}
3951
const existing = document.getElementById(embedId);
4052
if (existing) {
4153
existing.remove();
4254
setIcon(btn, "message-circle");
4355
return;
4456
}
4557

46-
const embedEl = document.createElement("bluesky-post") as HTMLElement;
58+
let embedEl: HTMLElement;
59+
if (actor) {
60+
embedEl = document.createElement("bluesky-profile-card");
61+
embedEl.setAttribute("actor", actor);
62+
} else {
63+
embedEl = document.createElement("bluesky-post");
64+
embedEl.setAttribute("src", uri!);
65+
}
66+
4767
embedEl.id = embedId;
48-
embedEl.setAttribute("src", uri);
4968
embedEl.setAttribute("allow-unauthenticated", "");
50-
embedEl.addClass("bsky-post-embed-wrapper");
5169

5270
btn.insertAdjacentElement("afterend", embedEl);
5371
setIcon(btn, "x");

src/util.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ export async function fetchOgImage(url: string): Promise<string | undefined> {
3737
}
3838

3939
export const BSKY_POST_RE = /https:\/\/bsky\.app\/profile\/([^/?#]+)\/post\/([A-Za-z0-9]+)/;
40+
export const BSKY_PROFILE_RE = /https:\/\/bsky\.app\/profile\/([^/?#]+)/;
41+
42+
export function bskyProfileActor(url: string): ActorIdentifier | null {
43+
const match = url.match(BSKY_PROFILE_RE);
44+
if (!match) return null;
45+
46+
const [, handleOrDid] = match;
47+
if (!handleOrDid) return null;
48+
49+
if (!isActorIdentifier(handleOrDid)) {
50+
return null
51+
}
52+
return handleOrDid;
53+
}
4054

4155
export function bskyPostATUri(url: string): ResourceUri | null {
4256
const match = url.match(BSKY_POST_RE);
@@ -69,7 +83,7 @@ export function UrlToRecordUri(url: string): ResourceUri | null {
6983
* Given an AT URI that may contain a handle, resolve the handle to a DID
7084
* and return the canonical AT URI
7185
*/
72-
export async function resolveHandleInAtUri(uri: ResourceUri): Promise<ResourceUri| null> {
86+
export async function resolveHandleInAtUri(uri: ResourceUri): Promise<ResourceUri | null> {
7387
const parsed = parseResourceUri(uri);
7488
if (!parsed.ok) return uri;
7589

0 commit comments

Comments
 (0)