import { editor, events, markdown, system, } from "@silverbulletmd/silverbullet/syscalls"; import { findNodeOfType, renderToText } from "../../plug-api/lib/tree.ts"; import { replaceNodesMatching } from "../../plug-api/lib/tree.ts"; import type { ParseTree } from "../../plug-api/lib/tree.ts"; import { encodePageURI, parsePageRef, } from "@silverbulletmd/silverbullet/lib/page_ref"; type ShareOption = { id: string; name: string; }; export async function shareCommand() { await editor.save(); const pageName = await editor.getCurrentPage(); const optionResponses: ShareOption[] = (await events.dispatchEvent("share:options", pageName)).flat(); console.log("All options", optionResponses); const selectedShareOption: any = await editor.filterBox( "Share", optionResponses, "Pick a share option", ); if (!selectedShareOption) { return; } console.log("Picked", selectedShareOption); let text = await editor.getText(); const selection = await editor.getSelection(); if (selection.from !== selection.to) { text = text.substring(selection.from, selection.to); } await events.dispatchEvent( `share:${selectedShareOption.id}`, text, ); } export function clipboardShareOptions() { return [ { id: "clean-markdown", name: "Copy to clipboard as clean markdown", }, { id: "rich-text", name: "Copy to clipboard as rich text", }, ]; } export async function clipboardMarkdownShare(text: string) { const pageName = await editor.getCurrentPage(); const tree = await markdown.parseMarkdown(text); let rendered = await system.invokeFunction( "markdown.expandCodeWidgets", tree, pageName, ); rendered = cleanMarkdown(rendered); await editor.copyToClipboard(renderToText(rendered).trim()); await editor.flashNotification("Copied to clipboard!"); } export function cleanMarkdown(tree: ParseTree): ParseTree { replaceNodesMatching(tree, (node) => { switch (node.type) { case "FrontMatter": return null; case "WikiLink": { const ref = findNodeOfType(node, "WikiLinkPage")!.children![0].text!; let linkText = ref.split("/").pop()!; const aliasNode = findNodeOfType(node, "WikiLinkAlias"); if (aliasNode) { linkText = aliasNode.children![0].text!; } const pageRef = parsePageRef(ref); return { text: `[${linkText}](${ typeof location !== "undefined" ? location.origin : "" }/${encodePageURI(pageRef.page)})`, }; } case "NamedAnchor": // Just remove these return null; case "CommandLink": { // Child 0 is CommandLinkMark, child 1 is CommandLinkPage const command = node.children![1].children![0].text!; let commandText = command; const aliasNode = findNodeOfType(node, "CommandLinkAlias"); if (aliasNode) { commandText = aliasNode.children![0].text!; } return { text: "`" + commandText + "`", }; } case "Attribute": // Just remove these return null; } }); return tree; } export async function clipboardRichTextShare(text: string) { const pageName = await editor.getCurrentPage(); const tree = await markdown.parseMarkdown(text); let rendered = await system.invokeFunction( "markdown.expandCodeWidgets", tree, pageName, ); rendered = cleanMarkdown(rendered); const html = await system.invokeFunction( "markdown.markdownToHtml", renderToText(rendered), ); console.log("HTML", html); await editor.copyToClipboard(new Blob([html], { type: "text/html" })); await editor.flashNotification("Copied to rich text to clipboard!"); }