livecodes-reveal-plugin
Version:
A plugin for Reveal.js that enables embedding and running LiveCodes code playgrounds directly within your slides. Supports multiple languages and frameworks, making it easy to create interactive, live coding presentations.
352 lines (350 loc) • 18.6 kB
JavaScript
// node_modules/livecodes/livecodes.js
var F = Object.create;
var Z = Object.defineProperty;
var V = Object.getOwnPropertyDescriptor;
var ee = Object.getOwnPropertyNames;
var te = Object.getPrototypeOf;
var ne = Object.prototype.hasOwnProperty;
var oe = (d, g) => () => (g || d((g = { exports: {} }).exports, g), g.exports);
var re = (d, g, b, y) => {
if (g && typeof g == "object" || typeof g == "function") for (let M of ee(g)) !ne.call(d, M) && M !== b && Z(d, M, { get: () => g[M], enumerable: !(y = V(g, M)) || y.enumerable });
return d;
};
var se = (d, g, b) => (b = d != null ? F(te(d)) : {}, re(g || !d || !d.__esModule ? Z(b, "default", { value: d, enumerable: true }) : b, d));
var $ = oe((ce, K) => {
var ie = (function() {
var d = String.fromCharCode, g = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$", y = {};
function M(r, e) {
if (!y[r]) {
y[r] = {};
for (var l = 0; l < r.length; l++) y[r][r.charAt(l)] = l;
}
return y[r][e];
}
var A = { compressToBase64: function(r) {
if (r == null) return "";
var e = A._compress(r, 6, function(l) {
return g.charAt(l);
});
switch (e.length % 4) {
default:
case 0:
return e;
case 1:
return e + "===";
case 2:
return e + "==";
case 3:
return e + "=";
}
}, decompressFromBase64: function(r) {
return r == null ? "" : r == "" ? null : A._decompress(r.length, 32, function(e) {
return M(g, r.charAt(e));
});
}, compressToUTF16: function(r) {
return r == null ? "" : A._compress(r, 15, function(e) {
return d(e + 32);
}) + " ";
}, decompressFromUTF16: function(r) {
return r == null ? "" : r == "" ? null : A._decompress(r.length, 16384, function(e) {
return r.charCodeAt(e) - 32;
});
}, compressToUint8Array: function(r) {
for (var e = A.compress(r), l = new Uint8Array(e.length * 2), n = 0, s = e.length; n < s; n++) {
var h = e.charCodeAt(n);
l[n * 2] = h >>> 8, l[n * 2 + 1] = h % 256;
}
return l;
}, decompressFromUint8Array: function(r) {
if (r == null) return A.decompress(r);
for (var e = new Array(r.length / 2), l = 0, n = e.length; l < n; l++) e[l] = r[l * 2] * 256 + r[l * 2 + 1];
var s = [];
return e.forEach(function(h) {
s.push(d(h));
}), A.decompress(s.join(""));
}, compressToEncodedURIComponent: function(r) {
return r == null ? "" : A._compress(r, 6, function(e) {
return b.charAt(e);
});
}, decompressFromEncodedURIComponent: function(r) {
return r == null ? "" : r == "" ? null : (r = r.replace(/ /g, "+"), A._decompress(r.length, 32, function(e) {
return M(b, r.charAt(e));
}));
}, compress: function(r) {
return A._compress(r, 16, function(e) {
return d(e);
});
}, _compress: function(r, e, l) {
if (r == null) return "";
var n, s, h = {}, v = {}, w = "", O = "", m = "", S = 2, P = 3, c = 2, f = [], t = 0, o = 0, x;
for (x = 0; x < r.length; x += 1) if (w = r.charAt(x), Object.prototype.hasOwnProperty.call(h, w) || (h[w] = P++, v[w] = true), O = m + w, Object.prototype.hasOwnProperty.call(h, O)) m = O;
else {
if (Object.prototype.hasOwnProperty.call(v, m)) {
if (m.charCodeAt(0) < 256) {
for (n = 0; n < c; n++) t = t << 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++;
for (s = m.charCodeAt(0), n = 0; n < 8; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
} else {
for (s = 1, n = 0; n < c; n++) t = t << 1 | s, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = 0;
for (s = m.charCodeAt(0), n = 0; n < 16; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
}
S--, S == 0 && (S = Math.pow(2, c), c++), delete v[m];
} else for (s = h[m], n = 0; n < c; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
S--, S == 0 && (S = Math.pow(2, c), c++), h[O] = P++, m = String(w);
}
if (m !== "") {
if (Object.prototype.hasOwnProperty.call(v, m)) {
if (m.charCodeAt(0) < 256) {
for (n = 0; n < c; n++) t = t << 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++;
for (s = m.charCodeAt(0), n = 0; n < 8; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
} else {
for (s = 1, n = 0; n < c; n++) t = t << 1 | s, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = 0;
for (s = m.charCodeAt(0), n = 0; n < 16; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
}
S--, S == 0 && (S = Math.pow(2, c), c++), delete v[m];
} else for (s = h[m], n = 0; n < c; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
S--, S == 0 && (S = Math.pow(2, c), c++);
}
for (s = 2, n = 0; n < c; n++) t = t << 1 | s & 1, o == e - 1 ? (o = 0, f.push(l(t)), t = 0) : o++, s = s >> 1;
for (; ; ) if (t = t << 1, o == e - 1) {
f.push(l(t));
break;
} else o++;
return f.join("");
}, decompress: function(r) {
return r == null ? "" : r == "" ? null : A._decompress(r.length, 32768, function(e) {
return r.charCodeAt(e);
});
}, _decompress: function(r, e, l) {
var n = [], s, h = 4, v = 4, w = 3, O = "", m = [], S, P, c, f, t, o, x, a = { val: l(0), position: e, index: 1 };
for (S = 0; S < 3; S += 1) n[S] = S;
for (c = 0, t = Math.pow(2, 2), o = 1; o != t; ) f = a.val & a.position, a.position >>= 1, a.position == 0 && (a.position = e, a.val = l(a.index++)), c |= (f > 0 ? 1 : 0) * o, o <<= 1;
switch (s = c) {
case 0:
for (c = 0, t = Math.pow(2, 8), o = 1; o != t; ) f = a.val & a.position, a.position >>= 1, a.position == 0 && (a.position = e, a.val = l(a.index++)), c |= (f > 0 ? 1 : 0) * o, o <<= 1;
x = d(c);
break;
case 1:
for (c = 0, t = Math.pow(2, 16), o = 1; o != t; ) f = a.val & a.position, a.position >>= 1, a.position == 0 && (a.position = e, a.val = l(a.index++)), c |= (f > 0 ? 1 : 0) * o, o <<= 1;
x = d(c);
break;
case 2:
return "";
}
for (n[3] = x, P = x, m.push(x); ; ) {
if (a.index > r) return "";
for (c = 0, t = Math.pow(2, w), o = 1; o != t; ) f = a.val & a.position, a.position >>= 1, a.position == 0 && (a.position = e, a.val = l(a.index++)), c |= (f > 0 ? 1 : 0) * o, o <<= 1;
switch (x = c) {
case 0:
for (c = 0, t = Math.pow(2, 8), o = 1; o != t; ) f = a.val & a.position, a.position >>= 1, a.position == 0 && (a.position = e, a.val = l(a.index++)), c |= (f > 0 ? 1 : 0) * o, o <<= 1;
n[v++] = d(c), x = v - 1, h--;
break;
case 1:
for (c = 0, t = Math.pow(2, 16), o = 1; o != t; ) f = a.val & a.position, a.position >>= 1, a.position == 0 && (a.position = e, a.val = l(a.index++)), c |= (f > 0 ? 1 : 0) * o, o <<= 1;
n[v++] = d(c), x = v - 1, h--;
break;
case 2:
return m.join("");
}
if (h == 0 && (h = Math.pow(2, w), w++), n[x]) O = n[x];
else if (x === v) O = P + P.charAt(0);
else return null;
m.push(O), n[v++] = P + O.charAt(0), h--, P = O, h == 0 && (h = Math.pow(2, w), w++);
}
} };
return A;
})();
typeof K != "undefined" && K != null && (K.exports = ie);
});
var W = se($());
async function de(d, g = {}) {
typeof d == "object" && !(d instanceof HTMLElement) && (d.headless || d.view === "headless") && (g = d, d = null);
let { config: b = {}, headless: y, loading: M = "lazy", view: A } = g, r = y || A === "headless", e = null, l = null;
if (typeof d == "string") e = document.querySelector(d);
else if (d instanceof HTMLElement) e = d;
else if (!(r && typeof d == "object")) throw new Error("A valid container element is required.");
if (!e) if (r) e = document.createElement("div"), z(e), document.body.appendChild(e);
else throw new Error(`Cannot find element: "${d}"`);
let n = new URL(ae(g)), s = n.origin;
n.searchParams.set("embed", "true"), n.searchParams.set("loading", r ? "eager" : M), n.searchParams.set("sdkVersion", "0.12.0"), typeof b == "object" && Object.keys(b).length > 0 && n.searchParams.set("config", "sdk");
let h = g.params;
typeof h == "object" && Object.keys(h).length > 0 && JSON.stringify(h).length < 1800 && Object.keys(h).forEach((i) => {
n.searchParams.set(i, encodeURIComponent(String(h[i])));
});
let v = false, w = "Cannot call API methods after calling `destroy()`.", O = [], m = (i, u = "message") => {
addEventListener(u, i), O.push(i);
}, P = await new Promise((i) => {
var C, U, R, k, j, B, q, J, N;
if (!e) return;
let u = e.dataset.height || e.style.height;
if (u && !r) {
let I = isNaN(Number(u)) ? u : u + "px";
e.style.height = I;
}
e.dataset.defaultStyles !== "false" && !r && ((C = e.style).backgroundColor || (C.backgroundColor = "#fff"), (U = e.style).border || (U.border = "1px solid black"), (R = e.style).borderRadius || (R.borderRadius = "8px"), (k = e.style).boxSizing || (k.boxSizing = "border-box"), (j = e.style).padding || (j.padding = "0"), (B = e.style).width || (B.width = "100%"), (q = e.style).height || (q.height = e.style.height || "300px"), e.style.minHeight = "200px", e.style.flexGrow = "1", (J = e.style).overflow || (J.overflow = "hidden"), (N = e.style).resize || (N.resize = "vertical"));
let E = "livecodes", L = e.querySelector(`iframe.${E}`), p = L || document.createElement("iframe");
p.classList.add(E), p.setAttribute("allow", "accelerometer; camera; encrypted-media; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; web-share"), p.setAttribute("allowtransparency", "true"), p.setAttribute("allowpaymentrequest", "true"), p.setAttribute("allowfullscreen", "true"), p.setAttribute("sandbox", "allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");
let H = M === "eager" ? "eager" : "lazy";
p.setAttribute("loading", H), r ? z(p) : (p.style.height = "100%", p.style.minHeight = "200px", p.style.width = "100%", p.style.margin = "0", p.style.border = "0", p.style.borderRadius = e.style.borderRadius), m(function I(T) {
var _;
T.source !== p.contentWindow || T.origin !== s || ((_ = T.data) == null ? void 0 : _.type) !== "livecodes-init" || (removeEventListener("message", I), l = Number(T.data.payload.appVersion.replace(/^v/, "")));
}), (!l || l < 46) && m(function I(T) {
var _, Q;
T.source !== p.contentWindow || T.origin !== s || ((_ = T.data) == null ? void 0 : _.type) !== "livecodes-get-config" || (removeEventListener("message", I), (Q = p.contentWindow) == null || Q.postMessage({ type: "livecodes-config", payload: b }, s));
}), p.onload = () => {
i(p);
}, p.src = n.href, L || e.appendChild(p);
}), c = new Promise((i) => {
m(function u(E) {
var L;
E.source !== P.contentWindow || E.origin !== s || ((L = E.data) == null ? void 0 : L.type) !== "livecodes-ready" || (removeEventListener("message", u), i(), c.settled = true);
});
}), f = () => v ? Promise.reject(w) : new Promise(async (i) => {
var E;
c.settled && i();
let u = { type: "livecodes-load" };
(E = P.contentWindow) == null || E.postMessage(u, s), await c, i();
}), t = (i, u) => new Promise(async (E, L) => {
var H;
if (v) return L(w);
await f();
let p = Y();
m(function C(U) {
var R, k;
if (!(U.source !== P.contentWindow || U.origin !== s || ((R = U.data) == null ? void 0 : R.type) !== "livecodes-api-response" || ((k = U.data) == null ? void 0 : k.id) !== p) && U.data.method === i) {
removeEventListener("message", C);
let j = U.data.payload;
j != null && j.error ? L(j.error) : E(j);
}
}), (H = P.contentWindow) == null || H.postMessage({ method: i, id: p, args: u }, s);
}), o = {}, x = ["load", "ready", "code", "console", "tests", "destroy"], a = (i, u) => {
var E;
if (v) throw new Error(w);
return x.includes(i) ? (t("watch", [i]), o[i] || (o[i] = []), (E = o[i]) == null || E.push(u), { remove: () => {
var L, p;
o[i] = (L = o[i]) == null ? void 0 : L.filter((H) => H !== u), ((p = o[i]) == null ? void 0 : p.length) === 0 && t("watch", [i, "unsubscribe"]);
} }) : { remove: () => {
} };
}, G = (i) => ({ "livecodes-app-loaded": "load", "livecodes-ready": "ready", "livecodes-change": "code", "livecodes-console": "console", "livecodes-test-results": "tests", "livecodes-destroy": "destroy" })[i];
m(async function(u) {
var p, H, C, U;
let E = G((H = (p = u.data) == null ? void 0 : p.type) != null ? H : "");
if (u.source !== P.contentWindow || u.origin !== s || !E || !o[E]) return;
let L = (C = u.data) == null ? void 0 : C.payload;
(U = o[E]) == null || U.forEach((R) => {
R(L);
});
});
let X = () => {
var i;
(i = P == null ? void 0 : P.remove) == null || i.call(P), Object.values(o).forEach((u) => {
u.length = 0;
}), O.forEach((u) => removeEventListener("message", u)), O.length = 0, D && e && D.unobserve(e), v = true;
}, D;
M === "lazy" && "IntersectionObserver" in window && (D = new IntersectionObserver((i, u) => {
i.forEach(async (E) => {
E.isIntersecting && (await f(), u.unobserve(e));
});
}, { rootMargin: "150px" }), D.observe(e));
function z(i) {
i.style.position = "absolute", i.style.top = "0", i.style.visibility = "hidden", i.style.opacity = "0";
}
let Y = () => (String(Math.random()) + Date.now().toFixed()).replace("0.", "");
return { load: () => f(), run: () => t("run"), format: (i) => t("format", [i]), getShareUrl: (i) => t("getShareUrl", [i]), getConfig: (i) => t("getConfig", [i]), setConfig: (i) => t("setConfig", [i]), getCode: () => t("getCode"), show: (i, u) => t("show", [i, u]), runTests: () => t("runTests"), onChange: (i) => a("code", i), watch: a, exec: (i, ...u) => t("exec", [i, ...u]), destroy: () => v ? Promise.reject(w) : (X(), Promise.resolve()) };
}
function ae(d = {}) {
let { appUrl: g = "https://livecodes.io", params: b = {}, config: y = {}, headless: M, import: A, lite: r, view: e, ...l } = d, n;
try {
n = new URL(g);
} catch (v) {
throw new Error(`${g} is not a valid URL.`);
}
let s = new URLSearchParams();
Object.entries(l).forEach(([v, w]) => {
w !== void 0 && n.searchParams.set(v, String(w));
});
let h = d.view === "headless" || M;
if (r && (console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`), typeof y == "object" && y.mode == null ? y.mode = "lite" : n.searchParams.set("lite", "true")), e && (console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'), typeof y == "object" && y.view == null && e !== "headless" ? y.view = e : n.searchParams.set("view", e)), typeof y == "string") try {
new URL(y), n.searchParams.set("config", encodeURIComponent(y));
} catch (v) {
throw new Error('"config" is not a valid URL or configuration object.');
}
else y && typeof y == "object" && Object.keys(y).length > 0 && (y.title && y.title !== "Untitled Project" && n.searchParams.set("title", y.title), y.description && y.description.length > 0 && n.searchParams.set("description", y.description), s.set("config", "code/" + (0, W.compressToEncodedURIComponent)(JSON.stringify(y))));
if (b && typeof b == "object" && Object.keys(b).length > 0) try {
s.set("params", (0, W.compressToEncodedURIComponent)(JSON.stringify(b)));
} catch (v) {
Object.keys(b).forEach((w) => {
n.searchParams.set(w, encodeURIComponent(String(b[w])));
});
}
return A && n.searchParams.set("x", encodeURIComponent(A)), h && n.searchParams.set("headless", "true"), s.toString().length > 0 && (n.hash = s.toString()), n.href;
}
// src/reveal.ts
var initIframeStyle = (iframe, styles) => {
for (const [key, value] of Object.entries(styles)) {
iframe.style[key] = value;
}
};
var applyConfigAndSdkFn = async function(sdkItem, sdkReadyfn, config) {
if (typeof config === "string") {
await fetch(config).then((res) => res.json()).then((json) => sdkItem.setConfig(json));
}
if (typeof sdkReadyfn === "function") {
sdkReadyfn(sdkItem);
}
};
var LiveCodes = {
id: "LiveCodes",
init(deck) {
const ContainerList = document.querySelectorAll("[data-livecodes]");
if (ContainerList.length < 1) {
return;
}
const containers = Array.from(ContainerList);
const config = deck.getConfig();
const globalOptions = config.livecodes || {};
const sdkReadyfn = config.livecodes?.sdkReady;
const customStyle = config.customStyle || {};
const promises = containers.map((container) => {
const localOptions = container.dataset.config || "{}";
const parsedLocalOptions = JSON.parse(localOptions);
let finalOptions;
if (typeof globalOptions.config === "string") {
finalOptions = {
...globalOptions,
...parsedLocalOptions,
config: {
...parsedLocalOptions.config
}
};
} else {
finalOptions = {
...globalOptions,
...parsedLocalOptions,
config: {
...globalOptions.config,
...parsedLocalOptions.config
}
};
}
if (typeof finalOptions.config === "object" && Object.keys(finalOptions.config).length === 0) {
delete finalOptions.config;
}
return de(container, finalOptions);
});
Promise.all(promises).then((sdk) => {
const iframes = document.querySelectorAll(".livecodes");
iframes.forEach(
(iframe) => initIframeStyle(iframe, { maxWidth: "100%", maxHeight: "100%", ...customStyle })
);
for (const sdkItem of sdk) {
applyConfigAndSdkFn(sdkItem, sdkReadyfn, globalOptions.config);
}
});
}
};
if (typeof window !== "undefined") {
window.LiveCodes = LiveCodes;
}
export {
LiveCodes
};