let WebR=null;let webR=null;let webRReady=false;let webRLoading=false;let shelter=null;const editors=[];let pendingRunBtn=null;const _editorIndexMap=new WeakMap();const banner=document.querySelector('.webr-loading-banner');async function loadAndInitWebR(){if(webRReady)return true;if(webRLoading)return false;webRLoading=true;if(banner){banner.textContent='\u23f3 Loading R environment (first run only)...';banner.classList.remove('hidden','ready');banner.style.maxHeight='50px';banner.style.padding='8px 16px';banner.style.margin='0 0 8px 0';banner.style.opacity='1';}
try{const mod=await import('https://webr.r-wasm.org/latest/webr.mjs');WebR=mod.WebR;webR=new WebR();await webR.init();shelter=await new webR.Shelter();webRReady=true;if(banner){banner.textContent='\u2705 R environment ready! Click Run or press Ctrl+Enter.';banner.classList.add('ready');setTimeout(()=>{banner.classList.add('hidden');},2500);}
document.querySelectorAll('.webr-run-btn').forEach(btn=>{btn.disabled=false;setRunBtnText(btn,'\u25b6 Run');});const contentEl=document.getElementById('content');const engHeader=contentEl.querySelector('.engagement-header');const runBtn=document.createElement('button');runBtn.className='webr-runall-btn';runBtn.onclick=function(){window.runAllWebR(this);};runBtn.textContent='\u25b6 Run All';if(engHeader){const wrapper=document.createElement('span');wrapper.className='webr-runall-inline';const dot=document.createElement('span');dot.className='engagement-meta-dot';dot.innerHTML='·';const label=document.createElement('span');label.className='webr-runall-label';label.textContent='R Ready';wrapper.appendChild(dot);wrapper.appendChild(label);wrapper.appendChild(runBtn);engHeader.appendChild(wrapper);requestAnimationFrame(()=>{wrapper.classList.add('visible');});}else{const firstH1=contentEl.querySelector('h1');const runAllBar=document.createElement('div');runAllBar.className='webr-runall-bar';runAllBar.innerHTML='R environment ready';runAllBar.appendChild(runBtn);if(firstH1&&firstH1.nextSibling){firstH1.parentNode.insertBefore(runAllBar,firstH1.nextSibling);}else{contentEl.insertBefore(runAllBar,contentEl.firstChild);}
requestAnimationFrame(()=>{runAllBar.classList.add('visible');});}
if(typeof gtag==='function'){gtag('event','webr_ready',{event_category:'WebR',event_label:document.title,code_block_count:document.querySelectorAll('.webr-container').length});}
return true;}catch(e){webRLoading=false;if(banner){banner.textContent='Failed to load R: '+e.message;banner.style.background='#fee2e2';banner.style.color='#991b1b';}
return false;}}
if(banner){banner.textContent='\u25b6 Click Run on any code block to start the R environment';banner.style.background='#f8fafb';banner.style.color='#656d76';banner.style.borderColor='#e1e4e8';}
(function(){const AD_TAGS={INS:1,IFRAME:1};const AD_PATTERN=/ezoic|ezojs|ezmob|adsbygoogle|google_ads|pagead|dfp-ad|gpt-ad/i;function isAdNode(n){if(!n||n.nodeType!==1)return false;if(AD_TAGS[n.tagName])return true;const cls=(typeof n.className==='string')?n.className:'';if(AD_PATTERN.test(cls))return true;if(n.id&&AD_PATTERN.test(n.id))return true;return false;}
function scrub(root){if(!root||!root.querySelectorAll)return;root.querySelectorAll('.webr-container ins, .webr-container iframe').forEach(el=>{try{el.remove();}catch(e){}});root.querySelectorAll('.webr-container [class*="ezoic"], .webr-container [id*="ezoic"], .webr-container [class*="adsbygoogle"]').forEach(el=>{try{el.remove();}catch(e){}});}
scrub(document);const adObs=new MutationObserver((mutations)=>{for(let i=0;i{try{el.remove();}catch(e){}});}}}}});document.querySelectorAll('.webr-container').forEach(c=>{adObs.observe(c,{childList:true,subtree:true});});})();const copyIcon='';const checkIcon='';const _allContainers=document.querySelectorAll('.webr-container');if(_allContainers[0])_allContainers[0].classList.add('engagement-unrun-first');document.addEventListener('click',function(e){const btn=e.target&&e.target.closest?e.target.closest('.webr-run-btn'):null;if(!btn)return;document.querySelectorAll('.webr-container.engagement-unrun-first').forEach(el=>el.classList.remove('engagement-unrun-first'));},true);function _attachCopyHandler(copyBtn){copyBtn.onclick=function(){const c=this.closest('.webr-container');const editorEl=c.querySelector('.webr-editor');const idx=_editorIndexMap.get(editorEl);const entry=editors[idx];const code=(entry&&entry.jar)?entry.jar.toString():editorEl.textContent;navigator.clipboard.writeText(code).then(()=>{copyBtn.innerHTML=checkIcon;copyBtn.classList.add('copied');setTimeout(()=>{copyBtn.innerHTML=copyIcon;copyBtn.classList.remove('copied');},1500);});};}
_allContainers.forEach(container=>{const codeBlock=container.querySelector('.webr-code-block');if(!codeBlock)return;if(codeBlock.querySelector('.webr-header')){const existingCopy=codeBlock.querySelector('.webr-copy-btn');if(existingCopy)_attachCopyHandler(existingCopy);return;}
const header=document.createElement('div');header.className='webr-header';const left=document.createElement('div');left.className='webr-header-left';const _titleText=container.getAttribute('data-block-title')||'Interactive R';const _titleEsc=_titleText.replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"');left.innerHTML=''
+'';const right=document.createElement('div');right.className='webr-header-right';const copyBtn=document.createElement('button');copyBtn.type='button';copyBtn.className='webr-copy-btn';copyBtn.setAttribute('aria-label','Copy code');copyBtn.title='Copy code';copyBtn.innerHTML=copyIcon;_attachCopyHandler(copyBtn);right.appendChild(copyBtn);const runBtn=codeBlock.querySelector('.webr-buttons .webr-run-btn');if(runBtn){runBtn.innerHTML='\u25b6 Run Ctrl+Enter';right.appendChild(runBtn);}
header.appendChild(left);header.appendChild(right);codeBlock.prepend(header);const outputEl=codeBlock.querySelector('.webr-output');if(outputEl){outputEl.setAttribute('aria-live','polite');outputEl.setAttribute('aria-atomic','false');outputEl.setAttribute('tabindex','-1');}});const allEditors=document.querySelectorAll('.webr-editor');allEditors.forEach((el,i)=>{_editorIndexMap.set(el,i);el.setAttribute('tabindex','0');el.setAttribute('role','textbox');el.setAttribute('aria-label','R code. Click or press Enter to edit.');});function _prismHighlight(el){if(!window.Prism||!window.Prism.languages||!window.Prism.languages.r){return;}
const code=el.textContent||'';const html=window.Prism.highlight(code,window.Prism.languages.r,'r');const lines=html.split('\n');el.innerHTML=lines.map(function(ln){return''+ln+'';}).join('\n');}
function _textOffsetInside(root,node,offset){if(!root.contains(node))return null;if(node.nodeType!==Node.TEXT_NODE){let total=0;const walker=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);let t;while((t=walker.nextNode())){if(node.contains(t)){const childIndex=Array.prototype.indexOf.call(node.childNodes,t);if(childIndex>=0&&childIndex=0&&caret<=code.length){try{jar.restore({start:caret,end:caret});}catch(_){}}}
document.addEventListener('click',function(e){const el=e.target&&e.target.closest?e.target.closest('.webr-editor'):null;if(!el)return;if(e.target.closest('.webr-editor-input'))return;hydrateEditor(el,e.clientX,e.clientY);},true);document.addEventListener('focusin',function(e){const el=e.target&&e.target.closest?e.target.closest('.webr-editor'):null;if(!el||el.dataset.webrHydrated)return;if(e.target.classList&&e.target.classList.contains('webr-editor-input'))return;hydrateEditor(el,null,null);},true);document.addEventListener('keydown',function(e){if(e.key!=='Enter'&&e.key!==' ')return;const el=e.target&&e.target.closest?e.target.closest('.webr-editor'):null;if(!el||el.dataset.webrHydrated)return;if(e.target.classList&&e.target.classList.contains('webr-editor-input'))return;e.preventDefault();hydrateEditor(el,null,null);},true);document.addEventListener('keydown',function(e){const target=e.target;if(!target||!target.classList||!target.classList.contains('webr-editor-input'))return;if((e.ctrlKey||e.metaKey)&&e.key==='Enter'){e.preventDefault();const container=target.closest('.webr-container');const btn=container&&container.querySelector('.webr-run-btn');if(btn&&!btn.disabled)btn.click();return;}
if(e.key==='Escape'){target.blur();}});const installedPkgs=new Set(['base','stats','graphics','grDevices','utils','datasets','methods']);async function ensurePackages(code){const libRegex=/(?:library|require)\s*\(\s*["']?([a-zA-Z0-9.]+)["']?\s*\)/g;const needed=[];let match;while((match=libRegex.exec(code))!==null){const pkg=match[1];if(!installedPkgs.has(pkg))needed.push(pkg);}
const installRegex=/install\.packages\s*\(\s*["']([a-zA-Z0-9.]+)["']\s*\)/g;while((match=installRegex.exec(code))!==null){const pkg=match[1];if(!installedPkgs.has(pkg))needed.push(pkg);}
if(needed.length>0){for(const pkg of needed){try{await webR.installPackages([pkg],{quiet:true});installedPkgs.add(pkg);}catch(e){console.warn('Failed to install '+pkg+':',e.message);}}}
return code.replace(/install\.packages\s*\([^)]+\)/g,'cat("Package already installed via WebR.\\n")');}
function setRunBtnText(btn,text){const shortcut='Ctrl+Enter';btn.innerHTML=text+' '+shortcut;}
let _firstRunDone=false;let _firstRunHint=null;let _firstRunHintShownAt=0;const _HINT_MIN_DISPLAY=2500;function removeFirstRunHint(){if(!_firstRunHint||!_firstRunHint.parentNode)return;const elapsed=Date.now()-_firstRunHintShownAt;const remaining=Math.max(0,_HINT_MIN_DISPLAY-elapsed);const h=_firstRunHint;_firstRunHint=null;setTimeout(()=>{h.classList.add('is-fading');setTimeout(()=>{if(h.parentNode)h.remove();},400);},remaining);}
window.runWebR=async function(btn){if(!_firstRunDone){_firstRunDone=true;const container=btn.closest('.webr-container');const outputEl=container.querySelector('.webr-output');if(outputEl){const hint=document.createElement('div');hint.className='webr-first-run-hint';hint.innerHTML=' Setting up R environment — first run takes a moment';outputEl.parentNode.insertBefore(hint,outputEl);_firstRunHint=hint;_firstRunHintShownAt=Date.now();setTimeout(removeFirstRunHint,15000);}}
if(!webRReady){if(webRLoading){pendingRunBtn=btn;btn.disabled=true;setRunBtnText(btn,'Loading R...');btn.classList.add('running');while(webRLoading&&!webRReady){await new Promise(r=>setTimeout(r,200));}
if(!webRReady){btn.disabled=false;setRunBtnText(btn,'\u25b6 Run');btn.classList.remove('running');return;}}else{btn.disabled=true;setRunBtnText(btn,'Loading R...');btn.classList.add('running');const ok=await loadAndInitWebR();if(!ok){btn.disabled=false;setRunBtnText(btn,'\u25b6 Run');btn.classList.remove('running');return;}}}
if(!shelter)return;const container=btn.closest('.webr-container');const editorEl=container.querySelector('.webr-editor');const outputEl=container.querySelector('.webr-output');const plotEl=container.querySelector('.webr-plot-output');const idx=_editorIndexMap.get(editorEl);const editorEntry=editors[idx];let code=(editorEntry&&editorEntry.jar)?editorEntry.jar.toString():editorEl.textContent;btn.disabled=true;setRunBtnText(btn,'Installing packages...');btn.classList.add('running');outputEl.textContent='';outputEl.classList.remove('has-content','has-error','has-message');outputEl.classList.add('is-loading');if(plotEl){plotEl.innerHTML='';plotEl.classList.remove('has-content');}
try{code=await ensurePackages(code);setRunBtnText(btn,'Running...');const result=await shelter.captureR(code,{withAutoprint:true,captureStreams:true,captureConditions:true,captureGraphics:{width:700,height:500}});let output='';if(result.output){for(const line of result.output){if(line.type==='stdout'||line.type==='stderr'){output+=line.data.endsWith('\n')?line.data:line.data+'\n';}}}
if(result.images&&result.images.length>0&&plotEl){plotEl.innerHTML='';for(const img of result.images){const canvas=document.createElement('canvas');canvas.width=img.width;canvas.height=img.height;canvas.style.maxWidth='100%';canvas.style.height='auto';const ctx=canvas.getContext('2d');ctx.fillStyle='#ffffff';ctx.fillRect(0,0,canvas.width,canvas.height);ctx.drawImage(img,0,0);plotEl.appendChild(canvas);}
plotEl.classList.add('has-content');}
if(output.trim()){outputEl.textContent=output.trimEnd();outputEl.classList.add('has-content');}else if(!result.images||result.images.length===0){try{const val=await result.result.toString();if(val&&val.trim()){outputEl.textContent=val.trimEnd();outputEl.classList.add('has-content');}}catch(e){}}
shelter.purge();shelter=await new webR.Shelter();if(typeof gtag==='function'){gtag('event','webr_code_run',{event_category:'WebR',event_label:document.title,code_block_index:idx,has_plot:!!(result.images&&result.images.length>0)});}}catch(err){outputEl.textContent='Error: '+err.message;outputEl.classList.add('has-error');if(typeof gtag==='function'){gtag('event','webr_code_error',{event_category:'WebR',event_label:document.title,code_block_index:idx,error_message:err.message.substring(0,100)});}}
removeFirstRunHint();outputEl.classList.remove('is-loading');if(outputEl.textContent.length>0){outputEl.style.opacity='0';requestAnimationFrame(()=>{outputEl.style.opacity='1';});}
btn.disabled=false;setRunBtnText(btn,'\u25b6 Run');btn.classList.remove('running');};window.resetWebR=async function(btn){const container=btn.closest('.webr-container');const editorEl=container.querySelector('.webr-editor');const outputEl=container.querySelector('.webr-output');const plotEl=container.querySelector('.webr-plot-output');const idx=_editorIndexMap.get(editorEl);const entry=editors[idx];if(entry&&entry.jar){entry.jar.updateCode(entry.originalCode);}
outputEl.textContent='';outputEl.classList.remove('has-content','has-error','has-message','is-loading');if(plotEl){plotEl.innerHTML='';plotEl.classList.remove('has-content');}};window.runAllWebR=async function(btn){if(!webRReady){btn.disabled=true;btn.textContent='Loading R...';btn.classList.add('running');const ok=await loadAndInitWebR();if(!ok){btn.disabled=false;btn.textContent='\u25b6 Run All Code Blocks';btn.classList.remove('running');return;}}
if(typeof gtag==='function'){gtag('event','webr_run_all',{event_category:'WebR',event_label:document.title,code_block_count:document.querySelectorAll('.webr-container').length});}
const allRunBtns=[...document.querySelectorAll('.webr-run-btn')];const total=allRunBtns.length;btn.disabled=true;for(let i=0;i{btn.textContent='\u25b6 Run All';btn.disabled=false;},2000);};