2024-04-04 21:39:27 +00:00
|
|
|
import { Plugin } from "obsidian";
|
|
|
|
|
|
|
|
const PREFIX = "swarnam";
|
|
|
|
|
|
|
|
function base64ToBytes(base64: string) {
|
|
|
|
const binString = atob(base64);
|
|
|
|
// @ts-expect-error
|
|
|
|
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
2022-04-15 18:13:31 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 21:39:27 +00:00
|
|
|
function bytesToBase64(bytes: Uint8Array) {
|
|
|
|
const binString = Array.from(bytes, (byte) =>
|
|
|
|
String.fromCodePoint(byte)
|
|
|
|
).join("");
|
|
|
|
return btoa(binString);
|
|
|
|
}
|
2022-04-15 18:13:31 +00:00
|
|
|
|
2024-04-04 21:39:27 +00:00
|
|
|
function asBase64(text: string) {
|
|
|
|
console.log({ text });
|
|
|
|
const b64 = bytesToBase64(new TextEncoder().encode(text));
|
|
|
|
console.log(console.log(new TextDecoder().decode(base64ToBytes(b64))));
|
|
|
|
return b64;
|
|
|
|
}
|
2022-04-15 18:13:31 +00:00
|
|
|
|
2024-04-04 21:39:27 +00:00
|
|
|
function getIframeDoc(htmlSource: string, cssSource: string, jsSource: string) {
|
|
|
|
const isDarkMode = window.matchMedia(
|
|
|
|
"(prefers-color-scheme: dark)"
|
|
|
|
).matches;
|
|
|
|
|
|
|
|
return `
|
|
|
|
<style>
|
|
|
|
body { font-family: sans-serif; color: ${isDarkMode ? "#fff" : "#000"} }
|
|
|
|
</style>
|
|
|
|
<style>
|
|
|
|
${cssSource}
|
|
|
|
</style>
|
2024-04-04 22:03:36 +00:00
|
|
|
<div class="${PREFIX}-html-container">
|
2024-04-04 21:39:27 +00:00
|
|
|
${htmlSource}
|
|
|
|
</div>
|
|
|
|
<script>
|
|
|
|
${jsSource}
|
|
|
|
</script>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function showError(msg: string, root: HTMLElement) {
|
|
|
|
root.classList.add("error");
|
|
|
|
root.createEl("p", { cls: "icon", text: "⚠️" });
|
|
|
|
root.createEl("p", { text: msg });
|
2022-04-15 18:13:31 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 21:39:27 +00:00
|
|
|
export default class SwarnamPlugin extends Plugin {
|
|
|
|
async onload() {
|
|
|
|
this.registerMarkdownCodeBlockProcessor(
|
|
|
|
"swarnam",
|
|
|
|
(source, el, ctx) => {
|
2024-04-04 22:03:36 +00:00
|
|
|
const root = el.createDiv({ cls: `${PREFIX}-root` });
|
2024-04-04 21:39:27 +00:00
|
|
|
|
|
|
|
let [
|
|
|
|
htmlSource = "",
|
|
|
|
cssSource = "",
|
|
|
|
jsSource = "",
|
|
|
|
// eslint-disable-next-line prefer-const
|
|
|
|
...others
|
|
|
|
] = source.split(/^\s*---\*---\s*$/m);
|
|
|
|
|
|
|
|
if (others.length > 0) {
|
|
|
|
showError(
|
|
|
|
"Swarnam only supports HTML, CSS and JS blocks but your snippet has more than 3 blocks.",
|
|
|
|
root
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2022-04-15 18:13:31 +00:00
|
|
|
|
2024-04-04 21:39:27 +00:00
|
|
|
htmlSource = htmlSource.trim();
|
|
|
|
cssSource = cssSource.trim();
|
|
|
|
jsSource = jsSource.trim();
|
2022-04-15 18:13:31 +00:00
|
|
|
|
2024-04-04 21:39:27 +00:00
|
|
|
if (!htmlSource) {
|
|
|
|
showError(
|
|
|
|
"A Swarnam block must at least contain HTML",
|
|
|
|
root
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const sourceRoot = root.createDiv({
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source-root`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
const htmlContainer = sourceRoot.createDiv({
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source-container`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
const htmlEl = htmlContainer.createEl("pre", {
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source ${PREFIX}-html-source`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
htmlContainer.createDiv({
|
|
|
|
text: "HTML",
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-badge ${PREFIX}-html-badge`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
htmlEl.setText(htmlSource);
|
|
|
|
|
|
|
|
if (cssSource) {
|
|
|
|
const cssContainer = sourceRoot.createDiv({
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source-container`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
const cssEl = cssContainer.createEl("pre", {
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source ${PREFIX}-css-source`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
cssContainer.createDiv({
|
|
|
|
text: "CSS",
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-badge ${PREFIX}-css-badge`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
cssEl.setText(cssSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (jsSource) {
|
|
|
|
const jsContainer = sourceRoot.createDiv({
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source-container`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
const jsEl = jsContainer.createEl("pre", {
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-source ${PREFIX}-js-source`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
jsContainer.createDiv({
|
|
|
|
text: "JS",
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-badge ${PREFIX}-js-badge`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
jsEl.setText(jsSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
const iframeEl = root.createEl("iframe", {
|
2024-04-04 22:03:36 +00:00
|
|
|
cls: `${PREFIX}-preview`,
|
2024-04-04 21:39:27 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
iframeEl.src = `data:text/html;base64;charset=UTF-8,${asBase64(
|
|
|
|
getIframeDoc(htmlSource, cssSource, jsSource)
|
|
|
|
)}`;
|
|
|
|
}
|
|
|
|
);
|
2022-04-15 18:13:31 +00:00
|
|
|
}
|
|
|
|
}
|