pull/329/head
Zef Hemel 2023-01-21 13:37:55 +01:00
parent 9fbe78dadd
commit a4c103e127
11 changed files with 137 additions and 16 deletions

2
.gitignore vendored
View File

@ -5,7 +5,7 @@ dist_bundle
dist
*.js.map
website_build
data.db
data.db*
publish-data.db
/index.json
.idea

View File

@ -42,3 +42,11 @@ export type CompleteEvent = {
linePrefix: string;
pos: number;
};
export type WidgetContent = {
html?: string;
script?: string;
url?: string;
height?: number;
width?: number;
};

View File

@ -409,6 +409,10 @@ functions:
events:
- unfurl:title-unfurl
embedWidget:
path: ./embed.ts:embedWidget
codeWidget: embed
# Random stuff
statsCommand:
path: ./stats.ts:statsCommand

47
plugs/core/embed.ts Normal file
View File

@ -0,0 +1,47 @@
import * as YAML from "yaml";
import type { WidgetContent } from "$sb/app_event.ts";
type EmbedConfig = {
url: string;
height?: number;
width?: number;
};
function extractYoutubeVideoId(url: string) {
let match = url.match(/youtube\.com\/watch\?v=([^&]+)/);
if (match) {
return match[1];
}
match = url.match(/youtu.be\/([^&]+)/);
if (match) {
return match[1];
}
return null;
}
export function embedWidget(
bodyText: string,
): WidgetContent {
try {
const data: EmbedConfig = YAML.parse(bodyText) as any;
let url = data.url;
const youtubeVideoId = extractYoutubeVideoId(url);
if (youtubeVideoId) {
url = `https://www.youtube.com/embed/${youtubeVideoId}`;
// Sensible video defaults
data.width = data.width || 560;
data.height = data.height || 315;
}
return {
url,
height: data.height,
width: data.width,
};
} catch (e: any) {
return {
html: `ERROR: Could not parse body as YAML: ${e.message}`,
script: "",
};
}
}

View File

@ -1,9 +1,10 @@
import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts";
import type { WidgetContent } from "$sb/app_event.ts";
import { renderMarkdownToHtml } from "./markdown_render.ts";
export async function markdownWidget(
bodyText: string,
): Promise<{ html: string; script: string }> {
): Promise<WidgetContent> {
const mdTree = await parseMarkdown(bodyText);
const html = renderMarkdownToHtml(mdTree, {

View File

@ -1,3 +1,4 @@
import { WidgetContent } from "../../plug-api/app_event.ts";
import { panelHtml } from "../components/panel.tsx";
import { Decoration, EditorState, syntaxTree, WidgetType } from "../deps.ts";
import type { Editor } from "../editor.tsx";
@ -20,6 +21,7 @@ class IFrameWidget extends WidgetType {
}
toDOM(): HTMLElement {
console.log("toDOM");
const iframe = document.createElement("iframe");
iframe.srcdoc = panelHtml;
// iframe.style.height = "0";
@ -60,17 +62,31 @@ class IFrameWidget extends WidgetType {
iframe.onload = () => {
// Subscribe to message event on global object (to receive messages from iframe)
globalThis.addEventListener("message", messageListener);
this.codeWidgetCallback(this.bodyText).then(({ html, script }) => {
iframe.contentWindow!.postMessage({
type: "html",
html,
script,
});
iframe.contentWindow!.onunload = () => {
// Unsubscribing from events
globalThis.removeEventListener("message", messageListener);
};
});
// Only run this code once
iframe.onload = null;
this.codeWidgetCallback(this.bodyText).then(
(widgetContent: WidgetContent) => {
if (widgetContent.html) {
iframe.contentWindow!.postMessage({
type: "html",
html: widgetContent.html,
script: widgetContent.script,
});
// iframe.contentWindow!.onunload = () => {
// // Unsubscribing from events
// globalThis.removeEventListener("message", messageListener);
// };
} else if (widgetContent.url) {
iframe.contentWindow!.location.href = widgetContent.url;
if (widgetContent.height) {
iframe.style.height = widgetContent.height + "px";
}
if (widgetContent.width) {
iframe.style.width = widgetContent.width + "px";
}
}
},
);
};
return iframe;
}

View File

@ -89,7 +89,7 @@ function loadJsByUrl(url) {
</script>
</head>
<body>
Send me HTML
Loading...
</body>
</html>`;

View File

@ -6,6 +6,7 @@ release.
## Next
* Fixed copy & paste, drag & drop of attachments in the [[Desktop]] app
* Continuous [[Sync]]
* Support for embedding [[Markdown/Code Widgets]].
---
## 0.2.8

View File

@ -8,6 +8,7 @@ We mentioned markdown _extensions_, here are the ones currently supported:
* Double-bracketed wiki links: `[[link to page]]`, optionally with aliases `[[link to page|alias]]`.
* Hashtags, e.g. `#mytag`.
* Command link syntax: `{[Stats: Show]}` rendered into a clickable button {[Stats: Show]}.
* [[Markdown/Code Widgets]]
* [Tables](https://www.markdownguide.org/extended-syntax/#tables)
* [Fenced code blocks](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks)
* [Task lists](https://www.markdownguide.org/extended-syntax/#task-lists)

View File

@ -0,0 +1,40 @@
Code widgets are a SilverBullet specific “extensions” to [[Markdown]]. Technically, its not an extension — it just gives new semantics to markdowns native fenced code blocks — code blocks that start with a triple backtick, specifying a programming language.
Currently, SilverBullet provides two code widgets as part of its built in [[🔌 Plugs]]:
* `embed`
* `markdown`
In addition, plugs like [[🔌 KaTeX]] and [[🔌 Mermaid]] add additional ones.
## Embed
This allows you to embed internet content into your page inside of an iframe. This is useful to, for instance, embed youtube videos. In fact, there is specific support for those.
Two examples.
First, embedding the silverbullet.md website into the silverbullet.md website (inception!):
```embed
url: https://silverbullet.md
```
and a Youtube video:
```embed
url: https://www.youtube.com/watch?v=VemS-cqAD5k
```
Note, there is specific support for youtube videos — it automatically will set width, height and replace the URL with an embed URL.
The body of an `embed` block is written in [[YAML]] and supports the following attributes:
* `url` (mandatory): the URL of the content to embed
* `height` (optional): the height of the embedded page in pixels
* `width` (optional): the width of the embedded page in pixels
## Markdown
You can embed markdown inside of markdown and live preview it. Is this useful? 🤷 not really, its more of a demo of how this works. Nevertheless, to each their own, heres an example:
```markdown
This is going to be **bold**
```

View File

@ -20,8 +20,11 @@ Now that we got that out of the way, lets have a look at some of SilverBullet
* **Self-hosted**: you own your data. All content is stored as plain files in a folder on disk. Back up, sync, edit, publish, script with any additional tools you like.
* SilverBullet is [open source, MIT licensed](https://github.com/silverbulletmd/silverbullet) software.
![Screencast screenshot](demo-video-screenshot.png)
To get a good feel of what SilverBullet is capable of, [have a look at this introduction video](https://youtu.be/VemS-cqAD5k).
To get a good feel of what SilverBullet is capable of, have a look at this introduction video.
```embed
url: https://youtu.be/VemS-cqAD5k
```
## Try it
Heres the kicker: