clearkrypt 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.well-known/clearkrypt.json +7 -0
  2. package/.wrangler/cache/pages.json +4 -0
  3. package/.wrangler/cache/wrangler-account.json +6 -0
  4. package/DEPLOYMENT_CLEARKRYPT.md +53 -0
  5. package/README.md +96 -0
  6. package/ai-plugin.json +12 -0
  7. package/bin/clearkrypt.js +55 -0
  8. package/course/duolingo_course.md +127 -0
  9. package/docs/AI_CRAWLER_GUIDE.md +74 -0
  10. package/docs/COMPILER_ARCHITECTURE.md +62 -0
  11. package/docs/COMPLETE_LANGUAGE_GUIDE.md +137 -0
  12. package/docs/LANGUAGE_SPEC.md +102 -0
  13. package/docs/LAYOUT_AND_STYLING.md +101 -0
  14. package/docs/ONLINE_SANDBOX_EXPORTS.md +28 -0
  15. package/docs/PLATFORM_TARGETS.md +35 -0
  16. package/docs/README.md +79 -0
  17. package/docs/STDLIB.md +74 -0
  18. package/docs/VISUAL_STUDIO.md +36 -0
  19. package/docs-site/app.css +3 -0
  20. package/docs-site/app.js +8 -0
  21. package/docs-site/clearkrypt/app.css +3 -0
  22. package/docs-site/clearkrypt/app.js +8 -0
  23. package/docs-site/clearkrypt/index.html +44 -0
  24. package/examples/fixit-dashboard/main.ck +29 -0
  25. package/examples/light-test-app/main.ck +38 -0
  26. package/examples/momeants-mini/main.ck +19 -0
  27. package/llms.txt +18 -0
  28. package/openapi.yaml +11 -0
  29. package/package.json +32 -0
  30. package/site/.well-known/clearkrypt.json +1 -0
  31. package/site/ai-index.json +1 -0
  32. package/site/app.css +3 -0
  33. package/site/app.js +23 -0
  34. package/site/assets/app.css +3 -0
  35. package/site/assets/app.js +23 -0
  36. package/site/assets/clearkrypt-logo.png +0 -0
  37. package/site/compiler/index.html +8 -0
  38. package/site/course/index.html +5 -0
  39. package/site/docs/index.html +69 -0
  40. package/site/extensions/index.html +31 -0
  41. package/site/index.html +19 -0
  42. package/site/llms.txt +2 -0
  43. package/site/robots.txt +3 -0
  44. package/site/sandbox/index.html +24 -0
  45. package/site/sitemap.xml +1 -0
  46. package/sitemap.xml +9 -0
  47. package/src/index.js +55 -0
  48. package/src/lexer.js +18 -0
  49. package/src/parser.js +52 -0
  50. package/src/semantic.js +5 -0
  51. package/src/targets/js.js +32 -0
  52. package/src/targets/pc.js +19 -0
  53. package/src/targets/phone.js +30 -0
  54. package/src/targets/project.js +24 -0
  55. package/src/targets/vmbytecode.js +8 -0
  56. package/src/targets/web.js +37 -0
  57. package/src/targets/worker.js +8 -0
  58. package/src/vm.js +5 -0
  59. package/stdlib/cloud.ck +2 -0
  60. package/stdlib/data.ck +2 -0
  61. package/stdlib/ui.ck +2 -0
  62. package/testapp.ck +35 -0
  63. package/tests/smoke.test.js +9 -0
  64. package/tools/print-course.js +2 -0
  65. package/tools/studio/index.html +1 -0
  66. package/tools/studio/studio.css +1 -0
  67. package/tools/studio/studio.js +52 -0
