2022-10-10 12:50:21 +00:00
|
|
|
import { nodeAtPos } from "../../common/tree.ts";
|
2022-07-30 11:39:40 +00:00
|
|
|
import {
|
|
|
|
filterBox,
|
|
|
|
flashNotification,
|
|
|
|
getCursor,
|
|
|
|
getText,
|
|
|
|
replaceRange,
|
2022-10-10 12:50:21 +00:00
|
|
|
} from "../../syscall/silverbullet-syscall/editor.ts";
|
|
|
|
import { parseMarkdown } from "../../syscall/silverbullet-syscall/markdown.ts";
|
|
|
|
import { dispatch as dispatchEvent } from "../../syscall/plugos-syscall/event.ts";
|
|
|
|
import { invokeFunction } from "../../syscall/silverbullet-syscall/system.ts";
|
2022-07-30 11:39:40 +00:00
|
|
|
|
|
|
|
type UnfurlOption = {
|
|
|
|
id: string;
|
|
|
|
name: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
export async function unfurlCommand() {
|
|
|
|
let mdTree = await parseMarkdown(await getText());
|
|
|
|
let nakedUrlNode = nodeAtPos(mdTree, await getCursor());
|
|
|
|
let url = nakedUrlNode!.children![0].text!;
|
|
|
|
console.log("Got URL to unfurl", url);
|
|
|
|
let optionResponses = await dispatchEvent("unfurl:options", url);
|
|
|
|
let options: UnfurlOption[] = [];
|
|
|
|
for (let resp of optionResponses) {
|
|
|
|
options.push(...resp);
|
|
|
|
}
|
|
|
|
let selectedUnfurl: any = await filterBox(
|
|
|
|
"Unfurl",
|
|
|
|
options,
|
|
|
|
"Select the unfurl strategy of your choice"
|
|
|
|
);
|
|
|
|
if (!selectedUnfurl) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
let replacement = await invokeFunction(
|
|
|
|
"server",
|
|
|
|
"unfurlExec",
|
|
|
|
selectedUnfurl.id,
|
|
|
|
url
|
|
|
|
);
|
|
|
|
await replaceRange(nakedUrlNode?.from!, nakedUrlNode?.to!, replacement);
|
|
|
|
} catch (e: any) {
|
|
|
|
await flashNotification(e.message, "error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function titleUnfurlOptions(url: string): Promise<UnfurlOption[]> {
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
id: "title-unfurl",
|
|
|
|
name: "Extract title",
|
|
|
|
},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run on the server because plugs will likely rely on fetch for this
|
|
|
|
export async function unfurlExec(id: string, url: string): Promise<string> {
|
|
|
|
let replacement = await dispatchEvent(`unfurl:${id}`, url);
|
2022-09-02 13:47:44 +00:00
|
|
|
if (replacement.length === 0) {
|
|
|
|
throw new Error("Unfurl failed");
|
|
|
|
} else {
|
|
|
|
return replacement[0];
|
|
|
|
}
|
2022-07-30 11:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const titleRegex = /<title[^>]*>\s*([^<]+)\s*<\/title\s*>/i;
|
|
|
|
|
|
|
|
export async function titleUnfurl(url: string): Promise<string> {
|
|
|
|
let response = await fetch(url);
|
|
|
|
if (response.status < 200 || response.status >= 300) {
|
|
|
|
console.error("Unfurl failed", await response.text());
|
|
|
|
throw new Error(`Failed to fetch: ${await response.statusText}`);
|
|
|
|
}
|
|
|
|
let body = await response.text();
|
|
|
|
let match = titleRegex.exec(body);
|
|
|
|
if (match) {
|
|
|
|
return `[${match[1]}](${url})`;
|
|
|
|
} else {
|
|
|
|
throw new Error("No title found");
|
|
|
|
}
|
|
|
|
}
|