@utsp/render 0.11.0-nightly.20251213152020.671c815 → 0.11.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.
- package/README.md +102 -8
- package/dist/2d/index.cjs +34 -0
- package/dist/2d/index.d.ts +907 -0
- package/dist/2d/index.mjs +34 -0
- package/dist/ansi/index.cjs +2 -0
- package/dist/ansi/index.d.ts +132 -0
- package/dist/ansi/index.mjs +2 -0
- package/dist/common/index.cjs +50 -0
- package/dist/common/index.d.ts +390 -0
- package/dist/common/index.mjs +50 -0
- package/dist/gl/index.cjs +127 -0
- package/dist/gl/index.d.ts +802 -0
- package/dist/gl/index.mjs +127 -0
- package/dist/index.cjs +10 -9
- package/dist/index.d.ts +154 -4
- package/dist/index.mjs +10 -9
- package/package.json +40 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var F=Object.defineProperty;var O=(g,t,e)=>t in g?F(g,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):g[t]=e;var f=(g,t)=>F(g,"name",{value:t,configurable:!0});var o=(g,t,e)=>(O(g,typeof t!="symbol"?t+"":t,e),e);var R=class R{constructor(t,e,i,s,a){o(this,"atlases");o(this,"charMap");o(this,"baseCharWidth");o(this,"baseCharHeight");o(this,"baseCellWidth");o(this,"baseCellHeight");o(this,"atlasColumns",16);o(this,"font");o(this,"SCALES",[1,2,4,8]);o(this,"colorCache",new Map);o(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=i,this.baseCellWidth=s??e,this.baseCellHeight=a??i,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,i]of this.font){let s=t%this.atlasColumns,a=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:s*this.baseCharWidth,y:a*this.baseCharHeight});for(let r of this.SCALES){let n=this.getOrCreateAtlas(r),h=s*n.charWidth,l=a*n.charHeight;this.renderBitmapToAtlas(n,i,h,l)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let i=this.baseCharWidth*t,s=this.baseCharHeight*t,r=Math.ceil(256/this.atlasColumns),n=document.createElement("canvas");n.width=this.atlasColumns*i,n.height=r*s;let h=n.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!h)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);h.imageSmoothingEnabled=!1,e={canvas:n,ctx:h,scale:t,charWidth:i,charHeight:s},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,i,s){let a=t.scale,r=t.ctx;r.fillStyle="#ffffff";for(let n=0;n<Math.min(e.length,this.baseCharHeight);n++){let h=e[n];for(let l=0;l<this.baseCharWidth;l++){let c=1<<7-l;h&c&&r.fillRect(i+l*a,s+n*a,a,a)}}}drawChar(t,e,i,s,a,r,n){let h=this.charMap.get(e);if(!h)return;let l=`${e}:${n}`,c=this.colorCache.get(l);if(c)c.lastUsed=performance.now();else{let v=this.createColoredGlyph(e,n,h);if(!v)return;c={canvas:v,lastUsed:performance.now()},this.colorCache.set(l,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let m=a/this.baseCellWidth,d=r/this.baseCellHeight,u=(this.baseCellWidth-this.baseCharWidth)/2*m,C=(this.baseCellHeight-this.baseCharHeight)/2*d,b=this.baseCharWidth*m,p=this.baseCharHeight*d;t.drawImage(c.canvas,i+u,s+C,b,p)}createColoredGlyph(t,e,i){let s=this.atlases.get(1);if(!s)return null;let a=s.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),r=a.data,n=this.hexToRgb(e);for(let c=0;c<r.length;c+=4)r[c+3]>0&&(r[c]=n.r,r[c+1]=n.g,r[c+2]=n.b);let h=document.createElement("canvas");h.width=this.baseCharWidth,h.height=this.baseCharHeight;let l=h.getContext("2d",{alpha:!0});return l?(l.imageSmoothingEnabled=!1,l.putImageData(a,0,0),h):null}hexToRgb(t){if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(n,h,l,c)=>h+h+l+l+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:255,g:255,b:255}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)};let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(t=1){return this.atlases.get(t)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(t){return this.charMap.has(t)}getAtlasDimensions(t=1){let e=this.atlases.get(t);if(e)return{width:e.canvas.width,height:e.canvas.height}}toDataURL(t=1,e="image/png"){return this.atlases.get(t)?.canvas.toDataURL(e)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let t of this.atlases.values())t.canvas.width=0,t.canvas.height=0;this.atlases.clear(),this.clearCache()}};f(R,"BitmapFontAtlas");var H=R;function D(g){return Math.sqrt(g)*16}f(D,"getAtlasColumns");function E(g){return g*256-1}f(E,"getMaxCharCode");function W(g,t){let e=Math.floor(g/256),i=g%256,s=Math.sqrt(t),a=e%s,r=Math.floor(e/s),n=i%16,h=Math.floor(i/16);return{col:a*16+n,row:r*16+h}}f(W,"getCharGridPosition");var A=class A{constructor(t){o(this,"atlasCanvas",null);o(this,"atlasCtx",null);o(this,"atlasImage",null);o(this,"glyphWidth");o(this,"glyphHeight");o(this,"cellWidth");o(this,"cellHeight");o(this,"atlasBlocks");o(this,"atlasColumns");o(this,"maxCharCode");o(this,"isLoaded",!1);o(this,"colorCache",new Map);o(this,"MAX_CACHE_SIZE",1024);this.glyphWidth=t.glyphWidth,this.glyphHeight=t.glyphHeight,this.cellWidth=t.cellWidth??t.glyphWidth,this.cellHeight=t.cellHeight??t.glyphHeight,this.atlasBlocks=t.atlasBlocks,this.atlasColumns=D(t.atlasBlocks),this.maxCharCode=E(t.atlasBlocks)}async loadFromPNG(t){return new Promise((e,i)=>{let s=new Uint8Array(t),a=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(a),n=new Image;n.onload=()=>{URL.revokeObjectURL(r);let h=this.atlasColumns*this.glyphWidth,l=this.atlasColumns*this.glyphHeight;if((n.width!==h||n.height!==l)&&console.warn(`ImageFontAtlas: Image size ${n.width}\xD7${n.height} doesn't match expected ${h}\xD7${l} for ${this.atlasBlocks} block(s) with ${this.glyphWidth}\xD7${this.glyphHeight} glyphs`),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=n.width,this.atlasCanvas.height=n.height,this.atlasCtx=this.atlasCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),!this.atlasCtx){i(new Error("Failed to create 2D context for atlas"));return}this.atlasCtx.imageSmoothingEnabled=!1,this.atlasCtx.drawImage(n,0,0),this.atlasImage=n,this.isLoaded=!0,e()},n.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for atlas"))},n.src=r})}isReady(){return this.isLoaded}getGlyphPosition(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=W(t,this.atlasBlocks);return{x:e*this.glyphWidth,y:i*this.glyphHeight}}getCharUV(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=W(t,this.atlasBlocks),s=e/this.atlasColumns,a=i/this.atlasColumns,r=(e+1)/this.atlasColumns,n=(i+1)/this.atlasColumns;return{u1:s,v1:a,u2:r,v2:n}}drawChar(t,e,i,s,a,r,n){if(!this.isLoaded||!this.atlasCanvas)return;let h=this.getGlyphPosition(e);if(!h)return;let l=`${e}:${n}`,c=this.colorCache.get(l);if(c)c.lastUsed=performance.now();else{let d=this.createColoredGlyph(e,n,h);if(!d)return;c={canvas:d,lastUsed:performance.now()},this.colorCache.set(l,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}if(t.imageSmoothingEnabled=!1,a===this.cellWidth&&r===this.cellHeight){let d=Math.floor((this.cellWidth-this.glyphWidth)/2),u=Math.floor((this.cellHeight-this.glyphHeight)/2);t.drawImage(c.canvas,Math.floor(i)+d,Math.floor(s)+u)}else{let d=a/this.cellWidth,u=r/this.cellHeight,C=Math.floor((this.cellWidth-this.glyphWidth)/2*d),b=Math.floor((this.cellHeight-this.glyphHeight)/2*u),p=Math.ceil(this.glyphWidth*d),v=Math.ceil(this.glyphHeight*u);t.drawImage(c.canvas,Math.floor(i)+C,Math.floor(s)+b,p,v)}}createColoredGlyph(t,e,i){if(!this.atlasCtx)return null;let s=this.atlasCtx.getImageData(i.x,i.y,this.glyphWidth,this.glyphHeight),a=s.data,r=this.parseColor(e);for(let l=0;l<a.length;l+=4)a[l+3]>0&&(a[l]=r.r,a[l+1]=r.g,a[l+2]=r.b);let n=document.createElement("canvas");n.width=this.glyphWidth,n.height=this.glyphHeight;let h=n.getContext("2d",{alpha:!0});return h?(h.putImageData(s,0,0),n):null}parseColor(t){if(t.startsWith("#")){let i=t.slice(1);return i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(t);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(){return this.atlasCanvas}getAtlasImage(){return this.atlasImage}getConfig(){return{glyphWidth:this.glyphWidth,glyphHeight:this.glyphHeight,cellWidth:this.cellWidth,cellHeight:this.cellHeight,atlasBlocks:this.atlasBlocks}}getGlyphDimensions(){return{width:this.glyphWidth,height:this.glyphHeight}}getCellDimensions(){return{width:this.cellWidth,height:this.cellHeight}}getAtlasDimensions(){return{width:this.atlasColumns*this.glyphWidth,height:this.atlasColumns*this.glyphHeight}}getAtlasColumns(){return this.atlasColumns}getMaxCharCode(){return this.maxCharCode}isValidCharCode(t){return t>=0&&t<=this.maxCharCode}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}destroy(){this.clearCache(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=null),this.atlasCtx=null,this.atlasImage=null,this.isLoaded=!1}};f(A,"ImageFontAtlas");var M=A;var I=class I{constructor(t,e){o(this,"canvas");o(this,"ctx");o(this,"container");o(this,"cols",0);o(this,"rows",0);o(this,"cellWidth",0);o(this,"cellHeight",0);o(this,"offsetX",0);o(this,"offsetY",0);o(this,"strokeColor","rgba(80, 80, 80, 0.4)");o(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let i=e?.zIndex??10;this.canvas.style.cssText=`
|
|
2
|
+
display: block !important;
|
|
3
|
+
position: absolute !important;
|
|
4
|
+
pointer-events: none !important;
|
|
5
|
+
image-rendering: pixelated !important;
|
|
6
|
+
image-rendering: crisp-edges !important;
|
|
7
|
+
z-index: ${i} !important;
|
|
8
|
+
`,this.container.appendChild(this.canvas);let s=this.canvas.getContext("2d");if(!s)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=s,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth))}setDimensions(t,e,i,s,a=0,r=0){this.cols=t,this.rows=e,this.cellWidth=i,this.cellHeight=s,this.offsetX=a,this.offsetY=r}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,i,s,a){let r=s.left-a.left,n=s.top-a.top,h=s.width,l=s.height;(this.canvas.width!==h||this.canvas.height!==l)&&(this.canvas.width=h,this.canvas.height=l);let c=this.canvas.style;c.width=`${h}px`,c.height=`${l}px`,c.left=`${r}px`,c.top=`${n}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=t>0?this.canvas.width/t:1,s=e>0?this.canvas.height/e:1,a=Math.min(i,s),r=this.cellWidth*a,n=this.cellHeight*a,h=this.cols*r,l=this.rows*n,c=this.offsetX*a,m=this.offsetY*a;if(!(h===0||l===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*a),this.ctx.beginPath();for(let d=0;d<=this.cols;d++){let u=c+d*r+.5;this.ctx.moveTo(u,m),this.ctx.lineTo(u,m+l)}for(let d=0;d<=this.rows;d++){let u=m+d*n+.5;this.ctx.moveTo(c,u),this.ctx.lineTo(c+h,u)}this.ctx.stroke()}}update(t,e,i,s,a,r,n=0,h=0){this.setDimensions(t,e,i,s,n,h),this.setCanvasSize(a,r),this.render()}setVisible(t){this.canvas.style.display=t?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};f(I,"GridOverlay");var w=I;import{ScalingMode as x}from"@utsp/types";var B=class B{constructor(t,e={}){o(this,"containerDiv");o(this,"canvas");o(this,"ctx");o(this,"parentElement");o(this,"cells");o(this,"cols",0);o(this,"rows",0);o(this,"fontSize");o(this,"fontFamily");o(this,"defaultFgColor");o(this,"defaultBgColor");o(this,"canvasBgColor");o(this,"cellWidth");o(this,"cellHeight");o(this,"offsetX",0);o(this,"offsetY",0);o(this,"fontType","web");o(this,"bitmapFont");o(this,"bitmapAtlas");o(this,"imageAtlas");o(this,"bitmapCharWidth",8);o(this,"bitmapCharHeight",8);o(this,"showDebugGrid");o(this,"debugGridColor");o(this,"gridOverlay");o(this,"fixedGridMode");o(this,"fixedCols");o(this,"fixedRows");o(this,"cellAspectRatio");o(this,"resizeObserver");o(this,"imageDataBuffer");o(this,"useImageDataRendering",!1);o(this,"paletteCache");o(this,"scalingMode",x.None);o(this,"currentScale",1);if(!t)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=t,this.fixedGridMode=!!(e.fixedCols&&e.fixedRows),this.fixedCols=e.fixedCols,this.fixedRows=e.fixedRows,this.cellAspectRatio=e.cellAspectRatio??10/14,this.cellWidth=e.cellWidth??10,this.cellHeight=e.cellHeight??14,this.fontSize=e.fontSize??12,this.fontFamily=e.fontFamily??"monospace",this.defaultFgColor=e.defaultFgColor??"#ffffff",this.defaultBgColor=e.defaultBgColor??"#000000",this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showDebugGrid=e.showDebugGrid??!1,this.debugGridColor=e.debugGridColor??"rgba(144, 24, 24, 1)",this.scalingMode=e.scalingMode??x.None,window.getComputedStyle(this.parentElement).position==="static"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminal2d-container",this.containerDiv.style.cssText=`
|
|
9
|
+
position: absolute !important;
|
|
10
|
+
top: 0 !important;
|
|
11
|
+
left: 0 !important;
|
|
12
|
+
right: 0 !important;
|
|
13
|
+
bottom: 0 !important;
|
|
14
|
+
width: 100% !important;
|
|
15
|
+
height: 100% !important;
|
|
16
|
+
overflow: visible !important;
|
|
17
|
+
contain: layout style !important;
|
|
18
|
+
display: flex !important;
|
|
19
|
+
justify-content: center !important;
|
|
20
|
+
align-items: center !important;
|
|
21
|
+
isolation: isolate !important;
|
|
22
|
+
`,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new w(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600,i,s;if(this.fontType==="image"&&this.imageAtlas){let m=this.imageAtlas.getCellDimensions();i=m.width,s=m.height}else this.fontType==="bitmap"?(i=this.bitmapCharWidth,s=this.bitmapCharHeight):(i=Math.round(this.cellWidth)||10,s=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(i),this.cellHeight=Math.round(s),this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let a=this.cols*this.cellWidth,r=this.rows*this.cellHeight,n=t/a,h=e/r,l=Math.min(n,h),c;switch(this.scalingMode){case x.Integer:c=Math.max(1,Math.floor(l));break;case x.Half:c=Math.max(.5,Math.floor(l*2)/2);break;case x.Quarter:c=Math.max(.25,Math.floor(l*4)/4);break;case x.Eighth:c=Math.max(.125,Math.floor(l*8)/8);break;case x.None:default:c=Math.max(.1,l);break}this.currentScale=c,this.canvas.width=a,this.canvas.height=r,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
|
|
23
|
+
flex-shrink: 0 !important;
|
|
24
|
+
flex-grow: 0 !important;
|
|
25
|
+
width: ${a}px !important;
|
|
26
|
+
height: ${r}px !important;
|
|
27
|
+
image-rendering: pixelated !important;
|
|
28
|
+
image-rendering: crisp-edges !important;
|
|
29
|
+
-ms-interpolation-mode: nearest-neighbor !important;
|
|
30
|
+
transform-origin: center center !important;
|
|
31
|
+
transform: scale(${c}) !important;
|
|
32
|
+
will-change: transform !important;
|
|
33
|
+
backface-visibility: hidden !important;
|
|
34
|
+
`,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),a=Math.min(e,this.rows);for(let r=0;r<a;r++)for(let n=0;n<s;n++)this.cells[r][n]=i[r][n]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,a){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,a)}fillRect(t,e,i,s,a=" ",r,n){for(let h=e;h<e+s;h++)for(let l=t;l<t+i;l++)this.setCell(l,h,a,r,n)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let a=0;a<t.width;a++){let r=t.cells[i];s<this.rows&&a<this.cols&&this.setCell(a,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let h=0;h<this.rows;h++)for(let l=0;l<this.cols;l++){let c=this.cells[h][l],m=this.parseColorToRGB(c.bgColor),d=this.parseColorToRGB(c.fgColor),u=c.char.charCodeAt(0),C=this.bitmapFont.get(u);for(let b=0;b<this.bitmapCharHeight;b++)for(let p=0;p<this.bitmapCharWidth;p++){let v=l*this.bitmapCharWidth+p,y=((h*this.bitmapCharHeight+b)*t+v)*4,k=!1;if(C&&b<C.length){let z=C[b],L=1<<7-p;k=(z&L)!==0}k?(i[y]=d.r,i[y+1]=d.g,i[y+2]=d.b,i[y+3]=d.a):(i[y]=m.r,i[y+1]=m.g,i[y+2]=m.b,i[y+3]=m.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,n=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,n),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(n,h,l,c)=>h+h+l+l+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),n=Math.floor(this.offsetY+(t+1)*this.cellHeight),h=r-s,l=n-a;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,a,h,l)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let m=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,m,s,a,h,l,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,a,h,l,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let m=s+(h-this.ctx.measureText(i.char).width)/2,d=a+(l-this.fontSize)/2;this.ctx.fillText(i.char,m,d)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,a,r){let n=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,n,e,i,s,a,r);return}if(!this.bitmapFont)return;let h=this.bitmapFont.get(n);if(!h)return;let l=s/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let m=0;m<Math.min(h.length,this.bitmapCharHeight);m++){let d=h[m],u=i+m*c,C=i+(m+1)*c;for(let b=0;b<this.bitmapCharWidth;b++){let p=1<<7-b;if(d&p){let v=e+b*l,G=e+(b+1)*l;this.ctx.fillRect(v,u,G-v,C-u)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new w(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,a=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==a){this.cells=this.createEmptyGrid();let n=Math.min(s,this.cols),h=Math.min(a,this.rows);for(let l=0;l<h;l++)for(let c=0;c<n;c++)this.cells[l][c]=r[l][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,a=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),n=Math.min(s,this.rows);for(let h=0;h<n;h++)for(let l=0;l<r;l++)this.cells[h][l]=a[h][l]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new H(t,e,i,s,a),this.cellWidth=s,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,a,r){this.fontType="image",this.imageAtlas=new M({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:a,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=f(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let a=e[s];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let a=0;a<t.width&&a<this.cols;a++){let r=s*t.width+a;if(r>=t.cells.length)break;let n=t.cells[r];if(!n)continue;let h=i(n.fgColorIndex),l=i(n.bgColorIndex);this.setCell(a,s,n.char??" ",h,l)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};f(B,"Terminal2D");var T=B;var S=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function $(g,t=S){return g<0||g>=t.length?"#ff00ff":t[g]}f($,"paletteIndexToColor");function U(g,t=S){let e=t.indexOf(g.toLowerCase());return e>=0?e:0}f(U,"colorToPaletteIndex");import{ScalingMode as ft}from"@utsp/types";export{H as BitmapFontAtlas,S as DEFAULT_PALETTE,w as GridOverlay,M as ImageFontAtlas,ft as ScalingMode,T as Terminal2D,U as colorToPaletteIndex,D as getAtlasColumns,W as getCharGridPosition,E as getMaxCharCode,$ as paletteIndexToColor};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var b=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var y=(r,e,t)=>e in r?b(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var d=(r,e)=>b(r,"name",{value:e,configurable:!0});var E=(r,e)=>{for(var t in e)b(r,t,{get:e[t],enumerable:!0})},G=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of N(e))!O.call(r,i)&&i!==t&&b(r,i,{get:()=>e[i],enumerable:!(o=B(e,i))||o.enumerable});return r};var z=r=>G(b({},"__esModule",{value:!0}),r);var C=(r,e,t)=>(y(r,typeof e!="symbol"?e+"":e,t),t);var F={};E(F,{TerminalANSI:()=>m,createTestRenderState:()=>v,hexToRGB:()=>T,rgbToHex:()=>$});module.exports=z(F);var S="\x1B[0m",H="\x1B[H",A="\x1B[2J",w="\x1B[?25l",P="\x1B[?25h",W=`
|
|
2
|
+
`,I=class I{constructor(e={}){C(this,"options");C(this,"fgCache",[]);C(this,"bgCache",[]);C(this,"lastPalette",null);this.options={optimizeColors:e.optimizeColors??!0,includeHome:e.includeHome??!0,hideCursor:e.hideCursor??!0,includeNewlines:e.includeNewlines??!0,includeReset:e.includeReset??!0}}buildColorCache(e){if(this.lastPalette!==e){this.fgCache=new Array(e.length),this.bgCache=new Array(e.length);for(let t=0;t<e.length;t++){let o=e[t];this.fgCache[t]=`\x1B[38;2;${o.r};${o.g};${o.b}m`,this.bgCache[t]=`\x1B[48;2;${o.r};${o.g};${o.b}m`}this.lastPalette=e}}render(e){let{width:t,height:o,cells:i,palette:s}=e;this.buildColorCache(s);let n="";this.options.hideCursor&&(n+=w),this.options.includeHome&&(n+=H);let g=-1,h=-1,x=this.options.optimizeColors,R=this.options.includeNewlines;for(let l=0;l<o;l++){let u=l*t;for(let a=0;a<t;a++){let c=i[u+a],p=c.fgColorIndex,f=c.bgColorIndex;x?(f!==h&&(n+=this.bgCache[f],h=f),p!==g&&(n+=this.fgCache[p],g=p)):(n+=this.bgCache[f],n+=this.fgCache[p]),n+=c.char||" "}R&&l<o-1&&(n+=W)}return this.options.includeReset&&(n+=S),n}renderRow(e,t){let{width:o,cells:i,palette:s}=e;this.buildColorCache(s);let n=`\x1B[${t+1};1H`,g=-1,h=-1,x=this.options.optimizeColors,R=t*o;for(let l=0;l<o;l++){let u=i[R+l],a=u.fgColorIndex,c=u.bgColorIndex;x?(c!==h&&(n+=this.bgCache[c],h=c),a!==g&&(n+=this.fgCache[a],g=a)):(n+=this.bgCache[c],n+=this.fgCache[a]),n+=u.char||" "}return this.options.includeReset&&(n+=S),n}clear(){return A+H}showCursor(){return P}hideCursor(){return w}reset(){return S}moveTo(e,t){return`\x1B[${e+1};${t+1}H`}};d(I,"TerminalANSI");var m=I;function T(r){let e=r.startsWith("#")?r.slice(1):r,t=e.length===3?e[0]+e[0]+e[1]+e[1]+e[2]+e[2]:e,o=parseInt(t,16);return{r:o>>16&255,g:o>>8&255,b:o&255,a:255}}d(T,"hexToRGB");function $(r){let e=r.r.toString(16).padStart(2,"0"),t=r.g.toString(16).padStart(2,"0"),o=r.b.toString(16).padStart(2,"0");return`#${e}${t}${o}`}d($,"rgbToHex");function v(r,e){let t=[{r:0,g:0,b:0,a:255},{r:128,g:0,b:0,a:255},{r:0,g:128,b:0,a:255},{r:128,g:128,b:0,a:255},{r:0,g:0,b:128,a:255},{r:128,g:0,b:128,a:255},{r:0,g:128,b:128,a:255},{r:192,g:192,b:192,a:255},{r:128,g:128,b:128,a:255},{r:255,g:0,b:0,a:255},{r:0,g:255,b:0,a:255},{r:255,g:255,b:0,a:255},{r:0,g:0,b:255,a:255},{r:255,g:0,b:255,a:255},{r:0,g:255,b:255,a:255},{r:255,g:255,b:255,a:255}];for(;t.length<256;)t.push({r:128,g:128,b:128,a:255});let o=[];for(let i=0;i<e;i++)for(let s=0;s<r;s++)o.push({char:String.fromCharCode(65+(s+i)%26),fgColorIndex:15,bgColorIndex:(s+i)%16,fgEmission:0,bgEmission:0});return{width:r,height:e,cells:o,palette:t}}d(v,"createTestRenderState");
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { RenderState, RGBColor } from '@utsp/types';
|
|
2
|
+
export { RGBColor, RenderState, RenderedCell } from '@utsp/types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TerminalANSI - ANSI escape sequence renderer for native terminals
|
|
6
|
+
*
|
|
7
|
+
* Renders RenderState to ANSI escape sequences for display in terminal emulators
|
|
8
|
+
* (cmd, PowerShell, bash, etc.) that support True Color (24-bit RGB).
|
|
9
|
+
*
|
|
10
|
+
* Uses the same 256-color palette (24-bit per color) as TerminalGL and Terminal2D.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { TerminalANSI } from '@utsp/render/ansi';
|
|
15
|
+
*
|
|
16
|
+
* const renderer = new TerminalANSI({ optimizeColors: true });
|
|
17
|
+
* const output = renderer.render(renderState);
|
|
18
|
+
* process.stdout.write(output);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Options for TerminalANSI renderer
|
|
24
|
+
*/
|
|
25
|
+
interface TerminalANSIOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Optimize color output by not repeating identical colors
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
optimizeColors?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Include cursor home sequence at the start of each render
|
|
33
|
+
* Set to true for full-screen rendering, false for partial updates
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
includeHome?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Include hide cursor sequence at the start of each render
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
hideCursor?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Include newlines at the end of each row
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
includeNewlines?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Include reset sequence at the end of render
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
includeReset?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* ANSI escape sequence renderer for native terminals
|
|
55
|
+
*
|
|
56
|
+
* Converts RenderState to a string with ANSI escape sequences
|
|
57
|
+
* that can be written to stdout for display in terminal emulators.
|
|
58
|
+
*
|
|
59
|
+
* Supports True Color (24-bit RGB) for full palette compatibility
|
|
60
|
+
* with TerminalGL and Terminal2D renderers.
|
|
61
|
+
*
|
|
62
|
+
* Performance optimizations:
|
|
63
|
+
* - Single string concatenation (no array joins)
|
|
64
|
+
* - Pre-cached color sequences per palette entry
|
|
65
|
+
* - Only cursor home + newlines (no per-cell cursor moves)
|
|
66
|
+
* - Color change tracking to skip redundant sequences
|
|
67
|
+
*/
|
|
68
|
+
declare class TerminalANSI {
|
|
69
|
+
private options;
|
|
70
|
+
private fgCache;
|
|
71
|
+
private bgCache;
|
|
72
|
+
private lastPalette;
|
|
73
|
+
constructor(options?: TerminalANSIOptions);
|
|
74
|
+
/**
|
|
75
|
+
* Build color cache from palette (only when palette changes)
|
|
76
|
+
*/
|
|
77
|
+
private buildColorCache;
|
|
78
|
+
/**
|
|
79
|
+
* Render a RenderState to ANSI escape sequence string (optimized)
|
|
80
|
+
*
|
|
81
|
+
* @param state - The render state from Core
|
|
82
|
+
* @returns ANSI escape sequence string ready for stdout
|
|
83
|
+
*/
|
|
84
|
+
render(state: RenderState): string;
|
|
85
|
+
/**
|
|
86
|
+
* Render a single row from RenderState (optimized)
|
|
87
|
+
* Useful for partial updates
|
|
88
|
+
*
|
|
89
|
+
* @param state - The render state from Core
|
|
90
|
+
* @param row - Row index (0-based)
|
|
91
|
+
* @returns ANSI escape sequence string for the row
|
|
92
|
+
*/
|
|
93
|
+
renderRow(state: RenderState, row: number): string;
|
|
94
|
+
/**
|
|
95
|
+
* Get ANSI sequence to clear the screen
|
|
96
|
+
*/
|
|
97
|
+
clear(): string;
|
|
98
|
+
/**
|
|
99
|
+
* Get ANSI sequence to show the cursor
|
|
100
|
+
*/
|
|
101
|
+
showCursor(): string;
|
|
102
|
+
/**
|
|
103
|
+
* Get ANSI sequence to hide the cursor
|
|
104
|
+
*/
|
|
105
|
+
hideCursor(): string;
|
|
106
|
+
/**
|
|
107
|
+
* Get ANSI sequence to reset all attributes
|
|
108
|
+
*/
|
|
109
|
+
reset(): string;
|
|
110
|
+
/**
|
|
111
|
+
* Get ANSI sequence to move cursor to position
|
|
112
|
+
* @param row - Row (0-indexed)
|
|
113
|
+
* @param col - Column (0-indexed)
|
|
114
|
+
*/
|
|
115
|
+
moveTo(row: number, col: number): string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parse CSS hex color to RGBColor
|
|
119
|
+
* @param hex - CSS hex color (e.g., "#FF0000" or "#F00")
|
|
120
|
+
*/
|
|
121
|
+
declare function hexToRGB(hex: string): RGBColor;
|
|
122
|
+
/**
|
|
123
|
+
* Convert RGBColor to CSS hex color
|
|
124
|
+
*/
|
|
125
|
+
declare function rgbToHex(color: RGBColor): string;
|
|
126
|
+
/**
|
|
127
|
+
* Create a simple test RenderState for debugging
|
|
128
|
+
*/
|
|
129
|
+
declare function createTestRenderState(width: number, height: number): RenderState;
|
|
130
|
+
|
|
131
|
+
export { TerminalANSI, createTestRenderState, hexToRGB, rgbToHex };
|
|
132
|
+
export type { TerminalANSIOptions };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var I=Object.defineProperty;var T=(o,e,t)=>e in o?I(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var b=(o,e)=>I(o,"name",{value:e,configurable:!0});var d=(o,e,t)=>(T(o,typeof e!="symbol"?e+"":e,t),t);var x="\x1B[0m",H="\x1B[H",$="\x1B[2J",w="\x1B[?25l",v="\x1B[?25h",B=`
|
|
2
|
+
`,S=class S{constructor(e={}){d(this,"options");d(this,"fgCache",[]);d(this,"bgCache",[]);d(this,"lastPalette",null);this.options={optimizeColors:e.optimizeColors??!0,includeHome:e.includeHome??!0,hideCursor:e.hideCursor??!0,includeNewlines:e.includeNewlines??!0,includeReset:e.includeReset??!0}}buildColorCache(e){if(this.lastPalette!==e){this.fgCache=new Array(e.length),this.bgCache=new Array(e.length);for(let t=0;t<e.length;t++){let r=e[t];this.fgCache[t]=`\x1B[38;2;${r.r};${r.g};${r.b}m`,this.bgCache[t]=`\x1B[48;2;${r.r};${r.g};${r.b}m`}this.lastPalette=e}}render(e){let{width:t,height:r,cells:i,palette:s}=e;this.buildColorCache(s);let n="";this.options.hideCursor&&(n+=w),this.options.includeHome&&(n+=H);let g=-1,h=-1,f=this.options.optimizeColors,m=this.options.includeNewlines;for(let l=0;l<r;l++){let u=l*t;for(let a=0;a<t;a++){let c=i[u+a],C=c.fgColorIndex,p=c.bgColorIndex;f?(p!==h&&(n+=this.bgCache[p],h=p),C!==g&&(n+=this.fgCache[C],g=C)):(n+=this.bgCache[p],n+=this.fgCache[C]),n+=c.char||" "}m&&l<r-1&&(n+=B)}return this.options.includeReset&&(n+=x),n}renderRow(e,t){let{width:r,cells:i,palette:s}=e;this.buildColorCache(s);let n=`\x1B[${t+1};1H`,g=-1,h=-1,f=this.options.optimizeColors,m=t*r;for(let l=0;l<r;l++){let u=i[m+l],a=u.fgColorIndex,c=u.bgColorIndex;f?(c!==h&&(n+=this.bgCache[c],h=c),a!==g&&(n+=this.fgCache[a],g=a)):(n+=this.bgCache[c],n+=this.fgCache[a]),n+=u.char||" "}return this.options.includeReset&&(n+=x),n}clear(){return $+H}showCursor(){return v}hideCursor(){return w}reset(){return x}moveTo(e,t){return`\x1B[${e+1};${t+1}H`}};b(S,"TerminalANSI");var R=S;function N(o){let e=o.startsWith("#")?o.slice(1):o,t=e.length===3?e[0]+e[0]+e[1]+e[1]+e[2]+e[2]:e,r=parseInt(t,16);return{r:r>>16&255,g:r>>8&255,b:r&255,a:255}}b(N,"hexToRGB");function O(o){let e=o.r.toString(16).padStart(2,"0"),t=o.g.toString(16).padStart(2,"0"),r=o.b.toString(16).padStart(2,"0");return`#${e}${t}${r}`}b(O,"rgbToHex");function y(o,e){let t=[{r:0,g:0,b:0,a:255},{r:128,g:0,b:0,a:255},{r:0,g:128,b:0,a:255},{r:128,g:128,b:0,a:255},{r:0,g:0,b:128,a:255},{r:128,g:0,b:128,a:255},{r:0,g:128,b:128,a:255},{r:192,g:192,b:192,a:255},{r:128,g:128,b:128,a:255},{r:255,g:0,b:0,a:255},{r:0,g:255,b:0,a:255},{r:255,g:255,b:0,a:255},{r:0,g:0,b:255,a:255},{r:255,g:0,b:255,a:255},{r:0,g:255,b:255,a:255},{r:255,g:255,b:255,a:255}];for(;t.length<256;)t.push({r:128,g:128,b:128,a:255});let r=[];for(let i=0;i<e;i++)for(let s=0;s<o;s++)r.push({char:String.fromCharCode(65+(s+i)%26),fgColorIndex:15,bgColorIndex:(s+i)%16,fgEmission:0,bgEmission:0});return{width:o,height:e,cells:r,palette:t}}b(y,"createTestRenderState");export{R as TerminalANSI,y as createTestRenderState,N as hexToRGB,O as rgbToHex};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";var f=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var A=(r,t,e)=>t in r?f(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var h=(r,t)=>f(r,"name",{value:t,configurable:!0});var L=(r,t)=>{for(var e in t)f(r,e,{get:t[e],enumerable:!0})},R=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of H(t))!z.call(r,i)&&i!==e&&f(r,i,{get:()=>t[i],enumerable:!(n=M(t,i))||n.enumerable});return r};var W=r=>R(f({},"__esModule",{value:!0}),r);var o=(r,t,e)=>(A(r,typeof t!="symbol"?t+"":t,e),e);var I={};L(I,{AutoplayOverlay:()=>y,DEFAULT_PALETTE:()=>b,GridOverlay:()=>g,PostProcessOverlay:()=>C,colorToPaletteIndex:()=>E,getAtlasColumns:()=>D,getCharGridPosition:()=>P,getMaxCharCode:()=>O,paletteIndexToColor:()=>T});module.exports=W(I);var b=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function T(r,t=b){return r<0||r>=t.length?"#ff00ff":t[r]}h(T,"paletteIndexToColor");function E(r,t=b){let e=t.indexOf(r.toLowerCase());return e>=0?e:0}h(E,"colorToPaletteIndex");var k=class k{constructor(t,e){o(this,"canvas");o(this,"ctx");o(this,"container");o(this,"cols",0);o(this,"rows",0);o(this,"cellWidth",0);o(this,"cellHeight",0);o(this,"offsetX",0);o(this,"offsetY",0);o(this,"strokeColor","rgba(80, 80, 80, 0.4)");o(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let n=e?.zIndex??10;this.canvas.style.cssText=`
|
|
2
|
+
display: block !important;
|
|
3
|
+
position: absolute !important;
|
|
4
|
+
pointer-events: none !important;
|
|
5
|
+
image-rendering: pixelated !important;
|
|
6
|
+
image-rendering: crisp-edges !important;
|
|
7
|
+
z-index: ${n} !important;
|
|
8
|
+
`,this.container.appendChild(this.canvas);let i=this.canvas.getContext("2d");if(!i)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=i,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth))}setDimensions(t,e,n,i,a=0,c=0){this.cols=t,this.rows=e,this.cellWidth=n,this.cellHeight=i,this.offsetX=a,this.offsetY=c}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,n,i,a){let c=i.left-a.left,l=i.top-a.top,s=i.width,v=i.height;(this.canvas.width!==s||this.canvas.height!==v)&&(this.canvas.width=s,this.canvas.height=v);let p=this.canvas.style;p.width=`${s}px`,p.height=`${v}px`,p.left=`${c}px`,p.top=`${l}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,n=t>0?this.canvas.width/t:1,i=e>0?this.canvas.height/e:1,a=Math.min(n,i),c=this.cellWidth*a,l=this.cellHeight*a,s=this.cols*c,v=this.rows*l,p=this.offsetX*a,x=this.offsetY*a;if(!(s===0||v===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*a),this.ctx.beginPath();for(let d=0;d<=this.cols;d++){let u=p+d*c+.5;this.ctx.moveTo(u,x),this.ctx.lineTo(u,x+v)}for(let d=0;d<=this.rows;d++){let u=x+d*l+.5;this.ctx.moveTo(p,u),this.ctx.lineTo(p+s,u)}this.ctx.stroke()}}update(t,e,n,i,a,c,l=0,s=0){this.setDimensions(t,e,n,i,l,s),this.setCanvasSize(a,c),this.render()}setVisible(t){this.canvas.style.display=t?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};h(k,"GridOverlay");var g=k;var w=class w{constructor(t,e={}){o(this,"container");o(this,"overlayDiv",null);o(this,"button",null);o(this,"options");o(this,"started",!1);o(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
|
|
9
|
+
position: absolute !important;
|
|
10
|
+
top: 0 !important;
|
|
11
|
+
left: 0 !important;
|
|
12
|
+
width: 100% !important;
|
|
13
|
+
height: 100% !important;
|
|
14
|
+
background-color: ${this.options.backgroundColor} !important;
|
|
15
|
+
display: flex !important;
|
|
16
|
+
justify-content: center !important;
|
|
17
|
+
align-items: center !important;
|
|
18
|
+
z-index: ${this.options.zIndex} !important;
|
|
19
|
+
cursor: pointer !important;
|
|
20
|
+
`,this.button=document.createElement("button"),this.button.className="utsp-autoplay-button",this.button.textContent=this.options.buttonText,this.button.style.cssText=`
|
|
21
|
+
padding: 16px 32px !important;
|
|
22
|
+
font-size: 18px !important;
|
|
23
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif !important;
|
|
24
|
+
font-weight: 600 !important;
|
|
25
|
+
color: ${this.options.buttonTextColor} !important;
|
|
26
|
+
background-color: ${this.options.buttonColor} !important;
|
|
27
|
+
border: none !important;
|
|
28
|
+
border-radius: 8px !important;
|
|
29
|
+
cursor: pointer !important;
|
|
30
|
+
transition: background-color 0.2s ease, transform 0.1s ease !important;
|
|
31
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
|
|
32
|
+
`,this.button.addEventListener("mouseenter",()=>{this.button&&(this.button.style.backgroundColor=`${this.options.buttonHoverColor} !important`,this.button.style.transform="scale(1.05)")}),this.button.addEventListener("mouseleave",()=>{this.button&&(this.button.style.backgroundColor=`${this.options.buttonColor} !important`,this.button.style.transform="scale(1)")}),this.button.addEventListener("click",e=>{e.stopPropagation(),this.start()}),this.overlayDiv.addEventListener("click",()=>{this.start()}),this.overlayDiv.appendChild(this.button),this.container.appendChild(this.overlayDiv)}start(){this.started||(this.started=!0,this.overlayDiv&&(this.overlayDiv.style.transition="opacity 0.3s ease",this.overlayDiv.style.opacity="0",setTimeout(()=>{this.removeOverlay()},300)),this.onStartCallback&&this.onStartCallback())}isStarted(){return this.started}isVisible(){return this.overlayDiv!==null&&!this.started}removeOverlay(){this.overlayDiv&&this.overlayDiv.parentElement&&this.overlayDiv.parentElement.removeChild(this.overlayDiv),this.overlayDiv=null,this.button=null}setButtonText(t){this.options.buttonText=t,this.button&&(this.button.textContent=t)}setOnStart(t){this.onStartCallback=t}destroy(){this.removeOverlay(),this.started=!1}};h(w,"AutoplayOverlay");var y=w;var m=require("@utsp/types");var S=class S{constructor(t,e){o(this,"canvas");o(this,"ctx");o(this,"containerDiv");o(this,"parentElement");o(this,"resizeObserver");o(this,"width",0);o(this,"height",0);o(this,"currentConfig",null);o(this,"configHash","");this.parentElement=t,this.containerDiv=document.createElement("div"),this.containerDiv.className="postprocess-container",this.containerDiv.style.cssText=`
|
|
33
|
+
position: absolute !important;
|
|
34
|
+
top: 0 !important;
|
|
35
|
+
left: 0 !important;
|
|
36
|
+
right: 0 !important;
|
|
37
|
+
bottom: 0 !important;
|
|
38
|
+
width: 100% !important;
|
|
39
|
+
height: 100% !important;
|
|
40
|
+
pointer-events: none !important;
|
|
41
|
+
z-index: 10 !important;
|
|
42
|
+
overflow: hidden !important;
|
|
43
|
+
`,this.canvas=document.createElement("canvas"),this.canvas.className="postprocess-canvas",this.canvas.style.cssText=`
|
|
44
|
+
position: absolute !important;
|
|
45
|
+
top: 0 !important;
|
|
46
|
+
left: 0 !important;
|
|
47
|
+
width: 100% !important;
|
|
48
|
+
height: 100% !important;
|
|
49
|
+
pointer-events: none !important;
|
|
50
|
+
`;let n=this.canvas.getContext("2d",{alpha:!0});if(!n)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=n,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(a=>{for(let c of a){let{width:l,height:s}=c.contentRect;l>0&&s>0&&this.handleResize(Math.floor(l),Math.floor(s))}}),this.resizeObserver.observe(this.parentElement);let i=this.parentElement.getBoundingClientRect();i.width>0&&i.height>0&&this.handleResize(Math.floor(i.width),Math.floor(i.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??m.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),n=this.currentConfig?.scanlines;this.setScanlines({enabled:n?.enabled??!0,opacity:e,pattern:n?.pattern??"horizontal",spacing:n?.spacing??2,thickness:n?.thickness??1,color:n?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??m.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),n=this.currentConfig?.scanlines;this.setScanlines({enabled:n?.enabled??!0,opacity:n?.opacity??m.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:n?.pattern??"horizontal",spacing:e,thickness:n?.thickness??1,color:n?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??m.POST_PROCESS_DEFAULTS.scanlines.opacity,n=t.pattern??"horizontal",i=t.spacing??2,a=t.thickness??1,c=t.color??{r:0,g:0,b:0},l=this.ctx;switch(l.fillStyle=`rgba(${c.r}, ${c.g}, ${c.b}, ${e})`,n){case"horizontal":for(let s=i-1;s<this.height;s+=i)l.fillRect(0,s,this.width,a);break;case"vertical":for(let s=i-1;s<this.width;s+=i)l.fillRect(s,0,a,this.height);break;case"grid":for(let s=i-1;s<this.height;s+=i)l.fillRect(0,s,this.width,a);for(let s=i-1;s<this.width;s+=i)l.fillRect(s,0,a,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};h(S,"PostProcessOverlay");var C=S;function D(r){return Math.sqrt(r)*16}h(D,"getAtlasColumns");function O(r){return r*256-1}h(O,"getMaxCharCode");function P(r,t){let e=Math.floor(r/256),n=r%256,i=Math.sqrt(t),a=e%i,c=Math.floor(e/i),l=n%16,s=Math.floor(n/16);return{col:a*16+l,row:c*16+s}}h(P,"getCharGridPosition");
|