package/openapi.yaml ADDED
@@ -0,0 +1,11 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: ClearKrypt Language Metadata
4
+ version: 0.1.0
5
+ paths:
6
+ /docs/AI_CRAWLER_GUIDE.md:
7
+ get:
8
+ summary: AI guide for ClearKrypt syntax and app generation
9
+ responses:
10
+ '200':
11
+ description: Markdown documentation
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "clearkrypt",
3
+ "version": "0.12.0",
4
+ "description": "ClearKrypt language compiler, VM, docs, sandbox, and course",
5
+ "type": "module",
6
+ "bin": {
7
+ "clearkrypt": "bin/clearkrypt.js",
8
+ "ck": "bin/clearkrypt.js"
9
+ },
10
+ "scripts": {
11
+ "test": "node tests/smoke.test.js",
12
+ "build": "node bin/clearkrypt.js build examples/fixit-dashboard/main.ck --target web --out dist/fixit-dashboard",
13
+ "course": "node tools/print-course.js",
14
+ "build:all": "node bin/clearkrypt.js build-all examples/fixit-dashboard/main.ck --out build",
15
+ "studio": "node bin/clearkrypt.js studio examples/fixit-dashboard/main.ck --out studio",
16
+ "site:preview": "npx serve site",
17
+ "deploy:site": "npx wrangler pages deploy site --project-name clearkrypt",
18
+ "deploy:docs": "npx wrangler pages deploy site/docs --project-name clearkey-docs"
19
+ },
20
+ "keywords": [
21
+ "language",
22
+ "compiler",
23
+ "vm",
24
+ "dsl",
25
+ "clearKey",
26
+ "cross-platform"
27
+ ],
28
+ "license": "MIT",
29
+ "engines": {
30
+ "node": ">=18"
31
+ }
32
+ }
@@ -0,0 +1 @@
1
+ {"name":"ClearKrypt","languageVersion":"0.7","docs":"/docs/","llms":"/llms.txt"}
@@ -0,0 +1 @@
1
+ {"name":"ClearKrypt","docs":"/docs/","sandbox":"/sandbox/","course":"/course/","compiler":"/compiler/","modules":["ui","data","auth","network","storage","platform","worker","crypto","ai","test","deploy"]}
package/site/app.css ADDED
@@ -0,0 +1,3 @@
1
+
2
+ :root{--bg:#050812;--panel:#0d1324;--panel2:#111a2d;--text:#f5f8ff;--muted:#a8b4cf;--line:rgba(255,255,255,.13);--cyan:#19d7ff;--blue:#2878ff;--violet:#8a3ffc;--orange:#ff9f16;--green:#38e8a6;--shadow:0 28px 90px rgba(0,0,0,.45)}
3
+ *{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;font-family:Inter,Segoe UI,Roboto,Arial,sans-serif;color:var(--text);background:radial-gradient(circle at 20% 0%,rgba(25,215,255,.16),transparent 30%),radial-gradient(circle at 80% 10%,rgba(138,63,252,.18),transparent 28%),linear-gradient(180deg,#04060c,#071021 55%,#050812);min-height:100vh}a{color:inherit;text-decoration:none}code,pre,textarea{font-family:ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",monospace}.wrap{max-width:1280px;margin:auto;padding-left:22px;padding-right:22px}.topbar,.top{position:sticky;top:0;z-index:30;backdrop-filter:blur(18px);background:rgba(5,8,18,.82);border-bottom:1px solid var(--line)}.nav{display:flex;align-items:center;justify-content:space-between;padding-top:16px;padding-bottom:16px}.brand{display:flex;gap:12px;align-items:center;font-weight:900;letter-spacing:-.03em}.brand img{width:48px;height:48px;object-fit:cover;border-radius:14px}.brand span{font-size:22px}.links,.navlinks{display:flex;gap:10px;flex-wrap:wrap}.links a,.navlinks a,.btn,.copyBtn,.target,.primary,button{border:1px solid var(--line);background:rgba(255,255,255,.075);padding:12px 16px;border-radius:16px;font-weight:850;color:var(--text);cursor:pointer;font-size:15px}.links a:hover,.navlinks a:hover,.btn:hover,.copyBtn:hover,.target:hover,button:hover{background:rgba(255,255,255,.13);transform:translateY(-1px)}.primary,.btn.primary{border:0;background:linear-gradient(135deg,var(--cyan),var(--blue),var(--violet));box-shadow:0 16px 45px rgba(40,120,255,.28)}.orange{border:0;background:linear-gradient(135deg,#ffb13d,#ff8a00);color:#080b12}.hero{padding:74px 22px 46px;display:grid;grid-template-columns:1.08fr .92fr;gap:42px;align-items:center}.eyebrow{display:inline-flex;gap:8px;align-items:center;border:1px solid var(--line);background:rgba(255,255,255,.07);border-radius:999px;padding:9px 13px;color:#dce7ff;font-weight:800}.dot{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 18px var(--green)}h1{font-size:clamp(48px,7vw,96px);line-height:.9;letter-spacing:-.075em;margin:20px 0}h2{font-size:clamp(32px,4vw,58px);line-height:1;letter-spacing:-.05em;margin:0 0 20px}h3{font-size:24px;margin:0 0 10px}.lead{font-size:21px;line-height:1.55;color:var(--muted);max-width:820px}.actions,.toolbar{display:flex;gap:12px;flex-wrap:wrap;margin:20px 0}.logo-card{border:1px solid var(--line);border-radius:34px;background:linear-gradient(145deg,rgba(255,255,255,.09),rgba(255,255,255,.035));box-shadow:var(--shadow);padding:24px;overflow:hidden}.logo-card img{width:100%;max-height:430px;object-fit:contain;border-radius:26px;display:block;background:#02040a}.section{padding:58px 22px}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}.card{border:1px solid var(--line);border-radius:28px;background:linear-gradient(145deg,rgba(255,255,255,.08),rgba(18,26,45,.78));padding:26px;box-shadow:0 20px 70px rgba(0,0,0,.22)}.card p{color:var(--muted);line-height:1.55;font-size:17px}.card.click{transition:.18s;display:block}.card.click:hover{border-color:rgba(25,215,255,.45);transform:translateY(-3px)}.pillrow{display:flex;gap:9px;flex-wrap:wrap;margin-top:16px}.pill{font-size:13px;color:#dce7ff;border:1px solid var(--line);border-radius:999px;padding:7px 10px;background:rgba(255,255,255,.06)}.footer{border-top:1px solid var(--line);color:var(--muted);padding:32px 22px;text-align:center}.search{width:100%;border:1px solid var(--line);background:#070c18;color:white;border-radius:18px;padding:16px 18px;font-size:18px;margin:16px 0 24px}.doc-layout{max-width:1420px;margin:auto;display:grid;grid-template-columns:300px 1fr;gap:22px;padding:28px 22px}.toc{position:sticky;top:98px;align-self:start;border:1px solid var(--line);border-radius:24px;background:rgba(255,255,255,.055);padding:18px}.toc a{display:block;color:var(--muted);padding:9px;border-radius:12px}.toc a:hover{background:rgba(255,255,255,.08);color:white}.doc-main{min-width:0}.doc-section{border:1px solid var(--line);border-radius:26px;background:rgba(255,255,255,.055);padding:26px;margin-bottom:18px}.doc-section p,.doc-section li{color:#c6d2e9;font-size:17px;line-height:1.55}.hide{display:none!important}.sandboxPage{max-width:1480px;margin:auto;padding:28px 22px}.sandboxGrid{display:grid;grid-template-columns:minmax(430px,.95fr) minmax(520px,1.05fr);gap:18px;align-items:stretch}.panel{border:1px solid var(--line);border-radius:28px;background:rgba(255,255,255,.055);box-shadow:0 20px 70px rgba(0,0,0,.25);overflow:hidden}.panelHead{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.055);font-weight:900}.editor{width:100%;height:560px;background:#050914;color:#f6fbff;border:0;padding:20px;font-size:16px;line-height:1.55;resize:vertical;outline:none}.highlight{min-height:220px}.preview{position:relative;min-height:560px;background:radial-gradient(circle at 20% 30%,rgba(25,215,255,.13),transparent 30%),linear-gradient(145deg,#151a26,#0b1020);overflow:hidden;padding:32px}.preview.stack{display:flex;flex-direction:column;gap:18px;align-items:flex-start}.preview.freeform{display:block}.ckEl{border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.12);backdrop-filter:blur(10px);border-radius:20px;padding:14px 18px;min-width:220px;max-width:520px;box-shadow:0 18px 50px rgba(0,0,0,.22)}.freeform .ckEl{position:absolute;cursor:grab;user-select:none}.ck-title{font-size:34px;font-weight:950;letter-spacing:-.035em;background:transparent;border:0;box-shadow:none;padding:0;min-width:0}.ck-text{color:#d8e1f5}.ck-card{background:rgba(255,255,255,.11)}.ckButton{background:linear-gradient(135deg,#ffb13d,#ff8a00);color:#090b10;font-weight:950;border:0;padding:14px 20px;border-radius:16px;display:inline-block}.targetTabs{display:flex;gap:10px;flex-wrap:wrap;margin:18px 0}.target.active{background:linear-gradient(135deg,var(--cyan),var(--blue),var(--violet));border:0}.exportGrid{display:grid;grid-template-columns:1fr;gap:16px}.codeViewport{border:1px solid rgba(135,165,255,.22);border-radius:22px;background:#050914;overflow:hidden}.codeHeader{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 14px;background:rgba(255,255,255,.055);border-bottom:1px solid rgba(135,165,255,.16);font-weight:900}.codeBlock{margin:0;padding:18px;overflow:auto;white-space:pre;min-height:120px;max-height:520px;color:#e8f1ff;line-height:1.6;font-size:14px}.copyIcon{display:inline-flex;align-items:center;gap:8px}.copyIcon svg{width:18px;height:18px}.kw{color:#7dd3fc;font-weight:900}.str{color:#fde68a}.num{color:#c4b5fd}.com{color:#94a3b8;font-style:italic}.type{color:#86efac;font-weight:900}.prop{color:#f0abfc}.tag{color:#67e8f9}.attr{color:#f9a8d4}.lesson{display:grid;grid-template-columns:90px 1fr auto;gap:16px;align-items:center}.badge-num{width:62px;height:62px;border-radius:20px;background:linear-gradient(135deg,var(--cyan),var(--violet));display:grid;place-items:center;font-weight:900;font-size:24px}.notice{border:1px solid rgba(56,232,166,.35);background:rgba(56,232,166,.08);color:#dfffee;border-radius:20px;padding:18px;margin:18px 0}@media(max-width:980px){.hero,.sandboxGrid,.doc-layout{grid-template-columns:1fr}.grid{grid-template-columns:1fr}.links,.navlinks{display:none}h1{font-size:52px}.logo-card img{max-height:290px}.toc{position:relative;top:0}.preview{min-height:480px}.editor{height:420px}}
package/site/app.js ADDED
@@ -0,0 +1,23 @@
1
+
2
+ const $=(s,r=document)=>r.querySelector(s);const $$=(s,r=document)=>[...r.querySelectorAll(s)];
3
+ function icon(){return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="11" height="11" rx="2"></rect><rect x="4" y="4" width="11" height="11" rx="2"></rect></svg>`}
4
+ async function copyRaw(text,btn){await navigator.clipboard.writeText(text||''); if(btn){const old=btn.innerHTML;btn.innerHTML=icon()+'Copied';setTimeout(()=>btn.innerHTML=old,900)}}
5
+ function copyEl(id,btn){copyRaw(($('#'+id)?.textContent)||($('#'+id)?.value)||'',btn)}
6
+ function escapeHtml(s){return String(s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]))}
7
+ function highlight(code,lang='ck'){let s=escapeHtml(code); if(lang==='ck'){s=s.replace(/("[^"]*")/g,'<span class="str">$1</span>').replace(/\b(app|use|style|screen|layout|title|text|button|card|type|store|task|when|otherwise|for|each|as|default|say|add|to|let|return|try|catch)\b/g,'<span class="kw">$1</span>').replace(/\b(Stack|Freeform|Grid|Dock|Text|Number|Boolean|List|Date|Task|AppStyle)\b/g,'<span class="type">$1</span>').replace(/(@pos|theme|accent|radius|spacing)\b/g,'<span class="prop">$1</span>').replace(/\b(\d+)\b/g,'<span class="num">$1</span>');}
8
+ else if(lang==='html'){s=s.replace(/(&lt;\/?[a-zA-Z0-9-]+)/g,'<span class="tag">$1</span>').replace(/([a-zA-Z-]+)=/g,'<span class="attr">$1</span>=');}
9
+ else if(['js','css','csharp','swift'].includes(lang)){s=s.replace(/("[^"]*"|'[^']*'|`[^`]*`)/g,'<span class="str">$1</span>').replace(/\b(const|let|var|function|return|class|public|sealed|new|string|object|import|struct|var|body|some|View|Button|Text|VStack|foreach|if|else|document|querySelectorAll|addEventListener)\b/g,'<span class="kw">$1</span>').replace(/\b(\d+)\b/g,'<span class="num">$1</span>').replace(/(\/\/.*)$/gm,'<span class="com">$1</span>');}
10
+ return s}
11
+ function codeViewport(id,title,code,lang){return `<div class="codeViewport"><div class="codeHeader"><span>${title}</span><button class="copyBtn copyIcon" onclick="copyRaw(document.getElementById('${id}').textContent,this)">${icon()}Copy</button></div><pre id="${id}" class="codeBlock lang-${lang}" data-raw="${escapeHtml(code)}"><code>${highlight(code,lang)}</code></pre></div>`}
12
+ function docSearch(){const q=($('#docSearch')?.value||'').toLowerCase();$$('.doc-section').forEach(sec=>sec.classList.toggle('hide',q&&!sec.innerText.toLowerCase().includes(q)));$$('.toc a').forEach(a=>{const target=$(a.getAttribute('href'));a.classList.toggle('hide',q&&!(a.innerText+' '+(target?.innerText||'')).toLowerCase().includes(q))})}
13
+ function parseCK(code){const app=(code.match(/app\s+"([^"]+)"/)||[])[1]||'ClearKrypt App';const uses=[...code.matchAll(/use\s+([a-zA-Z_][\w.]*)/g)].map(m=>m[1]);const style={theme:(code.match(/theme:\s*(\w+)/)||[])[1]||'dark',accent:(code.match(/accent:\s*(\w+)/)||[])[1]||'cyan',radius:+((code.match(/radius:\s*(\d+)/)||[])[1]||22),spacing:+((code.match(/spacing:\s*(\d+)/)||[])[1]||18)};const screen=(code.match(/screen\s+(\w+)\s*{([\s\S]*)}\s*$/)||[]);const body=screen[2]||code;const layout=(body.match(/layout\s+(Stack|Freeform|Grid|Dock)/i)||[])[1]||'Stack';const elements=[];const re=/(title|text|button)\s+"([^"]+)"(?:\s+@pos\((\d+),\s*(\d+)\))?/g;let m;while((m=re.exec(body)))elements.push({type:m[1],label:m[2],x:+(m[3]||0),y:+(m[4]||0)});const cardRe=/card\s*{([\s\S]*?)}/g;while((m=cardRe.exec(body))){const inner=m[1];const texts=[...inner.matchAll(/text\s+"([^"]+)"/g)].map(x=>x[1]);const buttons=[...inner.matchAll(/button\s+"([^"]+)"/g)].map(x=>x[1]);elements.push({type:'card',label:texts[0]||'Card',texts,buttons})}return{app,uses,style,layout,elements}}
14
+ function renderSandbox(){const ed=$('#ckEditor'),pv=$('#preview');if(!ed||!pv)return;const ir=parseCK(ed.value);pv.innerHTML='';pv.className='preview '+(ir.layout.toLowerCase()==='freeform'?'freeform':'stack');let i=0;for(const e of ir.elements){const el=document.createElement('div');el.dataset.type=e.type;el.dataset.label=e.label;if(e.type==='title'){el.className='ckEl ck-title';el.textContent=e.label}else if(e.type==='button'){el.className='ckButton';el.textContent=e.label}else if(e.type==='card'){el.className='ckEl ck-card';el.innerHTML=`<b>${escapeHtml(e.label)}</b>${(e.texts||[]).slice(1).map(t=>`<p>${escapeHtml(t)}</p>`).join('')}${(e.buttons||[]).map(b=>`<button class="ckButton">${escapeHtml(b)}</button>`).join('')}`}else{el.className='ckEl ck-text';el.textContent=e.label}if(ir.layout.toLowerCase()==='freeform'){el.classList.add('ckEl');el.style.left=(e.x||60+i*30)+'px';el.style.top=(e.y||60+i*88)+'px';makeDrag(el)}pv.appendChild(el);i++}}
15
+ function makeDrag(el){let sx,sy,ox,oy;el.onpointerdown=e=>{sx=e.clientX;sy=e.clientY;ox=parseInt(el.style.left)||0;oy=parseInt(el.style.top)||0;el.setPointerCapture(e.pointerId)};el.onpointermove=e=>{if(sx==null)return;el.style.left=Math.max(0,ox+e.clientX-sx)+'px';el.style.top=Math.max(0,oy+e.clientY-sy)+'px'};el.onpointerup=()=>{if(sx==null)return;sx=null;updateCodePositions()}}
16
+ function updateCodePositions(){const ed=$('#ckEditor');let code=ed.value;$$('#preview .ckEl,#preview .ckButton').forEach(el=>{if(!['title','text','button'].includes(el.dataset.type))return;const label=el.dataset.label.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');const type=el.dataset.type;const x=parseInt(el.style.left)||0,y=parseInt(el.style.top)||0;const r=new RegExp(`${type}\\s+"${label}"(?:\\s+@pos\\(\\d+,\\s*\\d+\\))?`);code=code.replace(r,`${type} "${el.dataset.label}" @pos(${x}, ${y})`)});ed.value=code;compileSandbox(false)}
17
+ function setLayoutMode(mode){const ed=$('#ckEditor');if(/layout\s+(Stack|Freeform|Grid|Dock)/i.test(ed.value))ed.value=ed.value.replace(/layout\s+(Stack|Freeform|Grid|Dock)/i,'layout '+mode);else ed.value=ed.value.replace(/screen\s+(\w+)\s*{/,`screen $1 {\n layout ${mode}`);compileSandbox()}
18
+ function safeName(s){return(s||'App').replace(/[^A-Za-z0-9]/g,'')||'App'}
19
+ function emitTargets(ir){const els=ir.elements.filter(e=>e.type!=='card'),cards=ir.elements.filter(e=>e.type==='card');const html=`<main class="ck-app">\n <section class="ck-screen">\n${els.map(e=>e.type==='button'?` <button class="ck-button">${e.label}</button>`:` <div class="ck-${e.type}">${e.label}</div>`).join('\n')}\n${cards.map(c=>` <article class="ck-card"><p>${c.label}</p>${(c.buttons||[]).map(b=>`<button class="ck-button">${b}</button>`).join('')}</article>`).join('\n')}\n </section>\n</main>`;const css=`:root { --ck-accent: #16dcff; --ck-radius: ${ir.style.radius}px; --ck-spacing: ${ir.style.spacing}px; }\nbody { margin:0; font-family: system-ui; background:#05070d; color:white; }\n.ck-screen { display:flex; flex-direction:column; gap:var(--ck-spacing); padding:42px; }\n.ck-title { font-size:32px; font-weight:900; }\n.ck-text { color:#cbd5e1; }\n.ck-button { width:max-content; border:0; border-radius:var(--ck-radius); padding:14px 20px; background:linear-gradient(135deg,#16dcff,#3378ff,#8f45ff); color:white; font-weight:900; }\n.ck-card { border:1px solid rgba(255,255,255,.16); border-radius:var(--ck-radius); padding:20px; background:rgba(255,255,255,.08); }`;const js=`const app = ${JSON.stringify(ir,null,2)};\ndocument.querySelectorAll('.ck-button').forEach(button => {\n button.addEventListener('click', () => console.log('ClearKrypt action from', button.textContent));\n});`;const index=`<!doctype html>\n<html>\n<head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width,initial-scale=1">\n <title>${ir.app}</title>\n <link rel="stylesheet" href="style.css">\n</head>\n<body>\n${html}\n <script src="main.js"></script>\n</body>\n</html>`;const inline=`<!doctype html>\n<html>\n<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${ir.app}</title><style>${css}</style></head>\n<body>${html}<script>${js.replace(/<\//g,'<\\/')}<\/script></body>\n</html>`;const csharp=`// ClearKrypt C# target sketch for .NET MAUI / Blazor\npublic sealed class ${safeName(ir.app)}App\n{\n public string Name => "${ir.app}";\n public string[] Modules => new[] { ${ir.uses.map(u=>'"'+u+'"').join(', ')} };\n\n public object Build()\n {\n return new StackLayout\n {\n Spacing = ${ir.style.spacing},\n Children =\n {\n${ir.elements.map(e=> e.type==='button'?` new Button { Text = "${e.label}" },`:` new Label { Text = "${e.label}" },`).join('\n')}\n }\n };\n }\n}`;const swift=`// ClearKrypt SwiftUI target sketch for Xcode / Apple platforms\nimport SwiftUI\n\nstruct ${safeName(ir.app)}View: View {\n var body: some View {\n VStack(alignment: .leading, spacing: ${ir.style.spacing}) {\n${ir.elements.map(e=> e.type==='button'?` Button("${e.label}") { print("ClearKrypt action") }`:` Text("${e.label}")${e.type==='title' ? '.font(.largeTitle).bold()' : ''}`).join('\n')}\n }\n .padding(32)\n }\n}`;const docs=`HTML Package emits three files together: index.html, style.css, and main.js.\n\nUse this for Cloudflare Pages, Firebase Hosting, Netlify, Vercel static deploys, or any static web host.\n\nCSS only and JS only are inspection tabs. Inline HTML is for quick demos. C# and Swift are native target sketches. Full native packaging remains a CLI build step.\n\nCLI examples:\nck build app.ck --target web --out dist/web\nck build app.ck --target phone --out dist/phone\nck build app.ck --target pc --out dist/pc\nck build-all app.ck --out dist`;return{html:{'index.html':index,'style.css':css,'main.js':js},css:{'style.css':css},js:{'main.js':js},inline:{'inline.html':inline},csharp:{'App.cs':csharp},swift:{'App.swift':swift},docs:{'TARGET_DOCS.txt':docs}}}
20
+ let currentTarget='html',currentOutputs={};function showTarget(t){currentTarget=t;$$('.target').forEach(b=>b.classList.toggle('active',b.dataset.target===t));const box=$('#outputFiles');if(!box)return;box.innerHTML='';const files=currentOutputs[t]||{};const langMap={html:'html',css:'css',js:'js',inline:'html',csharp:'csharp',swift:'swift',docs:'txt'};Object.entries(files).forEach(([name,code],i)=>{box.insertAdjacentHTML('beforeend',codeViewport('out_'+t+'_'+i,name,code,langMap[t]||'txt'))})}
21
+ function compileSandbox(rerender=true){const ed=$('#ckEditor');if(!ed)return;if(rerender)renderSandbox();const ck=$('#ckHighlighted');if(ck)ck.innerHTML='<code>'+highlight(ed.value,'ck')+'</code>';currentOutputs=emitTargets(parseCK(ed.value));showTarget(currentTarget)}
22
+ let xp=0,step=0;function choose(btn,ok){$$('.choice',btn.parentElement).forEach(b=>b.disabled=true);btn.classList.add(ok?'correct':'wrong');if(ok)xp+=10;$('#xp')&&( $('#xp').innerText=xp);$('.bar')&&($('.bar').style.width=Math.min(100,xp)+'%');setTimeout(nextLesson,700)}function nextLesson(){const arr=$$('.challenge');if(!arr.length)return;arr[step]?.classList.remove('active');step=(step+1)%arr.length;arr[step].classList.add('active');$$('.choice',arr[step]).forEach(b=>{b.disabled=false;b.classList.remove('correct','wrong')})}
23
+ window.addEventListener('DOMContentLoaded',()=>{compileSandbox();$('#ckEditor')?.addEventListener('input',()=>compileSandbox());$('#docSearch')?.addEventListener('input',docSearch);$$('pre[data-lang]').forEach((p,i)=>{const raw=p.textContent.trim();const lang=p.dataset.lang||'ck';const vp=document.createElement('div');vp.innerHTML=codeViewport('doccode_'+i,p.dataset.title||lang,raw,lang);p.replaceWith(vp.firstChild)})});
@@ -0,0 +1,3 @@
1
+
2
+ :root{--bg:#050812;--panel:#0d1324;--panel2:#111a2d;--text:#f5f8ff;--muted:#a8b4cf;--line:rgba(255,255,255,.13);--cyan:#19d7ff;--blue:#2878ff;--violet:#8a3ffc;--orange:#ff9f16;--green:#38e8a6;--shadow:0 28px 90px rgba(0,0,0,.45)}
3
+ *{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;font-family:Inter,Segoe UI,Roboto,Arial,sans-serif;color:var(--text);background:radial-gradient(circle at 20% 0%,rgba(25,215,255,.16),transparent 30%),radial-gradient(circle at 80% 10%,rgba(138,63,252,.18),transparent 28%),linear-gradient(180deg,#04060c,#071021 55%,#050812);min-height:100vh}a{color:inherit;text-decoration:none}code,pre,textarea{font-family:ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",monospace}.wrap{max-width:1280px;margin:auto;padding-left:22px;padding-right:22px}.topbar,.top{position:sticky;top:0;z-index:30;backdrop-filter:blur(18px);background:rgba(5,8,18,.82);border-bottom:1px solid var(--line)}.nav{display:flex;align-items:center;justify-content:space-between;padding-top:16px;padding-bottom:16px}.brand{display:flex;gap:12px;align-items:center;font-weight:900;letter-spacing:-.03em}.brand img{width:48px;height:48px;object-fit:cover;border-radius:14px}.brand span{font-size:22px}.links,.navlinks{display:flex;gap:10px;flex-wrap:wrap}.links a,.navlinks a,.btn,.copyBtn,.target,.primary,button{border:1px solid var(--line);background:rgba(255,255,255,.075);padding:12px 16px;border-radius:16px;font-weight:850;color:var(--text);cursor:pointer;font-size:15px}.links a:hover,.navlinks a:hover,.btn:hover,.copyBtn:hover,.target:hover,button:hover{background:rgba(255,255,255,.13);transform:translateY(-1px)}.primary,.btn.primary{border:0;background:linear-gradient(135deg,var(--cyan),var(--blue),var(--violet));box-shadow:0 16px 45px rgba(40,120,255,.28)}.orange{border:0;background:linear-gradient(135deg,#ffb13d,#ff8a00);color:#080b12}.hero{padding:74px 22px 46px;display:grid;grid-template-columns:1.08fr .92fr;gap:42px;align-items:center}.eyebrow{display:inline-flex;gap:8px;align-items:center;border:1px solid var(--line);background:rgba(255,255,255,.07);border-radius:999px;padding:9px 13px;color:#dce7ff;font-weight:800}.dot{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 18px var(--green)}h1{font-size:clamp(48px,7vw,96px);line-height:.9;letter-spacing:-.075em;margin:20px 0}h2{font-size:clamp(32px,4vw,58px);line-height:1;letter-spacing:-.05em;margin:0 0 20px}h3{font-size:24px;margin:0 0 10px}.lead{font-size:21px;line-height:1.55;color:var(--muted);max-width:820px}.actions,.toolbar{display:flex;gap:12px;flex-wrap:wrap;margin:20px 0}.logo-card{border:1px solid var(--line);border-radius:34px;background:linear-gradient(145deg,rgba(255,255,255,.09),rgba(255,255,255,.035));box-shadow:var(--shadow);padding:24px;overflow:hidden}.logo-card img{width:100%;max-height:430px;object-fit:contain;border-radius:26px;display:block;background:#02040a}.section{padding:58px 22px}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}.card{border:1px solid var(--line);border-radius:28px;background:linear-gradient(145deg,rgba(255,255,255,.08),rgba(18,26,45,.78));padding:26px;box-shadow:0 20px 70px rgba(0,0,0,.22)}.card p{color:var(--muted);line-height:1.55;font-size:17px}.card.click{transition:.18s;display:block}.card.click:hover{border-color:rgba(25,215,255,.45);transform:translateY(-3px)}.pillrow{display:flex;gap:9px;flex-wrap:wrap;margin-top:16px}.pill{font-size:13px;color:#dce7ff;border:1px solid var(--line);border-radius:999px;padding:7px 10px;background:rgba(255,255,255,.06)}.footer{border-top:1px solid var(--line);color:var(--muted);padding:32px 22px;text-align:center}.search{width:100%;border:1px solid var(--line);background:#070c18;color:white;border-radius:18px;padding:16px 18px;font-size:18px;margin:16px 0 24px}.doc-layout{max-width:1420px;margin:auto;display:grid;grid-template-columns:300px 1fr;gap:22px;padding:28px 22px}.toc{position:sticky;top:98px;align-self:start;border:1px solid var(--line);border-radius:24px;background:rgba(255,255,255,.055);padding:18px}.toc a{display:block;color:var(--muted);padding:9px;border-radius:12px}.toc a:hover{background:rgba(255,255,255,.08);color:white}.doc-main{min-width:0}.doc-section{border:1px solid var(--line);border-radius:26px;background:rgba(255,255,255,.055);padding:26px;margin-bottom:18px}.doc-section p,.doc-section li{color:#c6d2e9;font-size:17px;line-height:1.55}.hide{display:none!important}.sandboxPage{max-width:1480px;margin:auto;padding:28px 22px}.sandboxGrid{display:grid;grid-template-columns:minmax(430px,.95fr) minmax(520px,1.05fr);gap:18px;align-items:stretch}.panel{border:1px solid var(--line);border-radius:28px;background:rgba(255,255,255,.055);box-shadow:0 20px 70px rgba(0,0,0,.25);overflow:hidden}.panelHead{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.055);font-weight:900}.editor{width:100%;height:560px;background:#050914;color:#f6fbff;border:0;padding:20px;font-size:16px;line-height:1.55;resize:vertical;outline:none}.highlight{min-height:220px}.preview{position:relative;min-height:560px;background:radial-gradient(circle at 20% 30%,rgba(25,215,255,.13),transparent 30%),linear-gradient(145deg,#151a26,#0b1020);overflow:hidden;padding:32px}.preview.stack{display:flex;flex-direction:column;gap:18px;align-items:flex-start}.preview.freeform{display:block}.ckEl{border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.12);backdrop-filter:blur(10px);border-radius:20px;padding:14px 18px;min-width:220px;max-width:520px;box-shadow:0 18px 50px rgba(0,0,0,.22)}.freeform .ckEl{position:absolute;cursor:grab;user-select:none}.ck-title{font-size:34px;font-weight:950;letter-spacing:-.035em;background:transparent;border:0;box-shadow:none;padding:0;min-width:0}.ck-text{color:#d8e1f5}.ck-card{background:rgba(255,255,255,.11)}.ckButton{background:linear-gradient(135deg,#ffb13d,#ff8a00);color:#090b10;font-weight:950;border:0;padding:14px 20px;border-radius:16px;display:inline-block}.targetTabs{display:flex;gap:10px;flex-wrap:wrap;margin:18px 0}.target.active{background:linear-gradient(135deg,var(--cyan),var(--blue),var(--violet));border:0}.exportGrid{display:grid;grid-template-columns:1fr;gap:16px}.codeViewport{border:1px solid rgba(135,165,255,.22);border-radius:22px;background:#050914;overflow:hidden}.codeHeader{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 14px;background:rgba(255,255,255,.055);border-bottom:1px solid rgba(135,165,255,.16);font-weight:900}.codeBlock{margin:0;padding:18px;overflow:auto;white-space:pre;min-height:120px;max-height:520px;color:#e8f1ff;line-height:1.6;font-size:14px}.copyIcon{display:inline-flex;align-items:center;gap:8px}.copyIcon svg{width:18px;height:18px}.kw{color:#7dd3fc;font-weight:900}.str{color:#fde68a}.num{color:#c4b5fd}.com{color:#94a3b8;font-style:italic}.type{color:#86efac;font-weight:900}.prop{color:#f0abfc}.tag{color:#67e8f9}.attr{color:#f9a8d4}.lesson{display:grid;grid-template-columns:90px 1fr auto;gap:16px;align-items:center}.badge-num{width:62px;height:62px;border-radius:20px;background:linear-gradient(135deg,var(--cyan),var(--violet));display:grid;place-items:center;font-weight:900;font-size:24px}.notice{border:1px solid rgba(56,232,166,.35);background:rgba(56,232,166,.08);color:#dfffee;border-radius:20px;padding:18px;margin:18px 0}@media(max-width:980px){.hero,.sandboxGrid,.doc-layout{grid-template-columns:1fr}.grid{grid-template-columns:1fr}.links,.navlinks{display:none}h1{font-size:52px}.logo-card img{max-height:290px}.toc{position:relative;top:0}.preview{min-height:480px}.editor{height:420px}}
@@ -0,0 +1,23 @@
1
+
2
+ const $=(s,r=document)=>r.querySelector(s);const $$=(s,r=document)=>[...r.querySelectorAll(s)];
3
+ function icon(){return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="11" height="11" rx="2"></rect><rect x="4" y="4" width="11" height="11" rx="2"></rect></svg>`}
4
+ async function copyRaw(text,btn){await navigator.clipboard.writeText(text||''); if(btn){const old=btn.innerHTML;btn.innerHTML=icon()+'Copied';setTimeout(()=>btn.innerHTML=old,900)}}
5
+ function copyEl(id,btn){copyRaw(($('#'+id)?.textContent)||($('#'+id)?.value)||'',btn)}
6
+ function escapeHtml(s){return String(s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]))}
7
+ function highlight(code,lang='ck'){let s=escapeHtml(code); if(lang==='ck'){s=s.replace(/("[^"]*")/g,'<span class="str">$1</span>').replace(/\b(app|use|style|screen|layout|title|text|button|card|type|store|task|when|otherwise|for|each|as|default|say|add|to|let|return|try|catch)\b/g,'<span class="kw">$1</span>').replace(/\b(Stack|Freeform|Grid|Dock|Text|Number|Boolean|List|Date|Task|AppStyle)\b/g,'<span class="type">$1</span>').replace(/(@pos|theme|accent|radius|spacing)\b/g,'<span class="prop">$1</span>').replace(/\b(\d+)\b/g,'<span class="num">$1</span>');}
8
+ else if(lang==='html'){s=s.replace(/(&lt;\/?[a-zA-Z0-9-]+)/g,'<span class="tag">$1</span>').replace(/([a-zA-Z-]+)=/g,'<span class="attr">$1</span>=');}
9
+ else if(['js','css','csharp','swift'].includes(lang)){s=s.replace(/("[^"]*"|'[^']*'|`[^`]*`)/g,'<span class="str">$1</span>').replace(/\b(const|let|var|function|return|class|public|sealed|new|string|object|import|struct|var|body|some|View|Button|Text|VStack|foreach|if|else|document|querySelectorAll|addEventListener)\b/g,'<span class="kw">$1</span>').replace(/\b(\d+)\b/g,'<span class="num">$1</span>').replace(/(\/\/.*)$/gm,'<span class="com">$1</span>');}
10
+ return s}
11
+ function codeViewport(id,title,code,lang){return `<div class="codeViewport"><div class="codeHeader"><span>${title}</span><button class="copyBtn copyIcon" onclick="copyRaw(document.getElementById('${id}').textContent,this)">${icon()}Copy</button></div><pre id="${id}" class="codeBlock lang-${lang}" data-raw="${escapeHtml(code)}"><code>${highlight(code,lang)}</code></pre></div>`}
12
+ function docSearch(){const q=($('#docSearch')?.value||'').toLowerCase();$$('.doc-section').forEach(sec=>sec.classList.toggle('hide',q&&!sec.innerText.toLowerCase().includes(q)));$$('.toc a').forEach(a=>{const target=$(a.getAttribute('href'));a.classList.toggle('hide',q&&!(a.innerText+' '+(target?.innerText||'')).toLowerCase().includes(q))})}
13
+ function parseCK(code){const app=(code.match(/app\s+"([^"]+)"/)||[])[1]||'ClearKrypt App';const uses=[...code.matchAll(/use\s+([a-zA-Z_][\w.]*)/g)].map(m=>m[1]);const style={theme:(code.match(/theme:\s*(\w+)/)||[])[1]||'dark',accent:(code.match(/accent:\s*(\w+)/)||[])[1]||'cyan',radius:+((code.match(/radius:\s*(\d+)/)||[])[1]||22),spacing:+((code.match(/spacing:\s*(\d+)/)||[])[1]||18)};const screen=(code.match(/screen\s+(\w+)\s*{([\s\S]*)}\s*$/)||[]);const body=screen[2]||code;const layout=(body.match(/layout\s+(Stack|Freeform|Grid|Dock)/i)||[])[1]||'Stack';const elements=[];const re=/(title|text|button)\s+"([^"]+)"(?:\s+@pos\((\d+),\s*(\d+)\))?/g;let m;while((m=re.exec(body)))elements.push({type:m[1],label:m[2],x:+(m[3]||0),y:+(m[4]||0)});const cardRe=/card\s*{([\s\S]*?)}/g;while((m=cardRe.exec(body))){const inner=m[1];const texts=[...inner.matchAll(/text\s+"([^"]+)"/g)].map(x=>x[1]);const buttons=[...inner.matchAll(/button\s+"([^"]+)"/g)].map(x=>x[1]);elements.push({type:'card',label:texts[0]||'Card',texts,buttons})}return{app,uses,style,layout,elements}}
14
+ function renderSandbox(){const ed=$('#ckEditor'),pv=$('#preview');if(!ed||!pv)return;const ir=parseCK(ed.value);pv.innerHTML='';pv.className='preview '+(ir.layout.toLowerCase()==='freeform'?'freeform':'stack');let i=0;for(const e of ir.elements){const el=document.createElement('div');el.dataset.type=e.type;el.dataset.label=e.label;if(e.type==='title'){el.className='ckEl ck-title';el.textContent=e.label}else if(e.type==='button'){el.className='ckButton';el.textContent=e.label}else if(e.type==='card'){el.className='ckEl ck-card';el.innerHTML=`<b>${escapeHtml(e.label)}</b>${(e.texts||[]).slice(1).map(t=>`<p>${escapeHtml(t)}</p>`).join('')}${(e.buttons||[]).map(b=>`<button class="ckButton">${escapeHtml(b)}</button>`).join('')}`}else{el.className='ckEl ck-text';el.textContent=e.label}if(ir.layout.toLowerCase()==='freeform'){el.classList.add('ckEl');el.style.left=(e.x||60+i*30)+'px';el.style.top=(e.y||60+i*88)+'px';makeDrag(el)}pv.appendChild(el);i++}}
15
+ function makeDrag(el){let sx,sy,ox,oy;el.onpointerdown=e=>{sx=e.clientX;sy=e.clientY;ox=parseInt(el.style.left)||0;oy=parseInt(el.style.top)||0;el.setPointerCapture(e.pointerId)};el.onpointermove=e=>{if(sx==null)return;el.style.left=Math.max(0,ox+e.clientX-sx)+'px';el.style.top=Math.max(0,oy+e.clientY-sy)+'px'};el.onpointerup=()=>{if(sx==null)return;sx=null;updateCodePositions()}}
16
+ function updateCodePositions(){const ed=$('#ckEditor');let code=ed.value;$$('#preview .ckEl,#preview .ckButton').forEach(el=>{if(!['title','text','button'].includes(el.dataset.type))return;const label=el.dataset.label.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');const type=el.dataset.type;const x=parseInt(el.style.left)||0,y=parseInt(el.style.top)||0;const r=new RegExp(`${type}\\s+"${label}"(?:\\s+@pos\\(\\d+,\\s*\\d+\\))?`);code=code.replace(r,`${type} "${el.dataset.label}" @pos(${x}, ${y})`)});ed.value=code;compileSandbox(false)}
17
+ function setLayoutMode(mode){const ed=$('#ckEditor');if(/layout\s+(Stack|Freeform|Grid|Dock)/i.test(ed.value))ed.value=ed.value.replace(/layout\s+(Stack|Freeform|Grid|Dock)/i,'layout '+mode);else ed.value=ed.value.replace(/screen\s+(\w+)\s*{/,`screen $1 {\n layout ${mode}`);compileSandbox()}
18
+ function safeName(s){return(s||'App').replace(/[^A-Za-z0-9]/g,'')||'App'}
19
+ function emitTargets(ir){const els=ir.elements.filter(e=>e.type!=='card'),cards=ir.elements.filter(e=>e.type==='card');const html=`<main class="ck-app">\n <section class="ck-screen">\n${els.map(e=>e.type==='button'?` <button class="ck-button">${e.label}</button>`:` <div class="ck-${e.type}">${e.label}</div>`).join('\n')}\n${cards.map(c=>` <article class="ck-card"><p>${c.label}</p>${(c.buttons||[]).map(b=>`<button class="ck-button">${b}</button>`).join('')}</article>`).join('\n')}\n </section>\n</main>`;const css=`:root { --ck-accent: #16dcff; --ck-radius: ${ir.style.radius}px; --ck-spacing: ${ir.style.spacing}px; }\nbody { margin:0; font-family: system-ui; background:#05070d; color:white; }\n.ck-screen { display:flex; flex-direction:column; gap:var(--ck-spacing); padding:42px; }\n.ck-title { font-size:32px; font-weight:900; }\n.ck-text { color:#cbd5e1; }\n.ck-button { width:max-content; border:0; border-radius:var(--ck-radius); padding:14px 20px; background:linear-gradient(135deg,#16dcff,#3378ff,#8f45ff); color:white; font-weight:900; }\n.ck-card { border:1px solid rgba(255,255,255,.16); border-radius:var(--ck-radius); padding:20px; background:rgba(255,255,255,.08); }`;const js=`const app = ${JSON.stringify(ir,null,2)};\ndocument.querySelectorAll('.ck-button').forEach(button => {\n button.addEventListener('click', () => console.log('ClearKrypt action from', button.textContent));\n});`;const index=`<!doctype html>\n<html>\n<head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width,initial-scale=1">\n <title>${ir.app}</title>\n <link rel="stylesheet" href="style.css">\n</head>\n<body>\n${html}\n <script src="main.js"></script>\n</body>\n</html>`;const inline=`<!doctype html>\n<html>\n<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${ir.app}</title><style>${css}</style></head>\n<body>${html}<script>${js.replace(/<\//g,'<\\/')}<\/script></body>\n</html>`;const csharp=`// ClearKrypt C# target sketch for .NET MAUI / Blazor\npublic sealed class ${safeName(ir.app)}App\n{\n public string Name => "${ir.app}";\n public string[] Modules => new[] { ${ir.uses.map(u=>'"'+u+'"').join(', ')} };\n\n public object Build()\n {\n return new StackLayout\n {\n Spacing = ${ir.style.spacing},\n Children =\n {\n${ir.elements.map(e=> e.type==='button'?` new Button { Text = "${e.label}" },`:` new Label { Text = "${e.label}" },`).join('\n')}\n }\n };\n }\n}`;const swift=`// ClearKrypt SwiftUI target sketch for Xcode / Apple platforms\nimport SwiftUI\n\nstruct ${safeName(ir.app)}View: View {\n var body: some View {\n VStack(alignment: .leading, spacing: ${ir.style.spacing}) {\n${ir.elements.map(e=> e.type==='button'?` Button("${e.label}") { print("ClearKrypt action") }`:` Text("${e.label}")${e.type==='title' ? '.font(.largeTitle).bold()' : ''}`).join('\n')}\n }\n .padding(32)\n }\n}`;const docs=`HTML Package emits three files together: index.html, style.css, and main.js.\n\nUse this for Cloudflare Pages, Firebase Hosting, Netlify, Vercel static deploys, or any static web host.\n\nCSS only and JS only are inspection tabs. Inline HTML is for quick demos. C# and Swift are native target sketches. Full native packaging remains a CLI build step.\n\nCLI examples:\nck build app.ck --target web --out dist/web\nck build app.ck --target phone --out dist/phone\nck build app.ck --target pc --out dist/pc\nck build-all app.ck --out dist`;return{html:{'index.html':index,'style.css':css,'main.js':js},css:{'style.css':css},js:{'main.js':js},inline:{'inline.html':inline},csharp:{'App.cs':csharp},swift:{'App.swift':swift},docs:{'TARGET_DOCS.txt':docs}}}
20
+ let currentTarget='html',currentOutputs={};function showTarget(t){currentTarget=t;$$('.target').forEach(b=>b.classList.toggle('active',b.dataset.target===t));const box=$('#outputFiles');if(!box)return;box.innerHTML='';const files=currentOutputs[t]||{};const langMap={html:'html',css:'css',js:'js',inline:'html',csharp:'csharp',swift:'swift',docs:'txt'};Object.entries(files).forEach(([name,code],i)=>{box.insertAdjacentHTML('beforeend',codeViewport('out_'+t+'_'+i,name,code,langMap[t]||'txt'))})}
21
+ function compileSandbox(rerender=true){const ed=$('#ckEditor');if(!ed)return;if(rerender)renderSandbox();const ck=$('#ckHighlighted');if(ck)ck.innerHTML='<code>'+highlight(ed.value,'ck')+'</code>';currentOutputs=emitTargets(parseCK(ed.value));showTarget(currentTarget)}
22
+ let xp=0,step=0;function choose(btn,ok){$$('.choice',btn.parentElement).forEach(b=>b.disabled=true);btn.classList.add(ok?'correct':'wrong');if(ok)xp+=10;$('#xp')&&( $('#xp').innerText=xp);$('.bar')&&($('.bar').style.width=Math.min(100,xp)+'%');setTimeout(nextLesson,700)}function nextLesson(){const arr=$$('.challenge');if(!arr.length)return;arr[step]?.classList.remove('active');step=(step+1)%arr.length;arr[step].classList.add('active');$$('.choice',arr[step]).forEach(b=>{b.disabled=false;b.classList.remove('correct','wrong')})}
23
+ window.addEventListener('DOMContentLoaded',()=>{compileSandbox();$('#ckEditor')?.addEventListener('input',()=>compileSandbox());$('#docSearch')?.addEventListener('input',docSearch);$$('pre[data-lang]').forEach((p,i)=>{const raw=p.textContent.trim();const lang=p.dataset.lang||'ck';const vp=document.createElement('div');vp.innerHTML=codeViewport('doccode_'+i,p.dataset.title||lang,raw,lang);p.replaceWith(vp.firstChild)})});
Binary file
@@ -0,0 +1,8 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ClearKrypt Compiler</title><link rel="stylesheet" href="../assets/app.css"><script defer src="../assets/app.js"></script><meta name="description" content="ClearKrypt cross-platform programming language docs, compiler, sandbox, and course."></head><body><header class="top"><div class="wrap nav"><a class="brand" href="../index.html"><img src="../assets/clearkrypt-logo.png" alt="ClearKrypt logo"><span>ClearKrypt</span></a><nav class="navlinks"><a href="../sandbox/">Sandbox</a><a href="../extensions/">Extensions</a><a href="../docs/">Docs</a><a href="../compiler/">Compiler</a><a href="../course/">Course</a></nav></div></header><main class="wrap section"><h2>Compiler and VM</h2><p class="lead">ClearKrypt must compile 1-to-1 from source to supported targets without AI translation. The compiler is the contract.</p><div class="grid"><div class="card"><h3>Lexer</h3><p>Reads source text and creates tokens: identifiers, strings, numbers, braces, decorators, operators, keywords.</p><pre>app "Demo" → APP STRING</pre></div><div class="card"><h3>Parser</h3><p>Turns tokens into an AST with nodes like AppDecl, UseDecl, ModelDecl, ScreenDecl, ButtonNode.</p><pre>ScreenDecl(name: Home, body: [...])</pre></div><div class="card"><h3>Semantic checker</h3><p>Confirms modules are imported, identifiers exist, types match, and target permissions are declared.</p><pre>button requires module ui</pre></div><div class="card"><h3>IR builder</h3><p>Creates platform-neutral ClearKrypt IR so all emitters receive the same meaning.</p><pre>{ kind:"Button", action:"go" }</pre></div><div class="card"><h3>VM</h3><p>Runs IR for testing, server tasks, scripted flows, and sandbox evaluation.</p><pre>ck run app.ck</pre></div><div class="card"><h3>Emitters</h3><p>Produce Web, Worker, Phone shell, PC shell, and documentation metadata.</p><pre>ck build-all main.ck --out dist</pre></div></div><section class="section"><h2>Compiler contract</h2><pre>ClearKrypt source must be deterministic.
2
+ The same input + same compiler version = same emitted output.
3
+ No AI inference is allowed in the compiler path.
4
+ Unknown command = compile error.
5
+ Missing module = compile error.
6
+ Invalid target permission = compile error.</pre></section>
7
+ <section class="wrap section"><h2>Target emitters</h2><div class="grid"><div class="card"><h3>Web emitter</h3><p>Produces HTML, CSS, and JS bundles from the same IR tree used by the preview renderer.</p></div><div class="card"><h3>Inline emitter</h3><p>Produces one self-contained HTML file for demos, docs, and quick sharing.</p></div><div class="card"><h3>C# emitter</h3><p>Maps screens to .NET-style StackLayout, Label, Button, and future MAUI components.</p></div><div class="card"><h3>Swift emitter</h3><p>Maps screens to SwiftUI VStack, Text, Button, and native styling concepts.</p></div></div></section>
8
+ </main><footer class="footer"><div class="wrap">ClearKrypt • write once, build everywhere • crawler-ready docs for humans and AI.</div></footer></body></html>
@@ -0,0 +1,5 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ClearKrypt Course</title><link rel="stylesheet" href="../assets/app.css"><script defer src="../assets/app.js"></script><meta name="description" content="ClearKrypt cross-platform programming language docs, compiler, sandbox, and course."></head><body><header class="top"><div class="wrap nav"><a class="brand" href="../index.html"><img src="../assets/clearkrypt-logo.png" alt="ClearKrypt logo"><span>ClearKrypt</span></a><nav class="navlinks"><a href="../sandbox/">Sandbox</a><a href="../extensions/">Extensions</a><a href="../docs/">Docs</a><a href="../compiler/">Compiler</a><a href="../course/">Course</a></nav></div></header><main class="wrap section"><h2>ClearKrypt Academy</h2><p class="lead">A visual, interactive beginner course. Earn XP by identifying commands, choosing modules, and fixing tiny apps.</p><div class="progress"><div class="bar"></div></div><p><b>XP:</b> <span id="xp">0</span></p><div class="lessonMap"><div class="node done" data-label="App">1</div><div class="node" data-label="Modules">2</div><div class="node" data-label="UI">3</div><div class="node" data-label="Data">4</div><div class="node locked" data-label="Builds">5</div></div><section class="card challenge active"><h3>Lesson 1: What starts every ClearKrypt app?</h3><p>Pick the command that names the application.</p><button class="choice" onclick="choose(this,false)">screen "Home"</button><button class="choice" onclick="choose(this,true)">app "My App"</button><button class="choice" onclick="choose(this,false)">use ui</button></section><section class="card challenge"><h3>Lesson 2: What does <code>use ui</code> do?</h3><p>Choose the best answer.</p><button class="choice" onclick="choose(this,true)">Imports visual commands like screen, title, text, button, card, and form.</button><button class="choice" onclick="choose(this,false)">Uploads the app to the internet.</button><button class="choice" onclick="choose(this,false)">Creates a database table.</button></section><section class="card challenge"><h3>Lesson 3: Fix the app</h3><p>This app uses <code>button</code>. What module is missing?</p><pre>app "Demo"
2
+
3
+ screen Home {
4
+ button "Start" { go Dashboard }
5
+ }</pre><button class="choice" onclick="choose(this,false)">use crypto</button><button class="choice" onclick="choose(this,true)">use ui</button><button class="choice" onclick="choose(this,false)">use worker</button></section><section class="card challenge"><h3>Lesson 4: Visual layout</h3><p>Which decorator stores a drag position?</p><button class="choice" onclick="choose(this,false)">@route(Home)</button><button class="choice" onclick="choose(this,true)">@pos(40, 120)</button><button class="choice" onclick="choose(this,false)">@database</button></section><section class="section"><h2>Course path</h2><div class="grid"><div class="card"><h3>Unit 1: First app</h3><p>app, use, screen, title, text, button.</p></div><div class="card"><h3>Unit 2: Visual UI</h3><p>Cards, forms, lists, grid, stack, @pos, responsive rules.</p></div><div class="card"><h3>Unit 3: Data</h3><p>Models, collections, queries, saves, updates, validation.</p></div><div class="card"><h3>Unit 4: Auth</h3><p>Users, roles, policies, guards, sessions.</p></div><div class="card"><h3>Unit 5: Build targets</h3><p>Web, phone, PC, worker, cloud, all-platform builds.</p></div><div class="card"><h3>Unit 6: Project mission</h3><p>Build a small inventory app and export it to web and phone.</p></div></div></section></main><footer class="footer"><div class="wrap">ClearKrypt • write once, build everywhere • crawler-ready docs for humans and AI.</div></footer></body></html>
@@ -0,0 +1,69 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ClearKrypt Docs</title><link rel="stylesheet" href="../assets/app.css"><script defer src="../assets/app.js"></script></head><body><header class="top"><div class="wrap nav"><a class="brand" href="../index.html"><img src="../assets/clearkrypt-logo.png" alt="ClearKrypt logo"><span>ClearKrypt Docs</span></a><nav class="navlinks"><a href="../sandbox/">Sandbox</a><a href="../extensions/">Extensions</a><a href="../compiler/">Compiler</a><a href="../course/">Course</a></nav></div></header><div class="doc-layout"><aside class="toc"><input id="docSearch" class="search" placeholder="Search docs..."><a href="#start">Start</a><a href="#app">app</a><a href="#use">use modules</a><a href="#style">style</a><a href="#screen">screen</a><a href="#layout">layout</a><a href="#ui">UI commands</a><a href="#data">data</a><a href="#targets">targets</a><a href="#examples">examples</a></aside><main class="doc-main"><article id="start" class="doc-section"><h1>ClearKrypt from zero</h1><p>ClearKrypt is a cross-platform application language. A ClearKrypt file describes app identity, imported capability modules, data types, styles, screens, layout, and actions. The compiler turns that source into deterministic web, phone, PC, worker, C#, and Swift target output.</p><pre data-lang="ck" data-title="hello.ck">app "Hello"
2
+ use ui
3
+
4
+ screen Home {
5
+ layout Stack
6
+ title "Hello ClearKrypt"
7
+ text "This is a complete app screen."
8
+ }</pre></article><article id="app" class="doc-section"><h2>The app command</h2><p><code>app</code> names the application and creates the root compilation unit. Build targets use it for the document title, package metadata, native bundle names, and AI/crawler descriptions.</p><pre data-lang="ck" data-title="app command">app "Inventory Portal"</pre></article><article id="use" class="doc-section"><h2>The use command</h2><p><code>use</code> imports a capability module. It is not decoration. The semantic checker uses modules to know which commands are legal, which runtime bridges are needed, and which target files to emit.</p><ul><li><b>use ui</b>: screens, layout, title, text, card, list, forms, buttons.</li><li><b>use data</b>: types, stores, lists, filters, sorting, local persistence.</li><li><b>use auth</b>: users, roles, login, protected screens.</li><li><b>use network</b>: API calls, fetch, retries, offline fallbacks.</li><li><b>use storage</b>: files, uploads, downloads, cached assets.</li><li><b>use platform</b>: phone/PC/web platform features and responsive behavior.</li><li><b>use worker</b>: Cloudflare Worker/serverless handlers.</li><li><b>use crypto</b>: hashing, signing, tokens, encryption helpers.</li><li><b>use ai</b>: AI-readable app schemas and structured prompts.</li><li><b>use test</b>: fixtures, assertions, smoke tests.</li><li><b>use deploy</b>: deployment metadata and output configuration.</li></ul><pre data-lang="ck" data-title="modules">use ui
9
+ use data
10
+ use auth
11
+ use network
12
+ use platform</pre></article><article id="style" class="doc-section"><h2>Styling</h2><p>ClearKrypt styling is explicit. The compiler should not guess the full design from <code>use ui</code>. A <code>style</code> block declares theme, accent, radius, spacing, density, typography, and component behavior.</p><pre data-lang="ck" data-title="style block">style AppStyle {
13
+ theme: dark
14
+ accent: cyan
15
+ radius: 22
16
+ spacing: 18
17
+ }</pre></article><article id="screen" class="doc-section"><h2>Screens</h2><p>A screen is a visible route or page. Each screen should specify a layout so the first compile is usable without dragging.</p><pre data-lang="ck" data-title="screen">screen Home {
18
+ layout Stack
19
+ title "Dashboard"
20
+ text "Everything aligns automatically."
21
+ button "Continue" {
22
+ say "Next"
23
+ }
24
+ }</pre></article><article id="layout" class="doc-section"><h2>Layout</h2><p><b>Stack</b> is the safe default. It aligns elements in order. <b>Freeform</b> enables optional drag positioning using <code>@pos(x, y)</code>. Dragging should refine a design, not rescue broken output.</p><pre data-lang="ck" data-title="layout modes">screen Home {
25
+ layout Stack
26
+ title "Aligned automatically"
27
+ }
28
+
29
+ screen DesignCanvas {
30
+ layout Freeform
31
+ title "Drag me" @pos(80, 70)
32
+ }</pre></article><article id="ui" class="doc-section"><h2>UI commands</h2><p>Core UI commands include <code>title</code>, <code>text</code>, <code>button</code>, <code>card</code>, <code>list</code>, <code>form</code>, <code>input</code>, <code>toggle</code>, <code>badge</code>, and <code>chart</code>. The current sandbox demonstrates the first set and the compiler package is designed to expand command support target-by-target.</p><pre data-lang="ck" data-title="ui commands">card {
33
+ text "Open work orders"
34
+ button "View" {
35
+ say "Opening"
36
+ }
37
+ }</pre></article><article id="data" class="doc-section"><h2>Data and stores</h2><p>Types define structure. Stores define persistence. Local stores compile to browser storage on web, local files or embedded databases on PC, and native storage bridges on phone.</p><pre data-lang="ck" data-title="data model">type Task {
38
+ id: Text
39
+ title: Text
40
+ done: Boolean
41
+ }
42
+
43
+ store local tasks as List&lt;Task&gt; default []</pre></article><article id="targets" class="doc-section"><h2>Compiler targets</h2><p>The online sandbox exposes web package, CSS, JS, inline HTML, C#, and SwiftUI views. The CLI also emits phone, PC, worker, and full web folders.</p><pre data-lang="js" data-title="CLI builds">ck build app.ck --target web --out dist/web
44
+ ck build app.ck --target phone --out dist/phone
45
+ ck build app.ck --target pc --out dist/pc
46
+ ck build-all app.ck --out dist</pre></article><article id="examples" class="doc-section"><h2>Complete light app</h2><pre data-lang="ck" data-title="complete app">app "ClearKrypt Test App"
47
+ use ui
48
+ use data
49
+ use platform
50
+
51
+ style AppStyle {
52
+ theme: dark
53
+ accent: cyan
54
+ radius: 22
55
+ spacing: 18
56
+ }
57
+
58
+ screen Home {
59
+ layout Stack
60
+ title "ClearKrypt Test App"
61
+ text "A simple app with clean automatic layout."
62
+ button "Add Test Task" {
63
+ say "Task added"
64
+ }
65
+ card {
66
+ text "First task card"
67
+ button "Open"
68
+ }
69
+ }</pre></article></main></div><footer class="footer">ClearKrypt docs are designed for brand-new users and AI crawlers.</footer></body></html>
@@ -0,0 +1,31 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ClearKrypt Extensions</title><link rel="stylesheet" href="../assets/app.css"><script defer src="../assets/app.js"></script><meta name="description" content="ClearKrypt cross-platform programming language docs, compiler, sandbox, and course."></head><body><header class="top"><div class="wrap nav"><a class="brand" href="../index.html"><img src="../assets/clearkrypt-logo.png" alt="ClearKrypt logo"><span>ClearKrypt</span></a><nav class="navlinks"><a href="../sandbox/">Sandbox</a><a href="../extensions/">Extensions</a><a href="../docs/">Docs</a><a href="../compiler/">Compiler</a><a href="../course/">Course</a></nav></div></header><main class="wrap section"><h2>Extensions</h2><p class="lead">Extensions are explicit capability modules. You import them with <code>use moduleName</code>. The compiler then knows which commands, APIs, permissions, and build outputs are legal.</p><div class="grid"><a class="card" href="#ui-kit"><h3>UI Kit</h3><p>Cards, shells, forms, lists, charts, maps, gestures, motion, themes, and accessibility primitives.</p><span class="pill">Open details</span></a><a class="card" href="#firebase"><h3>Firebase Adapter</h3><p>Auth, Firestore, Storage, Functions, rules, indexes, seed workflows, and emulator mapping.</p><span class="pill">Open details</span></a><a class="card" href="#cloudflare"><h3>Cloudflare Adapter</h3><p>Pages, Workers, KV, R2, D1, Queues, Durable Objects, cron triggers, and edge routing.</p><span class="pill">Open details</span></a><a class="card" href="#phone"><h3>Phone Exporter</h3><p>Capacitor/React Native style mobile wrapper, native bridge, camera, location, push, files, and offline cache.</p><span class="pill">Open details</span></a><a class="card" href="#pc"><h3>PC Exporter</h3><p>Desktop shell, local file access, tray apps, offline-first sync, local database, and auto-update hooks.</p><span class="pill">Open details</span></a><a class="card" href="#ai"><h3>AI Templates</h3><p>Crawler-readable app templates and rules so AI tools can generate valid ClearKrypt without guessing.</p><span class="pill">Open details</span></a></div><section class="section"><h2>Extension details</h2><div class="grid"><article id="ui-kit" class="card"><h3>UI Kit</h3><p>Adds commands for visual app composition: screen, shell, card, form, input, table, chart, map, modal, drawer, tabs, route, animation, and @pos metadata.</p><pre>use ui
2
+
3
+ config ui {
4
+ enabled: true
5
+ target: "all"
6
+ }</pre></article><article id="firebase" class="card"><h3>Firebase Adapter</h3><p>Compiles data/auth/storage/task declarations to Firebase-ready project structures and security-rule hints.</p><pre>use firebase
7
+
8
+ config firebase {
9
+ enabled: true
10
+ target: "all"
11
+ }</pre></article><article id="cloudflare" class="card"><h3>Cloudflare Adapter</h3><p>Compiles service and endpoint blocks to Worker handlers and Pages assets.</p><pre>use cloudflare
12
+
13
+ config cloudflare {
14
+ enabled: true
15
+ target: "all"
16
+ }</pre></article><article id="phone" class="card"><h3>Phone Exporter</h3><p>Packages the web bundle for phone targets and maps native commands through platform bridges.</p><pre>use phone
17
+
18
+ config phone {
19
+ enabled: true
20
+ target: "all"
21
+ }</pre></article><article id="pc" class="card"><h3>PC Exporter</h3><p>Packages desktop targets with local storage, files, menus, tray, and offline sync patterns.</p><pre>use pc
22
+
23
+ config pc {
24
+ enabled: true
25
+ target: "all"
26
+ }</pre></article><article id="ai" class="card"><h3>AI Templates</h3><p>Provides llms.txt, schema JSON, examples, and grammar summaries so AI assistants can create ClearKrypt apps.</p><pre>use ai
27
+
28
+ config ai {
29
+ enabled: true
30
+ target: "all"
31
+ }</pre></article></div></section></main><footer class="footer"><div class="wrap">ClearKrypt • write once, build everywhere • crawler-ready docs for humans and AI.</div></footer></body></html>
@@ -0,0 +1,19 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ClearKrypt Language</title><link rel="stylesheet" href="assets/app.css"><script defer src="assets/app.js"></script><meta name="description" content="ClearKrypt cross-platform programming language docs, compiler, sandbox, and course."></head><body><header class="top"><div class="wrap nav"><a class="brand" href="index.html"><img src="assets/clearkrypt-logo.png" alt="ClearKrypt logo"><span>ClearKrypt</span></a><nav class="navlinks"><a href="sandbox/">Sandbox</a><a href="extensions/">Extensions</a><a href="docs/">Docs</a><a href="compiler/">Compiler</a><a href="course/">Course</a></nav></div></header><main class="wrap hero"><section><div class="eyebrow">New language • real compiler package • visual layout metadata</div><h1>A cross-platform language designed to be understood on day one.</h1><p class="lead">ClearKrypt is a Dart-like, export-anywhere language concept with explicit modules, a VM/IR pipeline, visual UI metadata, searchable docs, and a browser sandbox that teaches code and layout together.</p><div class="toolbar"><a class="btn primary" href="sandbox/">Open Sandbox</a><a class="btn" href="docs/">Read Docs</a><a class="btn orange" href="course/">Start Course</a></div></section><aside class="heroLogo"><img src="assets/clearkrypt-logo.png" alt="ClearKrypt logo"></aside></main><section class="wrap section"><h2>What is included</h2><div class="grid"><div class="card"><h3>Language</h3><p>Apps, modules, types, screens, state, tasks, services, storage, auth, routes, layout, events, and native bridges.</p></div><div class="card"><h3>Compiler + VM</h3><p>Lexer, parser, semantic checker, IR, VM runtime, and deterministic exports for web, worker, phone, and PC shells.</p></div><div class="card"><h3>Visual workflow</h3><p>Drag elements in the sandbox and ClearKrypt writes back stable <code>@pos(x, y)</code> metadata.</p></div></div></section><section class="wrap section"><h2>ClearKrypt in one glance</h2><div class="split"><pre id="homecode">app "Inventory"
2
+ use ui
3
+ use data
4
+ use auth
5
+ use platform
6
+
7
+ model Item {
8
+ id: Text
9
+ name: Text
10
+ count: Number
11
+ }
12
+
13
+ screen Home {
14
+ title "Inventory" @pos(40, 36)
15
+ text "Live stock count" @pos(40, 98)
16
+ button "Add Item" @pos(40, 160) {
17
+ go AddItem
18
+ }
19
+ }</pre><div class="card"><h3>What does <code>use ui</code> mean?</h3><p>It imports the UI standard module. Without it, commands like <code>screen</code>, <code>title</code>, <code>text</code>, <code>button</code>, <code>card</code>, <code>list</code>, and layout decorators are unavailable. ClearKrypt keeps modules explicit so AI, humans, and compilers know exactly which capabilities the app uses.</p><a class="btn primary" href="docs/#modules">See all modules</a></div></div></section><footer class="footer"><div class="wrap">ClearKrypt • write once, build everywhere • crawler-ready docs for humans and AI.</div></footer></body></html>
package/site/llms.txt ADDED
@@ -0,0 +1,2 @@
1
+ # ClearKrypt
2
+ ClearKrypt is a cross-platform programming language. Start with /docs/ for syntax, modules, UI, data, auth, platform APIs, compiler, build targets, and examples. Important modules: ui, data, auth, network, storage, platform, worker, crypto, ai, test, deploy. ClearKrypt uses app "Name", use module, model, screen, task, endpoint, and target blocks. UI position metadata uses @pos(x, y).
@@ -0,0 +1,3 @@
1
+ User-agent: *
2
+ Allow: /
3
+ Sitemap: https://clearkrypt.clearkey.solutions/sitemap.xml
@@ -0,0 +1,24 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ClearKrypt Sandbox</title><link rel="stylesheet" href="../assets/app.css"><script defer src="../assets/app.js"></script></head><body><header class="top"><div class="wrap nav"><a class="brand" href="../index.html"><img src="../assets/clearkrypt-logo.png" alt="ClearKrypt logo"><span>ClearKrypt Sandbox</span></a><nav class="navlinks"><a href="../index.html">Home</a><a href="../extensions/">Extensions</a><a href="../docs/">Docs</a><a href="../compiler/">Compiler</a><a href="../course/">Course</a></nav></div></header><main class="sandboxPage"><span class="eyebrow"><span class="dot"></span> Live compiler preview</span><h2>Write ClearKrypt. Preview it. Export real target code.</h2><p class="lead">The left side is ClearKrypt source. The right side is the visual preview. The output section below always renders code viewports with copy buttons and syntax coloring.</p><div class="toolbar"><button class="primary" onclick="compileSandbox()">Compile</button><button onclick="setLayoutMode('Stack')">Stack layout</button><button onclick="setLayoutMode('Freeform')">Freeform + drag</button><button class="copyBtn copyIcon" onclick="copyEl('ckEditor',this)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="11" height="11" rx="2"></rect><rect x="4" y="4" width="11" height="11" rx="2"></rect></svg>Copy ClearKrypt</button></div><div class="sandboxGrid"><section class="panel"><div class="panelHead"><span>main.ck editor</span></div><textarea id="ckEditor" class="editor" spellcheck="false">app "Light Test"
2
+ use ui
3
+ use data
4
+ use platform
5
+
6
+ style AppStyle {
7
+ theme: dark
8
+ accent: cyan
9
+ radius: 22
10
+ spacing: 18
11
+ }
12
+
13
+ screen Home {
14
+ layout Stack
15
+ title "ClearKrypt Test App"
16
+ text "Stack layout aligns this automatically. Dragging is optional."
17
+ button "Add Test Task" {
18
+ say "Task added"
19
+ }
20
+ card {
21
+ text "First clean card"
22
+ button "Open"
23
+ }
24
+ }</textarea></section><section class="panel"><div class="panelHead"><span>Visual preview</span><span>drag only in Freeform</span></div><div id="preview" class="preview"></div></section></div><section class="section"><h2>Target outputs</h2><p class="lead">Selecting <b>HTML Package</b> shows all applicable web files together: <b>index.html</b>, <b>style.css</b>, and <b>main.js</b>. CSS/JS tabs are separate inspection views.</p><div class="targetTabs"><button class="target active" data-target="html" onclick="showTarget('html')">HTML Package</button><button class="target" data-target="css" onclick="showTarget('css')">CSS only</button><button class="target" data-target="js" onclick="showTarget('js')">JS only</button><button class="target" data-target="inline" onclick="showTarget('inline')">Inline HTML</button><button class="target" data-target="csharp" onclick="showTarget('csharp')">C#</button><button class="target" data-target="swift" onclick="showTarget('swift')">SwiftUI</button><button class="target" data-target="docs" onclick="showTarget('docs')">Target Docs</button></div><div id="outputFiles" class="exportGrid"></div></section><section class="section"><h2>Syntax-colored ClearKrypt source</h2><div class="codeViewport"><div class="codeHeader"><span>main.ck highlighted</span><button class="copyBtn copyIcon" onclick="copyEl('ckEditor',this)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="11" height="11" rx="2"></rect><rect x="4" y="4" width="11" height="11" rx="2"></rect></svg>Copy</button></div><pre id="ckHighlighted" class="codeBlock"></pre></div></section></main><footer class="footer"><div class="wrap">ClearKrypt • deterministic target emitters • HTML package, CSS, JS, inline HTML, C#, SwiftUI, phone, PC, worker.</div></footer></body></html>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>https://clearkrypt.clearkey.solutions/</loc></url><url><loc>https://clearkrypt.clearkey.solutions/docs/</loc></url><url><loc>https://clearkrypt.clearkey.solutions/sandbox/</loc></url><url><loc>https://clearkrypt.clearkey.solutions/extensions/</loc></url><url><loc>https://clearkrypt.clearkey.solutions/compiler/</loc></url><url><loc>https://clearkrypt.clearkey.solutions/course/</loc></url></urlset>
package/sitemap.xml ADDED
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url><loc>/docs/LANGUAGE_SPEC.md</loc></url>
4
+ <url><loc>/docs/STDLIB.md</loc></url>
5
+ <url><loc>/docs/PLATFORM_TARGETS.md</loc></url>
6
+ <url><loc>/docs/VISUAL_STUDIO.md</loc></url>
7
+ <url><loc>/docs/AI_CRAWLER_GUIDE.md</loc></url>
8
+ <url><loc>/llms.txt</loc></url>
9
+ </urlset>
package/src/index.js ADDED
@@ -0,0 +1,55 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { lex } from './lexer.js';
4
+ import { parse } from './parser.js';
5
+ import { analyze } from './semantic.js';
6
+ import { emitJS } from './targets/js.js';
7
+ import { emitWeb } from './targets/web.js';
8
+ import { emitWorker } from './targets/worker.js';
9
+ import { emitPhone } from './targets/phone.js';
10
+ import { emitPC } from './targets/pc.js';
11
+ import { emitProject } from './targets/project.js';
12
+ import { emitVM } from './targets/vmbytecode.js';
13
+ import { CKVM } from './vm.js';
14
+
15
+ export async function compileSource(source, opts={}){
16
+ const tokens = lex(source);
17
+ const ast = parse(tokens);
18
+ const checked = analyze(ast);
19
+ const target = opts.target || 'vm';
20
+ if(target==='js') return emitJS(checked, opts);
21
+ if(target==='web') return emitWeb(checked, opts);
22
+ if(target==='worker') return emitWorker(checked, opts);
23
+ if(target==='phone') return emitPhone(checked, opts);
24
+ if(target==='pc') return emitPC(checked, opts);
25
+ if(target==='project') return emitProject(checked, opts);
26
+ if(target==='vm') return emitVM(checked, opts);
27
+ throw new Error(`Unknown target ${target}`);
28
+ }
29
+ export async function compileFile(file, opts={}){
30
+ if(!file) throw new Error('Missing input file');
31
+ const source = fs.readFileSync(file,'utf8');
32
+ const result = await compileSource(source, opts);
33
+ if(opts.outDir){ fs.mkdirSync(opts.outDir,{recursive:true});
34
+ const files=[];
35
+ for(const [name, content] of Object.entries(result.outputFiles || {'main.json': JSON.stringify(result,null,2)})){
36
+ const p=path.join(opts.outDir,name); fs.mkdirSync(path.dirname(p),{recursive:true}); fs.writeFileSync(p,content); files.push(p);
37
+ }
38
+ result.files=files;
39
+ }
40
+ return result;
41
+ }
42
+ export async function runFile(file){ const bc = await compileFile(file,{target:'vm'}); const vm = new CKVM(); await vm.run(bc.program); }
43
+ export function initProject(name){
44
+ fs.mkdirSync(name,{recursive:true}); fs.mkdirSync(path.join(name,'src'),{recursive:true});
45
+ fs.writeFileSync(path.join(name,'clearkrypt.json'), JSON.stringify({name, entry:'src/main.ck', targets:['web','phone','pc','worker','vm','project']}, null, 2));
46
+ fs.writeFileSync(path.join(name,'src/main.ck'), `app "${name}"
47
+
48
+ screen Home {
49
+ title "${name}"
50
+ text "Built with ClearKrypt"
51
+ button "Continue" { say "Hello from ClearKrypt" }
52
+ }
53
+ `);
54
+ console.log(`✓ Created ${name}`);
55
+ }
package/src/lexer.js ADDED
@@ -0,0 +1,18 @@
1
+ const KEYWORDS = new Set(['app','use','type','screen','task','intent','let','const','return','when','otherwise','for','each','in','is','not','and','or','true','false','null','say','print','save','to','from','where','sort','desc','asc','show','as','go','with','button','card','text','title','data','watch','changes','changed','notify','users','all','role','import','export','enum','match','case','default','try','catch','throw','require','async','await','layout','theme','section','row','column','input','toggle','list','grid','nav','image','spacer','store','local','default','add']);
2
+ export function lex(src){
3
+ const t=[]; let i=0,line=1,col=1;
4
+ const push=(type,value)=>t.push({type,value,line,col});
5
+ const adv=()=>{ const c=src[i++]; if(c==='\n'){line++; col=1}else col++; return c; };
6
+ while(i<src.length){ let c=src[i];
7
+ if(/\s/.test(c)){adv(); continue;}
8
+ if(c==='/' && src[i+1]==='/'){ while(i<src.length && src[i]!='\n') adv(); continue; }
9
+ if(c==='/' && src[i+1]==='*'){ adv(); adv(); while(i<src.length && !(src[i]==='*'&&src[i+1]==='/')) adv(); adv(); adv(); continue; }
10
+ if(c==='"' || c==="'"){ const q=adv(); let s=''; while(i<src.length && src[i]!==q){ if(src[i]=='\\'){adv(); const esc=adv(); s += ({n:'\n',t:'\t',r:'\r','"':'"',"'":"'",'\\':'\\'}[esc] ?? esc); } else s+=adv(); } if(src[i]!==q) throw new Error(`Unclosed string at ${line}:${col}`); adv(); push('string',s); continue; }
11
+ if(/[0-9]/.test(c)){ let n=''; while(/[0-9.]/.test(src[i]||'')) n+=adv(); push('number', Number(n)); continue; }
12
+ if(/[A-Za-z_]/.test(c)){ let id=''; while(/[A-Za-z0-9_]/.test(src[i]||'')) id+=adv(); push(KEYWORDS.has(id)?'kw':'id',id); continue; }
13
+ const two=src.slice(i,i+2); if(['->','=>','==','!=','<=','>=','+=','-=','*=','/=','&&','||'].includes(two)){push('op',two); adv(); adv(); continue;}
14
+ if('{}()[],:.+-*/%=<>@'.includes(c)){ push('sym',adv()); continue; }
15
+ throw new Error(`Unexpected character ${c} at ${line}:${col}`);
16
+ }
17
+ t.push({type:'eof',value:'<eof>',line,col}); return t;
18
+ }
package/src/parser.js ADDED
@@ -0,0 +1,52 @@
1
+ export function parse(tokens){ let i=0; const peek=(n=0)=>tokens[i+n]; const at=(v)=>peek().value===v; const is=(type,val)=>peek().type===type && (val===undefined || peek().value===val); const take=()=>tokens[i++]; const expect=(v)=>{ if(!at(v)) throw new Error(`Expected ${v}, got ${peek().value} at ${peek().line}:${peek().col}`); return take();}; const expectType=(type)=>{ if(peek().type!==type) throw new Error(`Expected ${type}, got ${peek().value}`); return take();}; const expectName=()=>{ if(peek().type!=='id' && peek().type!=='kw') throw new Error(`Expected name, got ${peek().value}`); return take();};
2
+ const program={kind:'Program', app:null, uses:[], declarations:[]};
3
+ while(!is('eof')){
4
+ if(at('app')){take(); program.app=expectType('string').value; continue;}
5
+ if(at('use')){take(); program.uses.push(expectName().value); continue;}
6
+ if(at('type')) program.declarations.push(parseType());
7
+ else if(at('store')) program.declarations.push(parseStore());
8
+ else if(at('screen')) program.declarations.push(parseScreen());
9
+ else if(at('task')) program.declarations.push(parseTask());
10
+ else if(at('intent')) program.declarations.push(parseIntent());
11
+ else program.declarations.push(parseStatement());
12
+ }
13
+ return program;
14
+ function parseType(){ expect('type'); const name=expectName().value; expect('{'); const fields=[]; while(!at('}')){ const fname=expectName().value; expect(':'); const ftype=parseTypeRef(); fields.push({name:fname,type:ftype}); if(at(',')) take(); } expect('}'); return {kind:'TypeDecl',name,fields}; }
15
+ function parseStore(){ expect('store'); let storage='memory'; if(at('local')||at('cloud')||at('session')) storage=take().value; const name=expectName().value; expect('as'); const type=parseTypeRef(); let value={kind:'Array',items:[]}; if(at('default')){take(); value=expr();} return {kind:'StoreDecl',storage,name,type,value}; }
16
+ function parseTypeRef(){ let n=expectName().value; if(at('<')){take(); const args=[]; while(!at('>')){args.push(parseTypeRef()); if(at(',')) take();} expect('>'); return {name:n,args}; } return {name:n,args:[]}; }
17
+ function block(){ expect('{'); const body=[]; while(!at('}')) body.push(parseStatement()); expect('}'); return body; }
18
+ function parseScreen(){ expect('screen'); const name=expectName().value; return {kind:'ScreenDecl',name,body:block()}; }
19
+ function parseTask(){ expect('task'); const name=expectName().value; expect('('); const params=[]; while(!at(')')){ const n=expectName().value; let type=null; if(at(':')){take(); type=parseTypeRef();} params.push({name:n,type}); if(at(',')) take(); } expect(')'); let returns=null; if(at('->')){take(); returns=parseTypeRef();} return {kind:'TaskDecl',name,params,returns,body:block()}; }
20
+ function parseIntent(){ expect('intent'); const name=expectType('string').value; return {kind:'IntentDecl',name,body:block()}; }
21
+ function parseMeta(){ const meta={}; while(at('@')){ take(); const name=expectName().value; if(at('(')){ take(); const args=[]; while(!at(')')){ args.push(expr()); if(at(',')) take(); } expect(')'); meta[name]=args; } else meta[name]=true; } return meta; }
22
+ function parseStatement(){
23
+ if(at('let')||at('const')){ const constant=at('const'); take(); const name=expectName().value; let type=null; if(at(':')){take(); type=parseTypeRef();} expect('='); const value=expr(); return {kind:'VarStmt',constant,name,type,value}; }
24
+ if(at('layout')){take(); const mode=expectName().value; const meta=parseMeta(); return {kind:'LayoutStmt',mode,meta};}
25
+ if(at('theme')){take(); const value=expr(); return {kind:'ThemeStmt',value};}
26
+ if(at('return')){take(); return {kind:'ReturnStmt',value: at('}')?null:expr()};}
27
+ if(at('say')||at('print')){ const k=take().value; return {kind:'PrintStmt',mode:k,value:expr()};}
28
+ if(at('title')||at('text')){ const k=take().value; const value=expr(); const meta=parseMeta(); return {kind:'UIStmt',ui:k,value,meta};}
29
+ if(at('button')){take(); const label=expr(); const meta=parseMeta(); return {kind:'ButtonStmt',label,meta,body:block()};}
30
+ if(at('card')){take(); const meta=parseMeta(); return {kind:'CardStmt',meta,body:block()};}
31
+ if(at('section')||at('row')||at('column')){ const ui=take().value; const meta=parseMeta(); return {kind:'ContainerStmt',ui,meta,body:block()};}
32
+ if(at('spacer')){take(); const size= is('number') ? {kind:'Literal',value:take().value} : {kind:'Literal',value:16}; return {kind:'SpacerStmt',size};}
33
+ if(at('list')){take(); const source=expr(); expect('as'); const item=expectName().value; const meta=parseMeta(); return {kind:'ListStmt',source,item,meta,body:block()};}
34
+ if(at('toggle')){take(); const value=expr(); const meta=parseMeta(); return {kind:'ToggleStmt',value,meta};}
35
+ if(at('input')){take(); const label=expr(); let bind=null; if(at('bind')){take(); bind=expr();} const meta=parseMeta(); return {kind:'InputStmt',label,bind,meta};}
36
+ if(at('add')){take(); let type=null; if(is('id')||is('kw')) type=take().value; const value=parseObjectLiteral(); expect('to'); const target=expectName().value; return {kind:'AddStmt',type,value,target};}
37
+ if(at('show')){take(); return {kind:'ShowStmt',value:expr(),body: at('{')?block():[]};}
38
+ if(at('go')){take(); const target=expectName().value; let value=null; if(at('with')){take(); value=expr();} return {kind:'GoStmt',target,value};}
39
+ if(at('when')){take(); const condition=expr(); const body=block(); let otherwise=[]; if(at('otherwise')){take(); otherwise=block();} return {kind:'WhenStmt',condition,body,otherwise};}
40
+ if(at('for')){take(); expect('each'); const item=expectName().value; expect('in'); const iterable=expr(); return {kind:'ForStmt',item,iterable,body:block()};}
41
+ if(at('require')){take(); return {kind:'RequireStmt',condition:expr()};}
42
+ const e=expr(); return {kind:'ExprStmt',value:e};
43
+ }
44
+ function parseObjectLiteral(){ expect('{'); const props=[]; while(!at('}')){ const k=expectName().value; expect(':'); props.push({key:k,value:expr()}); if(at(',')) take(); } expect('}'); return {kind:'Object',props}; }
45
+ function expr(){ return logic(); }
46
+ function logic(){ let e=compare(); while(at('and')||at('or')||at('&&')||at('||')){ const op=take().value; e={kind:'Binary',op,left:e,right:compare()}; } return e; }
47
+ function compare(){ let e=term(); while(['is','==','!=','<','>','<=','>='].includes(peek().value)){ let op=take().value; if(op==='is' && at('not')){take(); op='is not';} e={kind:'Binary',op,left:e,right:term()}; } return e; }
48
+ function term(){ let e=factor(); while(at('+')||at('-')){ const op=take().value; e={kind:'Binary',op,left:e,right:factor()}; } return e; }
49
+ function factor(){ let e=call(); while(at('*')||at('/')||at('%')){ const op=take().value; e={kind:'Binary',op,left:e,right:call()}; } return e; }
50
+ function call(){ let e=primary(); while(true){ if(at('(')){take(); const args=[]; while(!at(')')){args.push(expr()); if(at(',')) take();} expect(')'); e={kind:'Call',callee:e,args};} else if(at('.')){take(); e={kind:'Member',object:e,property:expectName().value};} else break;} return e; }
51
+ function primary(){ if(is('string')||is('number')) return {kind:'Literal',value:take().value}; if(at('true')||at('false')) return {kind:'Literal',value:take().value==='true'}; if(at('null')){take(); return {kind:'Literal',value:null};} if(is('id') || (is('kw') && !['true','false','null'].includes(peek().value))) return {kind:'Identifier',name:take().value}; if(at('[')){take(); const items=[]; while(!at(']')){ if((is('id')||is('kw')) && peek(1).value==='{'){ const type=take().value; const obj=parseObjectLiteral(); obj.typedAs=type; items.push(obj);} else { items.push(expr()); } if(at(',')) take();} expect(']'); return {kind:'Array',items};} if(at('{')) return parseObjectLiteral(); if(at('(')){take(); const e=expr(); expect(')'); return e;} throw new Error(`Expected expression, got ${peek().value}`); }
52
+ }
@@ -0,0 +1,5 @@
1
+ export function analyze(ast){
2
+ const names = new Set();
3
+ for(const d of ast.declarations){ if(d.name){ if(names.has(d.name)) throw new Error(`Duplicate declaration ${d.name}`); names.add(d.name); } }
4
+ return {...ast, meta:{name: ast.app || 'ClearKryptApp', checkedAt:new Date().toISOString()}};
5
+ }