Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

livecodes

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

livecodes - npm Package Compare versions

Comparing version
0.13.0
to
0.14.0
+104
LiveCodes.svelte
<script lang="ts">
import { createPlayground, type EmbedOptions, type Playground, type Props } from './svelte.js';
let {
class: className = '',
style = {},
height = undefined,
sdkReady = undefined,
config = undefined,
appUrl = undefined,
import: importUrl = undefined,
headless = undefined,
lite = undefined,
loading = undefined,
params = undefined,
template = undefined,
view = undefined,
}: Props = $props();
let container: HTMLDivElement;
// Internal mutable state — intentionally plain variables (not $state)
// so they don't create reactive dependencies inside the effect.
// We only want the effect to re-run when *props* change.
let playground: Playground | undefined;
let configCache = '';
let otherOptionsCache = '';
function buildOtherOptions() {
const opts: Omit<EmbedOptions, 'config'> = {};
if (appUrl !== undefined) opts.appUrl = appUrl;
if (importUrl !== undefined) opts.import = importUrl;
if (headless !== undefined) opts.headless = headless;
if (lite !== undefined) opts.lite = lite;
if (loading !== undefined) opts.loading = loading;
if (params !== undefined) opts.params = params;
if (template !== undefined) opts.template = template;
if (view !== undefined) opts.view = view;
return opts;
}
function styleToString(obj: Record<string, string>, height?: string): string {
return (
Object.entries(obj)
.filter(([key]) => (key === 'height' && height ? false : true))
.map(([key, val]) => {
const kebab = key.replace(/([A-Z])/g, '-$1').toLowerCase();
return `${kebab}: ${val}`;
})
.join('; ') + (height ? `; height: ${Number(height) ? `${height}px` : height}` : '')
);
}
let styleString = $derived(styleToString(style, height));
let generation = 0;
$effect(() => {
if (!container) return;
const currentConfig = config;
const currentSdkReady = sdkReady;
const otherOptions = buildOtherOptions();
const otherOptionsStr = JSON.stringify(otherOptions);
const configStr = JSON.stringify(currentConfig || '');
const currentGeneration = ++generation;
// avoid race conditions if props change while doing async operation (creating playground)
const isStale = () => currentGeneration !== generation;
if (!playground || otherOptionsCache !== otherOptionsStr) {
otherOptionsCache = otherOptionsStr;
configCache = configStr;
playground?.destroy();
playground = undefined;
createPlayground(container, { config: currentConfig, ...otherOptions }).then((sdk) => {
if (isStale()) {
sdk.destroy();
return;
}
playground = sdk;
if (typeof currentSdkReady === 'function') {
currentSdkReady(sdk);
}
});
} else {
if (configCache === configStr) return;
configCache = configStr;
if (currentConfig) {
playground.setConfig(currentConfig);
}
}
});
$effect(() => {
return () => {
++generation;
playground?.destroy();
};
});
</script>
<div bind:this={container} class={className} style={styleString} data-height={height}></div>
var oe=Object.create;var Q=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ie=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var le=(d,u)=>()=>(u||d((u={exports:{}}).exports,u),u.exports);var ce=(d,u,m,f)=>{if(u&&typeof u=="object"||typeof u=="function")for(let v of se(u))!ae.call(d,v)&&v!==m&&Q(d,v,{get:()=>u[v],enumerable:!(f=re(u,v))||f.enumerable});return d};var de=(d,u,m)=>(m=d!=null?oe(ie(d)):{},ce(u||!d||!d.__esModule?Q(m,"default",{value:d,enumerable:!0}):m,d));var Z=le((be,K)=>{var fe=function(){var d=String.fromCharCode,u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function v(o,r){if(!f[o]){f[o]={};for(var e=0;e<o.length;e++)f[o][o.charAt(e)]=e}return f[o][r]}var x={compressToBase64:function(o){if(o==null)return"";var r=x._compress(o,6,function(e){return u.charAt(e)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(o){return o==null?"":o==""?null:x._decompress(o.length,32,function(r){return v(u,o.charAt(r))})},compressToUTF16:function(o){return o==null?"":x._compress(o,15,function(r){return d(r+32)})+" "},decompressFromUTF16:function(o){return o==null?"":o==""?null:x._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=x.compress(o),e=new Uint8Array(r.length*2),n=0,l=r.length;n<l;n++){var g=r.charCodeAt(n);e[n*2]=g>>>8,e[n*2+1]=g%256}return e},decompressFromUint8Array:function(o){if(o==null)return x.decompress(o);for(var r=new Array(o.length/2),e=0,n=r.length;e<n;e++)r[e]=o[e*2]*256+o[e*2+1];var l=[];return r.forEach(function(g){l.push(d(g))}),x.decompress(l.join(""))},compressToEncodedURIComponent:function(o){return o==null?"":x._compress(o,6,function(r){return m.charAt(r)})},decompressFromEncodedURIComponent:function(o){return o==null?"":o==""?null:(o=o.replace(/ /g,"+"),x._decompress(o.length,32,function(r){return v(m,o.charAt(r))}))},compress:function(o){return x._compress(o,16,function(r){return d(r)})},_compress:function(o,r,e){if(o==null)return"";var n,l,g={},w={},E="",S="",b="",P=2,R=3,c=2,h=[],t=0,s=0,A;for(A=0;A<o.length;A+=1)if(E=o.charAt(A),Object.prototype.hasOwnProperty.call(g,E)||(g[E]=R++,w[E]=!0),S=b+E,Object.prototype.hasOwnProperty.call(g,S))b=S;else{if(Object.prototype.hasOwnProperty.call(w,b)){if(b.charCodeAt(0)<256){for(n=0;n<c;n++)t=t<<1,s==r-1?(s=0,h.push(e(t)),t=0):s++;for(l=b.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}else{for(l=1,n=0;n<c;n++)t=t<<1|l,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=0;for(l=b.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}P--,P==0&&(P=Math.pow(2,c),c++),delete w[b]}else for(l=g[b],n=0;n<c;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1;P--,P==0&&(P=Math.pow(2,c),c++),g[S]=R++,b=String(E)}if(b!==""){if(Object.prototype.hasOwnProperty.call(w,b)){if(b.charCodeAt(0)<256){for(n=0;n<c;n++)t=t<<1,s==r-1?(s=0,h.push(e(t)),t=0):s++;for(l=b.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}else{for(l=1,n=0;n<c;n++)t=t<<1|l,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=0;for(l=b.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}P--,P==0&&(P=Math.pow(2,c),c++),delete w[b]}else for(l=g[b],n=0;n<c;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1;P--,P==0&&(P=Math.pow(2,c),c++)}for(l=2,n=0;n<c;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1;for(;;)if(t=t<<1,s==r-1){h.push(e(t));break}else s++;return h.join("")},decompress:function(o){return o==null?"":o==""?null:x._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,r,e){var n=[],l,g=4,w=4,E=3,S="",b=[],P,R,c,h,t,s,A,i={val:e(0),position:r,index:1};for(P=0;P<3;P+=1)n[P]=P;for(c=0,t=Math.pow(2,2),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;switch(l=c){case 0:for(c=0,t=Math.pow(2,8),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;A=d(c);break;case 1:for(c=0,t=Math.pow(2,16),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;A=d(c);break;case 2:return""}for(n[3]=A,R=A,b.push(A);;){if(i.index>o)return"";for(c=0,t=Math.pow(2,E),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;switch(A=c){case 0:for(c=0,t=Math.pow(2,8),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;n[w++]=d(c),A=w-1,g--;break;case 1:for(c=0,t=Math.pow(2,16),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;n[w++]=d(c),A=w-1,g--;break;case 2:return b.join("")}if(g==0&&(g=Math.pow(2,E),E++),n[A])S=n[A];else if(A===w)S=R+R.charAt(0);else return null;b.push(S),n[w++]=R+S.charAt(0),g--,R=S,g==0&&(g=Math.pow(2,E),E++)}}};return x}();typeof K!="undefined"&&K!=null&&(K.exports=fe)});import{useEffect as me,useRef as he}from"preact/hooks";import{jsx as ye}from"preact/jsx-runtime";var z=de(Z());var ue={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},pe=()=>{if(typeof navigator=="undefined")return"default";let d=navigator.userAgent;return/Firefox\//i.test(d)?"firefox":/Chrome\//i.test(d)?"chrome":"default"},X=()=>ue[pe()].filter(d=>{var m,f,v;let u=(v=(f=(m=globalThis.document)==null?void 0:m.featurePolicy)==null?void 0:f.features)==null?void 0:v.call(f);return u?u.includes(d):!0}).join("; ");async function G(d,u={}){typeof d=="object"&&!(d instanceof HTMLElement)&&(d.headless||d.view==="headless")&&(u=d,d=null);let m=6e4,{config:f={},headless:v,loading:x="lazy",view:o}=u,r=v||o==="headless",e=null,n=null,l=a=>{a.style.position="absolute",a.style.top="0",a.style.visibility="hidden",a.style.opacity="0"};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"),l(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${d}"`);let g=new URL(ge(u)),w=g.origin;g.searchParams.set("embed","true"),g.searchParams.set("loading",r?"eager":x),g.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&g.searchParams.set("config","sdk");let E=u.params;typeof E=="object"&&Object.keys(E).length>0&&JSON.stringify(E).length<1800&&Object.keys(E).forEach(a=>{g.searchParams.set(a,encodeURIComponent(String(E[a])))});let S=!1,b="Cannot call API methods after calling `destroy()`.",P=[],R=(a,p="message")=>{addEventListener(p,a),P.push(a)},c=(a,p="message")=>{removeEventListener(p,a);let C=P.indexOf(a);C>-1&&P.splice(C,1)},t=await new Promise(a=>{var M,H,T,I,_,U,W,B,$;if(!e)return;let p=e.dataset.height||e.style.height;if(p&&!r){let N=isNaN(Number(p))?p:p+"px";e.style.height=N}e.dataset.defaultStyles!=="false"&&!r&&((M=e.style).backgroundColor||(M.backgroundColor="#fff"),(H=e.style).border||(H.border="1px solid black"),(T=e.style).borderRadius||(T.borderRadius="8px"),(I=e.style).boxSizing||(I.boxSizing="border-box"),(_=e.style).padding||(_.padding="0"),(U=e.style).width||(U.width="100%"),(W=e.style).height||(W.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(B=e.style).overflow||(B.overflow="hidden"),($=e.style).resize||($.resize="vertical"),getComputedStyle(e).getPropertyValue("display")==="inline"&&(e.style.display="block"));let C="livecodes",O=e.querySelector(`iframe.${C}`),y=O||document.createElement("iframe");y.classList.add(C),y.setAttribute("allow",X()),y.setAttribute("allowtransparency","true"),y.setAttribute("allowpaymentrequest","true"),y.setAttribute("allowfullscreen","true"),y.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let k=x==="eager"?"eager":"lazy";y.setAttribute("loading",k),r?l(y):(y.style.height="100%",y.style.minHeight="200px",y.style.width="100%",y.style.margin="0",y.style.border="0",y.style.borderRadius=e.style.borderRadius),R(function N(j){var D;j.source!==y.contentWindow||j.origin!==w||((D=j.data)==null?void 0:D.type)!=="livecodes-init"||(c(N),n=Number(j.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&R(function N(j){var D,q;j.source!==y.contentWindow||j.origin!==w||((D=j.data)==null?void 0:D.type)!=="livecodes-get-config"||(c(N),(q=y.contentWindow)==null||q.postMessage({type:"livecodes-config",payload:f},w))}),y.onload=()=>{a(y)},y.src=g.href,O||e.appendChild(y)}),s=new Promise(a=>{R(function p(C){var O;C.source!==t.contentWindow||C.origin!==w||((O=C.data)==null?void 0:O.type)!=="livecodes-ready"||(c(p),a(),s.settled=!0)})}),A=()=>S?Promise.reject(b):new Promise(async a=>{var C;s.settled&&a();let p={type:"livecodes-load"};(C=t.contentWindow)==null||C.postMessage(p,w),await s,a()}),i=(a,p)=>new Promise(async(C,O)=>{var H;if(S)return O(b);await A();let y=ne(),k=setTimeout(()=>{c(M),O(new Error(`SDK call "${a}" timed out after ${m}ms.`))},m);function M(T){var I,_;if(!(T.source!==t.contentWindow||T.origin!==w||((I=T.data)==null?void 0:I.type)!=="livecodes-api-response"||((_=T.data)==null?void 0:_.id)!==y)&&T.data.method===a){clearTimeout(k),c(M);let U=T.data.payload;U!=null&&U.error?O(U.error):C(U)}}R(M),(H=t.contentWindow)==null||H.postMessage({method:a,id:y,args:p},w)}),L={},V=["load","ready","code","console","tests","destroy"],J=(a,p)=>{var C;if(S)throw new Error(b);return V.includes(a)?(i("watch",[a]),L[a]||(L[a]=[]),(C=L[a])==null||C.push(p),{remove:()=>{var O,y;L[a]=(O=L[a])==null?void 0:O.filter(k=>k!==p),((y=L[a])==null?void 0:y.length)===0&&i("watch",[a,"unsubscribe"])}}):{remove:()=>{}}},ee=a=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[a];R(async function(p){var y,k,M,H;let C=ee((k=(y=p.data)==null?void 0:y.type)!=null?k:"");if(p.source!==t.contentWindow||p.origin!==w||!C||!L[C])return;let O=(M=p.data)==null?void 0:M.payload;(H=L[C])==null||H.forEach(T=>{T(O)})});let te=()=>{var a;(a=t==null?void 0:t.remove)==null||a.call(t),Object.values(L).forEach(p=>{p.length=0}),P.forEach(p=>removeEventListener("message",p)),P.length=0,F&&e&&F.unobserve(e),S=!0},F;x==="lazy"&&"IntersectionObserver"in window&&(F=new IntersectionObserver((a,p)=>{a.forEach(async C=>{C.isIntersecting&&(await A(),p.unobserve(e))})},{rootMargin:"150px"}),F.observe(e));let ne=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>A(),run:()=>i("run"),format:a=>i("format",[a]),getShareUrl:a=>i("getShareUrl",[a]),getConfig:a=>i("getConfig",[a]),setConfig:a=>i("setConfig",[a]),getCode:()=>i("getCode"),show:(a,p)=>i("show",[a,p]),runTests:()=>i("runTests"),onChange:a=>J("code",a),watch:J,exec:(a,...p)=>i("exec",[a,...p]),destroy:()=>S?Promise.reject(b):(te(),Promise.resolve())}}function ge(d={}){let{appUrl:u="https://livecodes.io",params:m={},config:f={},headless:v,import:x,lite:o,view:r,...e}=d,n;try{n=new URL(u)}catch(w){throw new Error(`${u} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(e).forEach(([w,E])=>{E!==void 0&&n.searchParams.set(w,String(E))});let g=d.view==="headless"||v;if(o&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":n.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&r!=="headless"?f.view=r:n.searchParams.set("view",r)),typeof f=="string")try{new URL(f),n.searchParams.set("config",encodeURIComponent(f))}catch(w){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&n.searchParams.set("title",f.title),f.description&&f.description.length>0&&n.searchParams.set("description",f.description),l.set("config","code/"+(0,z.compressToEncodedURIComponent)(JSON.stringify(f))));if(m&&typeof m=="object"&&Object.keys(m).length>0)try{l.set("params",(0,z.compressToEncodedURIComponent)(JSON.stringify(m)))}catch(w){Object.keys(m).forEach(E=>{n.searchParams.set(E,encodeURIComponent(String(m[E])))})}return x&&n.searchParams.set("x",encodeURIComponent(x)),g&&n.searchParams.set("headless","true"),l.toString().length>0&&(n.hash=l.toString()),n.href}function Y(d){let{useEffect:u,useRef:m}=d;return function(v){let x=m(null),o=m(void 0),r=m(""),e=m(""),n=m(0),l=m(!1),g=v.className||"",w=v.style||{},E=v.height&&Number(v.height)?`${v.height}px`:v.height;return u(()=>{var i;if(!x.current)return;let{className:S,style:b,height:P,sdkReady:R,config:c,...h}=v,t=++n.current,s=()=>n.current!==t||l.current,A=JSON.stringify(h);if(!o.current||e.current!==A)e.current=A,r.current=JSON.stringify(c),(i=o.current)==null||i.destroy(),o.current=void 0,G(x.current,{config:c,...h}).then(L=>{if(s()){L.destroy();return}o.current=L,typeof R=="function"&&R(L)});else{let L=JSON.stringify(c);if(r.current===L)return;r.current=L,c&&o.current.setConfig(c)}},[v]),u(()=>()=>{var S;l.current=!0,(S=o.current)==null||S.destroy(),o.current=void 0},[]),{containerRef:x,className:g,style:w,height:E}}}var ve=Y({useEffect:me,useRef:he});function we(d){let{containerRef:u,className:m,style:f,height:v}=ve(d);return ye("div",{ref:u,className:m,style:{...f,...v?{height:v}:{}},"data-height":v})}export{we as default};
---
name: livecodes/configuration
description: >
Configure playground behavior through Config object, query parameters, EmbedOptions,
editor settings, processors, external resources, and custom settings. Load this skill
when setting up project content, configuring CSS processors, or customizing display.
type: core
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:docs/docs/configuration/configuration-object.mdx
- live-codes/livecodes:docs/docs/configuration/query-params.mdx
- live-codes/livecodes:src/sdk/models.ts
---
# LiveCodes — Configure Playground
LiveCodes uses configuration objects to define project content and behavior. Config can be passed to `createPlayground` or set via URL parameters.
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Full config object
createPlayground('#container', {
config: {
title: 'My Project',
markup: { language: 'html', content: '<h1>Hello</h1>' },
style: { language: 'css', content: 'h1 { color: blue; }' },
script: { language: 'javascript', content: 'console.log("hi")' },
activeEditor: 'script',
},
});
// Query params (simpler syntax)
createPlayground('#container', {
params: {
html: '<h1>Hello</h1>',
css: 'h1 { color: blue; }',
js: 'console.log("hi")',
console: 'open',
},
});
```
## Core Patterns
### Configure each editor
```javascript
const config = {
markup: {
language: 'markdown',
content: '# Title\n\nParagraph',
contentUrl: 'https://example.com/content.md', // Alternative to content
},
style: {
language: 'scss',
content: '$color: blue; h1 { color: $color; }',
},
script: {
language: 'typescript',
content: 'const x: number = 1;',
hiddenContent: 'export function helper() {}', // Hidden but evaluated
},
};
```
### Enable CSS processors
```javascript
const config = {
style: { language: 'css', content: '...' },
processors: ['tailwindcss', 'autoprefixer'], // Processors run in order
};
```
### Add external resources
```javascript
const config = {
stylesheets: ['https://cdn.jsdelivr.net/npm/tailwindcss@3/dist/tailwind.min.css'],
scripts: ['https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js'],
};
```
### Configure tests
```javascript
const config = {
tests: {
language: 'typescript',
content: `
import { sum } from './script';
test('sums numbers', () => {
expect(sum(1, 2)).toBe(3);
});
`,
},
};
```
### Set display mode
```javascript
const config = {
mode: 'simple', // 'full' | 'focus' | 'simple' | 'lite' | 'editor' | 'codeblock' | 'result'
view: 'result', // 'split' | 'editor' | 'result'
readonly: true, // Read-only mode
};
```
### Configure editor settings
```javascript
const config = {
editor: 'monaco', // 'monaco' | 'codemirror' | 'codejar' | 'auto'
theme: 'dark', // 'light' | 'dark'
editorTheme: 'vs-dark', // See themes in docs
fontFamily: 'Fira Code',
fontSize: 14,
useTabs: false,
tabSize: 2,
lineNumbers: true,
wordWrap: false,
emmet: true,
editorMode: 'vim', // 'vim' | 'emacs' | undefined
};
```
### Add custom imports
```javascript
const config = {
imports: {
'my-lib': 'https://my-cdn.com/lib.js',
'my-lib/submodule': 'https://my-cdn.com/sub.js',
},
};
```
### Use URL query parameters
URL: `https://livecodes.io/?js=console.log("Hello")&console=open&theme=light`
```javascript
// Equivalent in createPlayground
createPlayground('#container', {
params: {
js: 'console.log("Hello")',
console: 'open',
theme: 'light',
},
});
```
### Hidden content for embedded playgrounds
```javascript
const config = {
script: {
language: 'javascript',
content: 'export function myFunc() { return 42; }',
hiddenContent: '// Hidden helper\nfunction helper() { return 1; }',
},
tests: {
language: 'javascript',
content: "import { myFunc } from './script';\ntest('works', () => expect(myFunc()).toBe(42))",
},
};
```
## Common Mistakes
### HIGH Confusing Config with EmbedOptions
Wrong:
```javascript
createPlayground('#container', {
config: {
appUrl: 'https://my-server.com', // Wrong: appUrl belongs in EmbedOptions
template: 'react', // Wrong: template belongs in EmbedOptions
},
});
```
Correct:
```javascript
createPlayground('#container', {
// EmbedOptions (SDK-level settings)
appUrl: 'https://my-server.com',
template: 'react',
loading: 'lazy',
headless: false,
// Config (Project content)
config: {
title: 'My Project',
markup: { language: 'html', content: '<h1>Hello</h1>' },
style: { language: 'css', content: '...' },
script: { language: 'javascript', content: '...' },
},
});
```
`EmbedOptions` controls how the playground is embedded (appUrl, template, loading, headless). `Config` controls the project content (languages, code, processors).
Source: docs/docs/sdk/js-ts.mdx — EmbedOptions section
### MEDIUM Params overriding config unexpectedly
Wrong:
```javascript
createPlayground('#container', {
config: {
markup: { language: 'html', content: '<h1>A</h1>' },
},
params: {
html: '<h1>B</h1>', // This overrides config.markup!
},
});
```
Correct:
```javascript
// Use one source or understand precedence:
// params > config > import > template
createPlayground('#container', {
params: {
html: '<h1>B</h1>',
},
// No config needed for simple cases
});
// Or use config only
createPlayground('#container', {
config: {
markup: { language: 'html', content: '<h1>A</h1>' },
},
});
```
When both `config` and `params` are provided, `params` takes precedence. Use one or the other for clarity.
Source: docs/docs/sdk/js-ts.mdx — Multiple Sources section
### MEDIUM Using incorrect language name
Wrong:
```javascript
const config = {
script: { language: 'react.js', content: '...' }, // Invalid
};
```
Correct:
```javascript
// Use language name, extension, or alias
const config = {
script: { language: 'react', content: '...' }, // Language name
// or
script: { language: 'jsx', content: '...' }, // Extension
// or
script: { language: 'react-jsx', content: '...' }, // Alias
};
```
Language names must match supported values. See languages reference for all options.
Source: src/sdk/models.ts — Language type
## Config Reference
### Project Content
| Property | Type | Default | Description |
| -------------- | --------------------------------- | ---------------------- | ---------------------------------------- |
| `title` | `string` | `"Untitled Project"` | Project title, used as result page title |
| `description` | `string` | `""` | Project description, used in search |
| `head` | `string` | `"<meta charset...>"` | Custom content for `<head>` element |
| `htmlAttrs` | `string \| object` | `'lang="en" class=""'` | Attributes for `<html>` element |
| `tags` | `string[]` | `[]` | Project tags for filtering/search |
| `activeEditor` | `"markup" \| "style" \| "script"` | `"markup"` | Which editor is visible |
| `languages` | `Language[]` | all languages | Enabled languages in editor dropdown |
### Editor Content (`markup`, `style`, `script`, `tests`)
Each editor config object supports:
| Property | Type | Default | Description |
| ------------------ | ----------------------- | ------------------ | --------------------------------------- |
| `language` | `Language` | (varies by editor) | Language name, extension, or alias |
| `content` | `string` | `""` | Initial code content |
| `contentUrl` | `string` | — | URL to load content from |
| `hiddenContent` | `string` | — | Hidden code (evaluated but not visible) |
| `hiddenContentUrl` | `string` | — | URL to load hidden content |
| `foldedLines` | `Array<{from, to}>` | — | Lines to fold on load |
| `title` | `string` | — | Override editor title |
| `hideTitle` | `boolean` | — | Hide editor title |
| `order` | `number` | `0` | Editor order in UI |
| `selector` | `string` | — | CSS selector for DOM import |
| `position` | `{lineNumber, column?}` | — | Initial cursor position |
### External Resources
| Property | Type | Default | Description |
| ------------- | -------------------------------------- | ------- | ------------------------------------------------ |
| `stylesheets` | `string[]` | `[]` | URLs for external CSS |
| `scripts` | `string[]` | `[]` | URLs for external JS |
| `cssPreset` | `"" \| "normalize.css" \| "reset-css"` | `""` | CSS preset to apply |
| `processors` | `Processor[]` | `[]` | CSS processors (tailwindcss, autoprefixer, etc.) |
### Module Resolution
| Property | Type | Default | Description |
| --------- | ---------------------------------- | ------- | --------------------------------------- |
| `imports` | `Record<string, string>` | `{}` | Custom import map for module resolution |
| `types` | `Record<string, string \| object>` | `{}` | Custom TypeScript type declarations |
### App Settings
| Property | Type | Default | Description |
| ----------------- | -------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------ |
| `readonly` | `boolean` | `false` | Read-only mode |
| `allowLangChange` | `boolean` | `true` | Allow changing editor language |
| `view` | `"split" \| "editor" \| "result"` | `"split"` | Default view |
| `mode` | `"full" \| "focus" \| "simple" \| "lite" \| "editor" \| "codeblock" \| "result"` | `"full"` | Display mode |
| `tools` | `object` | `{enabled: "all", active: "", status: ""}` | Tools pane config |
| `zoom` | `1 \| 0.5 \| 0.25` | `1` | Result page zoom level |
### User Settings
| Property | Type | Default | Description |
| ---------------- | -------------------------------------------- | ---------------------- | ------------------------------------------ |
| `autoupdate` | `boolean` | `true` | Auto-run result on code change |
| `autosave` | `boolean` | `false` | Auto-save on code change |
| `autotest` | `boolean` | `false` | Auto-run tests on code change |
| `delay` | `number` | `1500` | Delay before autoupdate/autosave (ms) |
| `formatOnsave` | `boolean` | `false` | Format code on save |
| `layout` | `"horizontal" \| "vertical" \| "responsive"` | `"responsive"` | Editor layout |
| `theme` | `"light" \| "dark"` | `"dark"` | App theme |
| `themeColor` | `string` | `"hsl(214, 40%, 50%)"` | App theme color |
| `editorTheme` | `string \| string[]` | — | Editor themes (see docs) |
| `appLanguage` | `string` | — | UI language code (e.g., `"ar"`, `"zh-CN"`) |
| `recoverUnsaved` | `boolean` | `true` | Enable recovery of unsaved project |
| `welcome` | `boolean` | `true` | Show welcome screen |
| `showSpacing` | `boolean` | `false` | Show element spacing in result |
### Editor Settings
| Property | Type | Default | Description |
| --------------- | ------------------------------------------------- | -------------------------- | --------------------------------- |
| `editor` | `"monaco" \| "codemirror" \| "codejar" \| "auto"` | — | Code editor to use |
| `fontFamily` | `string` | — | Editor font family |
| `fontSize` | `number` | `14` (full) / `12` (embed) | Editor font size |
| `useTabs` | `boolean` | `false` | Use tabs instead of spaces |
| `tabSize` | `number` | `2` | Spaces per indent level |
| `lineNumbers` | `boolean \| "relative"` | `true` | Show line numbers |
| `wordWrap` | `boolean` | `false` | Enable word wrap |
| `closeBrackets` | `boolean` | `true` | Auto-close brackets/quotes |
| `foldRegions` | `boolean` | `false` | Fold #region blocks on load |
| `minimap` | `boolean` | `false` | Show minimap (Monaco) |
| `emmet` | `boolean` | `true` | Enable Emmet |
| `editorMode` | `"vim" \| "emacs"` | — | Editor key bindings |
| `semicolons` | `boolean` | `true` | Use semicolons in formatting |
| `singleQuote` | `boolean` | `true` | Use single quotes in formatting |
| `trailingComma` | `boolean` | `true` | Use trailing commas in formatting |
## EmbedOptions Reference
| Property | Type | Default | Description |
| ---------- | ------------------------------ | ------------------------- | ------------------------------------ |
| `appUrl` | `string` | `"https://livecodes.io/"` | URL to self-hosted LiveCodes |
| `config` | `Config \| string` | `{}` | Project config or URL to config JSON |
| `template` | `string` | — | Starter template name |
| `import` | `string` | — | URL to import code from |
| `params` | `object` | `{}` | URL query parameters |
| `loading` | `"eager" \| "lazy" \| "click"` | `"lazy"` | When to load playground |
| `headless` | `boolean` | `false` | Run without UI |
## Query Parameters
Many config options can be set via URL parameters:
```
https://livecodes.io/?template=react&theme=light&console=open
```
| Param | Config Equivalent |
| ------------- | --------------------------------- |
| `template` | `EmbedOptions.template` |
| `x` | `EmbedOptions.import` |
| `files` | Files to import (comma-separated) |
| `raw` | Import URL as raw language |
| `active` | `activeEditor` |
| `mode` | `mode` |
| `theme` | `theme` |
| `console` | `tools.status` |
| `no-defaults` | Skip default template |
Boolean params: `?lite`, `?autoupdate=false`
Array params: `?processors=tailwindcss,autoprefixer`
Custom settings: `?customSettings.template.prerender=false`
---
name: livecodes/display-modes
description: >
Configure how the playground is displayed: full, focus, simple, lite, editor,
codeblock, and result modes. Load this skill when choosing display mode for
embeddings, configuring read-only views, or showing only result or editor.
type: core
library: livecodes
library_version: 0.13.0
requires:
- configuration
sources:
- live-codes/livecodes:docs/docs/features/display-modes.mdx
- live-codes/livecodes:docs/docs/features/lite.mdx
---
This skill builds on configuration. Read it first for foundational concepts.
# LiveCodes — Display Modes
Display modes control what UI elements are shown in the playground. Choose mode based on your embedding use case.
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Via config object
createPlayground('#container', {
config: { mode: 'simple' },
});
// Via query params
createPlayground('#container', {
params: { mode: 'result' },
});
// Via URL
// https://livecodes.io/?mode=lite&template=react
```
## Core Patterns
### Full mode (default)
Complete playground with toolbars, all editors, result pane.
```javascript
// Default mode - no need to specify
createPlayground('#container', {
template: 'react',
});
// Mode is 'full' by default
```
### Simple mode (embeds)
One editor + result. Ideal for embedded playgrounds with limited space.
```javascript
createPlayground('#container', {
config: {
mode: 'simple',
layout: 'vertical', // 'vertical' or 'horizontal'
activeEditor: 'script',
editor: 'monaco', // 'monaco' or 'codemirror' (default)
},
params: {
js: 'console.log("Hello")',
console: 'open',
},
});
// With style editor
createPlayground('#container', {
config: {
mode: 'simple',
layout: 'vertical',
activeEditor: 'script',
editor: 'monaco',
},
});
```
### Lite mode
Lightweight editor for faster loading. Minimal features.
```javascript
createPlayground('#container', {
config: { mode: 'lite' },
template: 'react',
});
// Via URL
// https://livecodes.io/?mode=lite&template=react
```
Lite mode features:
- Uses CodeJar editor (light-weight)
- No minimap, no advanced autocomplete
- Still supports all languages
- Faster initial load
### Editor mode (code only)
No result pane. Shows only the editors.
```javascript
createPlayground('#container', {
config: { mode: 'editor' },
template: 'react',
});
```
Use for:
- Code review interfaces
- Teaching code patterns
- Read-only snippet viewers
### Codeblock mode (read-only)
Static code display with copy button on hover. No editing.
```javascript
createPlayground('#container', {
config: {
mode: 'codeblock',
editor: 'monaco', // Optional: use Monaco instead of CodeJar
},
params: { html: '<h1>Hello World</h1>' },
});
```
Use for:
- Blog posts with code snippets
- Documentation
- One-way code display
### Result mode (output only)
Shows only the result page with a drawer to open in full playground.
```javascript
createPlayground('#container', {
params: {
mode: 'result',
template: 'react',
},
});
// Show console in result mode
createPlayground('#container', {
params: {
mode: 'result',
tools: 'console|full',
js: 'console.log("Hello World")',
},
});
```
Use for:
- Demo showcase
- Embedded output
- Presentations
### Focus mode
Minimal UI: editors, result, console only. No menus or secondary controls.
```javascript
createPlayground('#container', {
config: { mode: 'focus' },
});
```
Toggle between focus and full in the app UI. Access via button in bottom-left corner.
## Display Mode vs Default View
| Concept | What it controls |
| ------- | ------------------------------ |
| Mode | What UI elements are loaded |
| View | Which pane is shown by default |
```javascript
// Mode: 'editor' - Only editors exist, no result pane
createPlayground('#container', {
config: { mode: 'editor' },
});
// Mode: 'full', View: 'editor' - All UI, editors shown by default
createPlayground('#container', {
config: {
mode: 'full', // Full UI
view: 'editor', // Show editors first
},
});
```
## Common Mistakes
### MEDIUM Confusing mode with view
Wrong:
```javascript
// Want to show result by default but use full UI
createPlayground('#container', {
config: { mode: 'result' }, // Result mode - no editors!
});
```
Correct:
```javascript
// Use view for default visible pane
createPlayground('#container', {
config: {
mode: 'full', // Full UI with all elements
view: 'result', // Show result by default
},
});
```
`mode` determines what elements exist. `view` determines which element is visible first.
Source: docs/docs/features/display-modes.mdx — Display Mode vs Default View section
### MEDIUM Tools not visible in result mode
```javascript
// Console won't show in result mode by default
createPlayground('#container', {
params: {
mode: 'result',
js: 'console.log("Hello")',
},
});
```
Correct:
```javascript
// Set tools to 'open' or 'full' in result mode
createPlayground('#container', {
params: {
mode: 'result',
tools: 'console|full', // Show console in full height
js: 'console.log("Hello")',
},
});
```
In result mode, tools pane is hidden by default. Set `tools: 'console|open'` or `tools: 'console|full'` to show it.
Source: docs/docs/features/display-modes.mdx — Result mode section
## Mode Reference
| Mode | Shows | Use Case |
| ----------- | -------------------------- | --------------------------- |
| `full` | All UI (default) | Full playground experience |
| `focus` | Editors + result + console | Minimal distractions |
| `simple` | One editor + result | Compact embeds |
| `lite` | Lightweight editor | Fast loading, basic editing |
| `editor` | Only editors | Code review, teaching |
| `codeblock` | Static code with copy | Read-only snippets |
| `result` | Only result page | Demo showcase |
## View Reference
| View | Description |
| -------- | ----------------------------------------- |
| `split` | Editors and result side by side (default) |
| `editor` | Editors visible, result hidden |
| `result` | Result visible, editors hidden |
## Tools Configuration
```javascript
const config = {
tools: {
enabled: ['console', 'compiled'], // or 'all'
active: 'console', // Which tool is open
status: 'open', // 'open', 'full', 'closed', 'none'
},
};
// Via params
params: {
tools: 'console|open', // Console open
tools: 'compiled|full', // Compiled code, full height
console: 'open', // Shorthand for console
}
```
---
name: livecodes/framework-wrappers
description: >
Use SDK with React, Vue, Svelte, Solid, Preact, and Web Components.
sdkReady callback pattern, reactive props, and framework-specific setup.
Load this skill when embedding LiveCodes in a framework application.
type: framework
library: livecodes
library_version: 0.13.0
requires:
- sdk-embedding
- sdk-methods
sources:
- live-codes/livecodes:docs/docs/sdk/react.mdx
- live-codes/livecodes:docs/docs/sdk/vue.mdx
- live-codes/livecodes:docs/docs/sdk/svelte.mdx
- live-codes/livecodes:docs/docs/sdk/solid.mdx
- live-codes/livecodes:docs/docs/sdk/preact.mdx
- live-codes/livecodes:docs/docs/sdk/web-components.mdx
- live-codes/livecodes:src/sdk/react.tsx
- live-codes/livecodes:src/sdk/vue.ts
---
This skill builds on sdk-embedding and sdk-methods. Read them first for foundational concepts about createPlayground, SDK methods, and configuration.
# LiveCodes — Framework SDK Wrappers
LiveCodes provides framework-specific components that wrap the core SDK. Each wrapper handles lifecycle, reactivity, and props.
## React
```jsx
import LiveCodes from 'livecodes/react';
// Basic usage
function App() {
return <LiveCodes template="react" />;
}
// With config
function App() {
const config = {
markup: { language: 'markdown', content: '# Hello World' },
};
return <LiveCodes config={config} height="400px" />;
}
// Access SDK methods via sdkReady
function App() {
const [playground, setPlayground] = useState(null);
const handleRun = async () => {
await playground?.run();
};
return (
<>
<LiveCodes
template="react"
sdkReady={setPlayground}
/>
<button onClick={handleRun}>Run</button>
</>
);
}
// TypeScript
import LiveCodes, { type Props } from 'livecodes/react';
const options: Props = {
config: { /* ... */ },
height: '500px',
};
export default () => <LiveCodes {...options} />;
```
### React: Available Props
| Prop | Type | Description |
| ---------------- | --------------------------- | -------------------------- |
| All EmbedOptions | — | Pass EmbedOptions as props |
| `className` | `string` | Container class name |
| `height` | `string` | Container height |
| `style` | `object` | Container styles |
| `sdkReady` | `(sdk: Playground) => void` | Callback with SDK instance |
### React: Reactive Props
```jsx
function App() {
const [config, setConfig] = useState({
markup: { language: 'html', content: '<h1>Hello</h1>' },
});
// Changing config uses setConfig() - no full reload
const switchToMarkdown = () => {
setConfig({
markup: { language: 'markdown', content: '# Hello' },
});
};
// Changing other props causes full reload
// <LiveCodes template={template} /> // changing template reloads
return (
<>
<LiveCodes config={config} />
<button onClick={switchToMarkdown}>Switch to Markdown</button>
</>
);
}
```
## Vue
```vue
<script setup>
import LiveCodes from 'livecodes/vue';
const config = {
markup: { language: 'markdown', content: '# Hello World' },
};
let playground;
const onReady = (sdk) => {
playground = sdk;
};
const run = async () => {
await playground?.run();
};
</script>
<template>
<LiveCodes :config="config" @sdk-ready="onReady" />
<button @click="run">Run</button>
</template>
<!-- With TypeScript -->
<script setup lang="ts">
import LiveCodes, { type Props } from 'livecodes/vue';
import type { Playground } from 'livecodes';
const options: Props = {
config: {
/* ... */
},
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
```
### Vue: Available Props
| Prop | Type | Description |
| ---------------- | -------- | -------------------------- |
| All EmbedOptions | — | Pass EmbedOptions as props |
| `height` | `string` | Container height |
### Vue: Events
| Event | Payload |
| ------------ | --------------------------- |
| `@sdk-ready` | `(sdk: Playground) => void` |
### Vue: Reactive Props
```vue
<script setup>
import { ref } from 'vue';
import LiveCodes from 'livecodes/vue';
const config = ref({
markup: { language: 'html', content: '<h1>Hello</h1>' },
});
// Uses setConfig() - no reload
const switchToMarkdown = () => {
config.value = {
markup: { language: 'markdown', content: '# Hello' },
};
};
</script>
<template>
<LiveCodes :config="config" />
<button @click="switchToMarkdown">Switch</button>
</template>
```
## Svelte
```svelte
<script>
import LiveCodes from 'livecodes/svelte';
let playground;
const config = {
markup: { language: 'markdown', content: '# Hello World' },
};
function onReady(sdk) {
playground = sdk;
}
async function run() {
await playground?.run();
}
</script>
<LiveCodes {config} on:sdkReady={onReady} />
<button on:click={run}>Run</button>
```
## Solid
```tsx
import LiveCodes from 'livecodes/solid';
import { createSignal } from 'solid-js';
function App() {
const [playground, setPlayground] = createSignal(null);
const config = {
markup: { language: 'markdown', content: '# Hello World' },
};
const handleRun = async () => {
await playground()?.run();
};
return (
<>
<LiveCodes config={config} sdkReady={setPlayground} />
<button onClick={handleRun}>Run</button>
</>
);
}
```
## Preact
```tsx
import LiveCodes from 'livecodes/preact';
import { useState } from 'preact/hooks';
function App() {
const [playground, setPlayground] = useState(null);
const handleRun = async () => {
await playground?.run();
};
return (
<>
<LiveCodes template="react" sdkReady={setPlayground} />
<button onClick={handleRun}>Run</button>
</>
);
}
```
## Web Components
```html
<script src="https://cdn.jsdelivr.net/npm/livecodes/web-components.js"></script>
<!-- Basic usage -->
<live-codes template="react"></live-codes>
<!-- With config property -->
<live-codes height="400px"></live-codes>
<script>
const playground = document.querySelector('live-codes');
playground.config = {
markup: { language: 'markdown', content: '# Hello' },
};
</script>
```
### Web Components: Declarative Code via Children
The web component supports providing code declaratively as child elements inside a wrapper `<template>`. This avoids JavaScript string escaping and enables IDE syntax highlighting.
The outer `<template>` makes inner `<style>` and `<script>` elements inert (no side effects on the embedding page).
#### Single-Editor Mode
```html
<live-codes height="400px">
<template>
<template lang="html">
<h1>Hello World</h1>
<p>Welcome to <strong>LiveCodes</strong></p>
</template>
<style lang="scss">
body {
font-family: sans-serif;
h1 {
color: royalblue;
}
}
</style>
<script lang="ts">
console.log('Hello from TypeScript!');
</script>
</template>
</live-codes>
```
If `lang` is omitted, defaults are `html`, `css`, and `javascript`.
#### Active Editor
Use the `active` boolean attribute to set the initially focused editor:
```html
<live-codes>
<template>
<template lang="html"><h1>Hello</h1></template>
<script lang="ts" active>
console.log('focused');
</script>
</template>
</live-codes>
```
#### Config and Params Attributes
Use `config` and `params` HTML attributes as JSON strings for non-code settings:
```html
<live-codes config='{"processors": ["tailwindcss"]}' params='{"console": "open"}'>
<template>
<template lang="html"><h1 class="text-3xl">Hello</h1></template>
</template>
</live-codes>
```
#### Merge Precedence
When combining children, config attribute, and config property:
1. **`config` property** (highest — explicit programmatic override)
2. **Children** (declarative defaults)
3. **`config` attribute** (lowest — inline JSON settings)
Same for `params`: attribute is merged with property, property wins for overlapping keys.
#### Reactivity
Children content is reactive. Changing content inside the wrapper `<template>` programmatically triggers `setConfig()`:
```html
<live-codes id="demo">
<template>
<style lang="css">
h1 {
color: blue;
}
</style>
</template>
</live-codes>
<script>
function changeColor() {
const wrapper = document.querySelector('#demo > template');
wrapper.content.querySelector('style').textContent = 'h1 { color: red; }';
// MutationObserver detects this → setConfig() called
}
</script>
```
## Common Mistakes
### HIGH Not using sdkReady to access SDK in frameworks
Wrong (React):
```jsx
function App() {
// No way to get SDK reference
return <LiveCodes template="react" />;
}
function handleRun() {
// Where's playground? Can't access SDK methods
playground.run(); // Error: playground is undefined
}
```
Correct (React):
```jsx
function App() {
const [playground, setPlayground] = useState(null);
const handleRun = async () => {
await playground?.run();
};
return (
<>
<LiveCodes template="react" sdkReady={setPlayground} />
<button onClick={handleRun}>Run</button>
</>
);
}
```
Correct (Vue):
```vue
<script setup>
import LiveCodes from 'livecodes/vue';
import { ref } from 'vue';
const playground = ref(null);
const onReady = (sdk) => {
playground.value = sdk;
};
</script>
<template>
<LiveCodes template="vue" @sdk-ready="onReady" />
</template>
```
The SDK is only available after the playground initializes. Use `sdkReady` (React), `@sdk-ready` (Vue), or `on:sdkReady` (Svelte) to get a reference.
Source: docs/docs/sdk/react.mdx, docs/docs/sdk/vue.mdx — sdkReady section
### MEDIUM Changing non-config props causes full reload
```jsx
// React - config changes use setConfig (no reload)
const [config, setConfig] = useState(initialConfig);
setConfig(newConfig); // Efficient update, no iframe reload
// React - other prop changes cause full reload
const [template, setTemplate] = useState('react');
setTemplate('vue'); // Destroys and recreates iframe
```
Changing `config` prop uses SDK's `setConfig()` method under the hood — efficient. Changing other props (`template`, `params`, `loading`) destroys and recreates the iframe.
If you need reactive changes, prefer updating `config` over changing other props.
Source: docs/docs/sdk/react.mdx — Reactive Props section
## Framework Installation
```bash
# React
npm install livecodes
import LiveCodes from 'livecodes/react';
# Vue 3
npm install livecodes
import LiveCodes from 'livecodes/vue';
# Svelte
npm install livecodes
import LiveCodes from 'livecodes/svelte';
# Solid
npm install livecodes
import LiveCodes from 'livecodes/solid';
# Preact
npm install livecodes
import LiveCodes from 'livecodes/preact';
# Web Components (CDN)
<script src="https://cdn.jsdelivr.net/npm/livecodes/web-components.js"></script>
```
## Exported Types
All frameworks export:
- `Props` — EmbedOptions plus framework-specific props
- `Playground` — SDK Playground interface
- `Config` — Configuration type
- `Code` — Code object type
- `Language` — Language string type
---
name: livecodes/getting-started
description: >
Quick start for standalone app at livecodes.io, embedding playgrounds with CDN or npm,
and self-hosting basics. Load this skill for initial setup and basic usage patterns.
type: lifecycle
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:README.md
- live-codes/livecodes:docs/docs/getting-started.mdx
---
# LiveCodes — Get Started
LiveCodes is a client-side code playground that runs in the browser. No server, no build step, no `npm install`.
## Quick Start
### Standalone App
1. Go to [livecodes.io](https://livecodes.io)
2. Start coding with 90+ languages
### Embedded Playground (CDN)
```html
<div id="container"></div>
<script type="module">
import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes';
createPlayground('#container', {
params: {
markdown: '# Hello LiveCodes!',
css: 'h1 { color: dodgerblue; }',
js: 'console.log("Hello, from JS!");',
console: 'open',
},
});
</script>
```
### Embedded Playground (npm)
```bash
npm install livecodes
```
```javascript
import { createPlayground } from 'livecodes';
createPlayground('#container', {
template: 'react',
});
```
### Self-Hosted
1. Download from [GitHub releases](https://github.com/live-codes/livecodes/releases)
2. Host on any static server (GitHub Pages, Netlify, Cloudflare Pages, etc.)
3. Point SDK to your instance:
```javascript
import { createPlayground } from 'livecodes';
createPlayground('#container', {
appUrl: 'https://your-domain.com/livecodes',
template: 'react',
});
```
## Basic Patterns
### Use a template
```javascript
createPlayground('#container', {
template: 'react', // react, vue, svelte, solid, angular, etc.
});
// Available templates:
// blank, javascript, typescript, react, react-native, vue, vue2, angular,
// preact, svelte, solid, lit, stencil, mdx, astro, jest, tailwindcss, python, ...
```
### Custom code
```javascript
createPlayground('#container', {
config: {
markup: {
language: 'markdown',
content: '# Hello World',
},
style: {
language: 'css',
content: 'h1 { color: blue; }',
},
script: {
language: 'javascript',
content: 'console.log("Hello!");',
},
activeEditor: 'script',
},
params: { console: 'open' },
});
```
### Generate shareable URL
```javascript
import { getPlaygroundUrl } from 'livecodes';
const url = getPlaygroundUrl({
config: {
markup: { language: 'markdown', content: '# Hello' },
},
});
// Share this URL
window.open(url);
```
### Permanent URL (pinned version)
For stable embeds that won't break with updates:
```javascript
// Use a specific version
createPlayground('#container', {
appUrl: 'https://v48.livecodes.io', // Permanent URL
template: 'react',
});
// SDK version pinning
import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes@0.13.0';
```
## Common Patterns by Use Case
### Documentation site embed
```javascript
// Minimal embed for docs
createPlayground('#container', {
params: {
js: `console.log("Hello World")`,
console: 'open',
},
loading: 'lazy', // Load when visible
});
// Or use markdown plugins (remark-livecodes, etc.)
// See: markdown-integration skill
```
### Blog post with code example
```javascript
// Simple, focused display
createPlayground('#container', {
config: {
mode: 'simple',
layout: 'vertical',
},
params: {
html: '<h1>Hello</h1>',
css: 'h1 { color: blue; }',
},
});
```
### Teaching/Tutorial
```javascript
// Show code with tests
createPlayground('#container', {
template: 'jest',
params: { tests: 'open' },
});
// Read-only code review
createPlayground('#container', {
config: {
mode: 'codeblock',
readonly: true,
},
params: { html: '<h1>Review this code</h1>' },
});
```
### Demo showcase
```javascript
// Result only
createPlayground('#container', {
params: {
mode: 'result',
template: 'react',
},
});
// Demo with console
createPlayground('#container', {
params: {
mode: 'result',
tools: 'console|full',
js: 'console.log("Demo output")',
},
});
```
## Framework Quick Start
### React
```jsx
import LiveCodes from 'livecodes/react';
export default function App() {
return <LiveCodes template="react" height="400px" />;
}
```
### Vue
```vue
<script setup>
import LiveCodes from 'livecodes/vue';
</script>
<template>
<LiveCodes template="vue" height="400px" />
</template>
```
### Svelte
```svelte
<script>
import LiveCodes from 'livecodes/svelte';
</script>
<LiveCodes template="svelte" height="400px" />
```
### Solid
```tsx
import LiveCodes from 'livecodes/solid';
function App() {
return <LiveCodes template="solid" height="400px" />;
}
```
### Web Components
```html
<script src="https://cdn.jsdelivr.net/npm/livecodes/web-components.js"></script>
<live-codes template="react" height="400px"></live-codes>
```
## Available Templates
| Template | Description |
| ------------- | ---------------------------- |
| `blank` | Empty project |
| `javascript` | Vanilla JavaScript |
| `typescript` | TypeScript |
| `react` | React |
| `vue` | Vue 3 SFC |
| `svelte` | Svelte SFC |
| `solid` | Solid |
| `angular` | Angular |
| `preact` | Preact |
| `tailwindcss` | Tailwind CSS |
| `bootstrap` | Bootstrap |
| `python` | Python |
| `python-wasm` | Python (WASM) |
| `jest` | Jest tests |
| `jest-react` | Jest + React Testing Library |
See [Full Template List](https://livecodes.io/docs/api/internal/type-aliases/TemplateName/) for all 70+ templates.
## Next Steps
- **Embed playgrounds**: Read `sdk-embedding` skill
- **Control via SDK**: Read `sdk-methods` skill
- **Configure behavior**: Read `configuration` skill
- **Use languages**: Read `language-support` skill
- **Import npm modules**: Read `module-resolution` skill
- **Self-host**: Read `self-hosting` skill
- **Integrate with docs**: Read `markdown-integration` skill
---
name: livecodes/gh-action
description: >
Use the "Preview in LiveCodes" GitHub Action to generate preview playground links
for pull request code changes. Automates playground creation and PR comments.
type: composition
library: livecodes
library_version: 0.13.0
requires: []
sources:
- live-codes/preview-in-livecodes:README.md
- live-codes/livecodes:docs/docs/gh-action.mdx
---
# LiveCodes — GitHub Action: Preview in LiveCodes
The [Preview in LiveCodes](https://github.com/live-codes/preview-in-livecodes) GitHub Action generates preview links to LiveCodes playgrounds for code changes in pull requests and posts them as PR comments.
**Use case:** Library authors can preview changes in the playground before merging PRs.
## How It Works
1. PR is created or updated
2. Action optionally installs dependencies and builds the project
3. Action scans `.livecodes/` folder for playground configurations
4. Generates playground URLs with your new code
5. Posts comment with preview links to the PR
## Setup
### Two Required Workflow Files
The action requires two workflow files that must be merged to the default branch first.
**1. Trigger workflow `.github/workflows/livecodes-preview.yml`:**
```yaml
name: livecodes
on: [pull_request]
jobs:
build_and_prepare:
runs-on: ubuntu-latest
name: Generate Playgrounds
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build and generate
uses: live-codes/preview-in-livecodes@v1
with:
# Optional: install-command: "npm install"
# Optional: build-command: "npm run build"
# Optional: base-url: "https://{{LC::REF}}.my-project.pages.dev"
```
**2. Comment workflow `.github/workflows/livecodes-post-comment.yml`:**
```yaml
name: comment
on:
workflow_run:
workflows: ['livecodes']
types:
- completed
jobs:
upload:
runs-on: ubuntu-latest
permissions:
pull-requests: write
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
steps:
- uses: live-codes/pr-comment-from-artifact@v1
with:
GITHUB_TOKEN: ${{ github.token }}
```
Two separate workflows are needed because each runs in a different security context. See [GitHub security article](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) for details.
## Action Inputs
| Input | Required | Description |
| ----------------- | -------- | ------------------------------------------------------ |
| `install-command` | No | Install command (e.g., `npm install`) |
| `build-command` | No | Build command (e.g., `npm run build`) |
| `base-url` | No | Base URL for deployed assets. Supports dynamic values. |
| `artifact` | No | Artifact name (default: `pr`) |
| `GITHUB_TOKEN` | No | GitHub token (default: `${{ github.token }}`) |
## Action Outputs
| Output | Description |
| --------- | -------------------------------------------------- |
| `message` | Markdown message with preview links for PR comment |
## Configure Playgrounds
Create JSON files in `.livecodes/` folder. Each file becomes a playground link.
### Example Configure Project JSON
**`.livecodes/hello-world.json`:**
```json
{
"title": "JavaScript Starter",
"markup": {
"language": "html",
"content": "<h1>Hello, World!</h1>"
},
"script": {
"language": "javascript",
"content": "import { demo } from 'my-lib';\n\ndemo();"
},
"imports": {
"my-lib": "{{LC::TO_DATA_URL(./index.js)}}"
}
}
```
The `title` property becomes the playground name in the message. If omitted, filename is used.
## Dynamic Values
Use these placeholders in project JSON and `base-url`:
| Placeholder | Description |
| ------------------- | ------------------------------ |
| `{{LC::REF}}` | Branch or tag name of PR head |
| `{{LC::SHA}}` | Full commit SHA |
| `{{LC::SHORT_SHA}}` | Short SHA (first 7 characters) |
| `{{LC::PR}}` | Pull request number |
| `{{LC::REPO}}` | Repository name |
### File Placeholders (project JSON only)
| Placeholder | Description |
| -------------------------------- | -------------------------------------------- |
| `{{LC::TO_URL(./file.js)}}` | URL of file with `base-url` prepended |
| `{{LC::TO_DATA_URL(./file.js)}}` | File converted to data URL (for small files) |
## Using Newly Added Code in Playgrounds
Three strategies to make PR code available to playgrounds:
### 1. Deploy to Preview URL (Recommended)
Use Cloudflare Pages or Netlify for automatic preview deployments.
```yaml
# workflow
base-url: 'https://{{LC::REF}}.my-project.pages.dev'
```
In project JSON:
```json
{
"imports": {
"my-lib": "{{LC::TO_URL(./dist/index.js)}}"
}
}
```
### 2. Use CDN Mirroring GitHub
Link to files via jsDelivr or similar:
```yaml
# workflow
base-url: 'https://cdn.jsdelivr.net/gh/{{LC::REPO}}@{{LC::SHA}}/'
```
### 3. Data URLs (Small Files Only)
Encode files directly. Stored at dpaste.com (limit: 1M chars, expires after 365 days).
```json
{
"imports": {
"my-lib": "{{LC::TO_DATA_URL(./index.js)}}"
}
}
```
## Common Mistakes
### HIGH Workflow files not on default branch
The workflow files must be merged to the default branch (e.g., `main`) before the action can be triggered by PRs.
Wrong:
```yaml
# Creating PR with workflow files
# Action won't run until merged to default branch
```
Correct:
```bash
# First merge workflow files to default branch
git checkout main
git merge feature/add-gh-action
git push
# Now PRs can trigger the action
```
Source: GitHub Actions documentation on workflow_run event
### MEDIUM Missing permissions for PR comments
The comment workflow needs `pull-requests: write` permission.
```yaml
jobs:
upload:
permissions:
pull-requests: write # Required!
```
### MEDIUM Using data URLs for large files
Data URLs are limited to ~1M characters at dpaste.com. Large builds will fail.
Wrong:
```json
{
"imports": {
"my-lib": "{{LC::TO_DATA_URL(./dist/bundle.js)}}" // Too large!
}
}
```
Correct:
```yaml
# Use base-url and TO_URL for large files
base-url: 'https://{{LC::REF}}.my-project.pages.dev'
```
## Example PR Comment Output
```markdown
## Preview in LiveCodes
**Latest commit:** abc1234
**Last updated:** Jan 15, 2024 3pm (UTC)
| Playground | Link |
| :------------: | ------------------------------------------------------------------ |
| **JavaScript** | [https://livecodes.io?x=code/...](https://livecodes.io?x=code/...) |
| **React** | [https://livecodes.io?x=code/...](https://livecodes.io?x=code/...) |
See [documentations](https://github.com/live-codes/preview-in-livecodes) for usage instructions.
```
## Related Skills
- **import-export** - Understanding project configuration objects
- **self-hosting** - Using custom `appUrl` for self-hosted playgrounds
---
name: livecodes/headless-mode
description: >
Run playground without visible UI using SDK methods directly. Load this skill
when building Markdown compilers, code formatters, or tools that need compiled
output without display.
type: core
library: livecodes
library_version: 0.13.0
requires:
- sdk-embedding
- sdk-methods
sources:
- live-codes/livecodes:docs/docs/sdk/headless.mdx
---
This skill builds on sdk-embedding and sdk-methods. Read them first for foundational concepts.
# LiveCodes — Headless Mode
Headless mode runs LiveCodes without any visible UI. Use SDK methods to compile code, get output, and react to events.
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Create headless playground - container is optional
const playground = await createPlayground({
headless: true,
config: {
markup: { language: 'markdown', content: '# Hello World' },
},
});
// Use SDK methods
const code = await playground.getCode();
console.log(code.markup.compiled); // "<h1>Hello World</h1>"
console.log(code.result); // Result page HTML
```
## Core Patterns
### Markdown compiler
```javascript
import { createPlayground } from 'livecodes';
let playground;
async function compileMarkdown(markdown) {
if (!playground) {
playground = await createPlayground({
headless: true,
config: { autoupdate: false },
});
}
await playground.setConfig({
markup: { language: 'markdown', content: markdown },
});
const code = await playground.getCode();
return code.markup.compiled;
}
// Usage
const html = await compileMarkdown('# Hello\n\nWorld');
console.log(html); // "<h1>Hello</h1>\n<p>World</p>"
```
### React/JSX compiler
```javascript
import { createPlayground } from 'livecodes';
let playground;
async function compileJSX(jsxCode) {
if (!playground) {
playground = await createPlayground({
headless: true,
config: { autoupdate: false },
});
}
await playground.setConfig({
script: { language: 'react', content: jsxCode },
});
const code = await playground.getCode();
return code.script.compiled;
}
const compiled = await compileJSX(`
function App() {
return <h1>Hello</h1>;
}
`);
```
### Python interpreter
```javascript
import { createPlayground } from 'livecodes';
let playground;
async function runPython(code) {
if (!playground) {
playground = await createPlayground({
headless: true,
config: { autoupdate: true },
});
}
// Set up console listener before running
const outputs = [];
playground.watch('console', ({ method, args }) => {
outputs.push({ method, args });
});
await playground.setConfig({
script: { language: 'python', content: code },
});
// Python runs automatically with autoupdate: true
// Or: await playground.run();
return outputs;
}
// Usage
const outputs = await runPython('print("Hello from Python!")');
// [{ method: 'log', args: ['Hello from Python!'] }]
```
### Get result HTML
```javascript
async function getResultHTML(config) {
const playground = await createPlayground({
headless: true,
config: { ...config, autoupdate: false },
});
await playground.setConfig(config);
const code = await playground.getCode();
return code.result; // Result page HTML
}
```
### Watch for changes
```javascript
const playground = await createPlayground({
headless: true,
config: { autoupdate: false },
});
// Watch for compiled code changes
playground.watch('code', ({ code, config }) => {
console.log('Compiled:', code.script.compiled);
});
// Change config - watch callback fires
await playground.setConfig({
script: { language: 'typescript', content: 'const x: number = 1;' },
});
```
## Common Mistakes
## Headless vs Visible Mode
| Aspect | Visible | Headless |
| --------- | ---------------- | ------------------------ |
| Container | Required | Optional |
| UI | Shown | Hidden |
| Use case | User interaction | Programmatic compilation |
## When to Use Headless
- **Markdown/MDX compiler** — Get compiled HTML without display
- **Code formatter** — Use Prettier via LiveCodes
- **Language transpiler** — TypeScript → JavaScript, SCSS → CSS
- **Testing pipelines** — Run and verify code programmatically
- **Python/Ruby/Go interpreter** — Execute WASM languages and capture output
---
name: livecodes/import-export
description: >
Import code from GitHub gists/files/repos, GitLab, URLs, DOM, and local files.
Export projects as HTML, JSON, ZIP, or to external services. Load this skill
when loading projects from external sources or exporting project state.
type: core
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:docs/docs/features/import.mdx
- live-codes/livecodes:docs/docs/features/export.mdx
---
# LiveCodes — Import and Export Code
LiveCodes imports code from external sources and exports projects in multiple formats.
## Setup
```javascript
import { createPlayground, getPlaygroundUrl } from 'livecodes';
// Import from URL
const playground = await createPlayground('#container', {
import: 'https://github.com/user/repo/blob/main/src/index.js',
});
// Import from URL via query param
// https://livecodes.io/?x=https://github.com/user/repo
// Export to shareable URL
const shareUrl = await playground.getShareUrl();
const shortUrl = await playground.getShareUrl(true);
```
## Core Patterns
### Import from GitHub
```javascript
// GitHub file
createPlayground('#container', {
import: 'https://github.com/lodash/lodash/blob/master/isObject.js',
});
// GitHub directory
createPlayground('#container', {
import: 'https://github.com/user/repo/tree/main/src',
});
// GitHub gist
createPlayground('#container', {
import: 'https://gist.github.com/abc123',
});
// Specify files from multi-file source
createPlayground('#container', {
import: 'https://github.com/user/repo/tree/main/src',
params: { files: 'App.tsx,styles.css,index.html' },
});
```
### Import from GitLab
```javascript
// GitLab snippet
createPlayground('#container', {
import: 'https://gitlab.com/-/snippets/12345',
});
// GitLab file
createPlayground('#container', {
import: 'https://gitlab.com/user/repo/-/blob/main/src/index.js',
});
```
### Import from URL
```javascript
// Raw code URL
createPlayground('#container', {
import: 'https://example.com/code.js',
});
// URL with language specified
createPlayground('#container', {
params: {
x: 'https://example.com/code',
lang: 'typescript', // Force language
},
});
// Import from Vue/TypeScript playgrounds
createPlayground('#container', {
import: 'https://play.vuejs.org/#...',
});
```
### Import from shared project
```javascript
// Short URL
createPlayground('#container', {
import: 'id/abc123', // Shared project ID
});
// Compressed config
createPlayground('#container', {
import: 'code/...', // Compressed base64 config
});
// Via URL
// https://livecodes.io/?x=id/abc123
// https://livecodes.io/?x=code/...
```
### Import from DOM
```javascript
// HTML page with code blocks
createPlayground('#container', {
import: 'https://example.com/blog-post',
});
// HTML must use specific structure:
// <code class="livecodes">
// <pre data-lang="html">...</pre>
// <pre data-lang="css">...</pre>
// <pre data-lang="javascript">...</pre>
// </code>
```
### Import via SDK config
```javascript
// Set config with code
await playground.setConfig({
markup: { language: 'html', content: '<h1>Hello</h1>' },
style: { language: 'css', content: 'h1 { color: blue; }' },
script: { language: 'javascript', content: 'console.log("hi")' },
});
// Set config from URL
await playground.setConfig('https://example.com/config.json');
```
### Specify files from multi-file sources
```javascript
// When importing directory or gist with multiple files
createPlayground('#container', {
import: 'https://github.com/user/repo/tree/main/src',
params: {
files: 'Counter.tsx,counter.css,index.html',
active: 'script', // Which editor to show: 'markup', 'style', 'script', or 0, 1, 2
},
});
```
### Export via SDK
```javascript
const playground = await createPlayground('#container', {
/* ... */
});
// Get share URL
const longUrl = await playground.getShareUrl(); // Long URL with compressed config
const shortUrl = await playground.getShareUrl(true); // Short URL
// Get config to save/export
const config = await playground.getConfig();
```
### Export via URL
```
# Long URL (compressed config)
https://livecodes.io/#config/...
# Short URL
https://livecodes.io/?x=id/abc123
```
## Common Import Sources
| Source | URL Pattern | Notes |
| --------------------- | --------------------------------- | ---------------------- |
| GitHub file | `github.com/user/repo/blob/...` | Single file |
| GitHub directory | `github.com/user/repo/tree/...` | Multiple files |
| GitHub gist | `gist.github.com/...` | Multi-file gists work |
| GitLab file | `gitlab.com/user/repo/-/blob/...` | Single file |
| GitLab snippet | `gitlab.com/-/snippets/...` | Snippet |
| JS Bin | `jsbin.com/...` | JS Bin embeds |
| Vue Playground | `play.vuejs.org/#...` | Vue SFC playground |
| TypeScript Playground | `typescriptlang.org/play#...` | TS playground |
| Raw URL | Any URL | Language auto-detected |
| Local files | Drag & drop | Standalone app only |
## File Selection Priority
When importing multiple files, LiveCodes prioritizes:
1. Files named `index.*`, `default.*` (markup)
2. Files named `style.*`, `styles.*` (style)
3. Files named `script.*`, `app.*`, `main.*`, `index.*` (script)
4. README and markdown files get lower priority
5. Use `files` parameter to explicitly select files
## SDK Import Methods
```javascript
// Option 1: EmbedOptions.import
createPlayground('#container', {
import: 'https://github.com/user/repo',
});
// Option 2: Query param x
createPlayground('#container', {
params: { x: 'https://github.com/user/repo' },
});
// Option 3: URL
// https://livecodes.io/?x=https://github.com/user/repo
// Option 4: setConfig with URL
await playground.setConfig('https://example.com/config.json');
```
# Language Reference
Complete reference for all supported languages, aliases, and extensions in LiveCodes.
## Language Assignment
Languages are assigned to editors:
| Editor | Languages |
| -------- | ------------------------------------------------ |
| `markup` | HTML, Markdown, template languages, diagrams |
| `style` | CSS, preprocessors (SCSS, Less, Stylus) |
| `script` | JavaScript, TypeScript, compiled languages, WASM |
## Markup Languages
| Name | Aliases & Extensions | Notes |
| ------------ | ------------------------------------- | ----------------------- |
| HTML | `html`, `htm` | Default markup language |
| Markdown | `markdown`, `md`, `mdown`, `mkdn` | Compiles to HTML |
| MDX | `mdx` | Markdown + JSX |
| Astro | `astro` | Astro SFC |
| Pug | `pug`, `jade` | Template engine |
| Haml | `haml` | Template engine |
| AsciiDoc | `asciidoc`, `adoc`, `asc` | Documentation format |
| Handlebars | `handlebars`, `hbs`, `mustache` | Template engine |
| EJS | `ejs` | Embedded JavaScript |
| Eta | `eta` | Template engine |
| Nunjucks | `nunjucks`, `njk` | Template engine |
| Liquid | `liquid`, `liquidjs` | Template engine |
| Dot | `dot` | Template engine |
| Twig | `twig` | Template engine |
| Vento | `vento`, `vto` | Template engine |
| Art-template | `art-template`, `art` | Template engine |
| Jinja | `jinja` | Template engine |
| BBCode | `bbcode`, `bb` | Forum markup |
| MJML | `mjml` | Email templates |
| Diagrams | `diagrams`, `diagram`, `graph`, `plt` | Graphviz, Mermaid, etc. |
| Rich Text | `richtext`, `rte`, `rich`, `rte.html` | WYSIWYG editor |
| Blockly | `blockly`, `blockly.xml` | Visual programming |
## Style Languages
| Name | Aliases & Extensions | Notes |
| ------- | -------------------- | ------------------------------------------ |
| CSS | `css` | Default style language |
| SCSS | `scss` | Sass (SCSS syntax) |
| Sass | `sass` | Sass (indented syntax) |
| Less | `less` | CSS preprocessor |
| Stylus | `stylus`, `styl` | CSS preprocessor |
| Stylis | `stylis` | CSS preprocessor |
| PostCSS | `postcss` | CSS processor (no default transformations) |
### CSS Processors
Enabled via `processors` config:
| Processor | Description |
| ------------------ | ---------------------- |
| `tailwindcss` | Tailwind CSS framework |
| `windicss` | Windi CSS framework |
| `unocss` | UnoCSS atomic CSS |
| `tokencss` | Design tokens |
| `lightningcss` | Fast CSS processing |
| `autoprefixer` | Vendor prefixes |
| `postcssPresetEnv` | Future CSS features |
| `cssmodules` | Scoped CSS |
| `purgecss` | Remove unused CSS |
| `cssnano` | CSS minification |
## Script Languages
### JavaScript & TypeScript
| Name | Aliases | Notes |
| ---------------- | ------------------------------------------------------ | ---------------------- |
| JavaScript | `javascript`, `js`, `mjs` | ES modules by default |
| TypeScript | `typescript`, `ts`, `mts` | Compiles to JavaScript |
| JSX | `jsx`, `react` | React JSX |
| TSX | `tsx`, `react-tsx`, `react.tsx` | React TSX |
| React Native JSX | `react-native`, `react-native.jsx`, `react-native-tsx` | React Native |
| Babel | `babel`, `es` | Babel transpilation |
| Sucrase | `sucrase` | Fast TypeScript/JSX |
| Flow | `flow` | Flow type checker |
| CoffeeScript | `coffeescript`, `coffee` | Compiles to JS |
| LiveScript | `livescript`, `ls` | Compiles to JS |
| Civet | `civet` | TypeScript alternative |
| Clio | `clio` | Functional language |
| Imba | `imba` | Compiles to JS |
| AssemblyScript | `assemblyscript`, `as` | Compiles to WASM |
| Rescript | `rescript`, `res`, `resi` | Compiles to JS |
| Reason | `reason`, `re`, `rei` | Compiles to JS |
| OCaml | `ocaml`, `ml`, `mli` | Compiles to JS |
### Framework Compilation
| Name | Aliases | Notes |
| ------- | ------------------------------------ | ------------------ |
| Vue | `vue`, `vue3`, `vue-app`, `app.vue` | Vue SFC |
| Vue 2 | `vue2` | Vue 2 SFC |
| Svelte | `svelte`, `svelte-app`, `app.svelte` | Svelte SFC |
| Solid | `solid`, `solid.jsx`, `solid.tsx` | Solid components |
| Stencil | `stencil`, `stencil.tsx` | Stencil components |
| Riot | `riot`, `riotjs` | Riot components |
| Malina | `malina`, `malinajs` | Malina components |
| Ripple | `ripple`, `ripplejs` | Ripple components |
| Angular | `angular` | Angular components |
### Backend Languages
| Name | Aliases | Notes |
| ------------- | ----------------------------------------- | ----------------------- |
| Python | `python`, `py` | Brython (Python -> JS) |
| Python (Wasm) | `pyodide`, `python-wasm`, `py-wasm` | Pyodide runtime (~15MB) |
| Ruby | `ruby`, `rb` | Opal (Ruby -> JS) |
| Ruby (Wasm) | `ruby-wasm`, `wasm.rb` | Ruby WASM |
| Go | `go`, `golang` | Gopherjs (Go -> JS) |
| Go (Wasm) | `go-wasm`, `wasm.go` | Go WASM |
| PHP | `php` | Uniter (PHP -> JS) |
| PHP | `php`, `php-wasm`, `wasm.php` | PHP WASM |
| C++ | `cpp`, `c`, `cpp-wasm`, `wasm.cpp` | Clang WASM |
| Java | `java` | Java runtime |
| C# | `csharp-wasm`, `cs`, `cs-wasm`, `wasm.cs` | C# WASM |
| R | `r`, `rlang`, `rstats`, `r-wasm` | R WASM |
| Lua | `lua`, `lua-wasm`, `luawasm`, `wasm.lua` | Lua WASM |
| Teal | `teal`, `tl` | Typed Lua |
| Fennel | `fennel`, `fnl` | Lua lisp |
| Julia | `julia`, `jl` | Julia runtime |
| Scheme | `scheme`, `scm` | BiwaScheme |
| Common Lisp | `commonlisp`, `common-lisp`, `lisp` | Common Lisp |
| ClojureScript | `clojurescript`, `clojure`, `cljs`, `clj` | Clojure |
| Perl | `perl`, `pl`, `pm` | Perl runtime |
| Gleam | `gleam` | Gleam language |
| Tcl | `tcl` | Tcl interpreter |
| WebAssembly | `wat`, `wast`, `wasm`, `webassembly` | WAT format |
### Data & Logic Languages
| Name | Aliases | Notes |
| ---------- | ------------------------------------------------------------ | ------------------- |
| SQL | `sql`, `sqlite`, `sqlite3` | SQLite in browser |
| PostgreSQL | `pg.sql`, `pgsql.sql`, `pgsql`, `pg`, `pglite`, `postgresql` | PGLite |
| Prolog | `prolog.pl`, `prolog` | Prolog logic |
| MiniZinc | `minizinc`, `mzn`, `dzn` | Constraint modeling |
| JSON | `json` | JSON data |
| XML | `xml` | XML data |
### Template Languages (Script context)
Can also be used in markup editor:
| Name | Aliases |
| ---------- | -------------------- |
| EJS | `ejs` |
| Eta | `eta` |
| Handlebars | `handlebars`, `hbs` |
| Mustache | `mustache` |
| Nunjucks | `nunjucks`, `njk` |
| Liquid | `liquid`, `liquidjs` |
| Dot | `dot` |
| Twig | `twig` |
| Vento | `vento`, `vto` |
| Jinja | `jinja` |
## CSS Presets
Pre-built CSS stylesheets:
| Preset | Description |
| --------------- | ---------------- |
| `normalize.css` | CSS reset |
| `reset-css` | Eric Meyer reset |
Set via config:
```javascript
const config = {
cssPreset: 'normalize.css', // or 'reset-css', or ''
};
```
## CDN Providers
For module resolution via CDN:
| Prefix | CDN |
| ---------- | --------------------- |
| (none) | esm.sh (default) |
| `esm.sh` | esm.sh |
| `skypack` | Skypack |
| `jsdelivr` | jsDelivr |
| `unpkg` | unpkg |
| `esm.run` | esm.run |
| `bundlejs` | bundlejs.com |
| `bundle` | bundlejs.com |
| `deno` | bundlejs.com (Deno) |
| `npm` | esm.sh |
| `node` | esm.sh |
| `jsr` | jsr.io via esm.sh |
| `pr:` | pkg.pr.new via esm.sh |
## Editor Defaults
| Editor | Default Language |
| ------ | ---------------- |
| Markup | `html` |
| Style | `css` |
| Script | `javascript` |
## Common Extensions
When loading files, extensions map to languages:
| Extension | Language |
| ------------------ | ---------- |
| `.html`, `.htm` | HTML |
| `.md`, `.markdown` | Markdown |
| `.jsx` | JSX |
| `.tsx` | TSX |
| `.ts` | TypeScript |
| `.vue` | Vue |
| `.svelte` | Svelte |
| `.scss`, `.sass` | SCSS/Sass |
| `.less` | Less |
| `.styl` | Stylus |
| `.py` | Python |
| `.rb` | Ruby |
| `.go` | Go |
| `.php` | PHP |
| `.java` | Java |
---
name: livecodes/language-support
description: >
Work with 90+ supported languages, compilers, CSS processors, and WASM-compiled
languages for markup, style, and script editors. Load this skill when configuring
languages, setting up CSS processors, or working with WASM-based languages like
Python, Ruby, or Go.
type: core
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:docs/docs/languages/index.mdx
- live-codes/livecodes:docs/docs/languages/_template.mdx
- live-codes/livecodes:docs/docs/features/css.mdx
references:
- references/languages.md
---
# LiveCodes — Work with Languages
LiveCodes supports 90+ languages across three editors: markup (HTML/templating), style (CSS/preprocessors), and script (JS/compiled languages).
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Basic language setup
createPlayground('#container', {
config: {
markup: { language: 'markdown', content: '# Hello' },
style: { language: 'scss', content: '$color: blue; body { color: $color; }' },
script: { language: 'typescript', content: 'const x: number = 1;' },
},
});
// WASM language (Python)
createPlayground('#container', {
config: {
script: { language: 'python-wasm', content: 'print("Hello from Python")' },
},
});
// Framework template
createPlayground('#container', { template: 'react' });
```
## Core Patterns
### Set language for each editor
```javascript
// Markup languages
markup: { language: 'html', content: '...' } // HTML
markup: { language: 'markdown', content: '...' } // Markdown
markup: { language: 'mdx', content: '...' } // MDX
markup: { language: 'pug', content: '...' } // Pug
markup: { language: 'handlebars', content: '...' } // Handlebars
// Style languages
style: { language: 'css', content: '...' } // CSS
style: { language: 'scss', content: '...' } // SCSS/Sass
style: { language: 'less', content: '...' } // Less
style: { language: 'stylus', content: '...' } // Stylus
// Script languages
script: { language: 'javascript', content: '...' } // JavaScript
script: { language: 'typescript', content: '...' } // TypeScript
script: { language: 'jsx', content: '...' } // JSX
script: { language: 'tsx', content: '...' } // TSX
```
### Use CSS processors
```javascript
const config = {
style: { language: 'css', content: '...' },
processors: [
'tailwindcss', // Tailwind CSS
'autoprefixer', // Add vendor prefixes
'postcssPresetEnv', // Use future CSS
'cssmodules', // CSS Modules
'cssnano', // Minify
],
};
// Processors run in order listed
// Tailwind should come before PostCSS tools
```
### Import styles from script
```javascript
// Import CSS in script editor
script: {
language: 'javascript',
content: `
import 'tailwindcss/utilities.css';
import './style.css'; // Gets added as a link tag
`,
}
// Get compiled CSS from style editor
import styles from './style.css';
console.log(styles); // CSS string
```
### WASM languages (first load is slow)
```javascript
// Python (Wasm)
script: { language: 'python-wasm', content: 'def greet(name): return f"Hello, {name}"' }
// Ruby (Wasm)
script: { language: 'ruby-wasm', content: 'puts "Hello from Ruby"' }
// Go (Wasm)
script: { language: 'go-wasm', content: 'package main\n\nfunc main() { println("Hello") }' }
```
WASM languages download large files on first use (5-20MB). Subsequent runs use cached WASM.
### Set editor title and position
```javascript
script: {
language: 'python-wasm',
content: 'print("Hello")',
title: 'Python', // Override displayed title
hideTitle: false, // Hide editor title
order: 0, // Editor order (0, 1, 2)
}
// Use hidden content for helper functions
script: {
language: 'javascript',
content: 'export function main() { return helper(); }',
hiddenContent: 'function helper() { return 42; }', // Hidden but evaluated
}
```
## Common Mistakes
### MEDIUM CSS processors in wrong order
Wrong:
```javascript
// PurgeCSS runs before Tailwind generates classes
processors: ['purgecss', 'tailwindcss', 'autoprefixer'];
```
Correct:
```javascript
// Correct order: Tailwind generates → PostCSS processes → PurgeCSS removes unused
processors: ['tailwindcss', 'autoprefixer', 'purgecss'];
```
Processors run in the order listed. Tailwind must generate classes before other processors. In the app UI, processors are ordered automatically.
Source: docs/docs/features/css.mdx — CSS Processors section
### MEDIUM WASM language first load appears slow
Wrong assumption:
```javascript
// Expecting instant execution for Python
script: { language: 'python-wasm', content: 'print("Hello")' }
// First run downloads ~15MB WASM file
```
Understanding:
```javascript
// WASM languages need initial download
// - Python (Pyodide): ~15MB
// - Ruby: ~10MB
// - Go: ~8MB
// Subsequent runs use cached WASM
// Consider showing loading indicator on first run
```
Source: docs/docs/languages/python-wasm.mdx
## Language Categories
| Editor | Categories | Examples |
| ------ | ----------------------------------- | --------------------------------------------------------- |
| Markup | HTML, Markdown, Templates, Diagrams | `html`, `markdown`, `pug`, `handlebars`, `mdx`, `astro` |
| Style | CSS, Preprocessors, PostCSS | `css`, `scss`, `less`, `stylus`, `postcss` |
| Script | JS, TypeScript, Compiled, WASM | `javascript`, `typescript`, `python`, `ruby`, `go`, `php` |
## Processor Reference
See [Full Language Reference](references/languages.md) for all 90+ languages, aliases, and extensions.
| Processor | Purpose |
| ------------------ | ----------------------------------- |
| `tailwindcss` | Utility-first CSS framework |
| `windicss` | Windi CSS (alternative to Tailwind) |
| `unocss` | Atomic CSS engine |
| `autoprefixer` | Add vendor prefixes |
| `postcssPresetEnv` | Use future CSS features |
| `cssmodules` | Scoped CSS classes |
| `cssnano` | Minify CSS |
| `lightningcss` | Fast CSS processing |
| `tokencss` | Design tokens |
---
name: livecodes/markdown-integration
description: >
Integrate LiveCodes with documentation sites using remark-livecodes,
markdown-it-livecodes, gatsby-remark-livecodes, or marked-livecodes for
Docusaurus, Astro, VitePress, Next.js, and Storybook.
type: composition
library: livecodes
library_version: 0.13.0
requires:
- sdk-embedding
sources:
- live-codes/livecodes:docs/docs/markdown-to-livecodes.mdx
---
This skill requires sdk-embedding. Read it first for foundational concepts.
# LiveCodes — Integrate with Documentation Sites
Convert Markdown/MDX code blocks to interactive LiveCodes playgrounds using plugins for popular documentation frameworks.
## Setup
### Docusaurus (remark-livecodes)
```bash
npm install -D remark-livecodes
```
```javascript
// docusaurus.config.js
module.exports = {
presets: [
[
'classic',
{
docs: {
remarkPlugins: [
[
require('remark-livecodes'),
{
/* options */
},
],
],
},
},
],
],
};
```
### Astro (remark-livecodes)
```bash
npm install -D remark-livecodes
```
```javascript
// astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import remarkLivecodes from 'remark-livecodes';
export default defineConfig({
integrations: [mdx()],
markdown: {
remarkPlugins: [
[
remarkLivecodes,
{
/* options */
},
],
],
},
});
```
### VitePress (markdown-it-livecodes)
```bash
npm install -D markdown-it-livecodes
```
```javascript
// .vitepress/config.js
import { defineConfig } from 'vitepress';
import markdownItLivecodes from 'markdown-it-livecodes';
export default defineConfig({
markdown: {
config: (md) => {
md.use(markdownItLivecodes, {
/* options */
});
},
},
});
```
### Next.js (remark-livecodes)
```bash
npm install -D remark-livecodes
```
```javascript
// next.config.js
import createMDX from '@next/mdx';
import remarkLivecodes from 'remark-livecodes';
const nextConfig = {
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
};
const withMDX = createMDX({
options: {
remarkPlugins: [
[
remarkLivecodes,
{
/* options */
},
],
],
},
});
export default withMDX(nextConfig);
```
### react-markdown
```bash
npm install remark-livecodes
```
````jsx
import Markdown from 'react-markdown';
import remarkLivecodes from 'remark-livecodes';
const markdown = '```jsx livecodes\nexport default () => <h1>Hello</h1>\n```';
<Markdown
remarkPlugins={[
[
remarkLivecodes,
{
/* options */
},
],
]}
>
{markdown}
</Markdown>;
````
### Storybook (remark-livecodes)
```javascript
// storybook/main.js
import remarkLivecodes from 'remark-livecodes';
export default {
addons: [
{
name: '@storybook/addon-docs',
options: {
mdxPluginOptions: {
mdxCompileOptions: {
remarkPlugins: [
[
remarkLivecodes,
{
/* options */
},
],
],
},
},
},
},
],
};
```
### Gatsby (gatsby-remark-livecodes)
```bash
npm install -D gatsby-remark-livecodes
```
```javascript
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
{
resolve: 'gatsby-remark-livecodes',
options: {
/* options */
},
},
],
},
},
],
};
```
## Usage
### Basic code block → Playground
````markdown
```jsx livecodes
import { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount((c) => c + 1)}>{count}</button>;
}
export default App;
```
````
Add `livecodes` to the code block language to render as an interactive playground.
### Button or Link instead of embed
````markdown
```jsx livecodes render=button
console.log('Edit in LiveCodes');
```
````
````markdown
```jsx livecodes render=link
console.log('Edit in LiveCodes');
```
````
| render | Behavior |
| ---------------------- | -------------------------------------------- |
| `playground` (default) | Embed playground in page |
| `button` | Show code block + "Edit in LiveCodes" button |
| `link` | Show code block + "Edit in LiveCodes" link |
| `meta` | Add URL to `data-livecodes-url` attribute |
## Options
Configure plugin options to apply to all code blocks:
```javascript
remarkPlugins: [
[remarkLivecodes, {
// Embed options
loading: 'lazy',
params: { console: 'open' },
// Plugin options
render: 'playground', // 'playground' | 'button' | 'link' | 'meta'
height: '400px',
className: 'my-playground',
auto: false, // Auto-enable for all code blocks
}],
],
```
## Meta Parameters
Configure individual code blocks with meta parameters:
````markdown
```jsx livecodes height=500px console=open theme=light
console.log('Hello World');
```
````
| Parameter | Description |
| ----------- | ------------------------------------------------------------------- |
| `livecodes` | Enable playground rendering |
| `render` | Render mode: `playground`, `button`, `link`, `meta` |
| `height` | Iframe height |
| `className` | CSS class for iframe/button/link |
| `lang` | Override language |
| `<param>` | Any LiveCodes query parameter (e.g., `console=open`, `theme=light`) |
### Common Meta Parameters
````markdown
```jsx livecodes render=button
// Button opens in LiveCodes
```
```py livecodes lang=py-wasm console=open
# Force Python (Wasm) language
print("Hello from Python")
```
```typescript livecodes theme=light editor=monaco
// Light theme, Monaco editor
const x: number = 1;
```
````
## Common Mistakes
### MEDIUM Not installing peer dependencies
```bash
# Each plugin requires its host library
npm install remark remark-livecodes # remark-livecodes
npm install marked marked-livecodes # marked-livecodes
npm install markdown-it markdown-it-livecodes # markdown-it-livecodes
npm install gatsby-plugin-remark gatsby-remark-livecodes # Gatsby
```
Install the host library alongside the LiveCodes plugin. Each plugin wraps a specific Markdown processor.
Source: docs/docs/markdown-to-livecodes.mdx — Installation sections
### LOW Forgetting livecodes parameter in code block
````markdown
```jsx
// This is just a static code block (no livecodes parameter)
export default () => <h1>Hello</h1>;
```
```jsx livecodes
// This becomes an interactive playground
export default () => <h1>Hello</h1>;
```
````
Without the `livecodes` parameter, the code block renders as static Markdown. Add it to enable the playground.
Set `auto: true` in options to convert all code blocks automatically.
Source: docs/docs/markdown-to-livecodes.mdx — Meta Parameters section
## Plugin Packages
| Package | Use With | Install |
| ------------------------- | ----------------------------------------------------- | ---------------------------------------- |
| `remark-livecodes` | Docusaurus, Astro, Next.js, Storybook, react-markdown | `npm install -D remark-livecodes` |
| `markdown-it-livecodes` | VitePress, Eleventy | `npm install -D markdown-it-livecodes` |
| `marked-livecodes` | Marked | `npm install -D marked-livecodes` |
| `gatsby-remark-livecodes` | Gatsby | `npm install -D gatsby-remark-livecodes` |
---
name: livecodes/module-resolution
description: >
Import npm, deno.land/x, jsr, and GitHub modules without build steps using
automatic CDN resolution, custom import maps, and CDN provider prefixes.
Load this skill when using bare module imports, configuring CDN providers,
or resolving import conflicts.
type: core
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:docs/docs/features/module-resolution.mdx
- live-codes/livecodes:src/livecodes/compiler/import-map.ts
---
# LiveCodes — Resolve Modules
LiveCodes automatically resolves bare module imports to CDN URLs using import maps. Use npm packages and other modules without `npm install` or build steps.
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Bare imports work automatically
createPlayground('#container', {
config: {
script: {
language: 'javascript',
content: `
import { v4 } from 'uuid'; // npm module
import React from 'react'; // npm module
import { useState } from 'react'; // Named import
console.log(v4());
`,
},
},
});
```
## Core Patterns
### Import npm packages
```javascript
// Default: uses esm.sh CDN
import { v4 } from 'uuid';
import React from 'react';
import { useState, useEffect } from 'react';
import { format } from 'date-fns';
// Specifying version
import React from 'react@18'; // React 18.x
import React from 'react@18.2.0'; // Exact version
import _ from 'lodash@4.17.21'; // Lodash specific version
```
### Use different CDN providers
```javascript
// esm.sh (default)
import React from 'react';
import React from 'esm.sh:react';
// Skypack
import React from 'skypack:react';
// jsDelivr
import React from 'jsdelivr:react';
// unpkg
import React from 'unpkg:react';
// Deno bundle
import { uuid } from 'deno:uuid';
// Full URL imports work too
import React from 'https://esm.sh/react@18';
```
### Import from Deno, GitHub, JSR
```javascript
// Deno.land/x (TS files auto-bundled)
import { uuid } from 'https://deno.land/x/uuid/mod.ts';
// JSR (Deno's npm-compatible registry)
import { yassify } from 'jsr:@kwhinnery/yassify';
// GitHub files (auto-bundled)
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts';
// Skip bundling with #nobundle
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts#nobundle';
// pkg.pr.new (unpublished packages)
import { Bench } from 'pr:tinybench@a832a55';
```
### Custom import maps
```javascript
// Via SDK config
createPlayground('#container', {
config: {
imports: {
'my-lib': 'https://my-cdn.com/lib.js',
'my-lib/utils': 'https://my-cdn.com/utils.js',
'my-private-package': 'https://my-server.com/package/index.js',
},
script: {
language: 'javascript',
content: `
import { something } from 'my-lib';
import { helper } from 'my-lib/utils';
`,
},
},
});
// Via custom settings in standalone app
// Settings → Custom Settings:
{
"imports": {
"my-lib": "https://my-cdn.com/lib.js"
}
}
```
### Change default CDN
```javascript
const config = {
customSettings: {
defaultCDN: 'skypack', // Use Skypack for all bare imports
},
script: {
language: 'javascript',
content: `import React from 'react'; // Now uses skypack`,
},
};
```
### Import CSS from script
```javascript
// URL ending in .css becomes <link>
import 'https://unpkg.com/github-markdown-css/github-markdown.css';
// Bare import for CSS
import 'github-markdown-css/github-markdown.css';
// Becomes: <link href="https://unpkg.com/github-markdown-css/github-markdown.css">
// Import compiled CSS from style editor
import styles from './style.css';
console.log(styles); // CSS string
```
## Common Mistakes
### HIGH Same module from different CDNs conflicts
Wrong:
```javascript
// React from different CDNs are DIFFERENT instances
import React from 'esm.sh:react'; // React instance A
import { createRoot } from 'skypack:react-dom/client'; // React instance B
// BREAKS: createRoot expects React instance A
```
Correct:
```javascript
// Always use same CDN (or no prefix = default)
import React from 'react';
import { createRoot } from 'react-dom/client';
// Or explicit same CDN
import React from 'esm.sh:react';
import { createRoot } from 'esm.sh:react-dom/client';
```
Module instances from different CDNs are separate. React context, hooks, and component state require the same instance.
Source: docs/docs/features/module-resolution.mdx — CDN Providers caution
### MEDIUM CommonJS require works but ESM preferred
Works but not recommended:
```javascript
const { v4 } = require('uuid'); // Works, converted to ESM
const React = require('react'); // Works
```
Preferred:
```javascript
import { v4 } from 'uuid';
import React from 'react';
```
LiveCodes converts `require` to ESM imports, but explicit ESM is clearer and matches local development.
Source: docs/docs/features/module-resolution.mdx — CommonJS Modules section
### LOW Not using #nobundle for pre-bundled URLs
When you want raw module URLs instead of bundling:
```javascript
// Without #nobundle, this gets bundled by bundlejs.com
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts';
// With #nobundle, get the raw URL
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts#nobundle';
```
Use `#nobundle` when the URL already serves bundled code or when you want to avoid bundling overhead.
Source: docs/docs/features/module-resolution.mdx — GitHub/GitLab/Bitbucket section
## CDN Provider Reference
| Prefix | CDN | URL Format |
| ----------- | ------------------- | --------------------------------------------- |
| (none) | esm.sh | `https://esm.sh/{package}` |
| `esm.sh:` | esm.sh | `https://esm.sh/{package}` |
| `skypack:` | Skypack | `https://cdn.skypack.dev/{package}` |
| `jsdelivr:` | jsDelivr | `https://cdn.jsdelivr.net/npm/{package}` |
| `unpkg:` | unpkg | `https://unpkg.com/{package}?module` |
| `bundle:` | bundlejs | `https://deno.bundlejs.com/?file&q={package}` |
| `deno:` | bundlejs | `https://deno.bundlejs.com/?file&q={url}` |
| `jsr:` | esm.sh (JSR) | `https://esm.sh/jsr/{package}` |
| `pr:` | esm.sh (pkg.pr.new) | `https://esm.sh/pr/{package}` |
## How It Works
1. **Bare imports** (`import x from 'package'`) are resolved via import maps
2. **Import map** maps bare specifiers to full CDN URLs
3. **CDN** (default: esm.sh) serves ESM versions of npm packages
4. **Deno/GitHub URLs** ending in `.ts/.tsx/.jsx` are bundled via bundlejs.com
5. **CommonJS** `require()` calls are transpiled to ESM imports
---
name: livecodes/sdk-embedding
description: >
Create and configure embedded playgrounds using createPlayground(), EmbedOptions,
container setup, loading modes (eager/lazy/click), and appUrl for self-hosted instances.
Load this skill when embedding LiveCodes in web pages, configuring playground
containers, or setting up SDK integration.
type: core
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:docs/docs/sdk/js-ts.mdx
- live-codes/livecodes:src/sdk/index.ts
- live-codes/livecodes:src/sdk/models.ts
---
# LiveCodes — Create Embedded Playground
LiveCodes is a client-side code playground that runs in the browser. Use `createPlayground` to embed interactive code editors in any web page.
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Minimal embed with template
createPlayground('#container', {
template: 'react',
});
// Embed with custom code
createPlayground('#container', {
config: {
markup: { language: 'html', content: '<h1>Hello World</h1>' },
style: { language: 'css', content: 'h1 { color: blue; }' },
script: { language: 'javascript', content: 'console.log("Hello");' },
},
});
// CDN usage (no bundler)
import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes';
createPlayground('#container', { template: 'vue' });
```
## Core Patterns
### Load playground lazily
Playgrounds load when they approach the viewport by default. Use `loading: 'eager'` for immediate load or `loading: 'click'` for click-to-load.
```javascript
createPlayground('#container', {
template: 'react',
loading: 'click', // Shows "Click to load" screen
});
```
### Configure via query params
For simple cases, use URL-style params instead of full config objects.
```javascript
createPlayground('#container', {
params: {
html: '<h1>Hello</h1>',
css: 'h1 { color: blue; }',
js: 'console.log("Hello")',
console: 'open',
},
});
```
### Use self-hosted instance
Point to your own LiveCodes deployment.
```javascript
createPlayground('#container', {
appUrl: 'https://playground.mywebsite.com',
template: 'react',
});
```
### Multiple sources priority
When providing multiple config sources, they override in order: `template` < `import` < `config` < `params`.
```javascript
createPlayground('#container', {
template: 'react', // Lowest priority
import: 'https://gist.github.com/...', // Overrides template
config: {
/* ... */
}, // Overrides import
params: { js: '...' }, // Highest priority
});
```
### Generate shareable URL
Create a link to the standalone app without embedding.
```javascript
import { getPlaygroundUrl } from 'livecodes';
const url = getPlaygroundUrl({
config: {
markup: { language: 'markdown', content: '# Hello World' },
},
});
// url = "https://livecodes.io/#config/..."
```
### Compress config for sharing
Compress a stringified config object for use in URL hashes or compact storage.
```javascript
import { compress } from 'livecodes';
const config = {
markup: { language: 'html', content: '<h1>Hello World</h1>' },
};
const compressed = compress(JSON.stringify(config));
```
### Decompress config
Decompress a string that was compressed with `compress`. Returns `null` if decompression fails.
```javascript
import { decompress } from 'livecodes';
const decompressed = decompress(compressedString);
if (decompressed) {
const config = JSON.parse(decompressed);
}
```
## Common Mistakes
### HIGH Container element not found throws error
Wrong:
```javascript
createPlayground('#nonexistent-container', { template: 'react' });
// Throws: "Cannot find element: \"#nonexistent-container\""
```
Correct:
```javascript
// Ensure container exists before calling
const container = document.querySelector('#container');
if (container) {
createPlayground('#container', { template: 'react' });
}
// Or use headless mode (container optional)
createPlayground({
view: 'headless',
config: {
/* ... */
},
});
```
`createPlayground` throws if the container selector matches no elements. In headless mode (`headless: true`), the container parameter is optional.
Source: src/sdk/index.ts — throws `"Cannot find element"` for invalid container
### HIGH Calling SDK methods after destroy() throws error
Wrong:
```javascript
const playground = await createPlayground('#container', options);
await playground.destroy();
await playground.run(); // Throws: "Cannot call API methods after calling `destroy()`."
```
Correct:
```javascript
const playground = await createPlayground('#container', options);
await playground.run();
// Use SDK methods while playground exists...
await playground.destroy(); // Last call — no more methods after this
```
Once `destroy()` is called, all subsequent SDK method calls throw with the message "Cannot call API methods after calling `destroy()`."
Source: src/sdk/index.ts — `alreadyDestroyedMessage` constant
### MEDIUM Invalid appUrl throws error
Wrong:
```javascript
createPlayground('#container', {
appUrl: 'my-playground', // Not a valid URL
});
// Throws: "my-playground is not a valid URL."
```
Correct:
```javascript
createPlayground('#container', {
appUrl: 'https://playground.example.com',
template: 'react',
});
```
The `appUrl` must be a parseable URL string. Use the full URL including protocol.
Source: src/sdk/index.ts — URL parsing in `getPlaygroundUrl`
### MEDIUM SDK method timeout after 60 seconds
SDK calls timeout after 60 seconds if the playground doesn't respond.
```javascript
// This can timeout if playground has infinite loop or slow WASM load
await playground.run(); // Times out after 60s
```
Handle with try/catch for long-running operations:
```javascript
try {
await playground.run();
} catch (error) {
if (error.message.includes('timed out')) {
console.error('Playground timed out');
}
}
```
Source: src/sdk/index.ts — `API_TIMEOUT = 60_000` (60 seconds)
---
name: livecodes/sdk-methods
description: >
Use SDK methods to interact with playgrounds: run, getCode, setConfig, getConfig,
watch, runTests, format, getShareUrl, show, destroy. Load this skill when
programmatically controlling embedded playgrounds, reacting to code changes,
or retrieving compiled output.
type: core
library: livecodes
library_version: 0.13.0
requires:
- sdk-embedding
sources:
- live-codes/livecodes:docs/docs/sdk/js-ts.mdx
- live-codes/livecodes:src/sdk/index.ts
---
This skill builds on sdk-embedding. Read it first for foundational concepts.
# LiveCodes — Use SDK Methods
The Playground object returned by `createPlayground` exposes methods to programmatically control the playground.
## Setup
```javascript
import { createPlayground } from 'livecodes';
const playground = await createPlayground('#container', {
template: 'react',
});
// All SDK methods return Promises
await playground.run();
const code = await playground.getCode();
await playground.setConfig({
/* new config */
});
```
## Core Patterns
### Run the playground
```javascript
// Run the result page (after any needed compilation)
await playground.run();
```
### Get current code and config
```javascript
// Get code from all editors
const code = await playground.getCode();
console.log(code.markup.content); // Source markup
console.log(code.markup.language); // Language name
console.log(code.markup.compiled); // Compiled output (if applicable)
console.log(code.result); // Result page HTML
// Get configuration object
const config = await playground.getConfig();
console.log(config.title);
console.log(config.markup.language);
// Get content-only config (without user preferences)
const contentConfig = await playground.getConfig(true);
```
### Update playground configuration
```javascript
// Load new project in place (no full reload)
await playground.setConfig({
markup: { language: 'markdown', content: '# New Content' },
});
// Get the resulting config
const newConfig = await playground.setConfig({
script: { language: 'typescript', content: 'const x: number = 1;' },
});
```
### Watch for changes
```javascript
// Watch for code changes
const codeWatcher = playground.watch('code', ({ code, config }) => {
console.log('Code changed:', code.script.content);
});
// Watch for console output
const consoleWatcher = playground.watch('console', ({ method, args }) => {
console[method](...args);
});
// Watch for test results
const testsWatcher = playground.watch('tests', ({ results, error }) => {
results.forEach((r) => console.log(r.status, r.testPath));
});
// Remove watchers when done
codeWatcher.remove();
consoleWatcher.remove();
```
### Run tests programmatically
```javascript
const { results } = await playground.runTests();
results.forEach((result) => {
console.log(result.status); // 'pass', 'fail', or 'skip'
console.log(result.errors); // Array of error strings
console.log(result.testPath); // ['describe', 'it']
});
```
### Show specific panel
```javascript
// Show editors
await playground.show('editor'); // Active editor
await playground.show('markup'); // Markup editor
await playground.show('style'); // Style editor
await playground.show('script'); // Script editor
// Show tools
await playground.show('console'); // Console panel
await playground.show('compiled'); // Compiled code viewer
await playground.show('tests'); // Tests panel
// Show result
await playground.show('result'); // Result page
await playground.show('toggle-result'); // Toggle result visibility
// With options
await playground.show('result', { full: true }); // Full screen
await playground.show('result', { zoom: 0.5 }); // 50% zoom
await playground.show('script', { line: 10, column: 5 }); // Scroll to line
```
### Format code
```javascript
// Format all editors
await playground.format();
// Format only active editor
await playground.format(false);
```
### Get share URL
```javascript
// Long URL with compressed config
const longUrl = await playground.getShareUrl();
// Short URL (requires share service)
const shortUrl = await playground.getShareUrl(true);
```
### Execute custom commands
```javascript
// Set broadcast token
await playground.exec('setBroadcastToken', 'my-token');
// Show version info
await playground.exec('showVersion');
```
### Destroy playground
```javascript
await playground.destroy();
// Playground removed from DOM, all event listeners cleaned up
```
## Common Mistakes
### HIGH Not awaiting async SDK methods
Wrong:
```javascript
const playground = await createPlayground('#container', {});
const code = playground.getCode(); // Returns Promise, not code
console.log(code); // Promise { <pending> }
```
Correct:
```javascript
const playground = await createPlayground('#container', {});
const code = await playground.getCode(); // Await the Promise
console.log(code.markup.content);
```
All SDK methods return Promises. Use `await` or `.then()` to get the result.
Source: docs/docs/sdk/js-ts.mdx — SDK methods section
### MEDIUM watch callback receives wrong data structure
Wrong:
```javascript
playground.watch('code', (data) => {
console.log(data.content); // Undefined
});
```
Correct:
```javascript
// 'code' event provides { code, config }
playground.watch('code', ({ code, config }) => {
console.log(code.markup.content);
console.log(code.style.content);
console.log(code.script.content);
console.log(code.result); // Result page HTML
});
// 'console' event provides { method, args }
playground.watch('console', ({ method, args }) => {
console[method](...args);
});
// 'tests' event provides { results, error? }
playground.watch('tests', ({ results, error }) => {
if (error) console.error(error);
results.forEach((r) => console.log(r.status));
});
```
Source: docs/docs/sdk/js-ts.mdx — watch method section
### LOW Using deprecated onChange instead of watch
Wrong:
```javascript
// Deprecated method
const watcher = playground.onChange(({ code, config }) => {
console.log('changed');
});
```
Correct:
```javascript
// Use watch instead
const watcher = playground.watch('code', ({ code, config }) => {
console.log('changed');
});
watcher.remove(); // When done watching
```
`onChange` is deprecated. Use `watch('code', callback)` instead.
Source: src/sdk/index.ts — `onChange` marked as deprecated
## SDK Method Reference
| Method | Returns | Description |
| ------------------------- | -------------------- | ---------------------------------------- |
| `load()` | `Promise<void>` | Load playground (for click-to-load mode) |
| `run()` | `Promise<void>` | Run the result page |
| `format(allEditors?)` | `Promise<void>` | Format code |
| `getShareUrl(shortUrl?)` | `Promise<string>` | Get shareable URL |
| `getConfig(contentOnly?)` | `Promise<Config>` | Get configuration |
| `setConfig(config)` | `Promise<Config>` | Update configuration |
| `getCode()` | `Promise<Code>` | Get code from all editors |
| `show(panel, options?)` | `Promise<void>` | Show specific panel |
| `runTests()` | `Promise<{results}>` | Run tests |
| `watch(event, fn)` | `{remove()}` | Subscribe to events |
| `exec(command, ...args)` | `Promise<any>` | Execute custom command |
| `destroy()` | `Promise<void>` | Clean up and remove |
---
name: livecodes/self-hosting
description: >
Deploy LiveCodes to static servers, GitHub Pages, or Docker. Configure SDK appUrl,
BASE_URL for subdirectories, and handle share/broadcast services. Load this skill
when self-hosting LiveCodes or using a custom app URL.
type: composition
library: livecodes
library_version: 0.13.0
requires:
- sdk-embedding
sources:
- live-codes/livecodes:docs/docs/features/self-hosting.mdx
---
This skill requires sdk-embedding. Read it first for foundational concepts.
# LiveCodes — Self-Host LiveCodes
LiveCodes runs entirely client-side. Host it on any static file server or CDN.
## Deployment Options
### Download Release
1. Download from [GitHub releases](https://github.com/live-codes/livecodes/releases)
2. Extract the `build` folder
3. Serve from any static host
```bash
# Files to serve
build/
├── index.html
├── livecodes/
│ ├── assets/
│ └── ...
└── docs/ (optional)
```
### Build from Source
```bash
git clone https://github.com/live-codes/livecodes.git
cd livecodes
npm install
npm run build # Build to build/ directory
npm run serve # Local preview at http://localhost:8080
npm run deploy # Build + deploy to GitHub Pages
```
### GitHub Pages (Built-in)
```bash
# Setup
npm install
npm run deploy # Deploys to gh-pages branch
```
Configure `CNAME` file for custom domain if needed.
### Docker
```bash
docker-compose up -d
```
Docker setup includes:
- HTTPS with auto-certificates
- Share service (short URLs)
- Broadcast server
- Open Graph meta tags
- Custom 404 page
```yaml
# docker-compose.yml
# See: docs/docs/advanced/docker.mdx for customization
```
### Other Static Hosts
- **Cloudflare Pages**: Connect repo, `npm run build`, serve `build/`
- **Netlify**: Connect repo, `npm run build`, serve `build/`
- **Firebase Hosting**: `firebase init hosting`, deploy `build/`
## Configure SDK for Self-Hosted App
```javascript
import { createPlayground } from 'livecodes';
createPlayground('#container', {
appUrl: 'https://playground.example.com',
template: 'react',
});
```
The `appUrl` tells the SDK where to load the playground iframe from.
## Custom Build
### Subdirectory Hosting
By default, LiveCodes expects to be at the root of a domain. For subdirectories:
```bash
# Host at https://example.com/playground/
npx cross-env BASE_URL="/playground/" npm run build
```
This sets `<base href="/playground/">` and adjusts all asset paths.
### Skip Building Docs
To link documentation to livecodes.io instead of building locally:
```bash
npx cross-env DOCS_BASE_URL=null npm run build:app
```
Docs links will point to `https://livecodes.io/docs/` instead of local docs.
## Services
Self-hosted apps use fallback services:
| Service | Default Hosted | Self-Hosted |
| ------------------ | --------------------- | -------------------------- |
| Share (short URLs) | dpaste.com (365 days) | dpaste.com or Docker setup |
| Broadcast | LiveCodes server | Docker setup required |
| GitHub Integration | LiveCodes OAuth | Your GitHub App |
### Docker for Full Services
Docker setup provides all services:
```bash
docker-compose up -d
# Serves at https://livecodes.localhost
```
See `docs/docs/advanced/docker.mdx` for configuration.
## Permanent URL for Stable Embeds
Use versioned URLs to prevent breaking changes:
```javascript
// Version-specific URL (never changes)
createPlayground('#container', {
appUrl: 'https://v48.livecodes.io',
template: 'react',
});
// Pin SDK version
import { createPlayground } from 'livecodes@0.13.0';
// or
import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes@0.13.0';
```
Permanent URLs format: `https://v{VERSION}.livecodes.io`
## Common Mistakes
### MEDIUM Not configuring BASE_URL for subdirectories
Wrong:
```bash
# Build default, serve at /playground/
npm run build
# Results in broken asset paths
```
Correct:
```bash
# Set BASE_URL for subdirectory
npx cross-env BASE_URL="/playground/" npm run build
```
Without `BASE_URL`, the app expects to be at root (`/`) and asset paths will be wrong.
Source: docs/docs/features/self-hosting.mdx — Custom Build section
### MEDIUM Self-hosted share URLs expire
```javascript
// dpaste.com deletes share URLs after 365 days
// For permanent self-hosted share:
// 1. Use Docker setup for own share service
// 2. Or use permanent URL pattern for embeds
```
The default dpaste.com service deletes shared URLs after one year. For permanent sharing, use Docker setup with your own share service.
Source: docs/docs/features/self-hosting.mdx — Services section
## Examples
### GitHub Pages
```bash
# Fork live-codes/livecodes
# Enable GitHub Pages in repo settings
npm install
npm run deploy
# Access at https://your-username.github.io/livecodes/
```
### Cloudflare Pages
```bash
# Build command: npm run build:app
# Output directory: build
# Environment: NODE_VERSION=18
# Access at https://your-subdomain.pages.dev/
```
### Docker VPS
```bash
git clone https://github.com/live-codes/livecodes.git
cd livecodes
docker-compose up -d
# Access at https://livecodes.localhost
# Configure domain in docker-compose.yml
```
---
name: livecodes
description: >-
Open-source, client-side code playground supporting 90+ languages/frameworks.
Runs entirely in the browser with SDK for embedding. Entry point for all
LiveCodes skills.
type: core
library: livecodes
library_version: 0.13.0
---
# LiveCodes Overview
LiveCodes is a feature-rich, open-source, client-side code playground that runs entirely in the browser. No server required. Supports 90+ languages/frameworks with a powerful SDK for embedding in any web application.
> **CRITICAL**: LiveCodes runs CLIENT-SIDE. No server, no build step, no backend. Do not confuse with server-based playgrounds.
> **CRITICAL**: All SDK methods are async (return Promises). Always `await` them or use `.then()`.
## Sub-Skills
| Task | Sub-Skill |
| ------------------------------------------------ | -------------------------------------------------------------------------- |
| Quick start for beginners | [livecodes/getting-started/SKILL.md](./getting-started/SKILL.md) |
| Create embedded playgrounds | [livecodes/sdk-embedding/SKILL.md](./sdk-embedding/SKILL.md) |
| Use SDK methods (run, getCode, setConfig, watch) | [livecodes/sdk-methods/SKILL.md](./sdk-methods/SKILL.md) |
| Compress/decompress config utilities | [livecodes/sdk-embedding/SKILL.md](./sdk-embedding/SKILL.md) |
| Configure via Config object, query params | [livecodes/configuration/SKILL.md](./configuration/SKILL.md) |
| Choose display mode (full, simple, result, etc.) | [livecodes/display-modes/SKILL.md](./display-modes/SKILL.md) |
| Run playgrounds without visible UI | [livecodes/headless-mode/SKILL.md](./headless-mode/SKILL.md) |
| Import/export code (GitHub, gists, files) | [livecodes/import-export/SKILL.md](./import-export/SKILL.md) |
| Work with 90+ languages and processors | [livecodes/language-support/SKILL.md](./language-support/SKILL.md) |
| Import npm packages without bundler | [livecodes/module-resolution/SKILL.md](./module-resolution/SKILL.md) |
| Write and run tests in the playground | [livecodes/testing/SKILL.md](./testing/SKILL.md) |
| Use with React, Vue, Svelte, Solid, Preact | [livecodes/framework-wrappers/SKILL.md](./framework-wrappers/SKILL.md) |
| Integrate with docs sites (Docusaurus, Astro) | [livecodes/markdown-integration/SKILL.md](./markdown-integration/SKILL.md) |
| Self-host on your own server | [livecodes/self-hosting/SKILL.md](./self-hosting/SKILL.md) |
| Preview PRs in LiveCodes (GitHub Action) | [livecodes/gh-action/SKILL.md](./gh-action/SKILL.md) |
## Quick Decision Tree
```
New to LiveCodes?
→ livecodes/getting-started
Need to embed a playground in your app?
→ livecodes/sdk-embedding
Need to control playground programmatically?
→ livecodes/sdk-methods
Need to configure project content (languages, theme, etc.)?
→ livecodes/configuration
Need to show code readonly or result-only?
→ livecodes/display-modes
Need to run playground without any UI?
→ livecodes/headless-mode
Need to use React/Vue/Svelte/etc.?
→ livecodes/framework-wrappers
Need to import npm packages or external modules?
→ livecodes/module-resolution
Need a specific language (Python, SASS, TypeScript)?
→ livecodes/language-support
Need to run tests in the playground?
→ livecodes/testing
Need to import code from GitHub/URL or export?
→ livecodes/import-export
Need to add playgrounds to markdown docs?
→ livecodes/markdown-integration
Need to host LiveCodes on your own server?
→ livecodes/self-hosting
Need to preview PR changes in playgrounds?
→ livecodes/gh-action
```
## Minimal Working Example
### CDN (quickest)
```html
<!doctype html>
<html>
<head>
<title>LiveCodes Demo</title>
</head>
<body>
<div id="container"></div>
<script type="module">
import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes';
createPlayground('#container', {
config: {
markup: { language: 'html', content: '<h1>Hello LiveCodes!</h1>' },
style: { language: 'css', content: 'h1 { color: blue; }' },
script: { language: 'javascript', content: 'console.log("Hello!");' },
},
});
</script>
</body>
</html>
```
### NPM
```bash
npm install livecodes
```
```javascript
import { createPlayground } from 'livecodes';
const playground = await createPlayground('#container', {
config: {
markup: { language: 'html', content: '<h1>Hello!</h1>' },
},
});
// SDK methods are async - always await
await playground.run();
const code = await playground.getCode();
```
### React
```jsx
import { useState } from 'react';
import LiveCodes from 'livecodes/react';
export default function App() {
const [playground, setPlayground] = useState(null);
return (
<>
<LiveCodes
config={{ markup: { language: 'html', content: '<h1>Hello!</h1>' } }}
sdkReady={setPlayground}
/>
<button onClick={() => playground?.run()}>Run</button>
</>
);
}
```
## Common Mistakes
### HIGH: SDK methods return Promises - always await
```javascript
// WRONG - code is a Promise, not actual code
const code = playground.getCode();
console.log(code.markup); // undefined!
// CORRECT - await the Promise
const code = await playground.getCode();
console.log(code.markup.content); // '<h1>Hello!</h1>'
```
### HIGH: Container must exist before createPlayground
```javascript
// WRONG - container doesn't exist yet
createPlayground('#container', { config }); // throws if #container not in DOM
// CORRECT - ensure container exists
const container = document.querySelector('#container');
if (container) {
createPlayground('#container', { config });
}
// OR use headless mode if no UI needed
createPlayground({ headless: true, config });
```
### HIGH: Config vs EmbedOptions confusion
```javascript
// WRONG - appUrl is not a config property
createPlayground('#container', {
config: {
appUrl: 'https://my-server.com', // ERROR: wrong place
},
});
// CORRECT - appUrl is an EmbedOption, not config
createPlayground('#container', {
appUrl: 'https://my-server.com', // EmbedOptions
config: {
// Config
markup: { language: 'html', content: '<h1>Hi</h1>' },
},
});
```
### MEDIUM: Different CDN imports create separate module instances
```javascript
// WRONG - two different React instances
import React from 'react'; // esm.sh
import { createRoot } from 'skypack:react-dom/client'; // Different React!
// CORRECT - use same CDN consistently
import React from 'react';
import { createRoot } from 'react-dom/client'; // Both from esm.sh (default)
```
---
name: livecodes/testing
description: >
Write and run automated tests with Jest and Testing Library in the browser.
Import code from script editor, use watch mode, and run tests programmatically.
Load this skill when writing tests for playground code or running tests via SDK.
type: core
library: livecodes
library_version: 0.13.0
sources:
- live-codes/livecodes:docs/docs/features/tests.mdx
---
# LiveCodes — Write and Run Tests
LiveCodes includes Jest and Testing Library for automated testing in the browser. Tests run against the result page in real-time.
## Setup
```javascript
import { createPlayground } from 'livecodes';
// Project with tests
createPlayground('#container', {
template: 'jest', // Jest starter template
params: { tests: 'open' }, // Show tests panel
});
// Custom test configuration
createPlayground('#container', {
config: {
activeEditor: 'script',
script: {
language: 'javascript',
content: `
export function add(a, b) {
return a + b;
}
export function greet(name) {
return 'Hello, ' + name;
}
`,
},
tests: {
language: 'javascript',
content: `
import { add, greet } from './script';
describe('add', () => {
test('adds numbers', () => {
expect(add(1, 2)).toBe(3);
});
test('handles negatives', () => {
expect(add(-1, -2)).toBe(-3);
});
});
describe('greet', () => {
test('greets by name', () => {
expect(greet('World')).toBe('Hello, World');
});
});
`,
},
},
params: { tests: 'open' },
});
```
## Core Patterns
### Test exports from script editor
```javascript
// Script editor (script.js)
export default function greet(name) {
return 'Hello, ' + name;
}
export const add = (a, b) => a + b;
// Also available in global scope
window.multiply = (a, b) => a * b;
```
```javascript
// Tests editor
import greet, { add } from './script'; // Relative import, no extension
describe('imports', () => {
test('greet', () => {
expect(greet('World')).toBe('Hello, World');
});
test('add', () => {
expect(add(1, 2)).toBe(3);
});
});
describe('globals', () => {
test('multiply', () => {
expect(window.multiply(2, 3)).toBe(6);
});
});
```
### Use Testing Library
```javascript
// React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event';
test('button click', async () => {
render(<MyComponent />);
await userEvent.click(screen.getByText('Click me'));
expect(screen.getByText('Clicked')).toBeInTheDocument();
});
// DOM Testing Library
import { getByText, waitFor } from '@testing-library/dom';
test('element appears', async () => {
document.body.innerHTML = '<div id="root"></div>';
// ... render something
await waitFor(() => {
expect(getByText(document.body, 'Loaded')).toBeTruthy();
});
});
```
### Run tests programmatically via SDK
```javascript
const playground = await createPlayground('#container', {
config: {
/* ... */
},
});
// Run tests and get results
const { results } = await playground.runTests();
results.forEach((result) => {
console.log(result.status); // 'pass', 'fail', or 'skip'
console.log(result.testPath); // ['describe', 'it']
console.log(result.duration); // milliseconds
console.log(result.errors); // string[] of error messages
});
// Watch for test results
playground.watch('tests', ({ results, error }) => {
if (error) {
console.error('Test error:', error);
return;
}
const passed = results.filter((r) => r.status === 'pass');
console.log(`${passed.length} tests passed`);
});
```
### Use Jest globals directly
```javascript
// Jest globals available without import
describe('my tests', () => {
test('passes', () => {
expect(1 + 1).toBe(2);
});
test('asynchronous', async () => {
const result = await someAsyncFunction();
expect(result).toBe('expected');
});
test.skip('skipped', () => {
// Not run
});
test.only('run only this', () => {
// Only this test runs
});
});
// Lifecycle hooks
beforeAll(() => {
/* runs once before all tests */
});
afterAll(() => {
/* runs once after all tests */
});
beforeEach(() => {
/* runs before each test */
});
afterEach(() => {
/* runs after each test */
});
// Mocks
jest.fn();
jest.mocked(obj);
jest.spyOn(obj, 'method');
```
### Use Chai assertions (alternative)
```javascript
import { assert } from 'chai';
describe('with Chai', () => {
test('assertions', () => {
assert.equal(1 + 1, 2);
assert.isArray([1, 2, 3]);
assert.include([1, 2, 3], 2);
});
});
```
## Test Panel Controls
In the standalone app or visible tests panel:
- **Run button**: Run tests (shortcut: Ctrl/Cmd + Alt + T)
- **Watch toggle**: Auto-run tests on code change
- **Reset button**: Clear test results
- **Edit button**: Open test editor (not available in embeds)
## Common Mistakes
### HIGH Script errors prevent tests from loading
Wrong:
```javascript
// Script editor has syntax error
export function add(a, b) {
return a + // Syntax error - missing operand
}
// Tests editor - tests never run because script failed
import { add } from './script';
test('add', () => expect(add(1, 2)).toBe(3));
```
Understanding:
```javascript
// Tests run against the result page
// Script errors prevent the page from loading
// Always ensure script compiles before testing
// Check the console for script errors
// Fix script errors before writing tests
```
Tests are added to the result page. Script errors (import errors, syntax errors) prevent the result page from loading, which prevents tests from running.
Source: docs/docs/features/tests.mdx — Example section
### MEDIUM Import path must be relative without extension
Wrong:
```javascript
import { add } from 'script'; // Missing ./
import { add } from './script.js'; // Has extension
```
Correct:
```javascript
import { add } from './script'; // Relative import, no extension
```
When importing from the script editor in tests, use relative imports without file extensions.
Source: docs/docs/features/tests.mdx — Importing Code section
## Supported Jest Features
| Feature | Support |
| ---------------------------- | -------------------- |
| `describe`, `test`, `it` | Full support |
| `xtest`, `xit`, `fit` | Skip/only tests |
| `xdescribe`, `fdescribe` | Skip/only suites |
| `beforeAll`, `afterAll` | Lifecycle hooks |
| `beforeEach`, `afterEach` | Lifecycle hooks |
| `expect` | Full matchers |
| `jest.fn()`, `jest.mocked()` | Function mocks |
| `jest.spyOn()` | Spy on methods |
| `jest.replaceProperty()` | Property replacement |
## Supported Testing Libraries
| Library | Import |
| --------------------- | ----------------------------------------------------------- |
| DOM Testing Library | `import { getByText, waitFor } from '@testing-library/dom'` |
| React Testing Library | `import { render, screen } from '@testing-library/react'` |
| jest-dom | `import '@testing-library/jest-dom'` |
| user-event | `import userEvent from '@testing-library/user-event'` |
| Chai | `import { assert } from 'chai'` |
Tests run in the browser using Jest. Libraries are automatically available — no import maps needed for testing libraries.
var oe=Object.create;var Q=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var se=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var le=(f,o)=>()=>(o||f((o={exports:{}}).exports,o),o.exports);var ce=(f,o,E,d)=>{if(o&&typeof o=="object"||typeof o=="function")for(let S of ie(o))!ae.call(f,S)&&S!==E&&Q(f,S,{get:()=>o[S],enumerable:!(d=re(o,S))||d.enumerable});return f};var de=(f,o,E)=>(E=f!=null?oe(se(f)):{},ce(o||!f||!f.__esModule?Q(E,"default",{value:f,enumerable:!0}):E,f));var G=le((Te,K)=>{var Pe=function(){var f=String.fromCharCode,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",E="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",d={};function S(s,r){if(!d[s]){d[s]={};for(var t=0;t<s.length;t++)d[s][s.charAt(t)]=t}return d[s][r]}var C={compressToBase64:function(s){if(s==null)return"";var r=C._compress(s,6,function(t){return o.charAt(t)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(s){return s==null?"":s==""?null:C._decompress(s.length,32,function(r){return S(o,s.charAt(r))})},compressToUTF16:function(s){return s==null?"":C._compress(s,15,function(r){return f(r+32)})+" "},decompressFromUTF16:function(s){return s==null?"":s==""?null:C._decompress(s.length,16384,function(r){return s.charCodeAt(r)-32})},compressToUint8Array:function(s){for(var r=C.compress(s),t=new Uint8Array(r.length*2),e=0,l=r.length;e<l;e++){var u=r.charCodeAt(e);t[e*2]=u>>>8,t[e*2+1]=u%256}return t},decompressFromUint8Array:function(s){if(s==null)return C.decompress(s);for(var r=new Array(s.length/2),t=0,e=r.length;t<e;t++)r[t]=s[t*2]*256+s[t*2+1];var l=[];return r.forEach(function(u){l.push(f(u))}),C.decompress(l.join(""))},compressToEncodedURIComponent:function(s){return s==null?"":C._compress(s,6,function(r){return E.charAt(r)})},decompressFromEncodedURIComponent:function(s){return s==null?"":s==""?null:(s=s.replace(/ /g,"+"),C._decompress(s.length,32,function(r){return S(E,s.charAt(r))}))},compress:function(s){return C._compress(s,16,function(r){return f(r)})},_compress:function(s,r,t){if(s==null)return"";var e,l,u={},g={},v="",x="",p="",b=2,O=3,m=2,w=[],n=0,i=0,A;for(A=0;A<s.length;A+=1)if(v=s.charAt(A),Object.prototype.hasOwnProperty.call(u,v)||(u[v]=O++,g[v]=!0),x=p+v,Object.prototype.hasOwnProperty.call(u,x))p=x;else{if(Object.prototype.hasOwnProperty.call(g,p)){if(p.charCodeAt(0)<256){for(e=0;e<m;e++)n=n<<1,i==r-1?(i=0,w.push(t(n)),n=0):i++;for(l=p.charCodeAt(0),e=0;e<8;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1}else{for(l=1,e=0;e<m;e++)n=n<<1|l,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=0;for(l=p.charCodeAt(0),e=0;e<16;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1}b--,b==0&&(b=Math.pow(2,m),m++),delete g[p]}else for(l=u[p],e=0;e<m;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1;b--,b==0&&(b=Math.pow(2,m),m++),u[x]=O++,p=String(v)}if(p!==""){if(Object.prototype.hasOwnProperty.call(g,p)){if(p.charCodeAt(0)<256){for(e=0;e<m;e++)n=n<<1,i==r-1?(i=0,w.push(t(n)),n=0):i++;for(l=p.charCodeAt(0),e=0;e<8;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1}else{for(l=1,e=0;e<m;e++)n=n<<1|l,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=0;for(l=p.charCodeAt(0),e=0;e<16;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1}b--,b==0&&(b=Math.pow(2,m),m++),delete g[p]}else for(l=u[p],e=0;e<m;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1;b--,b==0&&(b=Math.pow(2,m),m++)}for(l=2,e=0;e<m;e++)n=n<<1|l&1,i==r-1?(i=0,w.push(t(n)),n=0):i++,l=l>>1;for(;;)if(n=n<<1,i==r-1){w.push(t(n));break}else i++;return w.join("")},decompress:function(s){return s==null?"":s==""?null:C._decompress(s.length,32768,function(r){return s.charCodeAt(r)})},_decompress:function(s,r,t){var e=[],l,u=4,g=4,v=3,x="",p=[],b,O,m,w,n,i,A,c={val:t(0),position:r,index:1};for(b=0;b<3;b+=1)e[b]=b;for(m=0,n=Math.pow(2,2),i=1;i!=n;)w=c.val&c.position,c.position>>=1,c.position==0&&(c.position=r,c.val=t(c.index++)),m|=(w>0?1:0)*i,i<<=1;switch(l=m){case 0:for(m=0,n=Math.pow(2,8),i=1;i!=n;)w=c.val&c.position,c.position>>=1,c.position==0&&(c.position=r,c.val=t(c.index++)),m|=(w>0?1:0)*i,i<<=1;A=f(m);break;case 1:for(m=0,n=Math.pow(2,16),i=1;i!=n;)w=c.val&c.position,c.position>>=1,c.position==0&&(c.position=r,c.val=t(c.index++)),m|=(w>0?1:0)*i,i<<=1;A=f(m);break;case 2:return""}for(e[3]=A,O=A,p.push(A);;){if(c.index>s)return"";for(m=0,n=Math.pow(2,v),i=1;i!=n;)w=c.val&c.position,c.position>>=1,c.position==0&&(c.position=r,c.val=t(c.index++)),m|=(w>0?1:0)*i,i<<=1;switch(A=m){case 0:for(m=0,n=Math.pow(2,8),i=1;i!=n;)w=c.val&c.position,c.position>>=1,c.position==0&&(c.position=r,c.val=t(c.index++)),m|=(w>0?1:0)*i,i<<=1;e[g++]=f(m),A=g-1,u--;break;case 1:for(m=0,n=Math.pow(2,16),i=1;i!=n;)w=c.val&c.position,c.position>>=1,c.position==0&&(c.position=r,c.val=t(c.index++)),m|=(w>0?1:0)*i,i<<=1;e[g++]=f(m),A=g-1,u--;break;case 2:return p.join("")}if(u==0&&(u=Math.pow(2,v),v++),e[A])x=e[A];else if(A===g)x=O+O.charAt(0);else return null;p.push(x),e[g++]=O+x.charAt(0),u--,O=x,u==0&&(u=Math.pow(2,v),v++)}}};return C}();typeof K!="undefined"&&K!=null&&(K.exports=Pe)});import{use as fe,effect as ue,className as me,style as ge,setAttribute as pe,template as he}from"solid-js/web";import{onMount as ye,createEffect as ve,on as we,onCleanup as Ee}from"solid-js";var be=he("<div>"),Z=f=>o=>{let E,d,S=JSON.stringify(o.config||""),C="",s=0,r=()=>{let e={};return o.appUrl!==void 0&&(e.appUrl=o.appUrl),o.import!==void 0&&(e.import=o.import),o.headless!==void 0&&(e.headless=o.headless),o.lite!==void 0&&(e.lite=o.lite),o.loading!==void 0&&(e.loading=o.loading),o.params!==void 0&&(e.params=o.params),o.template!==void 0&&(e.template=o.template),o.view!==void 0&&(e.view=o.view),e},t=()=>{if(!E)return;let e=o.config,l=o.sdkReady,u=r(),g=JSON.stringify(u),v=++s,x=()=>v!==s;if(!d||C!==g)C=g,S=JSON.stringify(e||""),d==null||d.destroy(),d=void 0,f(E,{config:e,...u}).then(p=>{if(x()){p.destroy();return}d=p,typeof l=="function"&&l(p)});else{let p=JSON.stringify(e);if(S===p)return;S=p,e&&d.setConfig(e)}};return ye(()=>{t()}),ve(we(()=>[o.config,o.appUrl,o.import,o.headless,o.lite,o.loading,o.params,o.template,o.view,o.sdkReady],()=>{t()},{defer:!0})),Ee(()=>{++s,d==null||d.destroy()}),(()=>{var e=be(),l=E;return typeof l=="function"?fe(l,e):E=e,ue(u=>{var g=o.class,v={...o.style,...o.height?{height:Number(o.height)?`${o.height}px`:o.height}:{}},x=o.height;return g!==u.e&&me(e,u.e=g),u.t=ge(e,v,u.t),x!==u.a&&pe(e,"data-height",u.a=x),u},{e:void 0,t:void 0,a:void 0}),e})()};var z=de(G());var Ce={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},xe=()=>{if(typeof navigator=="undefined")return"default";let f=navigator.userAgent;return/Firefox\//i.test(f)?"firefox":/Chrome\//i.test(f)?"chrome":"default"},X=()=>Ce[xe()].filter(f=>{var E,d,S;let o=(S=(d=(E=globalThis.document)==null?void 0:E.featurePolicy)==null?void 0:d.features)==null?void 0:S.call(d);return o?o.includes(f):!0}).join("; ");async function Y(f,o={}){typeof f=="object"&&!(f instanceof HTMLElement)&&(f.headless||f.view==="headless")&&(o=f,f=null);let E=6e4,{config:d={},headless:S,loading:C="lazy",view:s}=o,r=S||s==="headless",t=null,e=null,l=a=>{a.style.position="absolute",a.style.top="0",a.style.visibility="hidden",a.style.opacity="0"};if(typeof f=="string")t=document.querySelector(f);else if(f instanceof HTMLElement)t=f;else if(!(r&&typeof f=="object"))throw new Error("A valid container element is required.");if(!t)if(r)t=document.createElement("div"),l(t),document.body.appendChild(t);else throw new Error(`Cannot find element: "${f}"`);let u=new URL(Ae(o)),g=u.origin;u.searchParams.set("embed","true"),u.searchParams.set("loading",r?"eager":C),u.searchParams.set("sdkVersion","0.14.0"),typeof d=="object"&&Object.keys(d).length>0&&u.searchParams.set("config","sdk");let v=o.params;typeof v=="object"&&Object.keys(v).length>0&&JSON.stringify(v).length<1800&&Object.keys(v).forEach(a=>{u.searchParams.set(a,encodeURIComponent(String(v[a])))});let x=!1,p="Cannot call API methods after calling `destroy()`.",b=[],O=(a,h="message")=>{addEventListener(h,a),b.push(a)},m=(a,h="message")=>{removeEventListener(h,a);let P=b.indexOf(a);P>-1&&b.splice(P,1)},n=await new Promise(a=>{var T,R,M,I,_,j,W,B,$;if(!t)return;let h=t.dataset.height||t.style.height;if(h&&!r){let D=isNaN(Number(h))?h:h+"px";t.style.height=D}t.dataset.defaultStyles!=="false"&&!r&&((T=t.style).backgroundColor||(T.backgroundColor="#fff"),(R=t.style).border||(R.border="1px solid black"),(M=t.style).borderRadius||(M.borderRadius="8px"),(I=t.style).boxSizing||(I.boxSizing="border-box"),(_=t.style).padding||(_.padding="0"),(j=t.style).width||(j.width="100%"),(W=t.style).height||(W.height=t.style.height||"300px"),t.style.minHeight="200px",t.style.flexGrow="1",(B=t.style).overflow||(B.overflow="hidden"),($=t.style).resize||($.resize="vertical"),getComputedStyle(t).getPropertyValue("display")==="inline"&&(t.style.display="block"));let P="livecodes",L=t.querySelector(`iframe.${P}`),y=L||document.createElement("iframe");y.classList.add(P),y.setAttribute("allow",X()),y.setAttribute("allowtransparency","true"),y.setAttribute("allowpaymentrequest","true"),y.setAttribute("allowfullscreen","true"),y.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let U=C==="eager"?"eager":"lazy";y.setAttribute("loading",U),r?l(y):(y.style.height="100%",y.style.minHeight="200px",y.style.width="100%",y.style.margin="0",y.style.border="0",y.style.borderRadius=t.style.borderRadius),O(function D(H){var N;H.source!==y.contentWindow||H.origin!==g||((N=H.data)==null?void 0:N.type)!=="livecodes-init"||(m(D),e=Number(H.data.payload.appVersion.replace(/^v/,"")))}),(!e||e<46)&&O(function D(H){var N,q;H.source!==y.contentWindow||H.origin!==g||((N=H.data)==null?void 0:N.type)!=="livecodes-get-config"||(m(D),(q=y.contentWindow)==null||q.postMessage({type:"livecodes-config",payload:d},g))}),y.onload=()=>{a(y)},y.src=u.href,L||t.appendChild(y)}),i=new Promise(a=>{O(function h(P){var L;P.source!==n.contentWindow||P.origin!==g||((L=P.data)==null?void 0:L.type)!=="livecodes-ready"||(m(h),a(),i.settled=!0)})}),A=()=>x?Promise.reject(p):new Promise(async a=>{var P;i.settled&&a();let h={type:"livecodes-load"};(P=n.contentWindow)==null||P.postMessage(h,g),await i,a()}),c=(a,h)=>new Promise(async(P,L)=>{var R;if(x)return L(p);await A();let y=ne(),U=setTimeout(()=>{m(T),L(new Error(`SDK call "${a}" timed out after ${E}ms.`))},E);function T(M){var I,_;if(!(M.source!==n.contentWindow||M.origin!==g||((I=M.data)==null?void 0:I.type)!=="livecodes-api-response"||((_=M.data)==null?void 0:_.id)!==y)&&M.data.method===a){clearTimeout(U),m(T);let j=M.data.payload;j!=null&&j.error?L(j.error):P(j)}}O(T),(R=n.contentWindow)==null||R.postMessage({method:a,id:y,args:h},g)}),k={},V=["load","ready","code","console","tests","destroy"],J=(a,h)=>{var P;if(x)throw new Error(p);return V.includes(a)?(c("watch",[a]),k[a]||(k[a]=[]),(P=k[a])==null||P.push(h),{remove:()=>{var L,y;k[a]=(L=k[a])==null?void 0:L.filter(U=>U!==h),((y=k[a])==null?void 0:y.length)===0&&c("watch",[a,"unsubscribe"])}}):{remove:()=>{}}},ee=a=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[a];O(async function(h){var y,U,T,R;let P=ee((U=(y=h.data)==null?void 0:y.type)!=null?U:"");if(h.source!==n.contentWindow||h.origin!==g||!P||!k[P])return;let L=(T=h.data)==null?void 0:T.payload;(R=k[P])==null||R.forEach(M=>{M(L)})});let te=()=>{var a;(a=n==null?void 0:n.remove)==null||a.call(n),Object.values(k).forEach(h=>{h.length=0}),b.forEach(h=>removeEventListener("message",h)),b.length=0,F&&t&&F.unobserve(t),x=!0},F;C==="lazy"&&"IntersectionObserver"in window&&(F=new IntersectionObserver((a,h)=>{a.forEach(async P=>{P.isIntersecting&&(await A(),h.unobserve(t))})},{rootMargin:"150px"}),F.observe(t));let ne=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>A(),run:()=>c("run"),format:a=>c("format",[a]),getShareUrl:a=>c("getShareUrl",[a]),getConfig:a=>c("getConfig",[a]),setConfig:a=>c("setConfig",[a]),getCode:()=>c("getCode"),show:(a,h)=>c("show",[a,h]),runTests:()=>c("runTests"),onChange:a=>J("code",a),watch:J,exec:(a,...h)=>c("exec",[a,...h]),destroy:()=>x?Promise.reject(p):(te(),Promise.resolve())}}function Ae(f={}){let{appUrl:o="https://livecodes.io",params:E={},config:d={},headless:S,import:C,lite:s,view:r,...t}=f,e;try{e=new URL(o)}catch(g){throw new Error(`${o} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(t).forEach(([g,v])=>{v!==void 0&&e.searchParams.set(g,String(v))});let u=f.view==="headless"||S;if(s&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof d=="object"&&d.mode==null?d.mode="lite":e.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof d=="object"&&d.view==null&&r!=="headless"?d.view=r:e.searchParams.set("view",r)),typeof d=="string")try{new URL(d),e.searchParams.set("config",encodeURIComponent(d))}catch(g){throw new Error('"config" is not a valid URL or configuration object.')}else d&&typeof d=="object"&&Object.keys(d).length>0&&(d.title&&d.title!=="Untitled Project"&&e.searchParams.set("title",d.title),d.description&&d.description.length>0&&e.searchParams.set("description",d.description),l.set("config","code/"+(0,z.compressToEncodedURIComponent)(JSON.stringify(d))));if(E&&typeof E=="object"&&Object.keys(E).length>0)try{l.set("params",(0,z.compressToEncodedURIComponent)(JSON.stringify(E)))}catch(g){Object.keys(E).forEach(v=>{e.searchParams.set(v,encodeURIComponent(String(E[v])))})}return C&&e.searchParams.set("x",encodeURIComponent(C)),u&&e.searchParams.set("headless","true"),l.toString().length>0&&(e.hash=l.toString()),e.href}var Se=Z(Y),_e=Se;export{_e as default};
var te=Object.create;var Q=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,se=Object.prototype.hasOwnProperty;var ie=(c,m)=>()=>(m||c((m={exports:{}}).exports,m),m.exports);var ae=(c,m,P,f)=>{if(m&&typeof m=="object"||typeof m=="function")for(let L of oe(m))!se.call(c,L)&&L!==P&&Q(c,L,{get:()=>m[L],enumerable:!(f=ne(m,L))||f.enumerable});return c};var le=(c,m,P)=>(P=c!=null?te(re(c)):{},ae(m||!c||!c.__esModule?Q(P,"default",{value:c,enumerable:!0}):P,c));var Z=ie((me,z)=>{var ce=function(){var c=String.fromCharCode,m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",P="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function L(s,r){if(!f[s]){f[s]={};for(var e=0;e<s.length;e++)f[s][s.charAt(e)]=e}return f[s][r]}var A={compressToBase64:function(s){if(s==null)return"";var r=A._compress(s,6,function(e){return m.charAt(e)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(s){return s==null?"":s==""?null:A._decompress(s.length,32,function(r){return L(m,s.charAt(r))})},compressToUTF16:function(s){return s==null?"":A._compress(s,15,function(r){return c(r+32)})+" "},decompressFromUTF16:function(s){return s==null?"":s==""?null:A._decompress(s.length,16384,function(r){return s.charCodeAt(r)-32})},compressToUint8Array:function(s){for(var r=A.compress(s),e=new Uint8Array(r.length*2),n=0,l=r.length;n<l;n++){var g=r.charCodeAt(n);e[n*2]=g>>>8,e[n*2+1]=g%256}return e},decompressFromUint8Array:function(s){if(s==null)return A.decompress(s);for(var r=new Array(s.length/2),e=0,n=r.length;e<n;e++)r[e]=s[e*2]*256+s[e*2+1];var l=[];return r.forEach(function(g){l.push(c(g))}),A.decompress(l.join(""))},compressToEncodedURIComponent:function(s){return s==null?"":A._compress(s,6,function(r){return P.charAt(r)})},decompressFromEncodedURIComponent:function(s){return s==null?"":s==""?null:(s=s.replace(/ /g,"+"),A._decompress(s.length,32,function(r){return L(P,s.charAt(r))}))},compress:function(s){return A._compress(s,16,function(r){return c(r)})},_compress:function(s,r,e){if(s==null)return"";var n,l,g={},y={},w="",C="",v="",E=2,S=3,d=2,h=[],t=0,o=0,x;for(x=0;x<s.length;x+=1)if(w=s.charAt(x),Object.prototype.hasOwnProperty.call(g,w)||(g[w]=S++,y[w]=!0),C=v+w,Object.prototype.hasOwnProperty.call(g,C))v=C;else{if(Object.prototype.hasOwnProperty.call(y,v)){if(v.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==r-1?(o=0,h.push(e(t)),t=0):o++;for(l=v.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}else{for(l=1,n=0;n<d;n++)t=t<<1|l,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=0;for(l=v.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}E--,E==0&&(E=Math.pow(2,d),d++),delete y[v]}else for(l=g[v],n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;E--,E==0&&(E=Math.pow(2,d),d++),g[C]=S++,v=String(w)}if(v!==""){if(Object.prototype.hasOwnProperty.call(y,v)){if(v.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==r-1?(o=0,h.push(e(t)),t=0):o++;for(l=v.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}else{for(l=1,n=0;n<d;n++)t=t<<1|l,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=0;for(l=v.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}E--,E==0&&(E=Math.pow(2,d),d++),delete y[v]}else for(l=g[v],n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;E--,E==0&&(E=Math.pow(2,d),d++)}for(l=2,n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;for(;;)if(t=t<<1,o==r-1){h.push(e(t));break}else o++;return h.join("")},decompress:function(s){return s==null?"":s==""?null:A._decompress(s.length,32768,function(r){return s.charCodeAt(r)})},_decompress:function(s,r,e){var n=[],l,g=4,y=4,w=3,C="",v=[],E,S,d,h,t,o,x,a={val:e(0),position:r,index:1};for(E=0;E<3;E+=1)n[E]=E;for(d=0,t=Math.pow(2,2),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;switch(l=d){case 0:for(d=0,t=Math.pow(2,8),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;x=c(d);break;case 1:for(d=0,t=Math.pow(2,16),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;x=c(d);break;case 2:return""}for(n[3]=x,S=x,v.push(x);;){if(a.index>s)return"";for(d=0,t=Math.pow(2,w),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;switch(x=d){case 0:for(d=0,t=Math.pow(2,8),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;n[y++]=c(d),x=y-1,g--;break;case 1:for(d=0,t=Math.pow(2,16),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;n[y++]=c(d),x=y-1,g--;break;case 2:return v.join("")}if(g==0&&(g=Math.pow(2,w),w++),n[x])C=n[x];else if(x===y)C=S+S.charAt(0);else return null;v.push(C),n[y++]=S+C.charAt(0),g--,S=C,g==0&&(g=Math.pow(2,w),w++)}}};return A}();typeof z!="undefined"&&z!=null&&(z.exports=ce)});var N=le(Z());var de={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},fe=()=>{if(typeof navigator=="undefined")return"default";let c=navigator.userAgent;return/Firefox\//i.test(c)?"firefox":/Chrome\//i.test(c)?"chrome":"default"},G=()=>de[fe()].filter(c=>{var P,f,L;let m=(L=(f=(P=globalThis.document)==null?void 0:P.featurePolicy)==null?void 0:f.features)==null?void 0:L.call(f);return m?m.includes(c):!0}).join("; ");async function ue(c,m={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(m=c,c=null);let P=6e4,{config:f={},headless:L,loading:A="lazy",view:s}=m,r=L||s==="headless",e=null,n=null,l=i=>{i.style.position="absolute",i.style.top="0",i.style.visibility="hidden",i.style.opacity="0"};if(typeof c=="string")e=document.querySelector(c);else if(c instanceof HTMLElement)e=c;else if(!(r&&typeof c=="object"))throw new Error("A valid container element is required.");if(!e)if(r)e=document.createElement("div"),l(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${c}"`);let g=new URL(pe(m)),y=g.origin;g.searchParams.set("embed","true"),g.searchParams.set("loading",r?"eager":A),g.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&g.searchParams.set("config","sdk");let w=m.params;typeof w=="object"&&Object.keys(w).length>0&&JSON.stringify(w).length<1800&&Object.keys(w).forEach(i=>{g.searchParams.set(i,encodeURIComponent(String(w[i])))});let C=!1,v="Cannot call API methods after calling `destroy()`.",E=[],S=(i,u="message")=>{addEventListener(u,i),E.push(i)},d=(i,u="message")=>{removeEventListener(u,i);let b=E.indexOf(i);b>-1&&E.splice(b,1)},t=await new Promise(i=>{var O,U,T,I,_,H,B,q,$;if(!e)return;let u=e.dataset.height||e.style.height;if(u&&!r){let D=isNaN(Number(u))?u:u+"px";e.style.height=D}e.dataset.defaultStyles!=="false"&&!r&&((O=e.style).backgroundColor||(O.backgroundColor="#fff"),(U=e.style).border||(U.border="1px solid black"),(T=e.style).borderRadius||(T.borderRadius="8px"),(I=e.style).boxSizing||(I.boxSizing="border-box"),(_=e.style).padding||(_.padding="0"),(H=e.style).width||(H.width="100%"),(B=e.style).height||(B.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(q=e.style).overflow||(q.overflow="hidden"),($=e.style).resize||($.resize="vertical"),getComputedStyle(e).getPropertyValue("display")==="inline"&&(e.style.display="block"));let b="livecodes",M=e.querySelector(`iframe.${b}`),p=M||document.createElement("iframe");p.classList.add(b),p.setAttribute("allow",G()),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 R=A==="eager"?"eager":"lazy";p.setAttribute("loading",R),r?l(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),S(function D(j){var F;j.source!==p.contentWindow||j.origin!==y||((F=j.data)==null?void 0:F.type)!=="livecodes-init"||(d(D),n=Number(j.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&S(function D(j){var F,J;j.source!==p.contentWindow||j.origin!==y||((F=j.data)==null?void 0:F.type)!=="livecodes-get-config"||(d(D),(J=p.contentWindow)==null||J.postMessage({type:"livecodes-config",payload:f},y))}),p.onload=()=>{i(p)},p.src=g.href,M||e.appendChild(p)}),o=new Promise(i=>{S(function u(b){var M;b.source!==t.contentWindow||b.origin!==y||((M=b.data)==null?void 0:M.type)!=="livecodes-ready"||(d(u),i(),o.settled=!0)})}),x=()=>C?Promise.reject(v):new Promise(async i=>{var b;o.settled&&i();let u={type:"livecodes-load"};(b=t.contentWindow)==null||b.postMessage(u,y),await o,i()}),a=(i,u)=>new Promise(async(b,M)=>{var U;if(C)return M(v);await x();let p=ee(),R=setTimeout(()=>{d(O),M(new Error(`SDK call "${i}" timed out after ${P}ms.`))},P);function O(T){var I,_;if(!(T.source!==t.contentWindow||T.origin!==y||((I=T.data)==null?void 0:I.type)!=="livecodes-api-response"||((_=T.data)==null?void 0:_.id)!==p)&&T.data.method===i){clearTimeout(R),d(O);let H=T.data.payload;H!=null&&H.error?M(H.error):b(H)}}S(O),(U=t.contentWindow)==null||U.postMessage({method:i,id:p,args:u},y)}),k={},Y=["load","ready","code","console","tests","destroy"],W=(i,u)=>{var b;if(C)throw new Error(v);return Y.includes(i)?(a("watch",[i]),k[i]||(k[i]=[]),(b=k[i])==null||b.push(u),{remove:()=>{var M,p;k[i]=(M=k[i])==null?void 0:M.filter(R=>R!==u),((p=k[i])==null?void 0:p.length)===0&&a("watch",[i,"unsubscribe"])}}):{remove:()=>{}}},X=i=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[i];S(async function(u){var p,R,O,U;let b=X((R=(p=u.data)==null?void 0:p.type)!=null?R:"");if(u.source!==t.contentWindow||u.origin!==y||!b||!k[b])return;let M=(O=u.data)==null?void 0:O.payload;(U=k[b])==null||U.forEach(T=>{T(M)})});let V=()=>{var i;(i=t==null?void 0:t.remove)==null||i.call(t),Object.values(k).forEach(u=>{u.length=0}),E.forEach(u=>removeEventListener("message",u)),E.length=0,K&&e&&K.unobserve(e),C=!0},K;A==="lazy"&&"IntersectionObserver"in window&&(K=new IntersectionObserver((i,u)=>{i.forEach(async b=>{b.isIntersecting&&(await x(),u.unobserve(e))})},{rootMargin:"150px"}),K.observe(e));let ee=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>x(),run:()=>a("run"),format:i=>a("format",[i]),getShareUrl:i=>a("getShareUrl",[i]),getConfig:i=>a("getConfig",[i]),setConfig:i=>a("setConfig",[i]),getCode:()=>a("getCode"),show:(i,u)=>a("show",[i,u]),runTests:()=>a("runTests"),onChange:i=>W("code",i),watch:W,exec:(i,...u)=>a("exec",[i,...u]),destroy:()=>C?Promise.reject(v):(V(),Promise.resolve())}}function pe(c={}){let{appUrl:m="https://livecodes.io",params:P={},config:f={},headless:L,import:A,lite:s,view:r,...e}=c,n;try{n=new URL(m)}catch(y){throw new Error(`${m} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(e).forEach(([y,w])=>{w!==void 0&&n.searchParams.set(y,String(w))});let g=c.view==="headless"||L;if(s&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":n.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&r!=="headless"?f.view=r:n.searchParams.set("view",r)),typeof f=="string")try{new URL(f),n.searchParams.set("config",encodeURIComponent(f))}catch(y){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&n.searchParams.set("title",f.title),f.description&&f.description.length>0&&n.searchParams.set("description",f.description),l.set("config","code/"+(0,N.compressToEncodedURIComponent)(JSON.stringify(f))));if(P&&typeof P=="object"&&Object.keys(P).length>0)try{l.set("params",(0,N.compressToEncodedURIComponent)(JSON.stringify(P)))}catch(y){Object.keys(P).forEach(w=>{n.searchParams.set(w,encodeURIComponent(String(P[w])))})}return A&&n.searchParams.set("x",encodeURIComponent(A)),g&&n.searchParams.set("headless","true"),l.toString().length>0&&(n.hash=l.toString()),n.href}export{ue as createPlayground};
/**
* LiveCodes SDK - A Code Playground That Just Works!
*
* This module is the main entry point for the LiveCodes SDK.
* It provides the core `createPlayground` and `getPlaygroundUrl` functions.
*
* @module livecodes
*/
import type { Code, Config, EmbedOptions, Language, Playground } from './models';
export type { Code, Config, EmbedOptions, Language, Playground };
/**
* Creates a LiveCodes playground.
*
* @param {string | HTMLElement} container - `HTMLElement` or a string representing a CSS selector. This is the container where the playground is rendered.
If not found, an error is thrown (except in [headless mode](https://livecodes.io/docs/sdk/headless), in which this parameter is optional and can be omitted).
* @param {EmbedOptions} options - The [embed options](https://livecodes.io/docs/sdk/js-ts#embed-options) for the playground (optional).
* @return {Promise<Playground>} A promise that resolves to a [`Playground`](https://livecodes.io/docs/api/interfaces/Playground/) object which exposes many [SDK methods](https://livecodes.io/docs/sdk/js-ts/#sdk-methods) that can be used to interact with the playground.
*/
export declare function createPlayground(container: string | HTMLElement, options?: EmbedOptions): Promise<Playground>;
export declare function createPlayground(options: EmbedOptions & {
view: 'headless';
}): Promise<Playground>;
/**
* Gets the URL to a LiveCodes playground (as a string) from the provided [options](https://livecodes.io/docs/sdk/js-ts#embed-options).
* This can be useful for providing links to run code in playgrounds.
*
* @param {EmbedOptions} options - The [options](https://livecodes.io/docs/sdk/js-ts#embed-options) for the playground.
* @return {string} The URL of the playground (as a string).
*
* large objects like config and params are store in the url hash params while the rest are in the search params
* unless config is a string in which case it is stored in searchParams
*/
export declare function getPlaygroundUrl(options?: EmbedOptions): string;
/**
* A utility function that allows compressing the stringified config object (e.g. for sharing in URL hash)
* It encodes it in base64 with a few tweaks to make it URI safe.
*
* This is the `compressToEncodedURIComponent` function re-exported from `lz-string` for convenience.
*
* @param {string} uncompressed - The string to be compressed (e.g. stringified config object)
* @return {string} The compressed string
*
* @example
* ```ts
* const compressed = compress(JSON.stringify(config));
* ```
*/
export declare const compress: (uncompressed: string) => string;
/**
* A utility function that allows decompressing the config object (compressed by {@link compress}).
* It decodes it to a string that should be JSON.parsed.
*
* This is the `decompressFromEncodedURIComponent` function re-exported from `lz-string` for convenience.
*
* @param {string} compressed - The string to be decompressed
* @return {string | null} The decompressed string or `null` if it fails
*
* @example
* ```ts
* const decompressed = decompress(str);
* if (decompressed) {
* try {
* const config = JSON.parse(decompressed);
* } catch {
* // invalid JSON
* }
* }
* ```
*/
export declare const decompress: (compressed: string) => string | null;

Sorry, the diff of this file is too big to display

/**
* LiveCodes Type Definitions
*
* This module contains all TypeScript types, interfaces, and type aliases
* used by the LiveCodes SDK, including configuration objects, editor types,
* and API definitions.
*
* @module
*/
/**
* Converts a union type to an intersection type.
* @typeParam U - The union type to convert
*/
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
/**
* Makes nested object types more readable by flattening intersecting types.
* @typeParam T - The type to prettify
*/
export type Prettify<T> = {
[K in keyof T]: T[K] extends object ? Prettify<T[K]> : T[K];
} & {};
/**
* Language name, alias or extension.
*/
export type Language = 'html' | 'htm' | 'markdown' | 'md' | 'mdown' | 'mkdn' | 'mdx' | 'astro' | 'pug' | 'jade' | 'haml' | 'asciidoc' | 'adoc' | 'asc' | 'mustache' | 'handlebars' | 'hbs' | 'ejs' | 'eta' | 'nunjucks' | 'njk' | 'liquid' | 'liquidjs' | 'dot' | 'twig' | 'vento' | 'vto' | 'art-template' | 'art' | 'jinja' | 'bbcode' | 'bb' | 'mjml' | 'diagrams' | 'diagram' | 'graph' | 'plt' | 'richtext' | 'rte' | 'rich' | 'rte.html' | 'css' | 'scss' | 'sass' | 'less' | 'stylus' | 'styl' | 'stylis' | 'postcss' | 'javascript' | 'js' | 'mjs' | 'json' | 'babel' | 'es' | 'sucrase' | 'typescript' | 'flow' | 'ts' | 'mts' | 'jsx' | 'tsx' | 'react' | 'react-jsx' | 'react.jsx' | 'react-tsx' | 'react.tsx' | 'react-native' | 'react-native.jsx' | 'react-native-tsx' | 'react-native.tsx' | 'vue' | 'vue3' | 'vue2' | 'vue-app' | 'app.vue' | 'svelte' | 'svelte-app' | 'app.svelte' | 'stencil' | 'stencil.tsx' | 'solid' | 'solid.jsx' | 'solid.tsx' | 'riot' | 'riotjs' | 'malina' | 'malinajs' | 'ripple' | 'ripplejs' | 'xht' | 'coffeescript' | 'coffee' | 'livescript' | 'ls' | 'civet' | 'clio' | 'imba' | 'assemblyscript' | 'as' | 'python' | 'py' | 'pyodide' | 'python-wasm' | 'py-wasm' | 'pythonwasm' | 'pywasm' | 'py3' | 'wasm.py' | 'r' | 'rlang' | 'rstats' | 'r-wasm' | 'ruby' | 'rb' | 'ruby-wasm' | 'wasm.rb' | 'rubywasm' | 'go' | 'golang' | 'go-wasm' | 'wasm.go' | 'gowasm' | 'php' | 'php-wasm' | 'phpwasm' | 'wasm.php' | 'cpp' | 'c' | 'C' | 'cp' | 'cxx' | 'c++' | 'cppm' | 'ixx' | 'ii' | 'hpp' | 'h' | 'cpp-wasm' | 'cppwasm' | 'cwasm' | 'wasm.cpp' | 'clang' | 'clang.cpp' | 'java' | 'csharp' | 'csharp-wasm' | 'cs' | 'cs-wasm' | 'wasm.cs' | 'perl' | 'pl' | 'pm' | 'lua' | 'lua-wasm' | 'luawasm' | 'wasm.lua' | 'teal' | 'tl' | 'fennel' | 'fnl' | 'julia' | 'jl' | 'scheme' | 'scm' | 'commonlisp' | 'common-lisp' | 'lisp' | 'clojurescript' | 'clojure' | 'cljs' | 'clj' | 'cljc' | 'edn' | 'gleam' | 'swift' | 'rescript' | 'res' | 'resi' | 'reason' | 're' | 'rei' | 'ocaml' | 'ml' | 'mli' | 'tcl' | 'wat' | 'wast' | 'webassembly' | 'wasm' | 'Binary' | 'sql' | 'sqlite' | 'sqlite3' | 'pg.sql' | 'pgsql.sql' | 'pgsql' | 'pg' | 'pglite' | 'pglite.sql' | 'postgresql' | 'postgres' | 'postgre.sql' | 'postgresql.sql' | 'prolog.pl' | 'prolog' | 'minizinc' | 'mzn' | 'dzn' | 'blockly' | 'blockly.xml' | 'xml' | 'pintora';
/**
* The identifier for each code editor pane in the playground.
*/
export type EditorId = 'markup' | 'style' | 'script';
/**
* Represents a position in a code editor,
* with 1-based line number and (optional) 1-based column number.
*/
export interface EditorPosition {
/** 1-based line number */
lineNumber: number;
/** 1-based column number (optional) */
column?: number;
}
/**
* The app theme mode.
*/
export type Theme = 'light' | 'dark';
/**
* CSS preprocessors and PostCSS plugins.
*/
export type Processor = 'postcss' | 'postcssImportUrl' | 'tailwindcss' | 'windicss' | 'unocss' | 'tokencss' | 'lightningcss' | 'autoprefixer' | 'postcssPresetEnv' | 'cssmodules' | 'purgecss' | 'cssnano';
/**
* CSS presets.
*/
export type CssPresetId = '' | 'normalize.css' | 'reset-css';
/**
* CDN providers for external resources.
*/
export type CDN = 'jspm' | 'skypack' | 'jsdelivr' | 'fastly.jsdelivr' | 'gcore.jsdelivr' | 'testingcf.jsdelivr' | 'jsdelivr.b-cdn' | 'jsdelivr.gh' | 'fastly.jsdelivr.gh' | 'gcore.jsdelivr.gh' | 'testingcf.jsdelivr.gh' | 'jsdelivr.b-cdn.gh' | 'jsdelivr.esm' | 'fastly.jsdelivr.esm' | 'gcore.jsdelivr.esm' | 'testingcf.jsdelivr.esm' | 'jsdelivr.b-cdn.esm' | 'esm.run' | 'esm.sh' | 'esbuild' | 'bundle.run' | 'unpkg' | 'npmcdn' | 'statically';
/**
* Supported UI/app languages for localization.
*/
export type AppLanguage = 'auto' | 'ar' | 'bn' | 'de' | 'en' | 'es' | 'fa' | 'fr' | 'hi' | 'id' | 'it' | 'ja' | 'nl' | 'pt' | 'tr' | 'ru' | 'ur' | 'zh-CN';
/**
* Starter template names.
*/
export type TemplateName = 'blank' | 'javascript' | 'typescript' | 'react' | 'react-native' | 'vue2' | 'vue' | 'angular' | 'preact' | 'svelte' | 'solid' | 'lit' | 'stencil' | 'mdx' | 'astro' | 'riot' | 'malina' | 'jquery' | 'backbone' | 'knockout' | 'jest' | 'jest-react' | 'bootstrap' | 'tailwindcss' | 'shadcn-ui' | 'daisyui' | 'd3' | 'phaser' | 'coffeescript' | 'livescript' | 'civet' | 'clio' | 'imba' | 'rescript' | 'reason' | 'ocaml' | 'python' | 'python-wasm' | 'r' | 'ruby' | 'ruby-wasm' | 'go' | 'go-wasm' | 'php' | 'php-wasm' | 'cpp' | 'cpp-wasm' | 'java' | 'csharp-wasm' | 'perl' | 'lua' | 'lua-wasm' | 'teal' | 'fennel' | 'julia' | 'scheme' | 'commonlisp' | 'clojurescript' | 'gleam' | 'tcl' | 'markdown' | 'assemblyscript' | 'wat' | 'sql' | 'postgresql' | 'prolog' | 'minizinc' | 'blockly' | 'diagrams';
/**
* Tools in the tools pane.
*/
export type ToolName = 'console' | 'compiled' | 'tests';
/**
* Status of the tools pane.
*/
export type ToolsPaneStatus = 'closed' | 'open' | 'full' | 'none' | '';
/**
* API commands for the SDK.
*/
export type APICommands = 'setBroadcastToken' | 'showVersion';
/**
* Screen names in the app.
*/
export type ScreenName = 'login' | 'info' | 'new' | 'open' | 'assets' | 'add-asset' | 'snippets' | 'add-snippet' | 'import' | 'resources' | 'share' | 'embed' | 'deploy' | 'sync' | 'backup' | 'broadcast' | 'welcome' | 'about' | 'custom-settings' | 'editor-settings' | 'code-to-image' | 'test-editor' | 'keyboard-shortcuts';
/**
* Themes for the Monaco editor.
*/
export type MonacoTheme = 'active4d' | 'all-hallows-eve' | 'amy' | 'birds-of-paradise' | 'blackboard' | 'brilliance-black' | 'brilliance-dull' | 'catppuccin-latte' | 'catppuccin-frappe' | 'catppuccin-macchiato' | 'catppuccin-mocha' | 'chrome-devtools' | 'clouds-midnight' | 'clouds' | 'cobalt' | 'cobalt2' | 'custom-vs-light' | 'custom-vs-dark' | 'dawn' | 'dracula' | 'dreamweaver' | 'eiffel' | 'espresso-libre' | 'github' | 'github-dark' | 'github-light' | 'hc-black' | 'hc-light' | 'idle' | 'idlefingers' | 'iplastic' | 'katzenmilch' | 'krtheme' | 'kuroir' | 'lazy' | 'magicwb-amiga' | 'merbivore-soft' | 'merbivore' | 'monochrome' | 'monochrome-dark' | 'monokai' | 'monokai-bright' | 'monoindustrial' | 'night-owl' | 'nord' | 'oceanic-next' | 'pastels-on-dark' | 'slush-and-poppies' | 'solarized-dark' | 'solarized-light' | 'spacecadet' | 'sunburst' | 'textmate-mac-classic' | 'tomorrow' | 'tomorrow-night' | 'tomorrow-night-blue' | 'tomorrow-night-bright' | 'tomorrow-night-eighties' | 'twilight' | 'upstream-sunburst' | 'vibrant-ink' | 'vs' | 'vs-dark' | 'xcode-default' | 'zenburnesque';
/**
* Themes for the CodeMirror editor.
*/
export type CodemirrorTheme = 'amy' | 'aura' | 'ayu-light' | 'barf' | 'basic-light' | 'basic-dark' | 'bespin' | 'birds-of-paradise' | 'boys-and-girls' | 'catppuccin-latte' | 'catppuccin-frappe' | 'catppuccin-macchiato' | 'catppuccin-mocha' | 'clouds' | 'cm-light' | 'cobalt' | 'cool-glow' | 'dracula' | 'espresso' | 'github-dark' | 'github-light' | 'gruvbox-dark' | 'gruvbox-light' | 'material-dark' | 'material-light' | 'monochrome' | 'monochrome-dark' | 'noctis-lilac' | 'nord' | 'one-dark' | 'rose-pine-dawn' | 'smoothy' | 'solarized-light' | 'solarized-dark' | 'tokyo-night' | 'tokyo-night-day' | 'tokyo-night-storm' | 'tomorrow';
/**
* Themes for the CodeJar editor.
*/
export type CodejarTheme = 'a11y-dark' | 'atom-dark' | 'base16-ateliersulphurpool-light' | 'catppuccin-latte' | 'catppuccin-frappe' | 'catppuccin-macchiato' | 'catppuccin-mocha' | 'cb' | 'coldark-cold' | 'coldark-dark' | 'coy' | 'coy-without-shadows' | 'darcula' | 'dark' | 'dracula' | 'duotone-dark' | 'duotone-earth' | 'duotone-forest' | 'duotone-light' | 'duotone-sea' | 'duotone-space' | 'funky' | 'ghcolors' | 'gruvbox-dark' | 'gruvbox-light' | 'holi-theme' | 'hopscotch' | 'laserwave' | 'lucario' | 'material-dark' | 'material-light' | 'material-oceanic' | 'monochrome' | 'monochrome-dark' | 'night-owl' | 'nord' | 'nord-2' | 'okaidia' | 'one-dark' | 'one-light' | 'pojoaque' | 'shades-of-purple' | 'solarized-dark-atom' | 'solarized-light' | 'synthwave84' | 'tomorrow' | 'twilight' | 'vs' | 'vsc-dark-plus' | 'xonokai' | 'z-touchs';
/**
* Editor theme that can be a Monaco, CodeMirror, or CodeJar theme,
* optionally with editor prefix and/or a theme suffix (light/dark).
* See [docs](https://livecodes.io/docs/configuration/configuration-object#editortheme) for details.
*/
export type EditorTheme = MonacoTheme | CodemirrorTheme | CodejarTheme | `${MonacoTheme}@${Theme}` | `${CodemirrorTheme}@${Theme}` | `${CodejarTheme}@${Theme}` | `monaco:${MonacoTheme}` | `codemirror:${CodemirrorTheme}` | `codejar:${CodejarTheme}` | `monaco:${MonacoTheme}@${Theme}` | `codemirror:${CodemirrorTheme}@${Theme}` | `codejar:${CodejarTheme}@${Theme}`;
/**
* Represents the result of a single test.
*/
export interface TestResult {
/** Time taken to run the test in milliseconds. */
duration: number;
/** Array of error messages if the test failed. */
errors: string[];
/** The status of the test. */
status: 'pass' | 'fail' | 'skip';
/** The path to the test in the test suite. */
testPath: string[];
}
/**
* Custom type declarations for module imports.
*/
export interface Types {
/** The module name and its type declaration URL */
[key: string]: string | {
url: string;
declareAsModule?: boolean;
declareAsGlobal?: boolean;
autoload?: boolean;
};
}
/**
* Configuration for each code editor pane in the playground.
*/
export interface Editor {
/**
* A language name, extension or alias (as defined in [language documentations](https://livecodes.io/docs/languages/)).
*
* For the list of supported values, see [Language](https://livecodes.io/docs/api/type-aliases/Language)
*/
language: Language;
/**
* The initial content of the code editor.
* @default ""
*/
content?: string;
/**
* A URL to load `content` from. It has to be a valid URL that is CORS-enabled.
*
* The URL is only fetched if `content` property had no value.
*/
contentUrl?: string;
/**
* Hidden content that gets evaluated without being visible in the code editor.
*
* This can be useful in embedded playgrounds (e.g. for adding helper functions, utilities or tests)
*/
hiddenContent?: string;
/**
* A URL to load `hiddenContent` from. It has to be a valid URL that is CORS-enabled.
*
* The URL is only fetched if `hiddenContent` property had no value.
*/
hiddenContentUrl?: string;
/**
* Lines that get folded when the editor loads.
*
* This can be used for less relevant content.
* @example [{ from: 5, to: 8 }, { from: 15, to: 20 }]
*/
foldedLines?: Array<{
from: number;
to: number;
}>;
/**
* If set, this is used as the title of the editor in the UI,
* overriding the default title set to the language name
* (e.g. `"Python"` can be used instead of `"Py (Wasm)"`).
*/
title?: string;
/**
* If `true`, the title of the code editor is hidden, however its code is still evaluated.
*
* This can be useful in embedded playgrounds (e.g. for hiding unnecessary code).
*/
hideTitle?: boolean;
/**
* The order of the editor in the UI.
* @default 0
*/
order?: number;
/**
* A CSS selector to load content from [DOM import](https://livecodes.io/docs/features/import#import-code-from-dom).
*/
selector?: string;
/**
* The initial position of the cursor in the code editor.
* @example {lineNumber: 5, column: 10}
*/
position?: EditorPosition;
}
/**
* Custom settings for the playground.
*/
export type CustomSettings = Partial<{
[key in Language | Processor]: any;
} & {
template: {
data?: any;
prerender?: boolean;
};
scriptType: 'module' | 'application/javascript' | 'application/ecmascript' | 'text/javascript' | 'text/ecmascript' | '' | 'text/liquid' | 'text/python' | 'text/r' | 'text/ruby-wasm' | 'text/x-uniter-php' | 'text/php-wasm' | 'text/cpp' | 'text/java' | 'text/csharp-wasm' | 'text/perl' | 'text/julia' | 'text/biwascheme' | 'text/commonlisp' | 'text/tcl' | 'text/prolog' | 'text/minizinc' | 'text/go-wasm' | 'application/json' | 'application/lua' | 'text/fennel' | 'application/wasm-uint8';
mapImports: boolean;
imports: Record<string, string>;
convertCommonjs: boolean;
defaultCDN: CDN;
types: Types;
}>;
/**
* Configuration for code formatting options.
*/
export interface FormatterConfig {
/**
* If `true`, lines are indented with tabs instead of spaces.
* @default false
*/
useTabs: boolean;
/**
* The number of spaces per indentation-level.
* @default 2
*/
tabSize: number;
/**
* Configures Prettier [code formatter](https://livecodes.io/docs/features/code-format) to use semi-colons.
* @default true
*/
semicolons: boolean;
/**
* Configures Prettier [code formatter](https://livecodes.io/docs/features/code-format) to use single quotes instead of double quotes.
* @default false
*/
singleQuote: boolean;
/**
* Configures Prettier [code formatter](https://livecodes.io/docs/features/code-format) to use [trailing commas](https://prettier.io/docs/en/options.html#trailing-commas).
* @default true
*/
trailingComma: boolean;
}
/**
* Configuration for code editor settings.
*/
export interface EditorConfig {
/**
* Selects the [code editor](https://livecodes.io/docs/features/editor-settings#code-editor) to use.
*
* If `undefined` (the default), Monaco editor is used on desktop,
* CodeMirror is used on mobile and in `simple` mode,
* while CodeJar is used in `codeblock` mode, in `lite` mode and in `readonly` playgrounds.
*
* If set to `auto`, Monaco editor is used on desktop and CodeMirror is used on mobile regardless of other settings.
*
* @default undefined
*/
editor: 'monaco' | 'codemirror' | 'codejar' | 'auto' | undefined;
/**
* Sets the app [theme](https://livecodes.io/docs/features/themes) to light/dark mode.
* @default "dark"
*/
theme: Theme;
/**
* Sets the app theme color.
* If `undefined`, it is set to `"hsl(214, 40%, 50%)"`.
* @default undefined
*/
themeColor: string | undefined;
/**
* Sets the [code editor](https://livecodes.io/docs/features/editor-settings) themes.
*
* See docs for [editor themes](https://livecodes.io/docs/configuration/configuration-object#editortheme) for details.
*
* @example "vs"
* @example "monaco:twilight, codemirror:one-dark"
* @example ["vs@light"]
* @example ["vs@light", "vs-dark@dark"]
* @example ["monaco:vs@light", "codemirror:github-light@light", "dracula@dark"]
*/
editorTheme: EditorTheme[] | string | undefined;
/**
* Sets the [code editor](https://livecodes.io/docs/features/editor-settings) font family.
*/
fontFamily: string | undefined;
/**
* Sets the font size.
*
* If `undefined` (the default), the font size is set to 14 for the full app and 12 for [embeds](https://livecodes.io/docs/features/embeds).
* @default undefined
*/
fontSize: number | undefined;
/**
* If `true`, lines are indented with tabs instead of spaces.
*
* Also used in [code formatting](https://livecodes.io/docs/features/code-format).
* @default false
*/
useTabs: boolean;
/**
* The number of spaces per indentation-level.
*
* Also used in [code formatting](https://livecodes.io/docs/features/code-format).
* @default 2
*/
tabSize: number;
/**
* Show line numbers in [code editor](https://livecodes.io/docs/features/editor-settings).
* @default true
*/
lineNumbers: boolean | 'relative';
/**
* Enables word-wrap for long lines.
* @default false
*/
wordWrap: boolean;
/**
* When set to `true`, regions marked by `#region` and `#endregion` comments are folded when the project is loaded.
* @default false
*/
foldRegions: boolean;
/**
* Use auto-complete to close brackets and quotes.
* @default true
*/
closeBrackets: boolean;
/**
* Enables minimap in code editor.
* @default false
*/
minimap: boolean;
/**
* Enables [Emmet](https://livecodes.io/docs/features/editor-settings#emmet).
* @default true
*/
emmet: boolean;
/**
* Sets [editor mode](https://livecodes.io/docs/features/editor-settings#editor-modes).
*/
editorMode: 'vim' | 'emacs' | undefined;
}
/**
* User preferences and settings for the playground.
*/
export interface UserConfig extends EditorConfig, FormatterConfig {
/**
* If `true`, the result page is automatically updated on code change,
* after time [delay](https://livecodes.io/docs/configuration/configuration-object#delay).
* @default true
*/
autoupdate: boolean;
/**
* If `true`, the project is automatically saved on code change,
* after time [delay](https://livecodes.io/docs/configuration/configuration-object#delay).
* @default false
*/
autosave: boolean;
/**
* If `true`, the project is watched for code changes which trigger tests to auto-run.
* @default false
*/
autotest: boolean;
/**
* Time delay (in milliseconds) following code change,
* after which the result page is updated (if [`autoupdate`](https://livecodes.io/docs/configuration/configuration-object#autoupdate) is `true`)
* and/or the project is saved (if [`autosave`](https://livecodes.io/docs/configuration/configuration-object#autosave) is `true`).
* @default 1500
*/
delay: number;
/**
* If `true`, the code is automatically [formatted](https://livecodes.io/docs/features/code-format) on saving the project.
* @default false
*/
formatOnsave: boolean;
/**
* Sets the app layout to horizontal or vertical.
* If set to `"responsive"` (the default) or `undefined`,
* the layout is vertical in small screens when the playground height is larger than its width,
* otherwise horizontal.
* @default "responsive"
*/
layout: 'responsive' | 'horizontal' | 'vertical' | undefined;
/**
* Enables [recovering last unsaved project](https://livecodes.io/docs/features/recover) when the app is reopened.
* @default true
*/
recoverUnsaved: boolean;
/**
* Enables [showing element spacing](https://livecodes.io/docs/features/result#show-spacings) in the result page.
* @default false
*/
showSpacing: boolean;
/**
* If `true`, the [welcome screen](https://livecodes.io/docs/features/welcome) is displayed when the app loads.
*/
welcome: boolean;
/**
* Sets the app UI language used.
*/
appLanguage: AppLanguage | undefined;
}
/**
* These are properties that define how the app behaves.
*/
export interface AppConfig {
/**
* If `true`, editors are loaded in read-only mode, where the user is not allowed to change the code.
*
* By default, when readonly is set to true, the light-weight code editor [CodeJar](https://livecodes.io/docs/features/editor-settings#code-editor) is used.
* If you wish to use another editor, set the [editor](https://livecodes.io/docs/configuration/configuration-object#editor) property.
* @default false
*/
readonly: boolean;
/**
* If `false`, the UI will not show the menu that allows changing editor language.
* @default true
*/
allowLangChange: boolean;
/**
* Sets the [default view](https://livecodes.io/docs/features/default-view) for the playground.
* @default "split"
*/
view?: 'split' | 'editor' | 'result';
/**
* Sets the [display mode](https://livecodes.io/docs/features/display-modes).
* @default "full"
*/
mode: 'full' | 'focus' | 'lite' | 'simple' | 'editor' | 'codeblock' | 'result';
/**
* Sets enabled and active tools and status of [tools pane](https://livecodes.io/docs/features/tools-pane).
* @default { enabled: "all", active: "", status: "" }
* @example
* ```js
* {
* "tools": {
* "enabled": ["console", "compiled"],
* "active": "console",
* "status": "open"
* }
* }
* ```
*/
tools: Partial<{
enabled: ToolName[] | 'all';
active: ToolName | '';
status: ToolsPaneStatus;
}>;
/**
* Sets result page [zoom level](https://livecodes.io/docs/features/result#result-page-zoom).
*/
zoom: 1 | 0.5 | 0.25;
}
/**
* The properties that define the content of the current [project](https://livecodes.io/docs/features/projects).
*/
export interface ContentConfig {
/**
* Project title.
* This is used as [result page](https://livecodes.io/docs/features/result) title and title meta tag.
* Also used in project search.
* @default "Untitled Project"
*/
title: string;
/**
* Project description. Used in [project](https://livecodes.io/docs/features/projects) search
* and [result page](https://livecodes.io/docs/features/result) description meta tag.
* @default ""
*/
description: string;
/**
* Content added to the [result page](https://livecodes.io/docs/features/result) `<head>` element.
* @default '<meta charset="UTF-8" />\n<meta name="viewport" content="width=device-width, initial-scale=1.0" />'
*/
head: string;
/**
* Attributes added to the [result page](https://livecodes.io/docs/features/result) `<html>` element.
* It can be an object or a string.
* @example <caption>Both of these become `<html lang="en" class="dark">`</caption>
* { lang: "en", class: "dark" }
* 'lang="en" class="dark"'
*/
htmlAttrs: Record<string, string> | string;
/**
* Project tags.
* Used in [project](https://livecodes.io/docs/features/projects) filter and search.
* @default []
*/
tags: string[];
/**
* Selects the active editor to show.
*
* Defaults to the last used editor for user, otherwise `"markup"`
* @type {`"markup"` | `"style"` | `"script"` | `undefined`}
*/
activeEditor: EditorId | undefined;
/**
* List of enabled languages.
*
* Defaults to all supported languages in full app and only current editor languages in [embeds](https://livecodes.io/docs/features/embeds).
*/
languages: Array<Language | Processor> | undefined;
/**
* An object that configures the language and content of the markup editor.
*
* See [docs](https://livecodes.io/docs/configuration/configuration-object/#markup) for details.
* @default { language: "html", content: "" }
*/
markup: Prettify<Editor>;
/**
* An object that configures the language and content of the style editor.
*
* See [docs](https://livecodes.io/docs/configuration/configuration-object/#markup) for details.
* @default { language: "css", content: "" }
*/
style: Prettify<Editor>;
/**
* An object that configures the language and content of the script editor.
*
* See [docs](https://livecodes.io/docs/configuration/configuration-object/#markup) for details.
* @default { language: "javascript", content: "" }
*/
script: Prettify<Editor>;
/**
* List of URLs for [external stylesheets](https://livecodes.io/docs/features/external-resources) to add to the [result page](https://livecodes.io/docs/features/result).
*/
stylesheets: string[];
/**
* List of URLs for [external scripts](https://livecodes.io/docs/features/external-resources) to add to the [result page](https://livecodes.io/docs/features/result).
*/
scripts: string[];
/**
* [CSS Preset](https://livecodes.io/docs/features/external-resources#css-presets) to use.
* @type {"" | "normalize.css" | "reset-css"}
*/
cssPreset: CssPresetId;
/**
* List of enabled [CSS processors](https://livecodes.io/docs/features/css/#css-processors).
*
* For the list of available processors, see [Processor](https://livecodes.io/docs/api/internal/type-aliases/Processor)
*/
processors: Processor[];
/**
* Defines [custom settings](https://livecodes.io/docs/advanced/custom-settings) for the current project.
*/
customSettings: Prettify<CustomSettings>;
/**
* Allows specifying custom [import maps](https://github.com/WICG/import-maps) for [module imports](https://livecodes.io/docs/features/module-resolution#custom-module-resolution).
*
* **Example**
*
* Setting `imports` like this:
* ```js
* "imports": {
* "moment": "https://cdn.jsdelivr.net/npm/moment@2.29.4/dist/moment.js"
* }
* ```
* results in the following import map:
* ```html
* <script type="importmap">
* {
* "imports": {
* "moment": "https://cdn.jsdelivr.net/npm/moment@2.29.4/dist/moment.js"
* }
* }
* </script>
* ```
* See docs for [Imports](https://livecodes.io/docs/configuration/configuration-object#imports)
* and [Custom Module Resolution](https://livecodes.io/docs/features/module-resolution/#custom-module-resolution)
*/
imports: {
[key: string]: string;
};
/**
* Allows providing custom TypeScript type declarations for better [editor intellisense](https://livecodes.io/docs/features/intellisense).
*
* It is an object where each key represents module name and value represents the types.
*
* See docs for [Types](https://livecodes.io/docs/configuration/configuration-object#types)
* and [Custom Types](https://livecodes.io/docs/features/intellisense#custom-types)
*
* @example
* ```js
* {
* "types": {
* "my-demo-lib": "https://my-custom-domain/my-type-declarations.d.ts"
* }
* }
* ```
* @example
* ```
* {
* "types": {
* "my-demo-lib": {
* "url": "https://my-custom-domain/types.d.ts",
* "autoload": true,
* "declareAsModule": true
* }
* }
* ```
*/
types: Prettify<Types>;
/**
* Configures the [language](https://livecodes.io/docs/features/tests#supported-languages)
* and content of [tests](https://livecodes.io/docs/features/tests).
*/
tests: Prettify<Partial<Editor>> | undefined;
/**
* This is a read-only property which specifies the current LiveCodes version.
*
* Version specified in [exported](https://livecodes.io/docs/features/export) projects allows automatically upgrading the project configuration when imported by an app with a newer version.
*/
readonly version: string;
}
/**
* The playground [configuration object](https://livecodes.io/docs/configuration/configuration-object).
*
* It is an object that holds the configuration and state of the playground.
*
* See [docs](https://livecodes.io/docs/configuration/configuration-object) for details.
*/
/**
* The playground configuration interface combining content, app, and user settings.
*/
export interface Config extends ContentConfig, AppConfig, UserConfig {
}
/**
* An object that contains the language, content and compiled code for each of the 3 [code editors](https://livecodes.io/docs/features/projects)
* and the [result page](https://livecodes.io/docs/features/result) HTML.
*
* See [docs](https://livecodes.io/docs/api/interfaces/Code) for details.
*/
export interface Code {
/** Markup editor code. */
markup: {
/** The language of the code. */
language: Language;
/** The source code. */
content: string;
/** The compiled code. */
compiled: string;
};
/** Style editor code. */
style: {
/** The language of the code. */
language: Language;
/** The source code. */
content: string;
/** The compiled code. */
compiled: string;
};
/** Script editor code. */
script: {
/** The language of the code. */
language: Language;
/** The source code. */
content: string;
/** The compiled code. */
compiled: string;
};
/** The HTML content of the result page. */
result: string;
}
/**
* Union of all watch function types for playground events.
*/
export type WatchFns = WatchLoad | WatchReady | WatchCode | WatchConsole | WatchTests | WatchDestroy;
/**
* Called when the playground first loads.
*/
export type WatchLoad = (event: 'load', fn: () => void) => {
remove: () => void;
};
/**
* Called when a new project is loaded (including when [imported](https://livecodes.io/docs/features/import)) and the playground is ready to run.
*/
export type WatchReady = (event: 'ready', fn: (data: {
config: Config;
}) => void) => {
remove: () => void;
};
/**
* Called when the playground "content" is changed (see [`getCode`](https://livecodes.io/docs/sdk/js-ts#getcode) and [`getConfig`](https://livecodes.io/docs/sdk/js-ts#getcode)).
*
* This includes changes in:
* - Code (in editors)
* - Editor [languages](https://livecodes.io/docs/languages/)
* - [CSS processors](https://livecodes.io/docs/features/css#css-processors)
* - [External resources](https://livecodes.io/docs/features/external-resources)
* - Project info (e.g. allows adding content in page head and attributes to `<html>` element)
* - [Custom settings](https://livecodes.io/docs/advanced/custom-settings) (e.g. allows changing [import maps](https://livecodes.io/docs/features/module-resolution#custom-module-resolution))
* - Project title
* - [Test](https://livecodes.io/docs/features/tests) code
*/
/**
* Watch function type for code changes in the playground.
*/
export type WatchCode = (event: 'code', fn: (data: {
code: Code;
config: Config;
}) => void) => {
remove: () => void;
};
/**
* Called when console methods are called in the result page.
*/
export type WatchConsole = (event: 'console', fn: (data: {
method: string;
args: any[];
}) => void) => {
remove: () => void;
};
/**
* Called when test results are available.
*/
export type WatchTests = (event: 'tests', fn: (data: {
results: TestResult[];
error?: string;
}) => void) => {
remove: () => void;
};
/**
* Called when the playground is destroyed.
*/
export type WatchDestroy = (event: 'destroy', fn: () => void) => {
remove: () => void;
};
/**
* The event name type for SDK watch functions.
*/
export type SDKEvent = Parameters<WatchFns>[0];
/**
* The event handler type for SDK watch functions.
*/
export type SDKEventHandler = Parameters<WatchFns>[1];
/**
* The combined watch function type that handles all events.
*/
export type WatchFn = UnionToIntersection<WatchFns>;
/**
* The SDK API interface for playground interaction.
*/
export interface API {
/**
* Runs the [result page](https://livecodes.io/docs/features/result) (after any required compilation for code).
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* await playground.run();
* // new result page is displayed
* });
* ```
*/
run: () => Promise<void>;
/**
* Formats the code.
*
* By default, the code in all editors (markup, style and script) is formatted.
* To format only the active editor, the value `false` should be passed as an argument.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* await playground.format();
* // code in editors is formatted
* });
* ```
*/
format: (allEditors?: boolean) => Promise<void>;
/**
* Gets a [share url](https://livecodes.io/docs/features/share) for the current project.
*
* By default, the url has a long query string representing the compressed encoded config object.
* If the argument `shortUrl` was set to `true`, a short url is generated.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* const longUrl = await playground.getShareUrl();
* const shortUrl = await playground.getShareUrl(true);
* });
* ```
*/
getShareUrl: (shortUrl?: boolean) => Promise<string>;
/**
* Gets a [configuration object](https://livecodes.io/docs/configuration/configuration-object) representing the playground state.
*
* This can be used to restore state if passed as an [EmbedOptions](https://livecodes.io/docs/sdk/js-ts#embed-options) property when [creating playgrounds](https://livecodes.io/docs/sdk/js-ts/#createplayground),
* or can be manipulated and loaded in run-time using [`setConfig`](https://livecodes.io/docs/sdk/js-ts#setconfig) method.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* const config = await playground.getConfig();
* });
* ```
*/
getConfig: (contentOnly?: boolean) => Promise<Config>;
/**
* Loads a new project using the passed configuration object.
* If the config is a string, it is assumed to be a URL to a JSON file that contains the configuration object.
*
* @throws It throws an error if the config object (or URL) is invalid.
*
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* const config = {
* markup: {
* language: "html",
* content: "Hello World!",
* },
* };
* const newConfig = await playground.setConfig(config);
* // new project loaded
* });
* ```
*/
setConfig: (config: Partial<Config> | string) => Promise<Config>;
/**
* Gets the playground code (including source code, source language and compiled code) for each editor (markup, style, script), in addition to result page HTML.
*
* See [Code](https://livecodes.io/docs/api/interfaces/Code) for the structure of the returned object.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* const code = await playground.getCode();
*
* // source code, language and compiled code for the script editor
* const { content, language, compiled } = code.script;
*
* // result page HTML
* const result = code.result;
* });
* ```
*/
getCode: () => Promise<Code>;
/**
* Shows the selected panel.
*
* See [docs](https://livecodes.io/docs/sdk/js-ts#show) for details.
* @example
* await playground.show("style");
* await playground.show("toggle-result");
* await playground.show("result", { full: true });
* await playground.show("script");
* await playground.show("result", { zoom: 0.5 });
* await playground.show("console", { full: true });
*/
show: (panel: EditorId | 'editor' | 'result' | 'toggle-result' | ToolName, options?: {
full?: boolean;
line?: number;
column?: number;
zoom?: Config['zoom'];
}) => Promise<void>;
/**
* Runs project [tests](https://livecodes.io/docs/features/tests) (if present) and gets test results.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* const { results } = await playground.runTests();
* });
* ```
*/
runTests: () => Promise<{
results: TestResult[];
}>;
/**
* Runs a callback function when code changes.
*
* @deprecated Use [`watch`](https://livecodes.io/docs/sdk/js-ts#watch) method instead.
*/
onChange: (fn: (data: {
code: Code;
config: Config;
}) => void) => {
remove: () => void;
};
/**
* Allows to watch for various playground events.
* It takes 2 arguments: event name and a callback function that will be called on every event.
*
* event name can be one of: `"load" | "ready" | "code" | "console" | "tests" | "destroy"`
*
* In some events, the callback function will be called with an object that supplies relevant data to the callback function (e.g. code, console output, test results).
*
* The watch method returns an object with a single method (`remove`), which when called will remove the callback from watching further events.
*
* See [docs](https://livecodes.io/docs/sdk/js-ts#watch) for details.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then((playground) => {
* const codeWatcher = playground.watch("code", ({ code, config }) => {
* // this will run on every code change
* console.log("code:", code);
* console.log("config:", config);
* });
*
* const consoleWatcher = playground.watch("console", ({ method, args }) => {
* // this will run on every console output
* console[method](...args);
* });
*
* const testsWatcher = playground.watch("tests", ({ results }) => {
* // this will run when tests run
* results.forEach((testResult) => {
* console.log("status:", testResult.status); // "pass", "fail" or "skip"
* console.log(testResult.errors); // array of errors as strings
* });
* });
*
* // then later
* codeWatcher.remove();
* consoleWatcher.remove();
* testsWatcher.remove();
* // events are no longer watched
* });
* ```
*/
watch: WatchFn;
/**
* Executes custom commands, including: `"setBroadcastToken"` and `"showVersion"`.
*
* See [docs](https://livecodes.io/docs/sdk/js-ts#exec) for details.
*/
exec: (command: APICommands, ...args: any[]) => Promise<{
output: any;
} | {
error: string;
}>;
/**
* Destroys the playground instance, and removes event listeners.
*
* Further call to any SDK methods throws an error.
* @example
* ```ts
* import { createPlayground } from "livecodes";
*
* createPlayground("#container").then(async (playground) => {
* await playground.destroy();
* // playground destroyed
* // any further SDK call throws an error
* });
* ```
*/
destroy: () => Promise<void>;
}
/**
* An object that represents the LiveCodes playground instance.
*
* The object exposes multiple [methods](https://livecodes.io/docs/sdk/js-ts/#sdk-methods) that can be used to interact with the playground.
*
* See [docs](https://livecodes.io/docs/sdk/js-ts) for details.
*/
export interface Playground extends API {
/**
* Loads the playground, if not already loaded.
*
* When the embed option [loading](https://livecodes.io/docs/sdk/js-ts#loading) is set to `"click"`, the playground is not loaded automatically.
* Instead, a screen is shown with "Click to load" button. Calling the SDK method `load()` allows loading the playground.
*
* If the playground was not loaded, calling any other method will load the playground first before executing.
*/
load: () => Promise<void>;
}
/**
* A CSS selector for importing code from DOM.
*
* See [docs](https://livecodes.io/docs/features/import/#import-code-from-dom) for details.
*/
export type languageSelector = `${Language}-selector`;
/**
* Tool names concatenated with commas, for use in {@link UrlQueryParams}.
*/
export type ToolNames = `${ToolName}` | `${ToolName},${ToolName}` | `${ToolName},${ToolName},${ToolName}`;
/**
* Tools status string combining tool names with their status for use in {@link UrlQueryParams}.
*/
export type ToolsStatus = `${ToolNames}|${Config['tools']['status']}`;
/**
* URL query parameters for playground configuration.
*/
export type UrlQueryParams = Partial<EmbedOptions & Omit<Config, 'activeEditor' | 'languages' | 'tags' | 'processors' | 'stylesheets' | 'scripts' | 'tools'> & {
screen: ScreenName;
} & {
new: '';
} & {
[key in Language]: string;
} & {
[key in languageSelector]: string;
} & {
sdkVersion: string;
config: string;
embed: boolean;
preview: boolean;
lite: boolean;
x: string;
files: string;
raw: Language;
language: Language;
lang: Language;
languages: string;
processors: string;
stylesheets: string;
scripts: string;
activeEditor: EditorId | 0 | 1 | 2;
active: EditorId | 0 | 1 | 2;
tags: string | string[];
'no-defaults': boolean;
scrollPosition: boolean;
disableAI: boolean;
tools: 'open' | 'full' | 'closed' | 'console' | 'compiled' | 'tests' | 'none' | ToolsStatus;
} & {
[key in ToolName]: 'open' | 'full' | 'closed' | 'none' | '' | 'true';
}>;
/**
* An object that represents the playground embed options.
*
* See [docs](https://livecodes.io/docs/sdk/js-ts/#embed-options) for details.
*/
export interface EmbedOptions {
/**
* Allows loading the playground from a custom URL
* (e.g. a [self-hosted app](https://livecodes.io/docs/features/self-hosting) or a [permanent URL](https://livecodes.io/docs/features/permanent-url)).
*
* If supplied with an invalid URL, an error is thrown.
* @default 'https://livecodes.io'
*/
appUrl?: string;
/**
* An object that represents the [URL Query parameters](https://livecodes.io/docs/configuration/query-params), that can be used to configure the playground.
*
* These 2 snippets produce similar output:
*
* ```js
* import { createPlayground } from 'livecodes';
*
* // use config
* createPlayground('#container', {
* config: {
* markup: {
* language: 'markdown',
* content: '# Hello World!',
* },
* },
* });
*
* // use params
* createPlayground('#container', { params: { md: '# Hello World!' } });
* ```
*/
params?: Prettify<UrlQueryParams>;
/**
* A [configuration object](https://livecodes.io/docs/configuration/configuration-object) or a URL to a JSON file representing a configuration object to load.
*
* If supplied and is not an object or a valid URL, an error is thrown.
* @default {}
*/
config?: Partial<Config> | string;
/**
* If `true`, the playground is loaded in [headless mode](https://livecodes.io/docs/sdk/headless).
* @default false
*/
headless?: boolean;
/**
* A resource to [import](https://livecodes.io/docs/features/import) (from any of the supported [sources](https://livecodes.io/docs/features/import#sources)).
*/
import?: string;
/**
* If `true`, the playground is loaded in [lite mode](https://livecodes.io/docs/features/lite).
*
* @deprecated
*
* Use `{ config: { mode: "lite" } }` instead
*
* @default false
*/
lite?: boolean;
/**
* Sets how the playground loads:
*
* - `"eager"`: The playground loads immediately.
* - `"lazy"`: A playground embedded low down in the page will not load until the user scrolls so that it approaches the viewport.
* - `"click"`: The playground does not load automatically. Instead, a "Click-to-load" screen is shown.
* @default "lazy"
*/
loading?: 'lazy' | 'click' | 'eager';
/**
* A [starter template](https://livecodes.io/docs/features/templates) to load.
* Allowed valued can be found [here](https://livecodes.io/docs/api/internal/type-aliases/TemplateName).
*/
template?: TemplateName;
/**
* The [default view](https://livecodes.io/docs/features/default-view) for the playground.
*
* When set to `"headless"`, the playground is loaded in [headless mode](https://livecodes.io/docs/sdk/headless).
*
* @deprecated
*
* The `view` option has been moved to `config.view`. For headless mode use `headless: true`.
*
* @default "split"
*/
view?: 'split' | 'editor' | 'result' | 'headless';
}
/**
* LiveCodes Preact Component
*
* This module provides a Preact component wrapper for embedding LiveCodes playgrounds.
*
* @module
*/
import type { JSX } from 'preact';
import type { EmbedOptions, Playground } from './models';
export type { Code, Config, EmbedOptions, Language, Playground } from './models';
/**
* Props for the LiveCodes Preact component.
*/
export interface Props extends EmbedOptions {
/** CSS class name for the container element. */
className?: string;
/** CSS styles for the container element. */
style?: Record<string, string>;
/** Height of the playground container. */
height?: string;
/** Callback function that receives the SDK instance when ready. */
sdkReady?: (sdk: Playground) => void;
}
/**
* A Preact component that renders a LiveCodes playground.
*
* Acts as a wrapper for the [LiveCodes JS SDK](https://livecodes.io/docs/sdk/js-ts).
* @see {@link https://livecodes.io/docs/sdk/preact}
*
* @prop {string} [appUrl] - The URL of the LiveCodes app. Defaults to `https://livecodes.io/`.
* @prop {object | string} [config] - The [config object](https://livecodes.io/docs/configuration/configuration-object) for the playground or the URL of the config file.
* @prop {string} [import] - A resource to [import](https://livecodes.io/docs/features/import) (from any of the supported [sources](https://livecodes.io/docs/features/import#sources)).
* @prop {boolean} [headless=false] - Whether to use the headless mode of LiveCodes.
* @prop {boolean} [lite=false] - Deprecated! Use `config={{ mode: "lite" }}` instead - Whether to use the lite mode of LiveCodes.
* @prop {string} [loading='lazy'] - When to load the playground.
* @prop {object} [params] - An object that represents [URL Query parameters](https://livecodes.io/docs/configuration/query-params).
* @prop {string} [template] - A [starter template](https://livecodes.io/docs/features/templates) to load.
* @prop {string} [view='split'] - Deprecated! The `view` option has been moved to `config.view`. For headless mode use `headless="true"` - The [default view](https://livecodes.io/docs/features/default-view) for the playground.
* @prop {string} [height] - Sets the [height of playground container](https://livecodes.io/docs/sdk/js-ts#height) element.
* @prop {string} [className] - Sets the class name of playground container element.
* @prop {object} [style] - Sets the style of playground container element.
* @prop {function} [sdkReady] - A callback function that will be called when the SDK is ready.
* @example
* ```jsx
* import LiveCodes from 'livecodes/preact';
*
* const config = {
* markup: {
* language: 'markdown',
* content: '# Hello World!',
* },
* };
* export default () => <LiveCodes config={config} />;
* ```
*/
export default function LiveCodes(props: Props): JSX.Element;
/**
* LiveCodes React Component
*
* This module provides a React component wrapper for embedding LiveCodes playgrounds.
*
* @module
*/
import React from 'react';
import type { EmbedOptions, Playground } from './models';
export type { Code, Config, EmbedOptions, Language, Playground } from './models';
/**
* Props for the LiveCodes React component.
*/
export interface Props extends EmbedOptions {
/** CSS class name for the container element. */
className?: string;
/** CSS styles for the container element. */
style?: Record<string, string>;
/** Height of the playground container. */
height?: string;
/** Callback function that receives the SDK instance when ready. */
sdkReady?: (sdk: Playground) => void;
}
/**
* A React component that renders a LiveCodes playground.
*
* Acts as a wrapper for the [LiveCodes JS SDK](https://livecodes.io/docs/sdk/js-ts).
* @see {@link https://livecodes.io/docs/sdk/react}
*
* @prop {string} [appUrl] - The URL of the LiveCodes app. Defaults to `https://livecodes.io/`.
* @prop {object | string} [config] - The [config object](https://livecodes.io/docs/configuration/configuration-object) for the playground or the URL of the config file.
* @prop {string} [import] - A resource to [import](https://livecodes.io/docs/features/import) (from any of the supported [sources](https://livecodes.io/docs/features/import#sources)).
* @prop {boolean} [headless=false] - Whether to use the headless mode of LiveCodes.
* @prop {boolean} [lite=false] - Deprecated! Use `config={{ mode: "lite" }}` instead - Whether to use the lite mode of LiveCodes.
* @prop {string} [loading='lazy'] - When to load the playground.
* @prop {object} [params] - An object that represents [URL Query parameters](https://livecodes.io/docs/configuration/query-params).
* @prop {string} [template] - A [starter template](https://livecodes.io/docs/features/templates) to load.
* @prop {string} [view='split'] - Deprecated! The `view` option has been moved to `config.view`. For headless mode use `headless="true"` - The [default view](https://livecodes.io/docs/features/default-view) for the playground.
* @prop {string} [height] - Sets the [height of playground container](https://livecodes.io/docs/sdk/js-ts#height) element.
* @prop {string} [className] - Sets the class name of playground container element.
* @prop {object} [style] - Sets the style of playground container element.
* @prop {function} [sdkReady] - A callback function that will be called when the SDK is ready.
* @example
* ```jsx
* import LiveCodes from 'livecodes/react';
*
* const config = {
* markup: {
* language: 'markdown',
* content: '# Hello World!',
* },
* };
* export default () => <LiveCodes config={config} />;
* ```
*/
export default function LiveCodes(props: Props): React.ReactElement<Props>;
/**
* LiveCodes SolidJS Component
*
* This module provides a SolidJS component wrapper for embedding LiveCodes playgrounds.
*
* @module
*/
import type { Component, JSX } from 'solid-js';
import type { EmbedOptions, Playground } from './models';
export type { Code, Config, EmbedOptions, Language, Playground } from './models';
/**
* Props for the LiveCodes SolidJS component.
*/
export interface Props extends EmbedOptions {
/** CSS class name for the container element. */
class?: string;
/** CSS styles for the container element. */
style?: JSX.CSSProperties;
/** Height of the playground container. */
height?: string;
/** Callback function that receives the SDK instance when ready. */
sdkReady?: (sdk: Playground) => void;
}
/**
* A SolidJS component that renders a LiveCodes playground.
*
* Acts as a wrapper for the [LiveCodes JS SDK](https://livecodes.io/docs/sdk/js-ts).
* @see {@link https://livecodes.io/docs/sdk/solid}
*
* @prop {string} [appUrl] - The URL of the LiveCodes app. Defaults to `https://livecodes.io/`.
* @prop {object | string} [config] - The [config object](https://livecodes.io/docs/configuration/configuration-object) for the playground or the URL of the config file.
* @prop {string} [import] - A resource to [import](https://livecodes.io/docs/features/import) (from any of the supported [sources](https://livecodes.io/docs/features/import#sources)).
* @prop {boolean} [headless=false] - Whether to use the headless mode of LiveCodes.
* @prop {boolean} [lite=false] - Deprecated! Use `config={{ mode: "lite" }}` instead - Whether to use the lite mode of LiveCodes.
* @prop {string} [loading='lazy'] - When to load the playground.
* @prop {object} [params] - An object that represents [URL Query parameters](https://livecodes.io/docs/configuration/query-params).
* @prop {string} [template] - A [starter template](https://livecodes.io/docs/features/templates) to load.
* @prop {string} [view='split'] - Deprecated! The `view` option has been moved to `config.view`. For headless mode use `headless="true"` - The [default view](https://livecodes.io/docs/features/default-view) for the playground.
* @prop {string} [height] - Sets the [height of playground container](https://livecodes.io/docs/sdk/js-ts#height) element.
* @prop {string} [class] - Sets the class name of playground container element.
* @prop {object} [style] - Sets the style of playground container element.
* @prop {function} [sdkReady] - A callback function that will be called when the SDK is ready.
* @example
* ```tsx
* import LiveCodes from 'livecodes/solid';
*
* const config = {
* markup: {
* language: 'markdown',
* content: '# Hello World!',
* },
* };
* export default () => <LiveCodes config={config} />;
* ```
*/
declare const LiveCodes: Component<Props>;
export default LiveCodes;
/**
* LiveCodes Svelte Component
*
* This module provides a Svelte component wrapper for embedding LiveCodes playgrounds.
*
* @module
*/
import type { EmbedOptions, Playground } from './models';
export { createPlayground } from './index';
export type { Code, Config, EmbedOptions, Language, Playground } from './models';
/**
* Props for the LiveCodes Svelte component.
*/
export interface Props extends EmbedOptions {
/** CSS class name for the container element. */
class?: string;
/** CSS styles for the container element. */
style?: Record<string, string>;
/** Height of the playground container. */
height?: string;
/** Callback function that receives the SDK instance when ready. */
sdkReady?: (sdk: Playground) => void;
}
/**
* A Svelte component that renders a LiveCodes playground.
*
* Acts as a wrapper for the [LiveCodes JS SDK](https://livecodes.io/docs/sdk/js-ts).
* @see {@link https://livecodes.io/docs/sdk/svelte}
*
* @prop {string} [appUrl] - The URL of the LiveCodes app. Defaults to `https://livecodes.io/`.
* @prop {object | string} [config] - The [config object](https://livecodes.io/docs/configuration/configuration-object) for the playground or the URL of the config file.
* @prop {string} [import] - A resource to [import](https://livecodes.io/docs/features/import) (from any of the supported [sources](https://livecodes.io/docs/features/import#sources)).
* @prop {boolean} [headless=false] - Whether to use the headless mode of LiveCodes.
* @prop {boolean} [lite=false] - Deprecated! Use `config={{ mode: "lite" }}` instead - Whether to use the lite mode of LiveCodes.
* @prop {string} [loading='lazy'] - When to load the playground.
* @prop {object} [params] - An object that represents [URL Query parameters](https://livecodes.io/docs/configuration/query-params).
* @prop {string} [template] - A [starter template](https://livecodes.io/docs/features/templates) to load.
* @prop {string} [view='split'] - Deprecated! The `view` option has been moved to `config.view`. For headless mode use `headless="true"` - The [default view](https://livecodes.io/docs/features/default-view) for the playground.
* @prop {string} [height] - Sets the [height of playground container](https://livecodes.io/docs/sdk/js-ts#height) element.
* @prop {string} [class] - Sets the class name of playground container element.
* @prop {object} [style] - Sets the style of playground container element.
* @prop {function} [sdkReady] - A callback function that will be called when the SDK is ready.
* @example
* ```svelte
* <script>
* import LiveCodes from 'livecodes/svelte';
*
* const config = {
* markup: {
* language: 'markdown',
* content: '# Hello World!',
* },
* };
* </script>
*
* <LiveCodes {config} />
* ```
*/
declare const LiveCodes: import('svelte').Component<Props, {}, ''>;
type LiveCodes = ReturnType<typeof LiveCodes>;
export default LiveCodes;
/**
* LiveCodes Vue Component
*
* This module provides a Vue component wrapper for embedding LiveCodes playgrounds.
*
* @module
*/
import type { AllowedComponentProps, ComponentCustomProps, ComponentOptionsMixin, DefineComponent, ExtractPropTypes, RendererElement, RendererNode, VNode, VNodeProps } from '@vue/runtime-core';
import type { EmbedOptions, Playground } from './models';
export type { Code, Config, EmbedOptions, Language, Playground } from './models';
/**
* Props for the LiveCodes Vue component.
*/
export interface Props extends EmbedOptions {
/** Height of the playground container. */
height?: string;
}
/**
* A Vue component that renders a LiveCodes playground.
*
* Acts as a wrapper for the [LiveCodes JS SDK](https://livecodes.io/docs/sdk/js-ts).
* @see {@link https://livecodes.io/docs/sdk/vue}
*
* @prop {string} [appUrl] - The URL of the LiveCodes app. Defaults to `https://livecodes.io/`.
* @prop {object | string} [config] - The [config object](https://livecodes.io/docs/configuration/configuration-object) for the playground or the URL of the config file.
* @prop {string} [import] - A resource to [import](https://livecodes.io/docs/features/import) (from any of the supported [sources](https://livecodes.io/docs/features/import#sources)).
* @prop {boolean} [headless=false] - Whether to use the headless mode of LiveCodes.
* @prop {boolean} [lite=false] - Deprecated! Use `config={{ mode: "lite" }}` instead - Whether to use the lite mode of LiveCodes.
* @prop {string} [loading='lazy'] - When to load the playground.
* @prop {object} [params] - An object that represents [URL Query parameters](https://livecodes.io/docs/configuration/query-params).
* @prop {string} [template] - A [starter template](https://livecodes.io/docs/features/templates) to load.
* @prop {string} [view='split'] - Deprecated! The `view` option has been moved to `config.view`. For headless mode use `headless="true"` - The [default view](https://livecodes.io/docs/features/default-view) for the playground.
* @prop {string} [height] - Sets the [height of playground container](https://livecodes.io/docs/sdk/js-ts#height) element.
* @prop {object} [style] - Sets the style of playground container element.
* @emits {event} [sdkReady] - When the playground initializes, the event `"sdkReady"` is emitted.
* @example
* ```html
* <script setup>
* import LiveCodes from 'livecodes/vue';
* </script>
*
* <template>
* <LiveCodes />
* </template>
* ```
*/
declare const LiveCodes: LiveCodesComponent;
export default LiveCodes;
type LiveCodesComponent = DefineComponent<Props, () => VNode<RendererNode, RendererElement, {
[key: string]: any;
}>, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
sdkReady: (sdk: Playground) => true;
}, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly<ExtractPropTypes<Props>> & {
onSdkReady?: (sdk: Playground) => void;
}, {}>;
/**
* LiveCodes Web Components
*
* This module provides Web Components for embedding LiveCodes playgrounds.
*
* @module
*/
import type { EmbedOptions, Playground } from './models';
export type { Code, Config, EmbedOptions, Language, Playground } from './models';
/**
* Props for the LiveCodes Web Component.
*/
export interface Props extends EmbedOptions {
/** Height of the playground container. */
height?: string;
/** The SDK instance. */
sdk?: Playground;
}
"use strict";(()=>{var oe=Object.create;var G=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var le=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var de=(l,p)=>()=>(p||l((p={exports:{}}).exports,p),p.exports);var fe=(l,p,t,r)=>{if(p&&typeof p=="object"||typeof p=="function")for(let g of ae(p))!ce.call(l,g)&&g!==t&&G(l,g,{get:()=>p[g],enumerable:!(r=se(p,g))||r.enumerable});return l};var ue=(l,p,t)=>(t=l!=null?oe(le(l)):{},fe(p||!l||!l.__esModule?G(t,"default",{value:l,enumerable:!0}):t,l));var Y=de((Ce,K)=>{var pe=function(){var l=String.fromCharCode,p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",r={};function g(i,o){if(!r[i]){r[i]={};for(var e=0;e<i.length;e++)r[i][i.charAt(e)]=e}return r[i][o]}var f={compressToBase64:function(i){if(i==null)return"";var o=f._compress(i,6,function(e){return p.charAt(e)});switch(o.length%4){default:case 0:return o;case 1:return o+"===";case 2:return o+"==";case 3:return o+"="}},decompressFromBase64:function(i){return i==null?"":i==""?null:f._decompress(i.length,32,function(o){return g(p,i.charAt(o))})},compressToUTF16:function(i){return i==null?"":f._compress(i,15,function(o){return l(o+32)})+" "},decompressFromUTF16:function(i){return i==null?"":i==""?null:f._decompress(i.length,16384,function(o){return i.charCodeAt(o)-32})},compressToUint8Array:function(i){for(var o=f.compress(i),e=new Uint8Array(o.length*2),n=0,u=o.length;n<u;n++){var m=o.charCodeAt(n);e[n*2]=m>>>8,e[n*2+1]=m%256}return e},decompressFromUint8Array:function(i){if(i==null)return f.decompress(i);for(var o=new Array(i.length/2),e=0,n=o.length;e<n;e++)o[e]=i[e*2]*256+i[e*2+1];var u=[];return o.forEach(function(m){u.push(l(m))}),f.decompress(u.join(""))},compressToEncodedURIComponent:function(i){return i==null?"":f._compress(i,6,function(o){return t.charAt(o)})},decompressFromEncodedURIComponent:function(i){return i==null?"":i==""?null:(i=i.replace(/ /g,"+"),f._decompress(i.length,32,function(o){return g(t,i.charAt(o))}))},compress:function(i){return f._compress(i,16,function(o){return l(o)})},_compress:function(i,o,e){if(i==null)return"";var n,u,m={},b={},E="",O="",_="",A=2,x=3,h=2,w=[],s=0,a=0,P;for(P=0;P<i.length;P+=1)if(E=i.charAt(P),Object.prototype.hasOwnProperty.call(m,E)||(m[E]=x++,b[E]=!0),O=_+E,Object.prototype.hasOwnProperty.call(m,O))_=O;else{if(Object.prototype.hasOwnProperty.call(b,_)){if(_.charCodeAt(0)<256){for(n=0;n<h;n++)s=s<<1,a==o-1?(a=0,w.push(e(s)),s=0):a++;for(u=_.charCodeAt(0),n=0;n<8;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1}else{for(u=1,n=0;n<h;n++)s=s<<1|u,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=0;for(u=_.charCodeAt(0),n=0;n<16;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1}A--,A==0&&(A=Math.pow(2,h),h++),delete b[_]}else for(u=m[_],n=0;n<h;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1;A--,A==0&&(A=Math.pow(2,h),h++),m[O]=x++,_=String(E)}if(_!==""){if(Object.prototype.hasOwnProperty.call(b,_)){if(_.charCodeAt(0)<256){for(n=0;n<h;n++)s=s<<1,a==o-1?(a=0,w.push(e(s)),s=0):a++;for(u=_.charCodeAt(0),n=0;n<8;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1}else{for(u=1,n=0;n<h;n++)s=s<<1|u,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=0;for(u=_.charCodeAt(0),n=0;n<16;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1}A--,A==0&&(A=Math.pow(2,h),h++),delete b[_]}else for(u=m[_],n=0;n<h;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1;A--,A==0&&(A=Math.pow(2,h),h++)}for(u=2,n=0;n<h;n++)s=s<<1|u&1,a==o-1?(a=0,w.push(e(s)),s=0):a++,u=u>>1;for(;;)if(s=s<<1,a==o-1){w.push(e(s));break}else a++;return w.join("")},decompress:function(i){return i==null?"":i==""?null:f._decompress(i.length,32768,function(o){return i.charCodeAt(o)})},_decompress:function(i,o,e){var n=[],u,m=4,b=4,E=3,O="",_=[],A,x,h,w,s,a,P,d={val:e(0),position:o,index:1};for(A=0;A<3;A+=1)n[A]=A;for(h=0,s=Math.pow(2,2),a=1;a!=s;)w=d.val&d.position,d.position>>=1,d.position==0&&(d.position=o,d.val=e(d.index++)),h|=(w>0?1:0)*a,a<<=1;switch(u=h){case 0:for(h=0,s=Math.pow(2,8),a=1;a!=s;)w=d.val&d.position,d.position>>=1,d.position==0&&(d.position=o,d.val=e(d.index++)),h|=(w>0?1:0)*a,a<<=1;P=l(h);break;case 1:for(h=0,s=Math.pow(2,16),a=1;a!=s;)w=d.val&d.position,d.position>>=1,d.position==0&&(d.position=o,d.val=e(d.index++)),h|=(w>0?1:0)*a,a<<=1;P=l(h);break;case 2:return""}for(n[3]=P,x=P,_.push(P);;){if(d.index>i)return"";for(h=0,s=Math.pow(2,E),a=1;a!=s;)w=d.val&d.position,d.position>>=1,d.position==0&&(d.position=o,d.val=e(d.index++)),h|=(w>0?1:0)*a,a<<=1;switch(P=h){case 0:for(h=0,s=Math.pow(2,8),a=1;a!=s;)w=d.val&d.position,d.position>>=1,d.position==0&&(d.position=o,d.val=e(d.index++)),h|=(w>0?1:0)*a,a<<=1;n[b++]=l(h),P=b-1,m--;break;case 1:for(h=0,s=Math.pow(2,16),a=1;a!=s;)w=d.val&d.position,d.position>>=1,d.position==0&&(d.position=o,d.val=e(d.index++)),h|=(w>0?1:0)*a,a<<=1;n[b++]=l(h),P=b-1,m--;break;case 2:return _.join("")}if(m==0&&(m=Math.pow(2,E),E++),n[P])O=n[P];else if(P===b)O=x+x.charAt(0);else return null;_.push(O),n[b++]=x+O.charAt(0),m--,x=O,m==0&&(m=Math.pow(2,E),E++)}}};return f}();typeof K!="undefined"&&K!=null&&(K.exports=pe)});var z=ue(Y());var ge={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},he=()=>{if(typeof navigator=="undefined")return"default";let l=navigator.userAgent;return/Firefox\//i.test(l)?"firefox":/Chrome\//i.test(l)?"chrome":"default"},X=()=>ge[he()].filter(l=>{var t,r,g;let p=(g=(r=(t=globalThis.document)==null?void 0:t.featurePolicy)==null?void 0:r.features)==null?void 0:g.call(r);return p?p.includes(l):!0}).join("; "),me={template:"markup",style:"style",script:"script"},ye={markup:"html",style:"css",script:"javascript"},ve=l=>{let t=l.replace(/^\n/,"").split(`
`);t.length>1&&t[t.length-1].trim()===""&&t.pop();let r=t.filter(f=>f.trim().length>0).map(f=>{let i=f.match(/^(\s*)/);return i?i[1].length:0}),g=r.length>0?Math.min(...r):0;return g===0?t.join(`
`):t.map(f=>f.slice(g)).join(`
`)},V=l=>{var t;let p;if(l instanceof HTMLTemplateElement){let r=l.ownerDocument.createElement("div");r.appendChild(l.content.cloneNode(!0)),p=r.innerHTML}else p=(t=l.textContent)!=null?t:"";return ve(p)},be=l=>{let p=l.split(".");if(!(p.length<2))return p[p.length-1]},W=l=>{let p=Array.from(l.children).find(f=>f instanceof HTMLTemplateElement&&!f.hasAttribute("lang")&&!f.hasAttribute("filename"));if(!p)return;let t=p.content,r=Array.from(t.children).filter(f=>f.tagName==="TEMPLATE"||f.tagName==="STYLE"||f.tagName==="SCRIPT");return r.length===0?void 0:r.some(f=>f.hasAttribute("filename"))?Ee(r):we(r)},we=l=>{let p={},t=new Set;for(let r of l){let g=r.tagName.toLowerCase(),f=me[g];if(!f||t.has(f))continue;t.add(f);let i=r.getAttribute("lang")||ye[f],o=V(r);p[f]={language:i,content:o},r.hasAttribute("active")&&(p.activeEditor=f)}return Object.keys(p).length>0?p:void 0},Ee=l=>{let p=[],t;for(let g of l){let f=g.getAttribute("filename");if(!f)continue;let i=V(g),e=g.getAttribute("lang")||be(f),n={filename:f,content:i};e&&(n.language=e),p.push(n),g.hasAttribute("active")&&(t=f)}if(p.length===0)return;let r={files:p};return t&&(r.activeEditor=t),r};async function ee(l,p={}){typeof l=="object"&&!(l instanceof HTMLElement)&&(l.headless||l.view==="headless")&&(p=l,l=null);let t=6e4,{config:r={},headless:g,loading:f="lazy",view:i}=p,o=g||i==="headless",e=null,n=null,u=c=>{c.style.position="absolute",c.style.top="0",c.style.visibility="hidden",c.style.opacity="0"};if(typeof l=="string")e=document.querySelector(l);else if(l instanceof HTMLElement)e=l;else if(!(o&&typeof l=="object"))throw new Error("A valid container element is required.");if(!e)if(o)e=document.createElement("div"),u(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${l}"`);let m=new URL(_e(p)),b=m.origin;m.searchParams.set("embed","true"),m.searchParams.set("loading",o?"eager":f),m.searchParams.set("sdkVersion","0.14.0"),typeof r=="object"&&Object.keys(r).length>0&&m.searchParams.set("config","sdk");let E=p.params;typeof E=="object"&&Object.keys(E).length>0&&JSON.stringify(E).length<1800&&Object.keys(E).forEach(c=>{m.searchParams.set(c,encodeURIComponent(String(E[c])))});let O=!1,_="Cannot call API methods after calling `destroy()`.",A=[],x=(c,y="message")=>{addEventListener(y,c),A.push(c)},h=(c,y="message")=>{removeEventListener(y,c);let C=A.indexOf(c);C>-1&&A.splice(C,1)},s=await new Promise(c=>{var T,U,L,R,I,H,q,$,Q;if(!e)return;let y=e.dataset.height||e.style.height;if(y&&!o){let D=isNaN(Number(y))?y:y+"px";e.style.height=D}e.dataset.defaultStyles!=="false"&&!o&&((T=e.style).backgroundColor||(T.backgroundColor="#fff"),(U=e.style).border||(U.border="1px solid black"),(L=e.style).borderRadius||(L.borderRadius="8px"),(R=e.style).boxSizing||(R.boxSizing="border-box"),(I=e.style).padding||(I.padding="0"),(H=e.style).width||(H.width="100%"),(q=e.style).height||(q.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",($=e.style).overflow||($.overflow="hidden"),(Q=e.style).resize||(Q.resize="vertical"),getComputedStyle(e).getPropertyValue("display")==="inline"&&(e.style.display="block"));let C="livecodes",S=e.querySelector(`iframe.${C}`),v=S||document.createElement("iframe");v.classList.add(C),v.setAttribute("allow",X()),v.setAttribute("allowtransparency","true"),v.setAttribute("allowpaymentrequest","true"),v.setAttribute("allowfullscreen","true"),v.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let k=f==="eager"?"eager":"lazy";v.setAttribute("loading",k),o?u(v):(v.style.height="100%",v.style.minHeight="200px",v.style.width="100%",v.style.margin="0",v.style.border="0",v.style.borderRadius=e.style.borderRadius),x(function D(j){var N;j.source!==v.contentWindow||j.origin!==b||((N=j.data)==null?void 0:N.type)!=="livecodes-init"||(h(D),n=Number(j.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&x(function D(j){var N,Z;j.source!==v.contentWindow||j.origin!==b||((N=j.data)==null?void 0:N.type)!=="livecodes-get-config"||(h(D),(Z=v.contentWindow)==null||Z.postMessage({type:"livecodes-config",payload:r},b))}),v.onload=()=>{c(v)},v.src=m.href,S||e.appendChild(v)}),a=new Promise(c=>{x(function y(C){var S;C.source!==s.contentWindow||C.origin!==b||((S=C.data)==null?void 0:S.type)!=="livecodes-ready"||(h(y),c(),a.settled=!0)})}),P=()=>O?Promise.reject(_):new Promise(async c=>{var C;a.settled&&c();let y={type:"livecodes-load"};(C=s.contentWindow)==null||C.postMessage(y,b),await a,c()}),d=(c,y)=>new Promise(async(C,S)=>{var U;if(O)return S(_);await P();let v=re(),k=setTimeout(()=>{h(T),S(new Error(`SDK call "${c}" timed out after ${t}ms.`))},t);function T(L){var R,I;if(!(L.source!==s.contentWindow||L.origin!==b||((R=L.data)==null?void 0:R.type)!=="livecodes-api-response"||((I=L.data)==null?void 0:I.id)!==v)&&L.data.method===c){clearTimeout(k),h(T);let H=L.data.payload;H!=null&&H.error?S(H.error):C(H)}}x(T),(U=s.contentWindow)==null||U.postMessage({method:c,id:v,args:y},b)}),M={},te=["load","ready","code","console","tests","destroy"],J=(c,y)=>{var C;if(O)throw new Error(_);return te.includes(c)?(d("watch",[c]),M[c]||(M[c]=[]),(C=M[c])==null||C.push(y),{remove:()=>{var S,v;M[c]=(S=M[c])==null?void 0:S.filter(k=>k!==y),((v=M[c])==null?void 0:v.length)===0&&d("watch",[c,"unsubscribe"])}}):{remove:()=>{}}},ne=c=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[c];x(async function(y){var v,k,T,U;let C=ne((k=(v=y.data)==null?void 0:v.type)!=null?k:"");if(y.source!==s.contentWindow||y.origin!==b||!C||!M[C])return;let S=(T=y.data)==null?void 0:T.payload;(U=M[C])==null||U.forEach(L=>{L(S)})});let ie=()=>{var c;(c=s==null?void 0:s.remove)==null||c.call(s),Object.values(M).forEach(y=>{y.length=0}),A.forEach(y=>removeEventListener("message",y)),A.length=0,F&&e&&F.unobserve(e),O=!0},F;f==="lazy"&&"IntersectionObserver"in window&&(F=new IntersectionObserver((c,y)=>{c.forEach(async C=>{C.isIntersecting&&(await P(),y.unobserve(e))})},{rootMargin:"150px"}),F.observe(e));let re=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>P(),run:()=>d("run"),format:c=>d("format",[c]),getShareUrl:c=>d("getShareUrl",[c]),getConfig:c=>d("getConfig",[c]),setConfig:c=>d("setConfig",[c]),getCode:()=>d("getCode"),show:(c,y)=>d("show",[c,y]),runTests:()=>d("runTests"),onChange:c=>J("code",c),watch:J,exec:(c,...y)=>d("exec",[c,...y]),destroy:()=>O?Promise.reject(_):(ie(),Promise.resolve())}}function _e(l={}){let{appUrl:p="https://livecodes.io",params:t={},config:r={},headless:g,import:f,lite:i,view:o,...e}=l,n;try{n=new URL(p)}catch(b){throw new Error(`${p} is not a valid URL.`)}let u=new URLSearchParams;Object.entries(e).forEach(([b,E])=>{E!==void 0&&n.searchParams.set(b,String(E))});let m=l.view==="headless"||g;if(i&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof r=="object"&&r.mode==null?r.mode="lite":n.searchParams.set("lite","true")),o&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof r=="object"&&r.view==null&&o!=="headless"?r.view=o:n.searchParams.set("view",o)),typeof r=="string")try{new URL(r),n.searchParams.set("config",encodeURIComponent(r))}catch(b){throw new Error('"config" is not a valid URL or configuration object.')}else r&&typeof r=="object"&&Object.keys(r).length>0&&(r.title&&r.title!=="Untitled Project"&&n.searchParams.set("title",r.title),r.description&&r.description.length>0&&n.searchParams.set("description",r.description),u.set("config","code/"+(0,z.compressToEncodedURIComponent)(JSON.stringify(r))));if(t&&typeof t=="object"&&Object.keys(t).length>0)try{u.set("params",(0,z.compressToEncodedURIComponent)(JSON.stringify(t)))}catch(b){Object.keys(t).forEach(E=>{n.searchParams.set(E,encodeURIComponent(String(t[E])))})}return f&&n.searchParams.set("x",encodeURIComponent(f)),m&&n.searchParams.set("headless","true"),u.toString().length>0&&(n.hash=u.toString()),n.href}var B=class extends HTMLElement{constructor(){super(...arguments);this._configCache="";this._otherOptionsCache="";this._connected=!1;this._updateScheduled=!1;this._generation=0}static get observedAttributes(){return["app-url","config","import","loading","params","template","view","height","headless","lite"]}connectedCallback(){this._connected=!0,this._observeChildren(),this._scheduleUpdate(),this.style.display="block"}disconnectedCallback(){var t,r;this._connected=!1,(t=this._childrenObserver)==null||t.disconnect(),this._childrenObserver=void 0,++this._generation,(r=this._playground)==null||r.destroy(),this._playground=void 0}attributeChangedCallback(t,r,g){r!==g&&this._connected&&this._scheduleUpdate()}get config(){return this._config}set config(t){this._config=t,this._connected&&this._scheduleUpdate()}get params(){return this._params}set params(t){this._params=t,this._connected&&this._scheduleUpdate()}get sdk(){return this._playground}destroy(){var t;++this._generation,(t=this._playground)==null||t.destroy(),this._playground=void 0}_observeChildren(){var r;(r=this._childrenObserver)==null||r.disconnect();let t=Array.from(this.children).find(g=>g instanceof HTMLTemplateElement&&!g.hasAttribute("lang")&&!g.hasAttribute("filename"));t&&(this._childrenObserver=new MutationObserver(()=>{if(!this._connected||!this._playground)return;let g=W(this);g&&this._playground.setConfig(g)}),this._childrenObserver.observe(t.content,{childList:!0,subtree:!0,characterData:!0}))}_scheduleUpdate(){this._updateScheduled||(this._updateScheduled=!0,queueMicrotask(()=>{this._updateScheduled=!1,this._connected&&this._update()}))}_getConfigAttribute(){let t=this.getAttribute("config");if(t!=null)try{return JSON.parse(t)}catch(r){return}}_getParamsAttribute(){let t=this.getAttribute("params");if(t!=null)try{return JSON.parse(t)}catch(r){return}}_getEmbedOptions(){let t={},r=this.getAttribute("app-url");r!=null&&(t.appUrl=r);let g=this.getAttribute("import");g!=null&&(t.import=g);let f=this.getAttribute("loading");f!=null&&(t.loading=f);let i=this.getAttribute("template");i!=null&&(t.template=i);let o=this.getAttribute("view");o!=null&&(t.view=o),this.hasAttribute("headless")&&(t.headless=!0),this.hasAttribute("lite")&&(t.lite=!0);let e=W(this),n=this._getConfigAttribute(),u=this._config;if(e||n||u!==void 0)if(typeof u=="string")t.config=u;else{let E={...n||{},...e||{},...u||{}};t.config=E}let m=this._getParamsAttribute(),b=this._params;return(m||b!==void 0)&&(t.params={...m||{},...b||{}}),t}_update(){var o;let{config:t,...r}=this._getEmbedOptions(),g=JSON.stringify(r),f=JSON.stringify(t||""),i=this.getAttribute("height");if(i!=null){let e=Number(i)?`${i}px`:i;this.dataset.height=e,this.style.height=e}if(!this._playground||this._otherOptionsCache!==g){let e=++this._generation;this._otherOptionsCache=g,this._configCache=f,(o=this._playground)==null||o.destroy(),this._playground=void 0,ee(this,{config:t,...r}).then(n=>{if(this._generation!==e){n.destroy();return}this._playground=n,this.dispatchEvent(new CustomEvent("sdkready",{detail:{sdk:n},bubbles:!0,composed:!0}))})}else{if(this._configCache===f)return;this._configCache=f,t&&this._playground.setConfig(t)}}};customElements.get("live-codes")||customElements.define("live-codes",B);})();
+1
-1

@@ -1,1 +0,1 @@

"use strict";var ee=Object.create;var K=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var se=(c,h)=>()=>(h||c((h={exports:{}}).exports,h),h.exports),ie=(c,h)=>{for(var E in h)K(c,E,{get:h[E],enumerable:!0})},$=(c,h,E,y)=>{if(h&&typeof h=="object"||typeof h=="function")for(let M of ne(h))!re.call(c,M)&&M!==E&&K(c,M,{get:()=>h[M],enumerable:!(y=te(h,M))||y.enumerable});return c};var ae=(c,h,E)=>(E=c!=null?ee(oe(c)):{},$(h||!c||!c.__esModule?K(E,"default",{value:c,enumerable:!0}):E,c)),le=c=>$(K({},"__esModule",{value:!0}),c);var G=se((pe,W)=>{var ce=function(){var c=String.fromCharCode,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",E="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 h.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(h,r.charAt(e))})},compressToUTF16:function(r){return r==null?"":A._compress(r,15,function(e){return c(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 m=e.charCodeAt(n);l[n*2]=m>>>8,l[n*2+1]=m%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(m){s.push(c(m))}),A.decompress(s.join(""))},compressToEncodedURIComponent:function(r){return r==null?"":A._compress(r,6,function(e){return E.charAt(e)})},decompressFromEncodedURIComponent:function(r){return r==null?"":r==""?null:(r=r.replace(/ /g,"+"),A._decompress(r.length,32,function(e){return M(E,r.charAt(e))}))},compress:function(r){return A._compress(r,16,function(e){return c(e)})},_compress:function(r,e,l){if(r==null)return"";var n,s,m={},v={},w="",O="",g="",S=2,P=3,d=2,f=[],t=0,o=0,x;for(x=0;x<r.length;x+=1)if(w=r.charAt(x),Object.prototype.hasOwnProperty.call(m,w)||(m[w]=P++,v[w]=!0),O=g+w,Object.prototype.hasOwnProperty.call(m,O))g=O;else{if(Object.prototype.hasOwnProperty.call(v,g)){if(g.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==e-1?(o=0,f.push(l(t)),t=0):o++;for(s=g.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<d;n++)t=t<<1|s,o==e-1?(o=0,f.push(l(t)),t=0):o++,s=0;for(s=g.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,d),d++),delete v[g]}else for(s=m[g],n=0;n<d;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,d),d++),m[O]=P++,g=String(w)}if(g!==""){if(Object.prototype.hasOwnProperty.call(v,g)){if(g.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==e-1?(o=0,f.push(l(t)),t=0):o++;for(s=g.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<d;n++)t=t<<1|s,o==e-1?(o=0,f.push(l(t)),t=0):o++,s=0;for(s=g.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,d),d++),delete v[g]}else for(s=m[g],n=0;n<d;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,d),d++)}for(s=2,n=0;n<d;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,m=4,v=4,w=3,O="",g=[],S,P,d,f,t,o,x,a={val:l(0),position:e,index:1};for(S=0;S<3;S+=1)n[S]=S;for(d=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++)),d|=(f>0?1:0)*o,o<<=1;switch(s=d){case 0:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;x=c(d);break;case 1:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;x=c(d);break;case 2:return""}for(n[3]=x,P=x,g.push(x);;){if(a.index>r)return"";for(d=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++)),d|=(f>0?1:0)*o,o<<=1;switch(x=d){case 0:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;n[v++]=c(d),x=v-1,m--;break;case 1:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;n[v++]=c(d),x=v-1,m--;break;case 2:return g.join("")}if(m==0&&(m=Math.pow(2,w),w++),n[x])O=n[x];else if(x===v)O=P+P.charAt(0);else return null;g.push(O),n[v++]=P+O.charAt(0),m--,P=O,m==0&&(m=Math.pow(2,w),w++)}}};return A}();typeof W!="undefined"&&W!=null&&(W.exports=ce)});var fe={};ie(fe,{createPlayground:()=>de,getPlaygroundUrl:()=>X});module.exports=le(fe);var z=ae(G());async function de(c,h={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(h=c,c=null);let{config:E={},headless:y,loading:M="lazy",view:A}=h,r=y||A==="headless",e=null,l=null;if(typeof c=="string")e=document.querySelector(c);else if(c instanceof HTMLElement)e=c;else if(!(r&&typeof c=="object"))throw new Error("A valid container element is required.");if(!e)if(r)e=document.createElement("div"),B(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${c}"`);let n=new URL(X(h)),s=n.origin;n.searchParams.set("embed","true"),n.searchParams.set("loading",r?"eager":M),n.searchParams.set("sdkVersion","0.13.0"),typeof E=="object"&&Object.keys(E).length>0&&n.searchParams.set("config","sdk");let m=h.params;typeof m=="object"&&Object.keys(m).length>0&&JSON.stringify(m).length<1800&&Object.keys(m).forEach(i=>{n.searchParams.set(i,encodeURIComponent(String(m[i])))});let v=!1,w="Cannot call API methods after calling `destroy()`.",O=[],g=(i,u="message")=>{addEventListener(u,i),O.push(i)},P=await new Promise(i=>{var C,U,R,k,j,q,J,N,Q;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"),(q=e.style).width||(q.width="100%"),(J=e.style).height||(J.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(N=e.style).overflow||(N.overflow="hidden"),(Q=e.style).resize||(Q.resize="vertical"));let b="livecodes",L=e.querySelector(`iframe.${b}`),p=L||document.createElement("iframe");p.classList.add(b),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?B(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),g(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)&&g(function I(T){var _,Z;T.source!==p.contentWindow||T.origin!==s||((_=T.data)==null?void 0:_.type)!=="livecodes-get-config"||(removeEventListener("message",I),(Z=p.contentWindow)==null||Z.postMessage({type:"livecodes-config",payload:E},s))}),p.onload=()=>{i(p)},p.src=n.href,L||e.appendChild(p)}),d=new Promise(i=>{g(function u(b){var L;b.source!==P.contentWindow||b.origin!==s||((L=b.data)==null?void 0:L.type)!=="livecodes-ready"||(removeEventListener("message",u),i(),d.settled=!0)})}),f=()=>v?Promise.reject(w):new Promise(async i=>{var b;d.settled&&i();let u={type:"livecodes-load"};(b=P.contentWindow)==null||b.postMessage(u,s),await d,i()}),t=(i,u)=>new Promise(async(b,L)=>{var H;if(v)return L(w);await f();let p=V();g(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):b(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 b;if(v)throw new Error(w);return x.includes(i)?(t("watch",[i]),o[i]||(o[i]=[]),(b=o[i])==null||b.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:()=>{}}},Y=i=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[i];g(async function(u){var p,H,C,U;let b=Y((H=(p=u.data)==null?void 0:p.type)!=null?H:"");if(u.source!==P.contentWindow||u.origin!==s||!b||!o[b])return;let L=(C=u.data)==null?void 0:C.payload;(U=o[b])==null||U.forEach(R=>{R(L)})});let F=()=>{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=!0},D;M==="lazy"&&"IntersectionObserver"in window&&(D=new IntersectionObserver((i,u)=>{i.forEach(async b=>{b.isIntersecting&&(await f(),u.unobserve(e))})},{rootMargin:"150px"}),D.observe(e));function B(i){i.style.position="absolute",i.style.top="0",i.style.visibility="hidden",i.style.opacity="0"}let V=()=>(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):(F(),Promise.resolve())}}function X(c={}){let{appUrl:h="https://livecodes.io",params:E={},config:y={},headless:M,import:A,lite:r,view:e,...l}=c,n;try{n=new URL(h)}catch(v){throw new Error(`${h} 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 m=c.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,z.compressToEncodedURIComponent)(JSON.stringify(y))));if(E&&typeof E=="object"&&Object.keys(E).length>0)try{s.set("params",(0,z.compressToEncodedURIComponent)(JSON.stringify(E)))}catch(v){Object.keys(E).forEach(w=>{n.searchParams.set(w,encodeURIComponent(String(E[w])))})}return A&&n.searchParams.set("x",encodeURIComponent(A)),m&&n.searchParams.set("headless","true"),s.toString().length>0&&(n.hash=s.toString()),n.href}
"use strict";var oe=Object.create;var N=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ie=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var le=(c,p)=>()=>(p||c((p={exports:{}}).exports,p),p.exports),ce=(c,p)=>{for(var w in p)N(c,w,{get:p[w],enumerable:!0})},Z=(c,p,w,f)=>{if(p&&typeof p=="object"||typeof p=="function")for(let L of se(p))!ae.call(c,L)&&L!==w&&N(c,L,{get:()=>p[L],enumerable:!(f=re(p,L))||f.enumerable});return c};var de=(c,p,w)=>(w=c!=null?oe(ie(c)):{},Z(p||!c||!c.__esModule?N(w,"default",{value:c,enumerable:!0}):w,c)),fe=c=>Z(N({},"__esModule",{value:!0}),c);var G=le((Ee,W)=>{var ue=function(){var c=String.fromCharCode,p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",w="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function L(s,r){if(!f[s]){f[s]={};for(var e=0;e<s.length;e++)f[s][s.charAt(e)]=e}return f[s][r]}var x={compressToBase64:function(s){if(s==null)return"";var r=x._compress(s,6,function(e){return p.charAt(e)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(s){return s==null?"":s==""?null:x._decompress(s.length,32,function(r){return L(p,s.charAt(r))})},compressToUTF16:function(s){return s==null?"":x._compress(s,15,function(r){return c(r+32)})+" "},decompressFromUTF16:function(s){return s==null?"":s==""?null:x._decompress(s.length,16384,function(r){return s.charCodeAt(r)-32})},compressToUint8Array:function(s){for(var r=x.compress(s),e=new Uint8Array(r.length*2),n=0,l=r.length;n<l;n++){var m=r.charCodeAt(n);e[n*2]=m>>>8,e[n*2+1]=m%256}return e},decompressFromUint8Array:function(s){if(s==null)return x.decompress(s);for(var r=new Array(s.length/2),e=0,n=r.length;e<n;e++)r[e]=s[e*2]*256+s[e*2+1];var l=[];return r.forEach(function(m){l.push(c(m))}),x.decompress(l.join(""))},compressToEncodedURIComponent:function(s){return s==null?"":x._compress(s,6,function(r){return w.charAt(r)})},decompressFromEncodedURIComponent:function(s){return s==null?"":s==""?null:(s=s.replace(/ /g,"+"),x._decompress(s.length,32,function(r){return L(w,s.charAt(r))}))},compress:function(s){return x._compress(s,16,function(r){return c(r)})},_compress:function(s,r,e){if(s==null)return"";var n,l,m={},y={},E="",C="",v="",b=2,S=3,d=2,h=[],t=0,o=0,A;for(A=0;A<s.length;A+=1)if(E=s.charAt(A),Object.prototype.hasOwnProperty.call(m,E)||(m[E]=S++,y[E]=!0),C=v+E,Object.prototype.hasOwnProperty.call(m,C))v=C;else{if(Object.prototype.hasOwnProperty.call(y,v)){if(v.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==r-1?(o=0,h.push(e(t)),t=0):o++;for(l=v.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}else{for(l=1,n=0;n<d;n++)t=t<<1|l,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=0;for(l=v.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}b--,b==0&&(b=Math.pow(2,d),d++),delete y[v]}else for(l=m[v],n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;b--,b==0&&(b=Math.pow(2,d),d++),m[C]=S++,v=String(E)}if(v!==""){if(Object.prototype.hasOwnProperty.call(y,v)){if(v.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==r-1?(o=0,h.push(e(t)),t=0):o++;for(l=v.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}else{for(l=1,n=0;n<d;n++)t=t<<1|l,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=0;for(l=v.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}b--,b==0&&(b=Math.pow(2,d),d++),delete y[v]}else for(l=m[v],n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;b--,b==0&&(b=Math.pow(2,d),d++)}for(l=2,n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;for(;;)if(t=t<<1,o==r-1){h.push(e(t));break}else o++;return h.join("")},decompress:function(s){return s==null?"":s==""?null:x._decompress(s.length,32768,function(r){return s.charCodeAt(r)})},_decompress:function(s,r,e){var n=[],l,m=4,y=4,E=3,C="",v=[],b,S,d,h,t,o,A,a={val:e(0),position:r,index:1};for(b=0;b<3;b+=1)n[b]=b;for(d=0,t=Math.pow(2,2),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;switch(l=d){case 0:for(d=0,t=Math.pow(2,8),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;A=c(d);break;case 1:for(d=0,t=Math.pow(2,16),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;A=c(d);break;case 2:return""}for(n[3]=A,S=A,v.push(A);;){if(a.index>s)return"";for(d=0,t=Math.pow(2,E),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;switch(A=d){case 0:for(d=0,t=Math.pow(2,8),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;n[y++]=c(d),A=y-1,m--;break;case 1:for(d=0,t=Math.pow(2,16),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;n[y++]=c(d),A=y-1,m--;break;case 2:return v.join("")}if(m==0&&(m=Math.pow(2,E),E++),n[A])C=n[A];else if(A===y)C=S+S.charAt(0);else return null;v.push(C),n[y++]=S+C.charAt(0),m--,S=C,m==0&&(m=Math.pow(2,E),E++)}}};return x}();typeof W!="undefined"&&W!=null&&(W.exports=ue)});var ve={};ce(ve,{compress:()=>he,createPlayground:()=>me,decompress:()=>ye,getPlaygroundUrl:()=>X});module.exports=fe(ve);var I=de(G());var pe={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},ge=()=>{if(typeof navigator=="undefined")return"default";let c=navigator.userAgent;return/Firefox\//i.test(c)?"firefox":/Chrome\//i.test(c)?"chrome":"default"},Y=()=>pe[ge()].filter(c=>{var w,f,L;let p=(L=(f=(w=globalThis.document)==null?void 0:w.featurePolicy)==null?void 0:f.features)==null?void 0:L.call(f);return p?p.includes(c):!0}).join("; ");async function me(c,p={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(p=c,c=null);let w=6e4,{config:f={},headless:L,loading:x="lazy",view:s}=p,r=L||s==="headless",e=null,n=null,l=i=>{i.style.position="absolute",i.style.top="0",i.style.visibility="hidden",i.style.opacity="0"};if(typeof c=="string")e=document.querySelector(c);else if(c instanceof HTMLElement)e=c;else if(!(r&&typeof c=="object"))throw new Error("A valid container element is required.");if(!e)if(r)e=document.createElement("div"),l(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${c}"`);let m=new URL(X(p)),y=m.origin;m.searchParams.set("embed","true"),m.searchParams.set("loading",r?"eager":x),m.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&m.searchParams.set("config","sdk");let E=p.params;typeof E=="object"&&Object.keys(E).length>0&&JSON.stringify(E).length<1800&&Object.keys(E).forEach(i=>{m.searchParams.set(i,encodeURIComponent(String(E[i])))});let C=!1,v="Cannot call API methods after calling `destroy()`.",b=[],S=(i,u="message")=>{addEventListener(u,i),b.push(i)},d=(i,u="message")=>{removeEventListener(u,i);let P=b.indexOf(i);P>-1&&b.splice(P,1)},t=await new Promise(i=>{var O,H,T,_,D,j,q,$,J;if(!e)return;let u=e.dataset.height||e.style.height;if(u&&!r){let F=isNaN(Number(u))?u:u+"px";e.style.height=F}e.dataset.defaultStyles!=="false"&&!r&&((O=e.style).backgroundColor||(O.backgroundColor="#fff"),(H=e.style).border||(H.border="1px solid black"),(T=e.style).borderRadius||(T.borderRadius="8px"),(_=e.style).boxSizing||(_.boxSizing="border-box"),(D=e.style).padding||(D.padding="0"),(j=e.style).width||(j.width="100%"),(q=e.style).height||(q.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",($=e.style).overflow||($.overflow="hidden"),(J=e.style).resize||(J.resize="vertical"),getComputedStyle(e).getPropertyValue("display")==="inline"&&(e.style.display="block"));let P="livecodes",M=e.querySelector(`iframe.${P}`),g=M||document.createElement("iframe");g.classList.add(P),g.setAttribute("allow",Y()),g.setAttribute("allowtransparency","true"),g.setAttribute("allowpaymentrequest","true"),g.setAttribute("allowfullscreen","true"),g.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let U=x==="eager"?"eager":"lazy";g.setAttribute("loading",U),r?l(g):(g.style.height="100%",g.style.minHeight="200px",g.style.width="100%",g.style.margin="0",g.style.border="0",g.style.borderRadius=e.style.borderRadius),S(function F(R){var K;R.source!==g.contentWindow||R.origin!==y||((K=R.data)==null?void 0:K.type)!=="livecodes-init"||(d(F),n=Number(R.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&S(function F(R){var K,Q;R.source!==g.contentWindow||R.origin!==y||((K=R.data)==null?void 0:K.type)!=="livecodes-get-config"||(d(F),(Q=g.contentWindow)==null||Q.postMessage({type:"livecodes-config",payload:f},y))}),g.onload=()=>{i(g)},g.src=m.href,M||e.appendChild(g)}),o=new Promise(i=>{S(function u(P){var M;P.source!==t.contentWindow||P.origin!==y||((M=P.data)==null?void 0:M.type)!=="livecodes-ready"||(d(u),i(),o.settled=!0)})}),A=()=>C?Promise.reject(v):new Promise(async i=>{var P;o.settled&&i();let u={type:"livecodes-load"};(P=t.contentWindow)==null||P.postMessage(u,y),await o,i()}),a=(i,u)=>new Promise(async(P,M)=>{var H;if(C)return M(v);await A();let g=ne(),U=setTimeout(()=>{d(O),M(new Error(`SDK call "${i}" timed out after ${w}ms.`))},w);function O(T){var _,D;if(!(T.source!==t.contentWindow||T.origin!==y||((_=T.data)==null?void 0:_.type)!=="livecodes-api-response"||((D=T.data)==null?void 0:D.id)!==g)&&T.data.method===i){clearTimeout(U),d(O);let j=T.data.payload;j!=null&&j.error?M(j.error):P(j)}}S(O),(H=t.contentWindow)==null||H.postMessage({method:i,id:g,args:u},y)}),k={},V=["load","ready","code","console","tests","destroy"],B=(i,u)=>{var P;if(C)throw new Error(v);return V.includes(i)?(a("watch",[i]),k[i]||(k[i]=[]),(P=k[i])==null||P.push(u),{remove:()=>{var M,g;k[i]=(M=k[i])==null?void 0:M.filter(U=>U!==u),((g=k[i])==null?void 0:g.length)===0&&a("watch",[i,"unsubscribe"])}}):{remove:()=>{}}},ee=i=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[i];S(async function(u){var g,U,O,H;let P=ee((U=(g=u.data)==null?void 0:g.type)!=null?U:"");if(u.source!==t.contentWindow||u.origin!==y||!P||!k[P])return;let M=(O=u.data)==null?void 0:O.payload;(H=k[P])==null||H.forEach(T=>{T(M)})});let te=()=>{var i;(i=t==null?void 0:t.remove)==null||i.call(t),Object.values(k).forEach(u=>{u.length=0}),b.forEach(u=>removeEventListener("message",u)),b.length=0,z&&e&&z.unobserve(e),C=!0},z;x==="lazy"&&"IntersectionObserver"in window&&(z=new IntersectionObserver((i,u)=>{i.forEach(async P=>{P.isIntersecting&&(await A(),u.unobserve(e))})},{rootMargin:"150px"}),z.observe(e));let ne=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>A(),run:()=>a("run"),format:i=>a("format",[i]),getShareUrl:i=>a("getShareUrl",[i]),getConfig:i=>a("getConfig",[i]),setConfig:i=>a("setConfig",[i]),getCode:()=>a("getCode"),show:(i,u)=>a("show",[i,u]),runTests:()=>a("runTests"),onChange:i=>B("code",i),watch:B,exec:(i,...u)=>a("exec",[i,...u]),destroy:()=>C?Promise.reject(v):(te(),Promise.resolve())}}function X(c={}){let{appUrl:p="https://livecodes.io",params:w={},config:f={},headless:L,import:x,lite:s,view:r,...e}=c,n;try{n=new URL(p)}catch(y){throw new Error(`${p} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(e).forEach(([y,E])=>{E!==void 0&&n.searchParams.set(y,String(E))});let m=c.view==="headless"||L;if(s&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":n.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&r!=="headless"?f.view=r:n.searchParams.set("view",r)),typeof f=="string")try{new URL(f),n.searchParams.set("config",encodeURIComponent(f))}catch(y){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&n.searchParams.set("title",f.title),f.description&&f.description.length>0&&n.searchParams.set("description",f.description),l.set("config","code/"+(0,I.compressToEncodedURIComponent)(JSON.stringify(f))));if(w&&typeof w=="object"&&Object.keys(w).length>0)try{l.set("params",(0,I.compressToEncodedURIComponent)(JSON.stringify(w)))}catch(y){Object.keys(w).forEach(E=>{n.searchParams.set(E,encodeURIComponent(String(w[E])))})}return x&&n.searchParams.set("x",encodeURIComponent(x)),m&&n.searchParams.set("headless","true"),l.toString().length>0&&(n.hash=l.toString()),n.href}var he=I.compressToEncodedURIComponent,ye=I.decompressFromEncodedURIComponent;

@@ -1,1 +0,1 @@

var F=Object.create;var Z=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.getPrototypeOf,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:!0}):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]=!0),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.13.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=!1,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=!0)})}),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=!0},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}export{de as createPlayground,ae as getPlaygroundUrl};
var te=Object.create;var Q=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,se=Object.prototype.hasOwnProperty;var ie=(c,m)=>()=>(m||c((m={exports:{}}).exports,m),m.exports);var ae=(c,m,P,f)=>{if(m&&typeof m=="object"||typeof m=="function")for(let L of oe(m))!se.call(c,L)&&L!==P&&Q(c,L,{get:()=>m[L],enumerable:!(f=ne(m,L))||f.enumerable});return c};var le=(c,m,P)=>(P=c!=null?te(re(c)):{},ae(m||!c||!c.__esModule?Q(P,"default",{value:c,enumerable:!0}):P,c));var Z=ie((ge,N)=>{var ce=function(){var c=String.fromCharCode,m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",P="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function L(s,r){if(!f[s]){f[s]={};for(var e=0;e<s.length;e++)f[s][s.charAt(e)]=e}return f[s][r]}var x={compressToBase64:function(s){if(s==null)return"";var r=x._compress(s,6,function(e){return m.charAt(e)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(s){return s==null?"":s==""?null:x._decompress(s.length,32,function(r){return L(m,s.charAt(r))})},compressToUTF16:function(s){return s==null?"":x._compress(s,15,function(r){return c(r+32)})+" "},decompressFromUTF16:function(s){return s==null?"":s==""?null:x._decompress(s.length,16384,function(r){return s.charCodeAt(r)-32})},compressToUint8Array:function(s){for(var r=x.compress(s),e=new Uint8Array(r.length*2),n=0,l=r.length;n<l;n++){var g=r.charCodeAt(n);e[n*2]=g>>>8,e[n*2+1]=g%256}return e},decompressFromUint8Array:function(s){if(s==null)return x.decompress(s);for(var r=new Array(s.length/2),e=0,n=r.length;e<n;e++)r[e]=s[e*2]*256+s[e*2+1];var l=[];return r.forEach(function(g){l.push(c(g))}),x.decompress(l.join(""))},compressToEncodedURIComponent:function(s){return s==null?"":x._compress(s,6,function(r){return P.charAt(r)})},decompressFromEncodedURIComponent:function(s){return s==null?"":s==""?null:(s=s.replace(/ /g,"+"),x._decompress(s.length,32,function(r){return L(P,s.charAt(r))}))},compress:function(s){return x._compress(s,16,function(r){return c(r)})},_compress:function(s,r,e){if(s==null)return"";var n,l,g={},y={},w="",C="",v="",E=2,S=3,d=2,h=[],t=0,o=0,A;for(A=0;A<s.length;A+=1)if(w=s.charAt(A),Object.prototype.hasOwnProperty.call(g,w)||(g[w]=S++,y[w]=!0),C=v+w,Object.prototype.hasOwnProperty.call(g,C))v=C;else{if(Object.prototype.hasOwnProperty.call(y,v)){if(v.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==r-1?(o=0,h.push(e(t)),t=0):o++;for(l=v.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}else{for(l=1,n=0;n<d;n++)t=t<<1|l,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=0;for(l=v.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}E--,E==0&&(E=Math.pow(2,d),d++),delete y[v]}else for(l=g[v],n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;E--,E==0&&(E=Math.pow(2,d),d++),g[C]=S++,v=String(w)}if(v!==""){if(Object.prototype.hasOwnProperty.call(y,v)){if(v.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==r-1?(o=0,h.push(e(t)),t=0):o++;for(l=v.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}else{for(l=1,n=0;n<d;n++)t=t<<1|l,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=0;for(l=v.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1}E--,E==0&&(E=Math.pow(2,d),d++),delete y[v]}else for(l=g[v],n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;E--,E==0&&(E=Math.pow(2,d),d++)}for(l=2,n=0;n<d;n++)t=t<<1|l&1,o==r-1?(o=0,h.push(e(t)),t=0):o++,l=l>>1;for(;;)if(t=t<<1,o==r-1){h.push(e(t));break}else o++;return h.join("")},decompress:function(s){return s==null?"":s==""?null:x._decompress(s.length,32768,function(r){return s.charCodeAt(r)})},_decompress:function(s,r,e){var n=[],l,g=4,y=4,w=3,C="",v=[],E,S,d,h,t,o,A,a={val:e(0),position:r,index:1};for(E=0;E<3;E+=1)n[E]=E;for(d=0,t=Math.pow(2,2),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;switch(l=d){case 0:for(d=0,t=Math.pow(2,8),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;A=c(d);break;case 1:for(d=0,t=Math.pow(2,16),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;A=c(d);break;case 2:return""}for(n[3]=A,S=A,v.push(A);;){if(a.index>s)return"";for(d=0,t=Math.pow(2,w),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;switch(A=d){case 0:for(d=0,t=Math.pow(2,8),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;n[y++]=c(d),A=y-1,g--;break;case 1:for(d=0,t=Math.pow(2,16),o=1;o!=t;)h=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=e(a.index++)),d|=(h>0?1:0)*o,o<<=1;n[y++]=c(d),A=y-1,g--;break;case 2:return v.join("")}if(g==0&&(g=Math.pow(2,w),w++),n[A])C=n[A];else if(A===y)C=S+S.charAt(0);else return null;v.push(C),n[y++]=S+C.charAt(0),g--,S=C,g==0&&(g=Math.pow(2,w),w++)}}};return x}();typeof N!="undefined"&&N!=null&&(N.exports=ce)});var I=le(Z());var de={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},fe=()=>{if(typeof navigator=="undefined")return"default";let c=navigator.userAgent;return/Firefox\//i.test(c)?"firefox":/Chrome\//i.test(c)?"chrome":"default"},G=()=>de[fe()].filter(c=>{var P,f,L;let m=(L=(f=(P=globalThis.document)==null?void 0:P.featurePolicy)==null?void 0:f.features)==null?void 0:L.call(f);return m?m.includes(c):!0}).join("; ");async function ye(c,m={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(m=c,c=null);let P=6e4,{config:f={},headless:L,loading:x="lazy",view:s}=m,r=L||s==="headless",e=null,n=null,l=i=>{i.style.position="absolute",i.style.top="0",i.style.visibility="hidden",i.style.opacity="0"};if(typeof c=="string")e=document.querySelector(c);else if(c instanceof HTMLElement)e=c;else if(!(r&&typeof c=="object"))throw new Error("A valid container element is required.");if(!e)if(r)e=document.createElement("div"),l(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${c}"`);let g=new URL(ue(m)),y=g.origin;g.searchParams.set("embed","true"),g.searchParams.set("loading",r?"eager":x),g.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&g.searchParams.set("config","sdk");let w=m.params;typeof w=="object"&&Object.keys(w).length>0&&JSON.stringify(w).length<1800&&Object.keys(w).forEach(i=>{g.searchParams.set(i,encodeURIComponent(String(w[i])))});let C=!1,v="Cannot call API methods after calling `destroy()`.",E=[],S=(i,u="message")=>{addEventListener(u,i),E.push(i)},d=(i,u="message")=>{removeEventListener(u,i);let b=E.indexOf(i);b>-1&&E.splice(b,1)},t=await new Promise(i=>{var O,H,T,_,D,j,B,q,$;if(!e)return;let u=e.dataset.height||e.style.height;if(u&&!r){let F=isNaN(Number(u))?u:u+"px";e.style.height=F}e.dataset.defaultStyles!=="false"&&!r&&((O=e.style).backgroundColor||(O.backgroundColor="#fff"),(H=e.style).border||(H.border="1px solid black"),(T=e.style).borderRadius||(T.borderRadius="8px"),(_=e.style).boxSizing||(_.boxSizing="border-box"),(D=e.style).padding||(D.padding="0"),(j=e.style).width||(j.width="100%"),(B=e.style).height||(B.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(q=e.style).overflow||(q.overflow="hidden"),($=e.style).resize||($.resize="vertical"),getComputedStyle(e).getPropertyValue("display")==="inline"&&(e.style.display="block"));let b="livecodes",M=e.querySelector(`iframe.${b}`),p=M||document.createElement("iframe");p.classList.add(b),p.setAttribute("allow",G()),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 U=x==="eager"?"eager":"lazy";p.setAttribute("loading",U),r?l(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),S(function F(R){var K;R.source!==p.contentWindow||R.origin!==y||((K=R.data)==null?void 0:K.type)!=="livecodes-init"||(d(F),n=Number(R.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&S(function F(R){var K,J;R.source!==p.contentWindow||R.origin!==y||((K=R.data)==null?void 0:K.type)!=="livecodes-get-config"||(d(F),(J=p.contentWindow)==null||J.postMessage({type:"livecodes-config",payload:f},y))}),p.onload=()=>{i(p)},p.src=g.href,M||e.appendChild(p)}),o=new Promise(i=>{S(function u(b){var M;b.source!==t.contentWindow||b.origin!==y||((M=b.data)==null?void 0:M.type)!=="livecodes-ready"||(d(u),i(),o.settled=!0)})}),A=()=>C?Promise.reject(v):new Promise(async i=>{var b;o.settled&&i();let u={type:"livecodes-load"};(b=t.contentWindow)==null||b.postMessage(u,y),await o,i()}),a=(i,u)=>new Promise(async(b,M)=>{var H;if(C)return M(v);await A();let p=ee(),U=setTimeout(()=>{d(O),M(new Error(`SDK call "${i}" timed out after ${P}ms.`))},P);function O(T){var _,D;if(!(T.source!==t.contentWindow||T.origin!==y||((_=T.data)==null?void 0:_.type)!=="livecodes-api-response"||((D=T.data)==null?void 0:D.id)!==p)&&T.data.method===i){clearTimeout(U),d(O);let j=T.data.payload;j!=null&&j.error?M(j.error):b(j)}}S(O),(H=t.contentWindow)==null||H.postMessage({method:i,id:p,args:u},y)}),k={},Y=["load","ready","code","console","tests","destroy"],W=(i,u)=>{var b;if(C)throw new Error(v);return Y.includes(i)?(a("watch",[i]),k[i]||(k[i]=[]),(b=k[i])==null||b.push(u),{remove:()=>{var M,p;k[i]=(M=k[i])==null?void 0:M.filter(U=>U!==u),((p=k[i])==null?void 0:p.length)===0&&a("watch",[i,"unsubscribe"])}}):{remove:()=>{}}},X=i=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[i];S(async function(u){var p,U,O,H;let b=X((U=(p=u.data)==null?void 0:p.type)!=null?U:"");if(u.source!==t.contentWindow||u.origin!==y||!b||!k[b])return;let M=(O=u.data)==null?void 0:O.payload;(H=k[b])==null||H.forEach(T=>{T(M)})});let V=()=>{var i;(i=t==null?void 0:t.remove)==null||i.call(t),Object.values(k).forEach(u=>{u.length=0}),E.forEach(u=>removeEventListener("message",u)),E.length=0,z&&e&&z.unobserve(e),C=!0},z;x==="lazy"&&"IntersectionObserver"in window&&(z=new IntersectionObserver((i,u)=>{i.forEach(async b=>{b.isIntersecting&&(await A(),u.unobserve(e))})},{rootMargin:"150px"}),z.observe(e));let ee=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>A(),run:()=>a("run"),format:i=>a("format",[i]),getShareUrl:i=>a("getShareUrl",[i]),getConfig:i=>a("getConfig",[i]),setConfig:i=>a("setConfig",[i]),getCode:()=>a("getCode"),show:(i,u)=>a("show",[i,u]),runTests:()=>a("runTests"),onChange:i=>W("code",i),watch:W,exec:(i,...u)=>a("exec",[i,...u]),destroy:()=>C?Promise.reject(v):(V(),Promise.resolve())}}function ue(c={}){let{appUrl:m="https://livecodes.io",params:P={},config:f={},headless:L,import:x,lite:s,view:r,...e}=c,n;try{n=new URL(m)}catch(y){throw new Error(`${m} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(e).forEach(([y,w])=>{w!==void 0&&n.searchParams.set(y,String(w))});let g=c.view==="headless"||L;if(s&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":n.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&r!=="headless"?f.view=r:n.searchParams.set("view",r)),typeof f=="string")try{new URL(f),n.searchParams.set("config",encodeURIComponent(f))}catch(y){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&n.searchParams.set("title",f.title),f.description&&f.description.length>0&&n.searchParams.set("description",f.description),l.set("config","code/"+(0,I.compressToEncodedURIComponent)(JSON.stringify(f))));if(P&&typeof P=="object"&&Object.keys(P).length>0)try{l.set("params",(0,I.compressToEncodedURIComponent)(JSON.stringify(P)))}catch(y){Object.keys(P).forEach(w=>{n.searchParams.set(w,encodeURIComponent(String(P[w])))})}return x&&n.searchParams.set("x",encodeURIComponent(x)),g&&n.searchParams.set("headless","true"),l.toString().length>0&&(n.hash=l.toString()),n.href}var ve=I.compressToEncodedURIComponent,we=I.decompressFromEncodedURIComponent;export{ve as compress,ye as createPlayground,we as decompress,ue as getPlaygroundUrl};

@@ -1,1 +0,1 @@

"use strict";var livecodes=(()=>{var ee=Object.create;var K=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var se=(c,h)=>()=>(h||c((h={exports:{}}).exports,h),h.exports),ie=(c,h)=>{for(var E in h)K(c,E,{get:h[E],enumerable:!0})},$=(c,h,E,y)=>{if(h&&typeof h=="object"||typeof h=="function")for(let M of ne(h))!re.call(c,M)&&M!==E&&K(c,M,{get:()=>h[M],enumerable:!(y=te(h,M))||y.enumerable});return c};var ae=(c,h,E)=>(E=c!=null?ee(oe(c)):{},$(h||!c||!c.__esModule?K(E,"default",{value:c,enumerable:!0}):E,c)),le=c=>$(K({},"__esModule",{value:!0}),c);var G=se((pe,W)=>{var ce=function(){var c=String.fromCharCode,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",E="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 h.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(h,r.charAt(e))})},compressToUTF16:function(r){return r==null?"":A._compress(r,15,function(e){return c(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 m=e.charCodeAt(n);l[n*2]=m>>>8,l[n*2+1]=m%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(m){s.push(c(m))}),A.decompress(s.join(""))},compressToEncodedURIComponent:function(r){return r==null?"":A._compress(r,6,function(e){return E.charAt(e)})},decompressFromEncodedURIComponent:function(r){return r==null?"":r==""?null:(r=r.replace(/ /g,"+"),A._decompress(r.length,32,function(e){return M(E,r.charAt(e))}))},compress:function(r){return A._compress(r,16,function(e){return c(e)})},_compress:function(r,e,l){if(r==null)return"";var n,s,m={},v={},w="",O="",g="",S=2,P=3,d=2,f=[],t=0,o=0,x;for(x=0;x<r.length;x+=1)if(w=r.charAt(x),Object.prototype.hasOwnProperty.call(m,w)||(m[w]=P++,v[w]=!0),O=g+w,Object.prototype.hasOwnProperty.call(m,O))g=O;else{if(Object.prototype.hasOwnProperty.call(v,g)){if(g.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==e-1?(o=0,f.push(l(t)),t=0):o++;for(s=g.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<d;n++)t=t<<1|s,o==e-1?(o=0,f.push(l(t)),t=0):o++,s=0;for(s=g.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,d),d++),delete v[g]}else for(s=m[g],n=0;n<d;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,d),d++),m[O]=P++,g=String(w)}if(g!==""){if(Object.prototype.hasOwnProperty.call(v,g)){if(g.charCodeAt(0)<256){for(n=0;n<d;n++)t=t<<1,o==e-1?(o=0,f.push(l(t)),t=0):o++;for(s=g.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<d;n++)t=t<<1|s,o==e-1?(o=0,f.push(l(t)),t=0):o++,s=0;for(s=g.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,d),d++),delete v[g]}else for(s=m[g],n=0;n<d;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,d),d++)}for(s=2,n=0;n<d;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,m=4,v=4,w=3,O="",g=[],S,P,d,f,t,o,x,a={val:l(0),position:e,index:1};for(S=0;S<3;S+=1)n[S]=S;for(d=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++)),d|=(f>0?1:0)*o,o<<=1;switch(s=d){case 0:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;x=c(d);break;case 1:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;x=c(d);break;case 2:return""}for(n[3]=x,P=x,g.push(x);;){if(a.index>r)return"";for(d=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++)),d|=(f>0?1:0)*o,o<<=1;switch(x=d){case 0:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;n[v++]=c(d),x=v-1,m--;break;case 1:for(d=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++)),d|=(f>0?1:0)*o,o<<=1;n[v++]=c(d),x=v-1,m--;break;case 2:return g.join("")}if(m==0&&(m=Math.pow(2,w),w++),n[x])O=n[x];else if(x===v)O=P+P.charAt(0);else return null;g.push(O),n[v++]=P+O.charAt(0),m--,P=O,m==0&&(m=Math.pow(2,w),w++)}}};return A}();typeof W!="undefined"&&W!=null&&(W.exports=ce)});var fe={};ie(fe,{createPlayground:()=>de,getPlaygroundUrl:()=>X});var z=ae(G());async function de(c,h={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(h=c,c=null);let{config:E={},headless:y,loading:M="lazy",view:A}=h,r=y||A==="headless",e=null,l=null;if(typeof c=="string")e=document.querySelector(c);else if(c instanceof HTMLElement)e=c;else if(!(r&&typeof c=="object"))throw new Error("A valid container element is required.");if(!e)if(r)e=document.createElement("div"),B(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${c}"`);let n=new URL(X(h)),s=n.origin;n.searchParams.set("embed","true"),n.searchParams.set("loading",r?"eager":M),n.searchParams.set("sdkVersion","0.13.0"),typeof E=="object"&&Object.keys(E).length>0&&n.searchParams.set("config","sdk");let m=h.params;typeof m=="object"&&Object.keys(m).length>0&&JSON.stringify(m).length<1800&&Object.keys(m).forEach(i=>{n.searchParams.set(i,encodeURIComponent(String(m[i])))});let v=!1,w="Cannot call API methods after calling `destroy()`.",O=[],g=(i,u="message")=>{addEventListener(u,i),O.push(i)},P=await new Promise(i=>{var C,U,R,k,j,q,J,N,Q;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"),(q=e.style).width||(q.width="100%"),(J=e.style).height||(J.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(N=e.style).overflow||(N.overflow="hidden"),(Q=e.style).resize||(Q.resize="vertical"));let b="livecodes",L=e.querySelector(`iframe.${b}`),p=L||document.createElement("iframe");p.classList.add(b),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?B(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),g(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)&&g(function I(T){var _,Z;T.source!==p.contentWindow||T.origin!==s||((_=T.data)==null?void 0:_.type)!=="livecodes-get-config"||(removeEventListener("message",I),(Z=p.contentWindow)==null||Z.postMessage({type:"livecodes-config",payload:E},s))}),p.onload=()=>{i(p)},p.src=n.href,L||e.appendChild(p)}),d=new Promise(i=>{g(function u(b){var L;b.source!==P.contentWindow||b.origin!==s||((L=b.data)==null?void 0:L.type)!=="livecodes-ready"||(removeEventListener("message",u),i(),d.settled=!0)})}),f=()=>v?Promise.reject(w):new Promise(async i=>{var b;d.settled&&i();let u={type:"livecodes-load"};(b=P.contentWindow)==null||b.postMessage(u,s),await d,i()}),t=(i,u)=>new Promise(async(b,L)=>{var H;if(v)return L(w);await f();let p=V();g(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):b(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 b;if(v)throw new Error(w);return x.includes(i)?(t("watch",[i]),o[i]||(o[i]=[]),(b=o[i])==null||b.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:()=>{}}},Y=i=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[i];g(async function(u){var p,H,C,U;let b=Y((H=(p=u.data)==null?void 0:p.type)!=null?H:"");if(u.source!==P.contentWindow||u.origin!==s||!b||!o[b])return;let L=(C=u.data)==null?void 0:C.payload;(U=o[b])==null||U.forEach(R=>{R(L)})});let F=()=>{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=!0},D;M==="lazy"&&"IntersectionObserver"in window&&(D=new IntersectionObserver((i,u)=>{i.forEach(async b=>{b.isIntersecting&&(await f(),u.unobserve(e))})},{rootMargin:"150px"}),D.observe(e));function B(i){i.style.position="absolute",i.style.top="0",i.style.visibility="hidden",i.style.opacity="0"}let V=()=>(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):(F(),Promise.resolve())}}function X(c={}){let{appUrl:h="https://livecodes.io",params:E={},config:y={},headless:M,import:A,lite:r,view:e,...l}=c,n;try{n=new URL(h)}catch(v){throw new Error(`${h} 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 m=c.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,z.compressToEncodedURIComponent)(JSON.stringify(y))));if(E&&typeof E=="object"&&Object.keys(E).length>0)try{s.set("params",(0,z.compressToEncodedURIComponent)(JSON.stringify(E)))}catch(v){Object.keys(E).forEach(w=>{n.searchParams.set(w,encodeURIComponent(String(E[w])))})}return A&&n.searchParams.set("x",encodeURIComponent(A)),m&&n.searchParams.set("headless","true"),s.toString().length>0&&(n.hash=s.toString()),n.href}return le(fe);})();
"use strict";(()=>{var ue=Object.create;var W=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,he=Object.prototype.hasOwnProperty;var ye=(e,a)=>()=>(a||e((a={exports:{}}).exports,a),a.exports),ve=(e,a)=>{for(var p in a)W(e,p,{get:a[p],enumerable:!0})},xe=(e,a,p,f)=>{if(a&&typeof a=="object"||typeof a=="function")for(let C of ge(a))!he.call(e,C)&&C!==p&&W(e,C,{get:()=>a[C],enumerable:!(f=pe(a,C))||f.enumerable});return e};var we=(e,a,p)=>(p=e!=null?ue(me(e)):{},xe(a||!e||!e.__esModule?W(p,"default",{value:e,enumerable:!0}):p,e));var re=ye((De,Z)=>{var Le=function(){var e=String.fromCharCode,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function C(i,o){if(!f[i]){f[i]={};for(var t=0;t<i.length;t++)f[i][i.charAt(t)]=t}return f[i][o]}var E={compressToBase64:function(i){if(i==null)return"";var o=E._compress(i,6,function(t){return a.charAt(t)});switch(o.length%4){default:case 0:return o;case 1:return o+"===";case 2:return o+"==";case 3:return o+"="}},decompressFromBase64:function(i){return i==null?"":i==""?null:E._decompress(i.length,32,function(o){return C(a,i.charAt(o))})},compressToUTF16:function(i){return i==null?"":E._compress(i,15,function(o){return e(o+32)})+" "},decompressFromUTF16:function(i){return i==null?"":i==""?null:E._decompress(i.length,16384,function(o){return i.charCodeAt(o)-32})},compressToUint8Array:function(i){for(var o=E.compress(i),t=new Uint8Array(o.length*2),r=0,d=o.length;r<d;r++){var h=o.charCodeAt(r);t[r*2]=h>>>8,t[r*2+1]=h%256}return t},decompressFromUint8Array:function(i){if(i==null)return E.decompress(i);for(var o=new Array(i.length/2),t=0,r=o.length;t<r;t++)o[t]=i[t*2]*256+i[t*2+1];var d=[];return o.forEach(function(h){d.push(e(h))}),E.decompress(d.join(""))},compressToEncodedURIComponent:function(i){return i==null?"":E._compress(i,6,function(o){return p.charAt(o)})},decompressFromEncodedURIComponent:function(i){return i==null?"":i==""?null:(i=i.replace(/ /g,"+"),E._decompress(i.length,32,function(o){return C(p,i.charAt(o))}))},compress:function(i){return E._compress(i,16,function(o){return e(o)})},_compress:function(i,o,t){if(i==null)return"";var r,d,h={},v={},w="",S="",x="",b=2,U=3,u=2,y=[],n=0,s=0,P;for(P=0;P<i.length;P+=1)if(w=i.charAt(P),Object.prototype.hasOwnProperty.call(h,w)||(h[w]=U++,v[w]=!0),S=x+w,Object.prototype.hasOwnProperty.call(h,S))x=S;else{if(Object.prototype.hasOwnProperty.call(v,x)){if(x.charCodeAt(0)<256){for(r=0;r<u;r++)n=n<<1,s==o-1?(s=0,y.push(t(n)),n=0):s++;for(d=x.charCodeAt(0),r=0;r<8;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1}else{for(d=1,r=0;r<u;r++)n=n<<1|d,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=0;for(d=x.charCodeAt(0),r=0;r<16;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1}b--,b==0&&(b=Math.pow(2,u),u++),delete v[x]}else for(d=h[x],r=0;r<u;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1;b--,b==0&&(b=Math.pow(2,u),u++),h[S]=U++,x=String(w)}if(x!==""){if(Object.prototype.hasOwnProperty.call(v,x)){if(x.charCodeAt(0)<256){for(r=0;r<u;r++)n=n<<1,s==o-1?(s=0,y.push(t(n)),n=0):s++;for(d=x.charCodeAt(0),r=0;r<8;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1}else{for(d=1,r=0;r<u;r++)n=n<<1|d,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=0;for(d=x.charCodeAt(0),r=0;r<16;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1}b--,b==0&&(b=Math.pow(2,u),u++),delete v[x]}else for(d=h[x],r=0;r<u;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1;b--,b==0&&(b=Math.pow(2,u),u++)}for(d=2,r=0;r<u;r++)n=n<<1|d&1,s==o-1?(s=0,y.push(t(n)),n=0):s++,d=d>>1;for(;;)if(n=n<<1,s==o-1){y.push(t(n));break}else s++;return y.join("")},decompress:function(i){return i==null?"":i==""?null:E._decompress(i.length,32768,function(o){return i.charCodeAt(o)})},_decompress:function(i,o,t){var r=[],d,h=4,v=4,w=3,S="",x=[],b,U,u,y,n,s,P,c={val:t(0),position:o,index:1};for(b=0;b<3;b+=1)r[b]=b;for(u=0,n=Math.pow(2,2),s=1;s!=n;)y=c.val&c.position,c.position>>=1,c.position==0&&(c.position=o,c.val=t(c.index++)),u|=(y>0?1:0)*s,s<<=1;switch(d=u){case 0:for(u=0,n=Math.pow(2,8),s=1;s!=n;)y=c.val&c.position,c.position>>=1,c.position==0&&(c.position=o,c.val=t(c.index++)),u|=(y>0?1:0)*s,s<<=1;P=e(u);break;case 1:for(u=0,n=Math.pow(2,16),s=1;s!=n;)y=c.val&c.position,c.position>>=1,c.position==0&&(c.position=o,c.val=t(c.index++)),u|=(y>0?1:0)*s,s<<=1;P=e(u);break;case 2:return""}for(r[3]=P,U=P,x.push(P);;){if(c.index>i)return"";for(u=0,n=Math.pow(2,w),s=1;s!=n;)y=c.val&c.position,c.position>>=1,c.position==0&&(c.position=o,c.val=t(c.index++)),u|=(y>0?1:0)*s,s<<=1;switch(P=u){case 0:for(u=0,n=Math.pow(2,8),s=1;s!=n;)y=c.val&c.position,c.position>>=1,c.position==0&&(c.position=o,c.val=t(c.index++)),u|=(y>0?1:0)*s,s<<=1;r[v++]=e(u),P=v-1,h--;break;case 1:for(u=0,n=Math.pow(2,16),s=1;s!=n;)y=c.val&c.position,c.position>>=1,c.position==0&&(c.position=o,c.val=t(c.index++)),u|=(y>0?1:0)*s,s<<=1;r[v++]=e(u),P=v-1,h--;break;case 2:return x.join("")}if(h==0&&(h=Math.pow(2,w),w++),r[P])S=r[P];else if(P===v)S=U+U.charAt(0);else return null;x.push(S),r[v++]=U+S.charAt(0),h--,U=S,h==0&&(h=Math.pow(2,w),w++)}}};return E}();typeof Z!="undefined"&&Z!=null&&(Z.exports=Le)});var be=typeof btoa=="function",$=typeof Buffer=="function",Be=typeof TextDecoder=="function"?new TextDecoder:void 0,ee=typeof TextEncoder=="function"?new TextEncoder:void 0,Ee="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",K=Array.prototype.slice.call(Ee),je=(e=>{let a={};return e.forEach((p,f)=>a[p]=f),a})(K);var _=String.fromCharCode.bind(String),He=typeof Uint8Array.from=="function"?Uint8Array.from.bind(Uint8Array):e=>new Uint8Array(Array.prototype.slice.call(e,0)),Ae=e=>e.replace(/=/g,"").replace(/[+\/]/g,a=>a=="+"?"-":"_");var Ce=e=>{let a,p,f,C,E="",i=e.length%3;for(let o=0;o<e.length;){if((p=e.charCodeAt(o++))>255||(f=e.charCodeAt(o++))>255||(C=e.charCodeAt(o++))>255)throw new TypeError("invalid character found");a=p<<16|f<<8|C,E+=K[a>>18&63]+K[a>>12&63]+K[a>>6&63]+K[a&63]}return i?E.slice(0,i-3)+"===".substring(i):E},ne=be?e=>btoa(e):$?e=>Buffer.from(e,"binary").toString("base64"):Ce,Pe=$?e=>Buffer.from(e).toString("base64"):e=>{let p=[];for(let f=0,C=e.length;f<C;f+=4096)p.push(_.apply(null,e.subarray(f,f+4096)));return ne(p.join(""))};var Se=e=>{if(e.length<2){var a=e.charCodeAt(0);return a<128?e:a<2048?_(192|a>>>6)+_(128|a&63):_(224|a>>>12&15)+_(128|a>>>6&63)+_(128|a&63)}else{var a=65536+(e.charCodeAt(0)-55296)*1024+(e.charCodeAt(1)-56320);return _(240|a>>>18&7)+_(128|a>>>12&63)+_(128|a>>>6&63)+_(128|a&63)}},Ue=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,Te=e=>e.replace(Ue,Se),te=$?e=>Buffer.from(e,"utf8").toString("base64"):ee?e=>Pe(ee.encode(e)):e=>ne(Te(e)),oe=(e,a=!1)=>a?Ae(te(e)):te(e);var J={};ve(J,{compress:()=>Oe,createPlayground:()=>q,decompress:()=>Re,getPlaygroundUrl:()=>ie});var H=we(re());var _e={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},Me=()=>{if(typeof navigator=="undefined")return"default";let e=navigator.userAgent;return/Firefox\//i.test(e)?"firefox":/Chrome\//i.test(e)?"chrome":"default"},se=()=>_e[Me()].filter(e=>{var p,f,C;let a=(C=(f=(p=globalThis.document)==null?void 0:p.featurePolicy)==null?void 0:f.features)==null?void 0:C.call(f);return a?a.includes(e):!0}).join("; ");async function q(e,a={}){typeof e=="object"&&!(e instanceof HTMLElement)&&(e.headless||e.view==="headless")&&(a=e,e=null);let p=6e4,{config:f={},headless:C,loading:E="lazy",view:i}=a,o=C||i==="headless",t=null,r=null,d=l=>{l.style.position="absolute",l.style.top="0",l.style.visibility="hidden",l.style.opacity="0"};if(typeof e=="string")t=document.querySelector(e);else if(e instanceof HTMLElement)t=e;else if(!(o&&typeof e=="object"))throw new Error("A valid container element is required.");if(!t)if(o)t=document.createElement("div"),d(t),document.body.appendChild(t);else throw new Error(`Cannot find element: "${e}"`);let h=new URL(ie(a)),v=h.origin;h.searchParams.set("embed","true"),h.searchParams.set("loading",o?"eager":E),h.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&h.searchParams.set("config","sdk");let w=a.params;typeof w=="object"&&Object.keys(w).length>0&&JSON.stringify(w).length<1800&&Object.keys(w).forEach(l=>{h.searchParams.set(l,encodeURIComponent(String(w[l])))});let S=!1,x="Cannot call API methods after calling `destroy()`.",b=[],U=(l,g="message")=>{addEventListener(g,l),b.push(l)},u=(l,g="message")=>{removeEventListener(g,l);let A=b.indexOf(l);A>-1&&b.splice(A,1)},n=await new Promise(l=>{var O,I,L,k,D,B,G,Y,X;if(!t)return;let g=t.dataset.height||t.style.height;if(g&&!o){let F=isNaN(Number(g))?g:g+"px";t.style.height=F}t.dataset.defaultStyles!=="false"&&!o&&((O=t.style).backgroundColor||(O.backgroundColor="#fff"),(I=t.style).border||(I.border="1px solid black"),(L=t.style).borderRadius||(L.borderRadius="8px"),(k=t.style).boxSizing||(k.boxSizing="border-box"),(D=t.style).padding||(D.padding="0"),(B=t.style).width||(B.width="100%"),(G=t.style).height||(G.height=t.style.height||"300px"),t.style.minHeight="200px",t.style.flexGrow="1",(Y=t.style).overflow||(Y.overflow="hidden"),(X=t.style).resize||(X.resize="vertical"),getComputedStyle(t).getPropertyValue("display")==="inline"&&(t.style.display="block"));let A="livecodes",T=t.querySelector(`iframe.${A}`),m=T||document.createElement("iframe");m.classList.add(A),m.setAttribute("allow",se()),m.setAttribute("allowtransparency","true"),m.setAttribute("allowpaymentrequest","true"),m.setAttribute("allowfullscreen","true"),m.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let R=E==="eager"?"eager":"lazy";m.setAttribute("loading",R),o?d(m):(m.style.height="100%",m.style.minHeight="200px",m.style.width="100%",m.style.margin="0",m.style.border="0",m.style.borderRadius=t.style.borderRadius),U(function F(j){var z;j.source!==m.contentWindow||j.origin!==v||((z=j.data)==null?void 0:z.type)!=="livecodes-init"||(u(F),r=Number(j.data.payload.appVersion.replace(/^v/,"")))}),(!r||r<46)&&U(function F(j){var z,V;j.source!==m.contentWindow||j.origin!==v||((z=j.data)==null?void 0:z.type)!=="livecodes-get-config"||(u(F),(V=m.contentWindow)==null||V.postMessage({type:"livecodes-config",payload:f},v))}),m.onload=()=>{l(m)},m.src=h.href,T||t.appendChild(m)}),s=new Promise(l=>{U(function g(A){var T;A.source!==n.contentWindow||A.origin!==v||((T=A.data)==null?void 0:T.type)!=="livecodes-ready"||(u(g),l(),s.settled=!0)})}),P=()=>S?Promise.reject(x):new Promise(async l=>{var A;s.settled&&l();let g={type:"livecodes-load"};(A=n.contentWindow)==null||A.postMessage(g,v),await s,l()}),c=(l,g)=>new Promise(async(A,T)=>{var I;if(S)return T(x);await P();let m=fe(),R=setTimeout(()=>{u(O),T(new Error(`SDK call "${l}" timed out after ${p}ms.`))},p);function O(L){var k,D;if(!(L.source!==n.contentWindow||L.origin!==v||((k=L.data)==null?void 0:k.type)!=="livecodes-api-response"||((D=L.data)==null?void 0:D.id)!==m)&&L.data.method===l){clearTimeout(R),u(O);let B=L.data.payload;B!=null&&B.error?T(B.error):A(B)}}U(O),(I=n.contentWindow)==null||I.postMessage({method:l,id:m,args:g},v)}),M={},le=["load","ready","code","console","tests","destroy"],Q=(l,g)=>{var A;if(S)throw new Error(x);return le.includes(l)?(c("watch",[l]),M[l]||(M[l]=[]),(A=M[l])==null||A.push(g),{remove:()=>{var T,m;M[l]=(T=M[l])==null?void 0:T.filter(R=>R!==g),((m=M[l])==null?void 0:m.length)===0&&c("watch",[l,"unsubscribe"])}}):{remove:()=>{}}},ce=l=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[l];U(async function(g){var m,R,O,I;let A=ce((R=(m=g.data)==null?void 0:m.type)!=null?R:"");if(g.source!==n.contentWindow||g.origin!==v||!A||!M[A])return;let T=(O=g.data)==null?void 0:O.payload;(I=M[A])==null||I.forEach(L=>{L(T)})});let de=()=>{var l;(l=n==null?void 0:n.remove)==null||l.call(n),Object.values(M).forEach(g=>{g.length=0}),b.forEach(g=>removeEventListener("message",g)),b.length=0,N&&t&&N.unobserve(t),S=!0},N;E==="lazy"&&"IntersectionObserver"in window&&(N=new IntersectionObserver((l,g)=>{l.forEach(async A=>{A.isIntersecting&&(await P(),g.unobserve(t))})},{rootMargin:"150px"}),N.observe(t));let fe=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>P(),run:()=>c("run"),format:l=>c("format",[l]),getShareUrl:l=>c("getShareUrl",[l]),getConfig:l=>c("getConfig",[l]),setConfig:l=>c("setConfig",[l]),getCode:()=>c("getCode"),show:(l,g)=>c("show",[l,g]),runTests:()=>c("runTests"),onChange:l=>Q("code",l),watch:Q,exec:(l,...g)=>c("exec",[l,...g]),destroy:()=>S?Promise.reject(x):(de(),Promise.resolve())}}function ie(e={}){let{appUrl:a="https://livecodes.io",params:p={},config:f={},headless:C,import:E,lite:i,view:o,...t}=e,r;try{r=new URL(a)}catch(v){throw new Error(`${a} is not a valid URL.`)}let d=new URLSearchParams;Object.entries(t).forEach(([v,w])=>{w!==void 0&&r.searchParams.set(v,String(w))});let h=e.view==="headless"||C;if(i&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":r.searchParams.set("lite","true")),o&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&o!=="headless"?f.view=o:r.searchParams.set("view",o)),typeof f=="string")try{new URL(f),r.searchParams.set("config",encodeURIComponent(f))}catch(v){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&r.searchParams.set("title",f.title),f.description&&f.description.length>0&&r.searchParams.set("description",f.description),d.set("config","code/"+(0,H.compressToEncodedURIComponent)(JSON.stringify(f))));if(p&&typeof p=="object"&&Object.keys(p).length>0)try{d.set("params",(0,H.compressToEncodedURIComponent)(JSON.stringify(p)))}catch(v){Object.keys(p).forEach(w=>{r.searchParams.set(w,encodeURIComponent(String(p[w])))})}return E&&r.searchParams.set("x",encodeURIComponent(E)),h&&r.searchParams.set("headless","true"),d.toString().length>0&&(r.hash=d.toString()),r.href}var Oe=H.compressToEncodedURIComponent,Re=H.decompressFromEncodedURIComponent;globalThis.livecodes=Object.assign(globalThis.livecodes||{},J);var ae;(ae=globalThis.document)!=null&&ae.currentScript&&"prefill"in globalThis.document.currentScript.dataset&&window.addEventListener("load",()=>{document.querySelectorAll(".livecodes").forEach(e=>{let a,p=e.dataset.options;if(p)try{a=JSON.parse(p)}catch(C){console.warn("Failed to parse options:",p)}let f=encodeURIComponent(`data:text/html;charset=UTF-8;base64,${oe(e.outerHTML)}`);e.innerHTML="",q(e,{import:f,...a})})});})();
{
"name": "livecodes",
"version": "0.13.0",
"version": "0.14.0",
"description": "A Code Playground That Just Works!",
"author": "Hatem Hosny",
"license": "MIT",
"keywords": ["playground", "code", "repl", "client", "sdk", "react", "vue", "svelte", "python"],
"private": false,
"homepage": "https://livecodes.io",
"repository": {
"url": "https://github.com/live-codes/livecodes"
},
"bugs": "https://github.com/live-codes/livecodes/issues",
"type": "module",

@@ -16,3 +16,3 @@ "main": "./livecodes.js",

"browser": "./livecodes.js",
"types": "./livecodes.d.ts",
"types": "./types/index.d.ts",
"exports": {

@@ -22,12 +22,54 @@ ".": {

"require": "./livecodes.cjs",
"default": "./livecodes.js"
"default": "./livecodes.js",
"types": "./types/index.d.ts"
},
"./react": {
"import": "./react.js"
"import": "./react.js",
"types": "./types/react.d.ts"
},
"./preact": {
"import": "./preact.js",
"types": "./types/preact.d.ts"
},
"./solid": {
"import": "./solid.js",
"types": "./types/solid.d.ts"
},
"./svelte": {
"svelte": "./LiveCodes.svelte",
"default": "./svelte.js",
"types": "./types/svelte.d.ts"
},
"./vue": {
"import": "./vue.js"
"import": "./vue.js",
"types": "./types/vue.d.ts"
},
"./web-components": {
"import": "./web-components.js",
"types": "./types/web-components.d.ts"
},
"./package.json": "./package.json"
}
},
"keywords": [
"playground",
"code",
"repl",
"sdk",
"preact",
"react",
"solid",
"svelte",
"vue",
"web-components",
"python",
"tanstack-intent"
],
"funding": [
"https://github.com/sponsors/live-codes",
"https://github.com/sponsors/hatemhosny",
"https://ko-fi.com/hatemhosny",
"https://paypal.me/hatemhosni",
"https://livecodes.io/docs/sponsor"
],
"private": false
}

@@ -1,1 +0,1 @@

var te=Object.create;var $=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var se=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var ie=(d,m)=>()=>(m||d((m={exports:{}}).exports,m),m.exports);var ae=(d,m,b,u)=>{if(m&&typeof m=="object"||typeof m=="function")for(let A of oe(m))!re.call(d,A)&&A!==b&&$(d,A,{get:()=>m[A],enumerable:!(u=ne(m,A))||u.enumerable});return d};var le=(d,m,b)=>(b=d!=null?te(se(d)):{},ae(m||!d||!d.__esModule?$(b,"default",{value:d,enumerable:!0}):b,d));var G=ie((ye,J)=>{var ce=function(){var d=String.fromCharCode,m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",u={};function A(s,e){if(!u[s]){u[s]={};for(var i=0;i<s.length;i++)u[s][s.charAt(i)]=i}return u[s][e]}var O={compressToBase64:function(s){if(s==null)return"";var e=O._compress(s,6,function(i){return m.charAt(i)});switch(e.length%4){default:case 0:return e;case 1:return e+"===";case 2:return e+"==";case 3:return e+"="}},decompressFromBase64:function(s){return s==null?"":s==""?null:O._decompress(s.length,32,function(e){return A(m,s.charAt(e))})},compressToUTF16:function(s){return s==null?"":O._compress(s,15,function(e){return d(e+32)})+" "},decompressFromUTF16:function(s){return s==null?"":s==""?null:O._decompress(s.length,16384,function(e){return s.charCodeAt(e)-32})},compressToUint8Array:function(s){for(var e=O.compress(s),i=new Uint8Array(e.length*2),n=0,r=e.length;n<r;n++){var y=e.charCodeAt(n);i[n*2]=y>>>8,i[n*2+1]=y%256}return i},decompressFromUint8Array:function(s){if(s==null)return O.decompress(s);for(var e=new Array(s.length/2),i=0,n=e.length;i<n;i++)e[i]=s[i*2]*256+s[i*2+1];var r=[];return e.forEach(function(y){r.push(d(y))}),O.decompress(r.join(""))},compressToEncodedURIComponent:function(s){return s==null?"":O._compress(s,6,function(e){return b.charAt(e)})},decompressFromEncodedURIComponent:function(s){return s==null?"":s==""?null:(s=s.replace(/ /g,"+"),O._decompress(s.length,32,function(e){return A(b,s.charAt(e))}))},compress:function(s){return O._compress(s,16,function(e){return d(e)})},_compress:function(s,e,i){if(s==null)return"";var n,r,y={},v={},w="",M="",g="",S=2,E=3,l=2,f=[],t=0,o=0,x;for(x=0;x<s.length;x+=1)if(w=s.charAt(x),Object.prototype.hasOwnProperty.call(y,w)||(y[w]=E++,v[w]=!0),M=g+w,Object.prototype.hasOwnProperty.call(y,M))g=M;else{if(Object.prototype.hasOwnProperty.call(v,g)){if(g.charCodeAt(0)<256){for(n=0;n<l;n++)t=t<<1,o==e-1?(o=0,f.push(i(t)),t=0):o++;for(r=g.charCodeAt(0),n=0;n<8;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1}else{for(r=1,n=0;n<l;n++)t=t<<1|r,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=0;for(r=g.charCodeAt(0),n=0;n<16;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1}S--,S==0&&(S=Math.pow(2,l),l++),delete v[g]}else for(r=y[g],n=0;n<l;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1;S--,S==0&&(S=Math.pow(2,l),l++),y[M]=E++,g=String(w)}if(g!==""){if(Object.prototype.hasOwnProperty.call(v,g)){if(g.charCodeAt(0)<256){for(n=0;n<l;n++)t=t<<1,o==e-1?(o=0,f.push(i(t)),t=0):o++;for(r=g.charCodeAt(0),n=0;n<8;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1}else{for(r=1,n=0;n<l;n++)t=t<<1|r,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=0;for(r=g.charCodeAt(0),n=0;n<16;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1}S--,S==0&&(S=Math.pow(2,l),l++),delete v[g]}else for(r=y[g],n=0;n<l;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1;S--,S==0&&(S=Math.pow(2,l),l++)}for(r=2,n=0;n<l;n++)t=t<<1|r&1,o==e-1?(o=0,f.push(i(t)),t=0):o++,r=r>>1;for(;;)if(t=t<<1,o==e-1){f.push(i(t));break}else o++;return f.join("")},decompress:function(s){return s==null?"":s==""?null:O._decompress(s.length,32768,function(e){return s.charCodeAt(e)})},_decompress:function(s,e,i){var n=[],r,y=4,v=4,w=3,M="",g=[],S,E,l,f,t,o,x,c={val:i(0),position:e,index:1};for(S=0;S<3;S+=1)n[S]=S;for(l=0,t=Math.pow(2,2),o=1;o!=t;)f=c.val&c.position,c.position>>=1,c.position==0&&(c.position=e,c.val=i(c.index++)),l|=(f>0?1:0)*o,o<<=1;switch(r=l){case 0:for(l=0,t=Math.pow(2,8),o=1;o!=t;)f=c.val&c.position,c.position>>=1,c.position==0&&(c.position=e,c.val=i(c.index++)),l|=(f>0?1:0)*o,o<<=1;x=d(l);break;case 1:for(l=0,t=Math.pow(2,16),o=1;o!=t;)f=c.val&c.position,c.position>>=1,c.position==0&&(c.position=e,c.val=i(c.index++)),l|=(f>0?1:0)*o,o<<=1;x=d(l);break;case 2:return""}for(n[3]=x,E=x,g.push(x);;){if(c.index>s)return"";for(l=0,t=Math.pow(2,w),o=1;o!=t;)f=c.val&c.position,c.position>>=1,c.position==0&&(c.position=e,c.val=i(c.index++)),l|=(f>0?1:0)*o,o<<=1;switch(x=l){case 0:for(l=0,t=Math.pow(2,8),o=1;o!=t;)f=c.val&c.position,c.position>>=1,c.position==0&&(c.position=e,c.val=i(c.index++)),l|=(f>0?1:0)*o,o<<=1;n[v++]=d(l),x=v-1,y--;break;case 1:for(l=0,t=Math.pow(2,16),o=1;o!=t;)f=c.val&c.position,c.position>>=1,c.position==0&&(c.position=e,c.val=i(c.index++)),l|=(f>0?1:0)*o,o<<=1;n[v++]=d(l),x=v-1,y--;break;case 2:return g.join("")}if(y==0&&(y=Math.pow(2,w),w++),n[x])M=n[x];else if(x===v)M=E+E.charAt(0);else return null;g.push(M),n[v++]=E+M.charAt(0),y--,E=M,y==0&&(y=Math.pow(2,w),w++)}}};return O}();typeof J!="undefined"&&J!=null&&(J.exports=ce)});import{useEffect as Y,useRef as fe,useState as k}from"react";var K=le(G());async function X(d,m={}){typeof d=="object"&&!(d instanceof HTMLElement)&&(d.headless||d.view==="headless")&&(m=d,d=null);let{config:b={},headless:u,loading:A="lazy",view:O}=m,s=u||O==="headless",e=null,i=null;if(typeof d=="string")e=document.querySelector(d);else if(d instanceof HTMLElement)e=d;else if(!(s&&typeof d=="object"))throw new Error("A valid container element is required.");if(!e)if(s)e=document.createElement("div"),W(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${d}"`);let n=new URL(de(m)),r=n.origin;n.searchParams.set("embed","true"),n.searchParams.set("loading",s?"eager":A),n.searchParams.set("sdkVersion","0.13.0"),typeof b=="object"&&Object.keys(b).length>0&&n.searchParams.set("config","sdk");let y=m.params;typeof y=="object"&&Object.keys(y).length>0&&JSON.stringify(y).length<1800&&Object.keys(y).forEach(a=>{n.searchParams.set(a,encodeURIComponent(String(y[a])))});let v=!1,w="Cannot call API methods after calling `destroy()`.",M=[],g=(a,p="message")=>{addEventListener(p,a),M.push(a)},E=await new Promise(a=>{var j,C,T,I,U,z,B,q,Q;if(!e)return;let p=e.dataset.height||e.style.height;if(p&&!s){let _=isNaN(Number(p))?p:p+"px";e.style.height=_}e.dataset.defaultStyles!=="false"&&!s&&((j=e.style).backgroundColor||(j.backgroundColor="#fff"),(C=e.style).border||(C.border="1px solid black"),(T=e.style).borderRadius||(T.borderRadius="8px"),(I=e.style).boxSizing||(I.boxSizing="border-box"),(U=e.style).padding||(U.padding="0"),(z=e.style).width||(z.width="100%"),(B=e.style).height||(B.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(q=e.style).overflow||(q.overflow="hidden"),(Q=e.style).resize||(Q.resize="vertical"));let P="livecodes",L=e.querySelector(`iframe.${P}`),h=L||document.createElement("iframe");h.classList.add(P),h.setAttribute("allow","accelerometer; camera; encrypted-media; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; web-share"),h.setAttribute("allowtransparency","true"),h.setAttribute("allowpaymentrequest","true"),h.setAttribute("allowfullscreen","true"),h.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let R=A==="eager"?"eager":"lazy";h.setAttribute("loading",R),s?W(h):(h.style.height="100%",h.style.minHeight="200px",h.style.width="100%",h.style.margin="0",h.style.border="0",h.style.borderRadius=e.style.borderRadius),g(function _(H){var D;H.source!==h.contentWindow||H.origin!==r||((D=H.data)==null?void 0:D.type)!=="livecodes-init"||(removeEventListener("message",_),i=Number(H.data.payload.appVersion.replace(/^v/,"")))}),(!i||i<46)&&g(function _(H){var D,Z;H.source!==h.contentWindow||H.origin!==r||((D=H.data)==null?void 0:D.type)!=="livecodes-get-config"||(removeEventListener("message",_),(Z=h.contentWindow)==null||Z.postMessage({type:"livecodes-config",payload:b},r))}),h.onload=()=>{a(h)},h.src=n.href,L||e.appendChild(h)}),l=new Promise(a=>{g(function p(P){var L;P.source!==E.contentWindow||P.origin!==r||((L=P.data)==null?void 0:L.type)!=="livecodes-ready"||(removeEventListener("message",p),a(),l.settled=!0)})}),f=()=>v?Promise.reject(w):new Promise(async a=>{var P;l.settled&&a();let p={type:"livecodes-load"};(P=E.contentWindow)==null||P.postMessage(p,r),await l,a()}),t=(a,p)=>new Promise(async(P,L)=>{var R;if(v)return L(w);await f();let h=ee();g(function j(C){var T,I;if(!(C.source!==E.contentWindow||C.origin!==r||((T=C.data)==null?void 0:T.type)!=="livecodes-api-response"||((I=C.data)==null?void 0:I.id)!==h)&&C.data.method===a){removeEventListener("message",j);let U=C.data.payload;U!=null&&U.error?L(U.error):P(U)}}),(R=E.contentWindow)==null||R.postMessage({method:a,id:h,args:p},r)}),o={},x=["load","ready","code","console","tests","destroy"],c=(a,p)=>{var P;if(v)throw new Error(w);return x.includes(a)?(t("watch",[a]),o[a]||(o[a]=[]),(P=o[a])==null||P.push(p),{remove:()=>{var L,h;o[a]=(L=o[a])==null?void 0:L.filter(R=>R!==p),((h=o[a])==null?void 0:h.length)===0&&t("watch",[a,"unsubscribe"])}}):{remove:()=>{}}},F=a=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[a];g(async function(p){var h,R,j,C;let P=F((R=(h=p.data)==null?void 0:h.type)!=null?R:"");if(p.source!==E.contentWindow||p.origin!==r||!P||!o[P])return;let L=(j=p.data)==null?void 0:j.payload;(C=o[P])==null||C.forEach(T=>{T(L)})});let V=()=>{var a;(a=E==null?void 0:E.remove)==null||a.call(E),Object.values(o).forEach(p=>{p.length=0}),M.forEach(p=>removeEventListener("message",p)),M.length=0,N&&e&&N.unobserve(e),v=!0},N;A==="lazy"&&"IntersectionObserver"in window&&(N=new IntersectionObserver((a,p)=>{a.forEach(async P=>{P.isIntersecting&&(await f(),p.unobserve(e))})},{rootMargin:"150px"}),N.observe(e));function W(a){a.style.position="absolute",a.style.top="0",a.style.visibility="hidden",a.style.opacity="0"}let ee=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>f(),run:()=>t("run"),format:a=>t("format",[a]),getShareUrl:a=>t("getShareUrl",[a]),getConfig:a=>t("getConfig",[a]),setConfig:a=>t("setConfig",[a]),getCode:()=>t("getCode"),show:(a,p)=>t("show",[a,p]),runTests:()=>t("runTests"),onChange:a=>c("code",a),watch:c,exec:(a,...p)=>t("exec",[a,...p]),destroy:()=>v?Promise.reject(w):(V(),Promise.resolve())}}function de(d={}){let{appUrl:m="https://livecodes.io",params:b={},config:u={},headless:A,import:O,lite:s,view:e,...i}=d,n;try{n=new URL(m)}catch(v){throw new Error(`${m} is not a valid URL.`)}let r=new URLSearchParams;Object.entries(i).forEach(([v,w])=>{w!==void 0&&n.searchParams.set(v,String(w))});let y=d.view==="headless"||A;if(s&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof u=="object"&&u.mode==null?u.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 u=="object"&&u.view==null&&e!=="headless"?u.view=e:n.searchParams.set("view",e)),typeof u=="string")try{new URL(u),n.searchParams.set("config",encodeURIComponent(u))}catch(v){throw new Error('"config" is not a valid URL or configuration object.')}else u&&typeof u=="object"&&Object.keys(u).length>0&&(u.title&&u.title!=="Untitled Project"&&n.searchParams.set("title",u.title),u.description&&u.description.length>0&&n.searchParams.set("description",u.description),r.set("config","code/"+(0,K.compressToEncodedURIComponent)(JSON.stringify(u))));if(b&&typeof b=="object"&&Object.keys(b).length>0)try{r.set("params",(0,K.compressToEncodedURIComponent)(JSON.stringify(b)))}catch(v){Object.keys(b).forEach(w=>{n.searchParams.set(w,encodeURIComponent(String(b[w])))})}return O&&n.searchParams.set("x",encodeURIComponent(O)),y&&n.searchParams.set("headless","true"),r.toString().length>0&&(n.hash=r.toString()),n.href}import{jsx as pe}from"react/jsx-runtime";function ue(d){let m=fe(null),[b,u]=k(d.className||""),[A,O]=k(d.style||{}),[s,e]=k(d.height),[i,n]=k(),[r,y]=k(JSON.stringify(d.config||"")),[v,w]=k("");return Y(()=>{if(!m.current)return;let{className:M,style:g,height:S,sdkReady:E,config:l,...f}=d;if(u(M||""),O(g||{}),e(S),!i||v!==JSON.stringify(f))w(JSON.stringify(f)),i==null||i.destroy(),X(m.current,{config:l,...f}).then(t=>{n(t),typeof E=="function"&&E(t)});else{if(r===JSON.stringify(l))return;y(JSON.stringify(l)),typeof l=="string"?fetch(l).then(t=>t.json()).then(t=>{i==null||i.setConfig(t)}):l&&i.setConfig(l)}},[d]),Y(()=>()=>{i==null||i.destroy()},[]),pe("div",{ref:m,className:b,style:A,"data-height":s})}export{ue as default};
var oe=Object.create;var Q=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ie=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var le=(d,u)=>()=>(u||d((u={exports:{}}).exports,u),u.exports);var ce=(d,u,m,f)=>{if(u&&typeof u=="object"||typeof u=="function")for(let v of se(u))!ae.call(d,v)&&v!==m&&Q(d,v,{get:()=>u[v],enumerable:!(f=re(u,v))||f.enumerable});return d};var de=(d,u,m)=>(m=d!=null?oe(ie(d)):{},ce(u||!d||!d.__esModule?Q(m,"default",{value:d,enumerable:!0}):m,d));var Z=le((be,K)=>{var fe=function(){var d=String.fromCharCode,u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function v(o,r){if(!f[o]){f[o]={};for(var e=0;e<o.length;e++)f[o][o.charAt(e)]=e}return f[o][r]}var x={compressToBase64:function(o){if(o==null)return"";var r=x._compress(o,6,function(e){return u.charAt(e)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(o){return o==null?"":o==""?null:x._decompress(o.length,32,function(r){return v(u,o.charAt(r))})},compressToUTF16:function(o){return o==null?"":x._compress(o,15,function(r){return d(r+32)})+" "},decompressFromUTF16:function(o){return o==null?"":o==""?null:x._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=x.compress(o),e=new Uint8Array(r.length*2),n=0,l=r.length;n<l;n++){var g=r.charCodeAt(n);e[n*2]=g>>>8,e[n*2+1]=g%256}return e},decompressFromUint8Array:function(o){if(o==null)return x.decompress(o);for(var r=new Array(o.length/2),e=0,n=r.length;e<n;e++)r[e]=o[e*2]*256+o[e*2+1];var l=[];return r.forEach(function(g){l.push(d(g))}),x.decompress(l.join(""))},compressToEncodedURIComponent:function(o){return o==null?"":x._compress(o,6,function(r){return m.charAt(r)})},decompressFromEncodedURIComponent:function(o){return o==null?"":o==""?null:(o=o.replace(/ /g,"+"),x._decompress(o.length,32,function(r){return v(m,o.charAt(r))}))},compress:function(o){return x._compress(o,16,function(r){return d(r)})},_compress:function(o,r,e){if(o==null)return"";var n,l,g={},w={},E="",R="",b="",P=2,S=3,c=2,h=[],t=0,s=0,A;for(A=0;A<o.length;A+=1)if(E=o.charAt(A),Object.prototype.hasOwnProperty.call(g,E)||(g[E]=S++,w[E]=!0),R=b+E,Object.prototype.hasOwnProperty.call(g,R))b=R;else{if(Object.prototype.hasOwnProperty.call(w,b)){if(b.charCodeAt(0)<256){for(n=0;n<c;n++)t=t<<1,s==r-1?(s=0,h.push(e(t)),t=0):s++;for(l=b.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}else{for(l=1,n=0;n<c;n++)t=t<<1|l,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=0;for(l=b.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}P--,P==0&&(P=Math.pow(2,c),c++),delete w[b]}else for(l=g[b],n=0;n<c;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1;P--,P==0&&(P=Math.pow(2,c),c++),g[R]=S++,b=String(E)}if(b!==""){if(Object.prototype.hasOwnProperty.call(w,b)){if(b.charCodeAt(0)<256){for(n=0;n<c;n++)t=t<<1,s==r-1?(s=0,h.push(e(t)),t=0):s++;for(l=b.charCodeAt(0),n=0;n<8;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}else{for(l=1,n=0;n<c;n++)t=t<<1|l,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=0;for(l=b.charCodeAt(0),n=0;n<16;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1}P--,P==0&&(P=Math.pow(2,c),c++),delete w[b]}else for(l=g[b],n=0;n<c;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1;P--,P==0&&(P=Math.pow(2,c),c++)}for(l=2,n=0;n<c;n++)t=t<<1|l&1,s==r-1?(s=0,h.push(e(t)),t=0):s++,l=l>>1;for(;;)if(t=t<<1,s==r-1){h.push(e(t));break}else s++;return h.join("")},decompress:function(o){return o==null?"":o==""?null:x._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,r,e){var n=[],l,g=4,w=4,E=3,R="",b=[],P,S,c,h,t,s,A,i={val:e(0),position:r,index:1};for(P=0;P<3;P+=1)n[P]=P;for(c=0,t=Math.pow(2,2),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;switch(l=c){case 0:for(c=0,t=Math.pow(2,8),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;A=d(c);break;case 1:for(c=0,t=Math.pow(2,16),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;A=d(c);break;case 2:return""}for(n[3]=A,S=A,b.push(A);;){if(i.index>o)return"";for(c=0,t=Math.pow(2,E),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;switch(A=c){case 0:for(c=0,t=Math.pow(2,8),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;n[w++]=d(c),A=w-1,g--;break;case 1:for(c=0,t=Math.pow(2,16),s=1;s!=t;)h=i.val&i.position,i.position>>=1,i.position==0&&(i.position=r,i.val=e(i.index++)),c|=(h>0?1:0)*s,s<<=1;n[w++]=d(c),A=w-1,g--;break;case 2:return b.join("")}if(g==0&&(g=Math.pow(2,E),E++),n[A])R=n[A];else if(A===w)R=S+S.charAt(0);else return null;b.push(R),n[w++]=S+R.charAt(0),g--,S=R,g==0&&(g=Math.pow(2,E),E++)}}};return x}();typeof K!="undefined"&&K!=null&&(K.exports=fe)});import{useEffect as me,useRef as he}from"react";var z=de(Z());var ue={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},pe=()=>{if(typeof navigator=="undefined")return"default";let d=navigator.userAgent;return/Firefox\//i.test(d)?"firefox":/Chrome\//i.test(d)?"chrome":"default"},G=()=>ue[pe()].filter(d=>{var m,f,v;let u=(v=(f=(m=globalThis.document)==null?void 0:m.featurePolicy)==null?void 0:f.features)==null?void 0:v.call(f);return u?u.includes(d):!0}).join("; ");async function Y(d,u={}){typeof d=="object"&&!(d instanceof HTMLElement)&&(d.headless||d.view==="headless")&&(u=d,d=null);let m=6e4,{config:f={},headless:v,loading:x="lazy",view:o}=u,r=v||o==="headless",e=null,n=null,l=a=>{a.style.position="absolute",a.style.top="0",a.style.visibility="hidden",a.style.opacity="0"};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"),l(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${d}"`);let g=new URL(ge(u)),w=g.origin;g.searchParams.set("embed","true"),g.searchParams.set("loading",r?"eager":x),g.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&g.searchParams.set("config","sdk");let E=u.params;typeof E=="object"&&Object.keys(E).length>0&&JSON.stringify(E).length<1800&&Object.keys(E).forEach(a=>{g.searchParams.set(a,encodeURIComponent(String(E[a])))});let R=!1,b="Cannot call API methods after calling `destroy()`.",P=[],S=(a,p="message")=>{addEventListener(p,a),P.push(a)},c=(a,p="message")=>{removeEventListener(p,a);let C=P.indexOf(a);C>-1&&P.splice(C,1)},t=await new Promise(a=>{var M,H,T,I,_,U,B,J,$;if(!e)return;let p=e.dataset.height||e.style.height;if(p&&!r){let N=isNaN(Number(p))?p:p+"px";e.style.height=N}e.dataset.defaultStyles!=="false"&&!r&&((M=e.style).backgroundColor||(M.backgroundColor="#fff"),(H=e.style).border||(H.border="1px solid black"),(T=e.style).borderRadius||(T.borderRadius="8px"),(I=e.style).boxSizing||(I.boxSizing="border-box"),(_=e.style).padding||(_.padding="0"),(U=e.style).width||(U.width="100%"),(B=e.style).height||(B.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(J=e.style).overflow||(J.overflow="hidden"),($=e.style).resize||($.resize="vertical"),getComputedStyle(e).getPropertyValue("display")==="inline"&&(e.style.display="block"));let C="livecodes",O=e.querySelector(`iframe.${C}`),y=O||document.createElement("iframe");y.classList.add(C),y.setAttribute("allow",G()),y.setAttribute("allowtransparency","true"),y.setAttribute("allowpaymentrequest","true"),y.setAttribute("allowfullscreen","true"),y.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let k=x==="eager"?"eager":"lazy";y.setAttribute("loading",k),r?l(y):(y.style.height="100%",y.style.minHeight="200px",y.style.width="100%",y.style.margin="0",y.style.border="0",y.style.borderRadius=e.style.borderRadius),S(function N(j){var D;j.source!==y.contentWindow||j.origin!==w||((D=j.data)==null?void 0:D.type)!=="livecodes-init"||(c(N),n=Number(j.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&S(function N(j){var D,q;j.source!==y.contentWindow||j.origin!==w||((D=j.data)==null?void 0:D.type)!=="livecodes-get-config"||(c(N),(q=y.contentWindow)==null||q.postMessage({type:"livecodes-config",payload:f},w))}),y.onload=()=>{a(y)},y.src=g.href,O||e.appendChild(y)}),s=new Promise(a=>{S(function p(C){var O;C.source!==t.contentWindow||C.origin!==w||((O=C.data)==null?void 0:O.type)!=="livecodes-ready"||(c(p),a(),s.settled=!0)})}),A=()=>R?Promise.reject(b):new Promise(async a=>{var C;s.settled&&a();let p={type:"livecodes-load"};(C=t.contentWindow)==null||C.postMessage(p,w),await s,a()}),i=(a,p)=>new Promise(async(C,O)=>{var H;if(R)return O(b);await A();let y=ne(),k=setTimeout(()=>{c(M),O(new Error(`SDK call "${a}" timed out after ${m}ms.`))},m);function M(T){var I,_;if(!(T.source!==t.contentWindow||T.origin!==w||((I=T.data)==null?void 0:I.type)!=="livecodes-api-response"||((_=T.data)==null?void 0:_.id)!==y)&&T.data.method===a){clearTimeout(k),c(M);let U=T.data.payload;U!=null&&U.error?O(U.error):C(U)}}S(M),(H=t.contentWindow)==null||H.postMessage({method:a,id:y,args:p},w)}),L={},V=["load","ready","code","console","tests","destroy"],W=(a,p)=>{var C;if(R)throw new Error(b);return V.includes(a)?(i("watch",[a]),L[a]||(L[a]=[]),(C=L[a])==null||C.push(p),{remove:()=>{var O,y;L[a]=(O=L[a])==null?void 0:O.filter(k=>k!==p),((y=L[a])==null?void 0:y.length)===0&&i("watch",[a,"unsubscribe"])}}):{remove:()=>{}}},ee=a=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[a];S(async function(p){var y,k,M,H;let C=ee((k=(y=p.data)==null?void 0:y.type)!=null?k:"");if(p.source!==t.contentWindow||p.origin!==w||!C||!L[C])return;let O=(M=p.data)==null?void 0:M.payload;(H=L[C])==null||H.forEach(T=>{T(O)})});let te=()=>{var a;(a=t==null?void 0:t.remove)==null||a.call(t),Object.values(L).forEach(p=>{p.length=0}),P.forEach(p=>removeEventListener("message",p)),P.length=0,F&&e&&F.unobserve(e),R=!0},F;x==="lazy"&&"IntersectionObserver"in window&&(F=new IntersectionObserver((a,p)=>{a.forEach(async C=>{C.isIntersecting&&(await A(),p.unobserve(e))})},{rootMargin:"150px"}),F.observe(e));let ne=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>A(),run:()=>i("run"),format:a=>i("format",[a]),getShareUrl:a=>i("getShareUrl",[a]),getConfig:a=>i("getConfig",[a]),setConfig:a=>i("setConfig",[a]),getCode:()=>i("getCode"),show:(a,p)=>i("show",[a,p]),runTests:()=>i("runTests"),onChange:a=>W("code",a),watch:W,exec:(a,...p)=>i("exec",[a,...p]),destroy:()=>R?Promise.reject(b):(te(),Promise.resolve())}}function ge(d={}){let{appUrl:u="https://livecodes.io",params:m={},config:f={},headless:v,import:x,lite:o,view:r,...e}=d,n;try{n=new URL(u)}catch(w){throw new Error(`${u} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(e).forEach(([w,E])=>{E!==void 0&&n.searchParams.set(w,String(E))});let g=d.view==="headless"||v;if(o&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":n.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&r!=="headless"?f.view=r:n.searchParams.set("view",r)),typeof f=="string")try{new URL(f),n.searchParams.set("config",encodeURIComponent(f))}catch(w){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&n.searchParams.set("title",f.title),f.description&&f.description.length>0&&n.searchParams.set("description",f.description),l.set("config","code/"+(0,z.compressToEncodedURIComponent)(JSON.stringify(f))));if(m&&typeof m=="object"&&Object.keys(m).length>0)try{l.set("params",(0,z.compressToEncodedURIComponent)(JSON.stringify(m)))}catch(w){Object.keys(m).forEach(E=>{n.searchParams.set(E,encodeURIComponent(String(m[E])))})}return x&&n.searchParams.set("x",encodeURIComponent(x)),g&&n.searchParams.set("headless","true"),l.toString().length>0&&(n.hash=l.toString()),n.href}function X(d){let{useEffect:u,useRef:m}=d;return function(v){let x=m(null),o=m(void 0),r=m(""),e=m(""),n=m(0),l=m(!1),g=v.className||"",w=v.style||{},E=v.height&&Number(v.height)?`${v.height}px`:v.height;return u(()=>{var i;if(!x.current)return;let{className:R,style:b,height:P,sdkReady:S,config:c,...h}=v,t=++n.current,s=()=>n.current!==t||l.current,A=JSON.stringify(h);if(!o.current||e.current!==A)e.current=A,r.current=JSON.stringify(c),(i=o.current)==null||i.destroy(),o.current=void 0,Y(x.current,{config:c,...h}).then(L=>{if(s()){L.destroy();return}o.current=L,typeof S=="function"&&S(L)});else{let L=JSON.stringify(c);if(r.current===L)return;r.current=L,c&&o.current.setConfig(c)}},[v]),u(()=>()=>{var R;l.current=!0,(R=o.current)==null||R.destroy(),o.current=void 0},[]),{containerRef:x,className:g,style:w,height:E}}}import{jsx as we}from"react/jsx-runtime";var ye=X({useEffect:me,useRef:he});function ve(d){let{containerRef:u,className:m,style:f,height:v}=ye(d);return we("div",{ref:u,className:m,style:{...f,...v?{height:v}:{}},"data-height":v})}export{ve as default};

@@ -121,3 +121,3 @@ # LiveCodes

- Developer-friendly build-free environment
- Powerful [SDK](https://livecodes.io/docs/sdk/) (available for [vanilla JavaScript, TypeScript](https://livecodes.io/docs/sdk/js-ts), [React](https://livecodes.io/docs/sdk/react), [Vue](https://livecodes.io/docs/sdk/vue), [Svelte](https://livecodes.io/docs/sdk/svelte) and [Solid](https://livecodes.io/docs/sdk/solid))
- Powerful [SDK](https://livecodes.io/docs/sdk/) (available for [JavaScript, TypeScript](https://livecodes.io/docs/sdk/js-ts), [React](https://livecodes.io/docs/sdk/react), [Vue](https://livecodes.io/docs/sdk/vue), [Svelte](https://livecodes.io/docs/sdk/svelte), [Solid](https://livecodes.io/docs/sdk/solid), [Preact](https://livecodes.io/docs/sdk/preact) and [web components](https://livecodes.io/docs/sdk/web-components))
- Comprehensive [Documentations](https://livecodes.io/docs/)

@@ -133,3 +133,3 @@ - Focused on [privacy and security](https://livecodes.io/docs/features/security)

The SDK is provided as a light-weight ([less than 5kb gzipped](https://bundlephobia.com/package/livecodes)), zero-dependencies [npm package](https://livecodes.io/docs/sdk/#npm-package), that is also available from [CDNs](https://livecodes.io/docs/sdk/#cdn). It can be used to create playgrounds with a wide variety of [configurations](https://livecodes.io/docs/configuration/configuration-object) and [embed options](https://livecodes.io/docs/sdk/js-ts#embed-options). In addition, [SDK methods](https://livecodes.io/docs/sdk/js-ts#sdk-methods) allow programmatic communication and control of the playgrounds during runtime.
The SDK is provided as a light-weight [npm package](https://livecodes.io/docs/sdk/#npm-package) (or [jsr package](https://livecodes.io/docs/sdk/#jsr)), that is also available from [CDNs](https://livecodes.io/docs/sdk/#cdn). It can be used to create playgrounds with a wide variety of [configurations](https://livecodes.io/docs/configuration/configuration-object) and [embed options](https://livecodes.io/docs/sdk/js-ts#embed-options). In addition, [SDK methods](https://livecodes.io/docs/sdk/js-ts#sdk-methods) allow programmatic communication and control of the playgrounds during runtime.

@@ -160,3 +160,3 @@ ### Installation

The [JavaScript SDK](https://livecodes.io/docs/sdk/js-ts) is framework/library agnostic. However, wrapper components are also provided for popular libraries (currently [React](https://livecodes.io/docs/sdk/react) and [Vue](https://livecodes.io/docs/sdk/vue)). The SDK can be used in [Svelte](https://livecodes.io/docs/sdk/svelte) and [Solid](https://livecodes.io/docs/sdk/solid) directly without wrappers. [TypeScript support](https://livecodes.io/docs/sdk/js-ts#typescript-types) provides type-safety and a great developer experience.
The [JavaScript SDK](https://livecodes.io/docs/sdk/js-ts) is framework/library agnostic. However, wrapper components are also provided for [React](https://livecodes.io/docs/sdk/react), [Vue](https://livecodes.io/docs/sdk/vue), [Svelte](https://livecodes.io/docs/sdk/svelte), [Solid](https://livecodes.io/docs/sdk/solid), [Preact](https://livecodes.io/docs/sdk/preact) and [web components](https://livecodes.io/docs/sdk/web-components). [TypeScript support](https://livecodes.io/docs/sdk/js-ts#typescript-types) provides type-safety and a great developer experience.

@@ -174,3 +174,3 @@ React SDK example: ([open in LiveCodes](https://livecodes.io/?x=code/N4IgLglmA2CmIC4QBkIDdYGED2ATWAzgAQBKsAhgMZhEDKAIgNJH4C22IANCPgZQE4QADpGwA7RCC4gAFhVySAPK1hhyRSjPL8CqgLwAdEAFUAKgDEAtAA4jRAPQA+A2OWr1Y8isMg0EWADuQtj8YHaU4mCwYmA+ARC4YDJ6+H6UsJbxiTKcRBBiUBDk0JZ8xbB6AIwAdAAMdk7SMmCs0ACCYGA6ktDkYgDmPtHhvQQEPkbSav0EiADaALrcVJAYAKK4UCGSfIIi0qzaANYArkKIoL0DJ+T98EjNrdIRMdFgkiAAvtwEYACecAuICu-Rud0klDGz0ibw+3xAu2E7wQlz6oNu9xAACsCAAPaGvGKSCCsYKhIioDA4XhEABm-GwrCIAHJoOhYBFePZ+BRqMyANwGfguIUuF6-DTiWkQfpEPREYCisREIiHfinIQIBVKlUqkFg2Ba5lqo64bABMTMzg63UvKIxI0AYiIAAlYNBoNgiAB1ELQXAAQitNu+Ss+guFYnFNAACr0-v0GScxLg5UQABQASjljiIikpWDwhElYmlg2ALzLnyIfkCPh5BBO0DCIAcjgjLlguLJNHwtPITdj8cT2GTuA7EnhvwBhDkqlmCEWPwESIXS5AkIIMYbqg+3CEDPSYxCa6WG5Ov0ZtFUkAGC+A8JJPfv8P+QkIF1fhDA9+BaINkhvoQK77NwdqwkgXzcBgOgQOIkgAMwIVM2DYNAv7ROQABGcAKEgxTQNIKzshC4gEGh8A-GoYAXhCnq6AonyfEAA))

};
const Playground = () => <LiveCodes config={config} view="result" />;
const Playground = () => <LiveCodes config={config} />;
export default Playground;

@@ -194,3 +194,3 @@ ```

<template>
<LiveCodes :config="config" view="result" />
<LiveCodes :config="config" />
</template>

@@ -213,2 +213,3 @@ ```

// this URL can be shared
console.log(url);

@@ -227,2 +228,4 @@ ```

See below for documentations for [contributors](#contribution) and [AI models](#for-ai-agents).
## Updates

@@ -252,4 +255,29 @@

Please refer to the [contribution guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md).
Please refer to the [contribution guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md) and [system documentation](https://github.com/live-codes/livecodes/blob/HEAD/docs/docs/contribution/README.md).
## For AI Agents
### llms.txt
For developers working with AI agents and language models, we provide specialized documentation files following the [llms.txt specification](https://llmstxt.org/):
- [llms.txt](https://livecodes.io/docs/llms.txt) - Concise documentation optimized for LLM context windows
- [llms-full.txt](https://livecodes.io/docs/llms-full.txt) - Comprehensive documentation including all referenced URLs
These files provide LLM-friendly content in a standardized format, helping language models understand and work with LiveCodes documentation. The format is designed to be both human and LLM readable.
### Intent Skills
If you use an AI coding agent, run:
```bash
npx @tanstack/intent@latest install
```
This loads the Intent skills for LiveCodes SDK. See [.agents/skills/livecodes/SKILL.md](https://github.com/live-codes/livecodes/blob/HEAD/.agents/skills/livecodes/SKILL.md) for the skill index.
### System Documentation
For internal architecture and system documentation, see [docs/docs/contribution/](https://github.com/live-codes/livecodes/blob/HEAD/docs/docs/contribution/README.md).
## Credits

@@ -333,3 +361,3 @@

## Sponsor
## Sponsor 💚

@@ -336,0 +364,0 @@ LiveCodes is free and open-source. The app does not contain ads or require subscription. It allows unlimited usage without any restrictions.

+1
-1

@@ -1,1 +0,1 @@

var te=Object.create;var X=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,se=Object.prototype.hasOwnProperty;var ie=(c,g)=>()=>(g||c((g={exports:{}}).exports,g),g.exports);var ae=(c,g,b,p)=>{if(g&&typeof g=="object"||typeof g=="function")for(let O of oe(g))!se.call(c,O)&&O!==b&&X(c,O,{get:()=>g[O],enumerable:!(p=ne(g,O))||p.enumerable});return c};var le=(c,g,b)=>(b=c!=null?te(re(c)):{},ae(g||!c||!c.__esModule?X(b,"default",{value:c,enumerable:!0}):b,c));var Y=ie((ve,D)=>{var ce=function(){var c=String.fromCharCode,g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",p={};function O(o,e){if(!p[o]){p[o]={};for(var l=0;l<o.length;l++)p[o][o.charAt(l)]=l}return p[o][e]}var x={compressToBase64:function(o){if(o==null)return"";var e=x._compress(o,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(o){return o==null?"":o==""?null:x._decompress(o.length,32,function(e){return O(g,o.charAt(e))})},compressToUTF16:function(o){return o==null?"":x._compress(o,15,function(e){return c(e+32)})+" "},decompressFromUTF16:function(o){return o==null?"":o==""?null:x._decompress(o.length,16384,function(e){return o.charCodeAt(e)-32})},compressToUint8Array:function(o){for(var e=x.compress(o),l=new Uint8Array(e.length*2),t=0,s=e.length;t<s;t++){var d=e.charCodeAt(t);l[t*2]=d>>>8,l[t*2+1]=d%256}return l},decompressFromUint8Array:function(o){if(o==null)return x.decompress(o);for(var e=new Array(o.length/2),l=0,t=e.length;l<t;l++)e[l]=o[l*2]*256+o[l*2+1];var s=[];return e.forEach(function(d){s.push(c(d))}),x.decompress(s.join(""))},compressToEncodedURIComponent:function(o){return o==null?"":x._compress(o,6,function(e){return b.charAt(e)})},decompressFromEncodedURIComponent:function(o){return o==null?"":o==""?null:(o=o.replace(/ /g,"+"),x._decompress(o.length,32,function(e){return O(b,o.charAt(e))}))},compress:function(o){return x._compress(o,16,function(e){return c(e)})},_compress:function(o,e,l){if(o==null)return"";var t,s,d={},v={},w="",P="",h="",S=2,E=3,f=2,u=[],n=0,r=0,M;for(M=0;M<o.length;M+=1)if(w=o.charAt(M),Object.prototype.hasOwnProperty.call(d,w)||(d[w]=E++,v[w]=!0),P=h+w,Object.prototype.hasOwnProperty.call(d,P))h=P;else{if(Object.prototype.hasOwnProperty.call(v,h)){if(h.charCodeAt(0)<256){for(t=0;t<f;t++)n=n<<1,r==e-1?(r=0,u.push(l(n)),n=0):r++;for(s=h.charCodeAt(0),t=0;t<8;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1}else{for(s=1,t=0;t<f;t++)n=n<<1|s,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=0;for(s=h.charCodeAt(0),t=0;t<16;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1}S--,S==0&&(S=Math.pow(2,f),f++),delete v[h]}else for(s=d[h],t=0;t<f;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1;S--,S==0&&(S=Math.pow(2,f),f++),d[P]=E++,h=String(w)}if(h!==""){if(Object.prototype.hasOwnProperty.call(v,h)){if(h.charCodeAt(0)<256){for(t=0;t<f;t++)n=n<<1,r==e-1?(r=0,u.push(l(n)),n=0):r++;for(s=h.charCodeAt(0),t=0;t<8;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1}else{for(s=1,t=0;t<f;t++)n=n<<1|s,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=0;for(s=h.charCodeAt(0),t=0;t<16;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1}S--,S==0&&(S=Math.pow(2,f),f++),delete v[h]}else for(s=d[h],t=0;t<f;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1;S--,S==0&&(S=Math.pow(2,f),f++)}for(s=2,t=0;t<f;t++)n=n<<1|s&1,r==e-1?(r=0,u.push(l(n)),n=0):r++,s=s>>1;for(;;)if(n=n<<1,r==e-1){u.push(l(n));break}else r++;return u.join("")},decompress:function(o){return o==null?"":o==""?null:x._decompress(o.length,32768,function(e){return o.charCodeAt(e)})},_decompress:function(o,e,l){var t=[],s,d=4,v=4,w=3,P="",h=[],S,E,f,u,n,r,M,a={val:l(0),position:e,index:1};for(S=0;S<3;S+=1)t[S]=S;for(f=0,n=Math.pow(2,2),r=1;r!=n;)u=a.val&a.position,a.position>>=1,a.position==0&&(a.position=e,a.val=l(a.index++)),f|=(u>0?1:0)*r,r<<=1;switch(s=f){case 0:for(f=0,n=Math.pow(2,8),r=1;r!=n;)u=a.val&a.position,a.position>>=1,a.position==0&&(a.position=e,a.val=l(a.index++)),f|=(u>0?1:0)*r,r<<=1;M=c(f);break;case 1:for(f=0,n=Math.pow(2,16),r=1;r!=n;)u=a.val&a.position,a.position>>=1,a.position==0&&(a.position=e,a.val=l(a.index++)),f|=(u>0?1:0)*r,r<<=1;M=c(f);break;case 2:return""}for(t[3]=M,E=M,h.push(M);;){if(a.index>o)return"";for(f=0,n=Math.pow(2,w),r=1;r!=n;)u=a.val&a.position,a.position>>=1,a.position==0&&(a.position=e,a.val=l(a.index++)),f|=(u>0?1:0)*r,r<<=1;switch(M=f){case 0:for(f=0,n=Math.pow(2,8),r=1;r!=n;)u=a.val&a.position,a.position>>=1,a.position==0&&(a.position=e,a.val=l(a.index++)),f|=(u>0?1:0)*r,r<<=1;t[v++]=c(f),M=v-1,d--;break;case 1:for(f=0,n=Math.pow(2,16),r=1;r!=n;)u=a.val&a.position,a.position>>=1,a.position==0&&(a.position=e,a.val=l(a.index++)),f|=(u>0?1:0)*r,r<<=1;t[v++]=c(f),M=v-1,d--;break;case 2:return h.join("")}if(d==0&&(d=Math.pow(2,w),w++),t[M])P=t[M];else if(M===v)P=E+E.charAt(0);else return null;h.push(P),t[v++]=E+P.charAt(0),d--,E=P,d==0&&(d=Math.pow(2,w),w++)}}};return x}();typeof D!="undefined"&&D!=null&&(D.exports=ce)});import{h as fe,onMounted as pe,onUnmounted as ue,ref as B,watch as ye}from"vue";var J=le(Y());async function K(c,g={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(g=c,c=null);let{config:b={},headless:p,loading:O="lazy",view:x}=g,o=p||x==="headless",e=null,l=null;if(typeof c=="string")e=document.querySelector(c);else if(c instanceof HTMLElement)e=c;else if(!(o&&typeof c=="object"))throw new Error("A valid container element is required.");if(!e)if(o)e=document.createElement("div"),z(e),document.body.appendChild(e);else throw new Error(`Cannot find element: "${c}"`);let t=new URL(de(g)),s=t.origin;t.searchParams.set("embed","true"),t.searchParams.set("loading",o?"eager":O),t.searchParams.set("sdkVersion","0.13.0"),typeof b=="object"&&Object.keys(b).length>0&&t.searchParams.set("config","sdk");let d=g.params;typeof d=="object"&&Object.keys(d).length>0&&JSON.stringify(d).length<1800&&Object.keys(d).forEach(i=>{t.searchParams.set(i,encodeURIComponent(String(d[i])))});let v=!1,w="Cannot call API methods after calling `destroy()`.",P=[],h=(i,y="message")=>{addEventListener(y,i),P.push(i)},E=await new Promise(i=>{var k,L,j,H,U,q,Q,Z,$;if(!e)return;let y=e.dataset.height||e.style.height;if(y&&!o){let _=isNaN(Number(y))?y:y+"px";e.style.height=_}e.dataset.defaultStyles!=="false"&&!o&&((k=e.style).backgroundColor||(k.backgroundColor="#fff"),(L=e.style).border||(L.border="1px solid black"),(j=e.style).borderRadius||(j.borderRadius="8px"),(H=e.style).boxSizing||(H.boxSizing="border-box"),(U=e.style).padding||(U.padding="0"),(q=e.style).width||(q.width="100%"),(Q=e.style).height||(Q.height=e.style.height||"300px"),e.style.minHeight="200px",e.style.flexGrow="1",(Z=e.style).overflow||(Z.overflow="hidden"),($=e.style).resize||($.resize="vertical"));let C="livecodes",A=e.querySelector(`iframe.${C}`),m=A||document.createElement("iframe");m.classList.add(C),m.setAttribute("allow","accelerometer; camera; encrypted-media; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; web-share"),m.setAttribute("allowtransparency","true"),m.setAttribute("allowpaymentrequest","true"),m.setAttribute("allowfullscreen","true"),m.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let R=O==="eager"?"eager":"lazy";m.setAttribute("loading",R),o?z(m):(m.style.height="100%",m.style.minHeight="200px",m.style.width="100%",m.style.margin="0",m.style.border="0",m.style.borderRadius=e.style.borderRadius),h(function _(T){var I;T.source!==m.contentWindow||T.origin!==s||((I=T.data)==null?void 0:I.type)!=="livecodes-init"||(removeEventListener("message",_),l=Number(T.data.payload.appVersion.replace(/^v/,"")))}),(!l||l<46)&&h(function _(T){var I,G;T.source!==m.contentWindow||T.origin!==s||((I=T.data)==null?void 0:I.type)!=="livecodes-get-config"||(removeEventListener("message",_),(G=m.contentWindow)==null||G.postMessage({type:"livecodes-config",payload:b},s))}),m.onload=()=>{i(m)},m.src=t.href,A||e.appendChild(m)}),f=new Promise(i=>{h(function y(C){var A;C.source!==E.contentWindow||C.origin!==s||((A=C.data)==null?void 0:A.type)!=="livecodes-ready"||(removeEventListener("message",y),i(),f.settled=!0)})}),u=()=>v?Promise.reject(w):new Promise(async i=>{var C;f.settled&&i();let y={type:"livecodes-load"};(C=E.contentWindow)==null||C.postMessage(y,s),await f,i()}),n=(i,y)=>new Promise(async(C,A)=>{var R;if(v)return A(w);await u();let m=ee();h(function k(L){var j,H;if(!(L.source!==E.contentWindow||L.origin!==s||((j=L.data)==null?void 0:j.type)!=="livecodes-api-response"||((H=L.data)==null?void 0:H.id)!==m)&&L.data.method===i){removeEventListener("message",k);let U=L.data.payload;U!=null&&U.error?A(U.error):C(U)}}),(R=E.contentWindow)==null||R.postMessage({method:i,id:m,args:y},s)}),r={},M=["load","ready","code","console","tests","destroy"],a=(i,y)=>{var C;if(v)throw new Error(w);return M.includes(i)?(n("watch",[i]),r[i]||(r[i]=[]),(C=r[i])==null||C.push(y),{remove:()=>{var A,m;r[i]=(A=r[i])==null?void 0:A.filter(R=>R!==y),((m=r[i])==null?void 0:m.length)===0&&n("watch",[i,"unsubscribe"])}}):{remove:()=>{}}},F=i=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[i];h(async function(y){var m,R,k,L;let C=F((R=(m=y.data)==null?void 0:m.type)!=null?R:"");if(y.source!==E.contentWindow||y.origin!==s||!C||!r[C])return;let A=(k=y.data)==null?void 0:k.payload;(L=r[C])==null||L.forEach(j=>{j(A)})});let V=()=>{var i;(i=E==null?void 0:E.remove)==null||i.call(E),Object.values(r).forEach(y=>{y.length=0}),P.forEach(y=>removeEventListener("message",y)),P.length=0,N&&e&&N.unobserve(e),v=!0},N;O==="lazy"&&"IntersectionObserver"in window&&(N=new IntersectionObserver((i,y)=>{i.forEach(async C=>{C.isIntersecting&&(await u(),y.unobserve(e))})},{rootMargin:"150px"}),N.observe(e));function z(i){i.style.position="absolute",i.style.top="0",i.style.visibility="hidden",i.style.opacity="0"}let ee=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>u(),run:()=>n("run"),format:i=>n("format",[i]),getShareUrl:i=>n("getShareUrl",[i]),getConfig:i=>n("getConfig",[i]),setConfig:i=>n("setConfig",[i]),getCode:()=>n("getCode"),show:(i,y)=>n("show",[i,y]),runTests:()=>n("runTests"),onChange:i=>a("code",i),watch:a,exec:(i,...y)=>n("exec",[i,...y]),destroy:()=>v?Promise.reject(w):(V(),Promise.resolve())}}function de(c={}){let{appUrl:g="https://livecodes.io",params:b={},config:p={},headless:O,import:x,lite:o,view:e,...l}=c,t;try{t=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&&t.searchParams.set(v,String(w))});let d=c.view==="headless"||O;if(o&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof p=="object"&&p.mode==null?p.mode="lite":t.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 p=="object"&&p.view==null&&e!=="headless"?p.view=e:t.searchParams.set("view",e)),typeof p=="string")try{new URL(p),t.searchParams.set("config",encodeURIComponent(p))}catch(v){throw new Error('"config" is not a valid URL or configuration object.')}else p&&typeof p=="object"&&Object.keys(p).length>0&&(p.title&&p.title!=="Untitled Project"&&t.searchParams.set("title",p.title),p.description&&p.description.length>0&&t.searchParams.set("description",p.description),s.set("config","code/"+(0,J.compressToEncodedURIComponent)(JSON.stringify(p))));if(b&&typeof b=="object"&&Object.keys(b).length>0)try{s.set("params",(0,J.compressToEncodedURIComponent)(JSON.stringify(b)))}catch(v){Object.keys(b).forEach(w=>{t.searchParams.set(w,encodeURIComponent(String(b[w])))})}return x&&t.searchParams.set("x",encodeURIComponent(x)),d&&t.searchParams.set("headless","true"),s.toString().length>0&&(t.hash=s.toString()),t.href}var me={appUrl:String,config:[Object,String],headless:Boolean,import:String,lite:Boolean,loading:String,params:Object,template:String,view:String,height:String},W=c=>JSON.parse(JSON.stringify(c)),he={props:me,emits:["sdkReady"],setup(c,g){let{height:b,...p}=c,O=B(),x=B(b||""),o=B(),{config:e,...l}=p,t=JSON.stringify(e),s=JSON.stringify(l);return pe(()=>{O.value&&K(O.value,W(p)).then(d=>{o.value=d,g.emit("sdkReady",d)})}),ye(c,async d=>{var S;if(!O.value||!o.value)return;let{height:v,...w}=d;x.value=v||"";let{config:P,...h}=w;typeof P=="string"&&(P=await fetch(P).then(E=>E.json())),JSON.stringify(h)!==s?(await((S=o.value)==null?void 0:S.destroy()),K(O.value,W(w)).then(E=>{o.value=E,g.emit("sdkReady",E)})):JSON.stringify(P)!==t&&o.value.setConfig(W(P)||{}),t=JSON.stringify(P),s=JSON.stringify(h)}),ue(()=>{var d;(d=o.value)==null||d.destroy()}),()=>{var d,v;return fe("div",{ref:O,"data-height":x.value},((v=(d=g.slots).default)==null?void 0:v.call(d))||"")}}},be=he;export{be as default};
var re=Object.create;var V=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,le=Object.prototype.hasOwnProperty;var ce=(c,m)=>()=>(m||c((m={exports:{}}).exports,m),m.exports);var de=(c,m,C,f)=>{if(m&&typeof m=="object"||typeof m=="function")for(let x of se(m))!le.call(c,x)&&x!==C&&V(c,x,{get:()=>m[x],enumerable:!(f=ie(m,x))||f.enumerable});return c};var fe=(c,m,C)=>(C=c!=null?re(ae(c)):{},de(m||!c||!c.__esModule?V(C,"default",{value:c,enumerable:!0}):C,c));var Y=ce((Ce,F)=>{var ue=function(){var c=String.fromCharCode,m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",C="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",f={};function x(o,r){if(!f[o]){f[o]={};for(var t=0;t<o.length;t++)f[o][o.charAt(t)]=t}return f[o][r]}var P={compressToBase64:function(o){if(o==null)return"";var r=P._compress(o,6,function(t){return m.charAt(t)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(o){return o==null?"":o==""?null:P._decompress(o.length,32,function(r){return x(m,o.charAt(r))})},compressToUTF16:function(o){return o==null?"":P._compress(o,15,function(r){return c(r+32)})+" "},decompressFromUTF16:function(o){return o==null?"":o==""?null:P._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=P.compress(o),t=new Uint8Array(r.length*2),n=0,l=r.length;n<l;n++){var p=r.charCodeAt(n);t[n*2]=p>>>8,t[n*2+1]=p%256}return t},decompressFromUint8Array:function(o){if(o==null)return P.decompress(o);for(var r=new Array(o.length/2),t=0,n=r.length;t<n;t++)r[t]=o[t*2]*256+o[t*2+1];var l=[];return r.forEach(function(p){l.push(c(p))}),P.decompress(l.join(""))},compressToEncodedURIComponent:function(o){return o==null?"":P._compress(o,6,function(r){return C.charAt(r)})},decompressFromEncodedURIComponent:function(o){return o==null?"":o==""?null:(o=o.replace(/ /g,"+"),P._decompress(o.length,32,function(r){return x(C,o.charAt(r))}))},compress:function(o){return P._compress(o,16,function(r){return c(r)})},_compress:function(o,r,t){if(o==null)return"";var n,l,p={},v={},u="",E="",w="",b=2,A=3,d=2,y=[],e=0,i=0,O;for(O=0;O<o.length;O+=1)if(u=o.charAt(O),Object.prototype.hasOwnProperty.call(p,u)||(p[u]=A++,v[u]=!0),E=w+u,Object.prototype.hasOwnProperty.call(p,E))w=E;else{if(Object.prototype.hasOwnProperty.call(v,w)){if(w.charCodeAt(0)<256){for(n=0;n<d;n++)e=e<<1,i==r-1?(i=0,y.push(t(e)),e=0):i++;for(l=w.charCodeAt(0),n=0;n<8;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1}else{for(l=1,n=0;n<d;n++)e=e<<1|l,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=0;for(l=w.charCodeAt(0),n=0;n<16;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1}b--,b==0&&(b=Math.pow(2,d),d++),delete v[w]}else for(l=p[w],n=0;n<d;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1;b--,b==0&&(b=Math.pow(2,d),d++),p[E]=A++,w=String(u)}if(w!==""){if(Object.prototype.hasOwnProperty.call(v,w)){if(w.charCodeAt(0)<256){for(n=0;n<d;n++)e=e<<1,i==r-1?(i=0,y.push(t(e)),e=0):i++;for(l=w.charCodeAt(0),n=0;n<8;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1}else{for(l=1,n=0;n<d;n++)e=e<<1|l,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=0;for(l=w.charCodeAt(0),n=0;n<16;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1}b--,b==0&&(b=Math.pow(2,d),d++),delete v[w]}else for(l=p[w],n=0;n<d;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1;b--,b==0&&(b=Math.pow(2,d),d++)}for(l=2,n=0;n<d;n++)e=e<<1|l&1,i==r-1?(i=0,y.push(t(e)),e=0):i++,l=l>>1;for(;;)if(e=e<<1,i==r-1){y.push(t(e));break}else i++;return y.join("")},decompress:function(o){return o==null?"":o==""?null:P._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,r,t){var n=[],l,p=4,v=4,u=3,E="",w=[],b,A,d,y,e,i,O,a={val:t(0),position:r,index:1};for(b=0;b<3;b+=1)n[b]=b;for(d=0,e=Math.pow(2,2),i=1;i!=e;)y=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=t(a.index++)),d|=(y>0?1:0)*i,i<<=1;switch(l=d){case 0:for(d=0,e=Math.pow(2,8),i=1;i!=e;)y=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=t(a.index++)),d|=(y>0?1:0)*i,i<<=1;O=c(d);break;case 1:for(d=0,e=Math.pow(2,16),i=1;i!=e;)y=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=t(a.index++)),d|=(y>0?1:0)*i,i<<=1;O=c(d);break;case 2:return""}for(n[3]=O,A=O,w.push(O);;){if(a.index>o)return"";for(d=0,e=Math.pow(2,u),i=1;i!=e;)y=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=t(a.index++)),d|=(y>0?1:0)*i,i<<=1;switch(O=d){case 0:for(d=0,e=Math.pow(2,8),i=1;i!=e;)y=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=t(a.index++)),d|=(y>0?1:0)*i,i<<=1;n[v++]=c(d),O=v-1,p--;break;case 1:for(d=0,e=Math.pow(2,16),i=1;i!=e;)y=a.val&a.position,a.position>>=1,a.position==0&&(a.position=r,a.val=t(a.index++)),d|=(y>0?1:0)*i,i<<=1;n[v++]=c(d),O=v-1,p--;break;case 2:return w.join("")}if(p==0&&(p=Math.pow(2,u),u++),n[O])E=n[O];else if(O===v)E=A+A.charAt(0);else return null;w.push(E),n[v++]=A+E.charAt(0),p--,A=E,p==0&&(p=Math.pow(2,u),u++)}}};return P}();typeof F!="undefined"&&F!=null&&(F.exports=ue)});import{h as ye,onMounted as he,onUnmounted as ve,ref as B,watch as we}from"vue";var K=fe(Y());var pe={chrome:["accelerometer","bluetooth","camera","clipboard-read","clipboard-write","display-capture","encrypted-media","geolocation","gyroscope","language-detector","language-model","local-network-access","microphone","midi","proofreader","rewriter","serial","summarizer","translator","web-share","writer","window-placement","xr-spatial-tracking"],firefox:["camera","display-capture","geolocation","microphone","web-share"],default:["accelerometer","ambient-light-sensor","camera","display-capture","encrypted-media","geolocation","gyroscope","microphone","midi","payment","serial","vr","web-share","xr-spatial-tracking"]},ge=()=>{if(typeof navigator=="undefined")return"default";let c=navigator.userAgent;return/Firefox\//i.test(c)?"firefox":/Chrome\//i.test(c)?"chrome":"default"},X=()=>pe[ge()].filter(c=>{var C,f,x;let m=(x=(f=(C=globalThis.document)==null?void 0:C.featurePolicy)==null?void 0:f.features)==null?void 0:x.call(f);return m?m.includes(c):!0}).join("; ");async function z(c,m={}){typeof c=="object"&&!(c instanceof HTMLElement)&&(c.headless||c.view==="headless")&&(m=c,c=null);let C=6e4,{config:f={},headless:x,loading:P="lazy",view:o}=m,r=x||o==="headless",t=null,n=null,l=s=>{s.style.position="absolute",s.style.top="0",s.style.visibility="hidden",s.style.opacity="0"};if(typeof c=="string")t=document.querySelector(c);else if(c instanceof HTMLElement)t=c;else if(!(r&&typeof c=="object"))throw new Error("A valid container element is required.");if(!t)if(r)t=document.createElement("div"),l(t),document.body.appendChild(t);else throw new Error(`Cannot find element: "${c}"`);let p=new URL(me(m)),v=p.origin;p.searchParams.set("embed","true"),p.searchParams.set("loading",r?"eager":P),p.searchParams.set("sdkVersion","0.14.0"),typeof f=="object"&&Object.keys(f).length>0&&p.searchParams.set("config","sdk");let u=m.params;typeof u=="object"&&Object.keys(u).length>0&&JSON.stringify(u).length<1800&&Object.keys(u).forEach(s=>{p.searchParams.set(s,encodeURIComponent(String(u[s])))});let E=!1,w="Cannot call API methods after calling `destroy()`.",b=[],A=(s,g="message")=>{addEventListener(g,s),b.push(s)},d=(s,g="message")=>{removeEventListener(g,s);let S=b.indexOf(s);S>-1&&b.splice(S,1)},e=await new Promise(s=>{var R,U,M,I,_,j,$,G,Q;if(!t)return;let g=t.dataset.height||t.style.height;if(g&&!r){let N=isNaN(Number(g))?g:g+"px";t.style.height=N}t.dataset.defaultStyles!=="false"&&!r&&((R=t.style).backgroundColor||(R.backgroundColor="#fff"),(U=t.style).border||(U.border="1px solid black"),(M=t.style).borderRadius||(M.borderRadius="8px"),(I=t.style).boxSizing||(I.boxSizing="border-box"),(_=t.style).padding||(_.padding="0"),(j=t.style).width||(j.width="100%"),($=t.style).height||($.height=t.style.height||"300px"),t.style.minHeight="200px",t.style.flexGrow="1",(G=t.style).overflow||(G.overflow="hidden"),(Q=t.style).resize||(Q.resize="vertical"),getComputedStyle(t).getPropertyValue("display")==="inline"&&(t.style.display="block"));let S="livecodes",L=t.querySelector(`iframe.${S}`),h=L||document.createElement("iframe");h.classList.add(S),h.setAttribute("allow",X()),h.setAttribute("allowtransparency","true"),h.setAttribute("allowpaymentrequest","true"),h.setAttribute("allowfullscreen","true"),h.setAttribute("sandbox","allow-same-origin allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts");let k=P==="eager"?"eager":"lazy";h.setAttribute("loading",k),r?l(h):(h.style.height="100%",h.style.minHeight="200px",h.style.width="100%",h.style.margin="0",h.style.border="0",h.style.borderRadius=t.style.borderRadius),A(function N(H){var D;H.source!==h.contentWindow||H.origin!==v||((D=H.data)==null?void 0:D.type)!=="livecodes-init"||(d(N),n=Number(H.data.payload.appVersion.replace(/^v/,"")))}),(!n||n<46)&&A(function N(H){var D,Z;H.source!==h.contentWindow||H.origin!==v||((D=H.data)==null?void 0:D.type)!=="livecodes-get-config"||(d(N),(Z=h.contentWindow)==null||Z.postMessage({type:"livecodes-config",payload:f},v))}),h.onload=()=>{s(h)},h.src=p.href,L||t.appendChild(h)}),i=new Promise(s=>{A(function g(S){var L;S.source!==e.contentWindow||S.origin!==v||((L=S.data)==null?void 0:L.type)!=="livecodes-ready"||(d(g),s(),i.settled=!0)})}),O=()=>E?Promise.reject(w):new Promise(async s=>{var S;i.settled&&s();let g={type:"livecodes-load"};(S=e.contentWindow)==null||S.postMessage(g,v),await i,s()}),a=(s,g)=>new Promise(async(S,L)=>{var U;if(E)return L(w);await O();let h=oe(),k=setTimeout(()=>{d(R),L(new Error(`SDK call "${s}" timed out after ${C}ms.`))},C);function R(M){var I,_;if(!(M.source!==e.contentWindow||M.origin!==v||((I=M.data)==null?void 0:I.type)!=="livecodes-api-response"||((_=M.data)==null?void 0:_.id)!==h)&&M.data.method===s){clearTimeout(k),d(R);let j=M.data.payload;j!=null&&j.error?L(j.error):S(j)}}A(R),(U=e.contentWindow)==null||U.postMessage({method:s,id:h,args:g},v)}),T={},ee=["load","ready","code","console","tests","destroy"],q=(s,g)=>{var S;if(E)throw new Error(w);return ee.includes(s)?(a("watch",[s]),T[s]||(T[s]=[]),(S=T[s])==null||S.push(g),{remove:()=>{var L,h;T[s]=(L=T[s])==null?void 0:L.filter(k=>k!==g),((h=T[s])==null?void 0:h.length)===0&&a("watch",[s,"unsubscribe"])}}):{remove:()=>{}}},te=s=>({"livecodes-app-loaded":"load","livecodes-ready":"ready","livecodes-change":"code","livecodes-console":"console","livecodes-test-results":"tests","livecodes-destroy":"destroy"})[s];A(async function(g){var h,k,R,U;let S=te((k=(h=g.data)==null?void 0:h.type)!=null?k:"");if(g.source!==e.contentWindow||g.origin!==v||!S||!T[S])return;let L=(R=g.data)==null?void 0:R.payload;(U=T[S])==null||U.forEach(M=>{M(L)})});let ne=()=>{var s;(s=e==null?void 0:e.remove)==null||s.call(e),Object.values(T).forEach(g=>{g.length=0}),b.forEach(g=>removeEventListener("message",g)),b.length=0,J&&t&&J.unobserve(t),E=!0},J;P==="lazy"&&"IntersectionObserver"in window&&(J=new IntersectionObserver((s,g)=>{s.forEach(async S=>{S.isIntersecting&&(await O(),g.unobserve(t))})},{rootMargin:"150px"}),J.observe(t));let oe=()=>(String(Math.random())+Date.now().toFixed()).replace("0.","");return{load:()=>O(),run:()=>a("run"),format:s=>a("format",[s]),getShareUrl:s=>a("getShareUrl",[s]),getConfig:s=>a("getConfig",[s]),setConfig:s=>a("setConfig",[s]),getCode:()=>a("getCode"),show:(s,g)=>a("show",[s,g]),runTests:()=>a("runTests"),onChange:s=>q("code",s),watch:q,exec:(s,...g)=>a("exec",[s,...g]),destroy:()=>E?Promise.reject(w):(ne(),Promise.resolve())}}function me(c={}){let{appUrl:m="https://livecodes.io",params:C={},config:f={},headless:x,import:P,lite:o,view:r,...t}=c,n;try{n=new URL(m)}catch(v){throw new Error(`${m} is not a valid URL.`)}let l=new URLSearchParams;Object.entries(t).forEach(([v,u])=>{u!==void 0&&n.searchParams.set(v,String(u))});let p=c.view==="headless"||x;if(o&&(console.warn(`Deprecation notice: "lite" option is deprecated. Use "config: { mode: 'lite' }" instead.`),typeof f=="object"&&f.mode==null?f.mode="lite":n.searchParams.set("lite","true")),r&&(console.warn('Deprecation notice: The "view" option has been moved to "config.view". For headless mode use "headless: true".'),typeof f=="object"&&f.view==null&&r!=="headless"?f.view=r:n.searchParams.set("view",r)),typeof f=="string")try{new URL(f),n.searchParams.set("config",encodeURIComponent(f))}catch(v){throw new Error('"config" is not a valid URL or configuration object.')}else f&&typeof f=="object"&&Object.keys(f).length>0&&(f.title&&f.title!=="Untitled Project"&&n.searchParams.set("title",f.title),f.description&&f.description.length>0&&n.searchParams.set("description",f.description),l.set("config","code/"+(0,K.compressToEncodedURIComponent)(JSON.stringify(f))));if(C&&typeof C=="object"&&Object.keys(C).length>0)try{l.set("params",(0,K.compressToEncodedURIComponent)(JSON.stringify(C)))}catch(v){Object.keys(C).forEach(u=>{n.searchParams.set(u,encodeURIComponent(String(C[u])))})}return P&&n.searchParams.set("x",encodeURIComponent(P)),p&&n.searchParams.set("headless","true"),l.toString().length>0&&(n.hash=l.toString()),n.href}var Ee={appUrl:String,config:[Object,String],headless:Boolean,import:String,lite:Boolean,loading:String,params:Object,template:String,view:String,height:String},W=c=>JSON.parse(JSON.stringify(c)),be={props:Ee,emits:["sdkReady"],setup(c,m){let{height:C,...f}=c,x=B(),P=B(C||""),o=B(),{config:r,...t}=f,n=JSON.stringify(r),l=JSON.stringify(t),p=0,v=u=>u!==p;return he(()=>{if(!x.value)return;let u=++p;z(x.value,W(f)).then(E=>{if(v(u)){E.destroy();return}o.value=E,m.emit("sdkReady",E)})}),we(c,async u=>{var y;if(!x.value)return;let{height:E,...w}=u,b=++p;E&&(P.value=E);let{config:A,...d}=w;!o.value||JSON.stringify(d)!==l?(l=JSON.stringify(d),n=JSON.stringify(A),(y=o.value)==null||y.destroy(),o.value=void 0,z(x.value,W(w)).then(e=>{if(v(b)){e.destroy();return}o.value=e,m.emit("sdkReady",e)})):JSON.stringify(A)!==n&&(n=JSON.stringify(A),A&&o.value.setConfig(W(A)||{}))}),ve(()=>{var u;++p,(u=o.value)==null||u.destroy()}),()=>{var u,E;return ye("div",{ref:x,style:P.value?{height:Number(P.value)?`${P.value}px`:P.value}:void 0},((E=(u=m.slots).default)==null?void 0:E.call(u))||"")}}},Me=be;export{Me as default};

Sorry, the diff of this file is too big to display