@hex1b/web-terminal 0.1.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/LICENSE +21 -0
- package/README.md +243 -0
- package/dist/fonts/cascadia-mono-nf/CascadiaMonoNF.woff2 +0 -0
- package/dist/fonts/cascadia-mono-nf/LICENSE.txt +94 -0
- package/dist/fonts/cascadia-mono-nf/README.md +29 -0
- package/dist/history-state.d.ts +27 -0
- package/dist/history-state.d.ts.map +1 -0
- package/dist/history-state.js +194 -0
- package/dist/history-state.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/input-policy.d.ts +42 -0
- package/dist/input-policy.d.ts.map +1 -0
- package/dist/input-policy.js +143 -0
- package/dist/input-policy.js.map +1 -0
- package/dist/mouse-input.d.ts +26 -0
- package/dist/mouse-input.d.ts.map +1 -0
- package/dist/mouse-input.js +356 -0
- package/dist/mouse-input.js.map +1 -0
- package/dist/protocol.d.ts +17 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +270 -0
- package/dist/protocol.js.map +1 -0
- package/dist/renderer.d.ts +113 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +595 -0
- package/dist/renderer.js.map +1 -0
- package/dist/selection-input.d.ts +36 -0
- package/dist/selection-input.d.ts.map +1 -0
- package/dist/selection-input.js +69 -0
- package/dist/selection-input.js.map +1 -0
- package/dist/selection-ui.d.ts +24 -0
- package/dist/selection-ui.d.ts.map +1 -0
- package/dist/selection-ui.js +113 -0
- package/dist/selection-ui.js.map +1 -0
- package/dist/terminal-font.d.ts +23 -0
- package/dist/terminal-font.d.ts.map +1 -0
- package/dist/terminal-font.js +85 -0
- package/dist/terminal-font.js.map +1 -0
- package/dist/terminal-sizing.d.ts +8 -0
- package/dist/terminal-sizing.d.ts.map +1 -0
- package/dist/terminal-sizing.js +38 -0
- package/dist/terminal-sizing.js.map +1 -0
- package/dist/terminal-theme.d.ts +2 -0
- package/dist/terminal-theme.d.ts.map +1 -0
- package/dist/terminal-theme.js +39 -0
- package/dist/terminal-theme.js.map +1 -0
- package/dist/terminal-worker.d.ts +2 -0
- package/dist/terminal-worker.d.ts.map +1 -0
- package/dist/terminal-worker.js +285 -0
- package/dist/terminal-worker.js.map +1 -0
- package/dist/types.d.ts +312 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +3 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +7 -0
- package/dist/validation.js.map +1 -0
- package/dist/web-terminal.d.ts +51 -0
- package/dist/web-terminal.d.ts.map +1 -0
- package/dist/web-terminal.js +728 -0
- package/dist/web-terminal.js.map +1 -0
- package/dist/wire-types.d.ts +218 -0
- package/dist/wire-types.d.ts.map +1 -0
- package/dist/wire-types.js +2 -0
- package/dist/wire-types.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import { LIMITS } from \"./protocol.js\";\nimport { loadFont, measureFont, normalizeFont } from \"./terminal-font.js\";\nimport type { FontMetrics, LoadedFont, NormalizedFont } from \"./terminal-font.js\";\nimport type { TerminalFont, TerminalSize } from \"./types.js\";\nimport type { FrameImage, FrameMetadata, ImagePlacement, TerminalCell } from \"./wire-types.js\";\n\ntype Vector4 = [number, number, number, number];\ninterface TextureResource { texture: GPUTexture; bindGroup: GPUBindGroup; width: number; height: number }\ninterface Shelf { x: number; y: number; rowHeight: number }\ninterface GlyphPlacement { key: string; cell: TerminalCell; x: number; y: number; width: number; height: number }\ninterface Glyph { colored: boolean; u0: number; v0: number; u1: number; v1: number }\ninterface Batch { resource: TextureResource; start: number; count: number }\n\nconst CELL_WIDTH = 10;\nconst CELL_HEIGHT = 20;\nconst MAX_QUADS = 1024 * 1024;\nconst MAX_GLYPHS = 16384;\nconst MAX_GLYPH_KEY_UNITS = 1024 * 1024;\nconst STRIDE = 16;\nconst WHITE: Vector4 = [1, 1, 1, 1];\n\nconst shader = /* wgsl */ `\nstruct Viewport { size: vec2f, padding: vec2f }\n@group(0) @binding(0) var<uniform> viewport: Viewport;\n@group(0) @binding(1) var image: texture_2d<f32>;\n@group(0) @binding(2) var imageSampler: sampler;\n\nstruct VertexOut {\n @builtin(position) position: vec4f,\n @location(0) uv: vec2f,\n @location(1) color: vec4f,\n @location(2) @interpolate(flat) mode: f32,\n}\n\n@vertex fn vertex(\n @builtin(vertex_index) index: u32,\n @location(0) rect: vec4f,\n @location(1) uvRect: vec4f,\n @location(2) color: vec4f,\n @location(3) mode: f32,\n) -> VertexOut {\n let corners = array<vec2f, 6>(\n vec2f(0, 0), vec2f(1, 0), vec2f(0, 1),\n vec2f(0, 1), vec2f(1, 0), vec2f(1, 1)\n );\n let corner = corners[index];\n let position = rect.xy + corner * rect.zw;\n var out: VertexOut;\n out.position = vec4f(position / viewport.size * vec2f(2, -2) + vec2f(-1, 1), 0, 1);\n out.uv = mix(uvRect.xy, uvRect.zw, corner);\n out.color = color;\n out.mode = mode;\n return out;\n}\n\n@fragment fn fragment(in: VertexOut) -> @location(0) vec4f {\n // Explicit LOD avoids derivative-uniformity requirements across solid/mask/image batches.\n let texel = textureSampleLevel(image, imageSampler, in.uv, 0);\n if (in.mode < 0.5) { return in.color; }\n if (in.mode < 1.5) { return vec4f(in.color.rgb, in.color.a * texel.a); }\n return texel * in.color;\n}`;\n\nfunction rgba(packed: number): Vector4 {\n return [\n (packed & 255) / 255,\n ((packed >>> 8) & 255) / 255,\n ((packed >>> 16) & 255) / 255,\n ((packed >>> 24) & 255) / 255,\n ];\n}\n\nfunction glyphKey(cell: TerminalCell): string {\n return `${cell.attributes & 5}/${cell.width}/${cell.text}`;\n}\n\n/** Shelf packer. Plans are computed before mutating the atlas used by a submitted frame. */\nfunction packGlyphs(glyphs: ReadonlyMap<string, TerminalCell>, size: number, scale: number,\n initial: Shelf = { x: 0, y: 0, rowHeight: 0 }): { placements: GlyphPlacement[]; shelf: Shelf } | null {\n let { x, y, rowHeight } = initial;\n const placements = [];\n for (const [key, cell] of glyphs) {\n const width = Math.ceil(cell.width * CELL_WIDTH * scale) + 4;\n const height = Math.ceil(CELL_HEIGHT * scale) + 4;\n if (width > size || height > size) return null;\n if (x + width > size) { x = 0; y += rowHeight; rowHeight = 0; }\n if (y + height > size) return null;\n placements.push({ key, cell, x, y, width, height });\n x += width;\n rowHeight = Math.max(rowHeight, height);\n }\n return { placements, shelf: { x, y, rowHeight } };\n}\n\n/** WebGPU instanced quads; Canvas2D is used only to rasterize reusable glyphs. */\nexport class TerminalRenderer {\n canvas: OffscreenCanvas;\n scale: number;\n backingScale: number;\n device: GPUDevice;\n fontConfiguration: NormalizedFont;\n fontMetrics: Map<number, FontMetrics>;\n context: GPUCanvasContext;\n images: Map<string, TextureResource>;\n glyphs: Map<string, Glyph>;\n imageUploadBytes: number;\n imagePayloadBytes: number;\n glyphUploadBytes: number;\n atlasRebuilds: number;\n textureBytes: number;\n instances: Float32Array<ArrayBuffer>;\n instanceBuffer: GPUBuffer | null;\n instanceBufferBytes: number;\n disposed: boolean;\n columns: number;\n rows: number;\n // Initialized by create() before the renderer can prepare or submit frames.\n font!: LoadedFont;\n format!: GPUTextureFormat;\n uniform!: GPUBuffer;\n sampler!: GPUSampler;\n pipeline!: GPURenderPipeline;\n rasterCanvas!: OffscreenCanvas;\n raster!: OffscreenCanvasRenderingContext2D;\n atlas!: TextureResource;\n glyphKeyUnits = 0;\n shelf: Shelf = { x: 0, y: 0, rowHeight: 0 };\n canvasLimited = false;\n width = 0;\n height = 0;\n quadCount = 0;\n batches: Batch[] = [];\n\n static async create(canvas: OffscreenCanvas, scale: number, onFatal: (error: Error | GPUError) => void,\n font: TerminalFont): Promise<TerminalRenderer> {\n const normalizedFont = normalizeFont(font);\n if (!self.isSecureContext) throw new Error(\"WebGPU requires HTTPS or localhost\");\n if (!navigator.gpu) throw new Error(\"WebGPU is unavailable in this browser worker\");\n const adapter = await navigator.gpu.requestAdapter();\n if (!adapter) throw new Error(\"No WebGPU adapter is available; check browser GPU support\");\n const device = await adapter.requestDevice();\n const renderer = new TerminalRenderer(canvas, scale, device, normalizedFont);\n device.lost.then(info => {\n if (!renderer.disposed) onFatal(new Error(`WebGPU device lost: ${info.message || info.reason}`));\n });\n device.addEventListener(\"uncapturederror\", event => onFatal(event.error));\n try {\n await renderer.initialize();\n return renderer;\n } catch (error) {\n renderer.dispose();\n throw error;\n }\n }\n\n constructor(canvas: OffscreenCanvas, scale: number, device: GPUDevice, font: NormalizedFont) {\n if (!Number.isFinite(scale) || scale < 0.5 || scale > 3) throw new Error(\"Invalid backing scale\");\n this.canvas = canvas;\n this.scale = scale;\n this.backingScale = scale;\n this.device = device;\n this.fontConfiguration = font;\n this.fontMetrics = new Map();\n const context = canvas.getContext(\"webgpu\");\n if (!context) throw new Error(\"Could not create an OffscreenCanvas WebGPU context\");\n this.context = context;\n this.images = new Map();\n this.glyphs = new Map();\n this.imageUploadBytes = 0;\n this.imagePayloadBytes = 0;\n this.glyphUploadBytes = 0;\n this.atlasRebuilds = 0;\n this.textureBytes = 0;\n this.instances = new Float32Array(4096 * STRIDE);\n this.instanceBuffer = null;\n this.instanceBufferBytes = 0;\n this.disposed = false;\n this.columns = 0;\n this.rows = 0;\n }\n\n async initialize() {\n this.font = await loadFont(this.fontConfiguration);\n const device = this.device;\n this.format = navigator.gpu.getPreferredCanvasFormat();\n this.context.configure({ device, format: this.format, alphaMode: \"opaque\" });\n this.uniform = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });\n this.sampler = device.createSampler({ minFilter: \"linear\", magFilter: \"linear\" });\n const module = device.createShaderModule({ code: shader });\n this.pipeline = await device.createRenderPipelineAsync({\n layout: \"auto\",\n vertex: {\n module,\n entryPoint: \"vertex\",\n buffers: [{\n arrayStride: STRIDE * 4,\n stepMode: \"instance\",\n attributes: [\n { shaderLocation: 0, offset: 0, format: \"float32x4\" },\n { shaderLocation: 1, offset: 16, format: \"float32x4\" },\n { shaderLocation: 2, offset: 32, format: \"float32x4\" },\n { shaderLocation: 3, offset: 48, format: \"float32\" },\n ],\n }],\n },\n fragment: {\n module,\n entryPoint: \"fragment\",\n targets: [{\n format: this.format,\n blend: {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\" },\n },\n }],\n },\n primitive: { topology: \"triangle-list\" },\n });\n this.rasterCanvas = new OffscreenCanvas(1, 1);\n const raster = this.rasterCanvas.getContext(\"2d\", { willReadFrequently: true });\n if (!raster) throw new Error(\"Worker glyph rasterization is unavailable\");\n this.raster = raster;\n this.resetAtlas(Math.min(2048, device.limits.maxTextureDimension2D));\n }\n\n createTexture(width: number, height: number, label: string): TextureResource {\n if (width > this.device.limits.maxTextureDimension2D || height > this.device.limits.maxTextureDimension2D) {\n throw new Error(`${label} exceeds the GPU texture dimension limit`);\n }\n const texture = this.device.createTexture({\n label,\n size: [width, height],\n format: \"rgba8unorm\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n });\n const bindGroup = this.device.createBindGroup({\n layout: this.pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: this.uniform } },\n { binding: 1, resource: texture.createView() },\n { binding: 2, resource: this.sampler },\n ],\n });\n return { texture, bindGroup, width, height };\n }\n\n resetAtlas(size: number): void {\n this.atlas?.texture.destroy();\n this.atlas = this.createTexture(size, size, \"Glyph atlas\");\n this.glyphs.clear();\n this.glyphKeyUnits = 0;\n this.shelf = { x: 0, y: 0, rowHeight: 0 };\n }\n\n resize(columns: number, rows: number, viewport?: TerminalSize): void {\n const width = columns * CELL_WIDTH;\n const height = rows * CELL_HEIGHT;\n const limit = this.device.limits.maxTextureDimension2D;\n const requested = Math.min(this.scale, viewport ? viewport.width / width : Infinity, viewport ? viewport.height / height : Infinity);\n this.canvasLimited = width * requested > limit || height * requested > limit;\n this.backingScale = Math.min(requested, limit / width, limit / height);\n const backingWidth = Math.max(1, Math.min(limit, Math.ceil(width * this.backingScale)));\n const backingHeight = Math.max(1, Math.min(limit, Math.ceil(height * this.backingScale)));\n if (this.columns === columns && this.rows === rows && this.canvas.width === backingWidth && this.canvas.height === backingHeight) return;\n this.columns = columns;\n this.rows = rows;\n this.width = width;\n this.height = height;\n this.canvas.width = backingWidth;\n this.canvas.height = backingHeight;\n this.device.queue.writeBuffer(this.uniform, 0, new Float32Array([width, height, 0, 0]));\n }\n\n /** Call only between submissions. Missing/over-budget resources terminate the session. */\n async updateImages(incoming: readonly FrameImage[], retainedKeys: readonly string[]): Promise<void> {\n const retained = new Set(retainedKeys);\n const replacements = new Map(incoming.map(image => [image.key, image]));\n let projectedBytes = 0;\n for (const key of retained) {\n const image = replacements.get(key) || this.images.get(key);\n if (!image) throw new Error(`Missing retained image resource: ${key}`);\n projectedBytes += image.width * image.height * 4;\n }\n if (projectedBytes > LIMITS.textureBytes) throw new Error(\"Retained images exceed the 256 MiB texture budget\");\n for (const [key, image] of this.images) {\n if (!retained.has(key) || replacements.has(key)) {\n image.texture.destroy();\n this.textureBytes -= image.width * image.height * 4;\n this.images.delete(key);\n }\n }\n for (const image of incoming) {\n const resource = this.createTexture(image.width, image.height, `Image ${image.key}`);\n try {\n if (image.format === \"rgba\") {\n this.device.queue.writeTexture(\n { texture: resource.texture },\n image.bytes,\n { bytesPerRow: image.width * 4, rowsPerImage: image.height },\n [image.width, image.height],\n );\n } else {\n // Check IHDR before decoding so a tiny PNG cannot claim unbounded decoded dimensions.\n const png = new DataView(image.bytes.buffer, image.bytes.byteOffset, image.bytes.byteLength);\n if (png.byteLength < 33 || png.getUint32(0) !== 0x89504e47 || png.getUint32(4) !== 0x0d0a1a0a ||\n png.getUint32(8) !== 13 || png.getUint32(12) !== 0x49484452 ||\n png.getUint32(16) !== image.width || png.getUint32(20) !== image.height) {\n throw new Error(`PNG header dimensions do not match resource ${image.key}`);\n }\n const bitmap = await createImageBitmap(new Blob([image.bytes], { type: \"image/png\" }), {\n premultiplyAlpha: \"none\",\n colorSpaceConversion: \"none\",\n });\n try {\n if (bitmap.width !== image.width || bitmap.height !== image.height) throw new Error(\"Decoded PNG dimension mismatch\");\n this.device.queue.copyExternalImageToTexture(\n { source: bitmap },\n { texture: resource.texture, premultipliedAlpha: false },\n [image.width, image.height],\n );\n } finally {\n bitmap.close();\n }\n }\n this.images.set(image.key, resource);\n this.textureBytes += image.width * image.height * 4;\n this.imageUploadBytes += image.width * image.height * 4;\n this.imagePayloadBytes += image.byteLength;\n } catch (error) {\n resource.texture.destroy();\n throw error;\n }\n }\n }\n\n prepareGlyphs(cells: readonly (TerminalCell | undefined)[]): void {\n const visible = new Map<string, TerminalCell>();\n for (const cell of cells) {\n if (!cell || !cell.width || !cell.text.trim() || (cell.attributes & 64)) continue;\n visible.set(glyphKey(cell), cell);\n }\n const keyUnits = (glyphs: ReadonlyMap<string, TerminalCell>) => [...glyphs.keys()].reduce((total, key) => total + key.length, 0);\n if (visible.size > MAX_GLYPHS || keyUnits(visible) > MAX_GLYPH_KEY_UNITS) {\n throw new Error(\"Visible glyph metadata exceeds the bounded glyph cache\");\n }\n const missing = new Map([...visible].filter(([key]) => !this.glyphs.has(key)));\n if (!missing.size) return;\n const metadataFits = this.glyphs.size + missing.size <= MAX_GLYPHS &&\n this.glyphKeyUnits + keyUnits(missing) <= MAX_GLYPH_KEY_UNITS;\n let plan = metadataFits ? packGlyphs(missing, this.atlas.width, this.scale, this.shelf) : null;\n if (!plan) {\n let size = this.atlas.width;\n const maxSize = Math.min(4096, this.device.limits.maxTextureDimension2D);\n while (!(plan = packGlyphs(visible, size, this.scale)) && size < maxSize) {\n size = Math.min(size * 2, maxSize);\n }\n if (!plan) throw new Error(\"Visible glyphs exceed the bounded 4096² mask atlas; reduce the grid or backing scale\");\n this.resetAtlas(size);\n this.atlasRebuilds++;\n }\n for (const placement of plan.placements) this.uploadGlyph(placement);\n this.shelf = plan.shelf;\n }\n\n uploadGlyph({ key, cell, x, y, width, height }: GlyphPlacement): void {\n const scale = this.scale;\n const raster = this.raster;\n const style = cell.attributes & 5;\n let metrics = this.fontMetrics.get(style);\n if (!metrics) {\n metrics = measureFont(raster, this.font.cssFamily, style, scale, CELL_WIDTH, CELL_HEIGHT);\n this.fontMetrics.set(style, metrics);\n }\n this.rasterCanvas.width = width;\n this.rasterCanvas.height = height;\n raster.font = metrics.font;\n raster.textBaseline = \"alphabetic\";\n raster.textAlign = \"left\";\n raster.fillStyle = \"white\";\n // One transform per font style, not per glyph: borders remain font outlines,\n // and graphemes are clipped to their server-owned span without individual stretching.\n raster.setTransform(metrics.xScale, 0, 0, metrics.yScale, 2, 2 + metrics.baseline);\n raster.fillText(cell.text, 0, 0);\n const pixels = raster.getImageData(0, 0, width, height);\n let colored = false;\n for (let i = 0; i < pixels.data.length; i += 4) {\n if (pixels.data[i + 3] && (pixels.data[i] !== pixels.data[i + 1] || pixels.data[i + 1] !== pixels.data[i + 2])) {\n colored = true;\n break;\n }\n }\n this.device.queue.writeTexture(\n { texture: this.atlas.texture, origin: [x, y] },\n pixels.data,\n { bytesPerRow: width * 4, rowsPerImage: height },\n [width, height],\n );\n this.glyphUploadBytes += width * height * 4;\n this.glyphs.set(key, {\n colored,\n u0: (x + 2) / this.atlas.width,\n v0: (y + 2) / this.atlas.height,\n u1: (x + 2 + cell.width * CELL_WIDTH * scale) / this.atlas.width,\n v1: (y + 2 + CELL_HEIGHT * scale) / this.atlas.height,\n });\n this.glyphKeyUnits += key.length;\n }\n\n /** Clip geometry and UVs together. Only adjacent compatible textures may coalesce. */\n quad(resource: TextureResource, x: number, y: number, width: number, height: number,\n color: Vector4, mode = 0, uv: Vector4 = [0, 0, 1, 1],\n clip: Vector4 = [0, 0, this.width, this.height]): void {\n if (width <= 0 || height <= 0 || color[3] <= 0) return;\n const left = Math.max(0, x, clip[0]);\n const top = Math.max(0, y, clip[1]);\n const right = Math.min(this.width, x + width, clip[0] + clip[2]);\n const bottom = Math.min(this.height, y + height, clip[1] + clip[3]);\n if (right <= left || bottom <= top) return;\n if (this.quadCount >= MAX_QUADS) throw new Error(\"Frame exceeds bounded quad budget\");\n const offset = this.quadCount * STRIDE;\n if (offset + STRIDE > this.instances.length) {\n const grown = new Float32Array(Math.min(this.instances.length * 2, MAX_QUADS * STRIDE));\n grown.set(this.instances);\n this.instances = grown;\n }\n const du = uv[2] - uv[0];\n const dv = uv[3] - uv[1];\n this.instances.set([\n left, top, right - left, bottom - top,\n uv[0] + (left - x) / width * du,\n uv[1] + (top - y) / height * dv,\n uv[0] + (right - x) / width * du,\n uv[1] + (bottom - y) / height * dv,\n ...color, mode, 0, 0, 0,\n ], offset);\n const last = this.batches[this.batches.length - 1];\n if (last?.resource === resource) last.count++;\n else this.batches.push({ resource, start: this.quadCount, count: 1 });\n this.quadCount++;\n }\n\n solid(x: number, y: number, width: number, height: number, color: Vector4): void {\n this.quad(this.atlas, x, y, width, height, color);\n }\n\n placement(placement: ImagePlacement): void {\n const image = this.images.get(placement.key);\n if (!image) throw new Error(`Placement texture is missing: ${placement.key}`);\n const { sourceX: sx, sourceY: sy, sourceWidth: sw, sourceHeight: sh } = placement;\n if (!sw || !sh || !placement.width || !placement.height) return;\n // Clip out-of-texture source regions in destination space instead of stretching edge texels.\n const sourceLeft = placement.x + Math.max(0, -sx) / sw * placement.width;\n const sourceTop = placement.y + Math.max(0, -sy) / sh * placement.height;\n const sourceRight = placement.x + Math.min(sw, image.width - sx) / sw * placement.width;\n const sourceBottom = placement.y + Math.min(sh, image.height - sy) / sh * placement.height;\n const left = Math.max(sourceLeft, placement.clipX);\n const top = Math.max(sourceTop, placement.clipY);\n const right = Math.min(sourceRight, placement.clipX + placement.clipWidth);\n const bottom = Math.min(sourceBottom, placement.clipY + placement.clipHeight);\n this.quad(\n image, placement.x, placement.y, placement.width, placement.height, WHITE, 2,\n [sx / image.width, sy / image.height, (sx + sw) / image.width, (sy + sh) / image.height],\n [left, top, Math.max(0, right - left), Math.max(0, bottom - top)],\n );\n }\n\n decorations(cell: TerminalCell, x: number, y: number, width: number, foreground: Vector4): void {\n if (cell.attributes & 128) this.solid(x, y + 10, width, 1, foreground);\n if (cell.attributes & 256) this.solid(x, y + 1, width, 1, foreground);\n const style = cell.underlineStyle || (cell.attributes & 8 ? 1 : 0);\n const color = rgba(cell.underlineColor);\n if (style === 1) this.solid(x, y + 18, width, 1, color);\n else if (style === 2) {\n this.solid(x, y + 16, width, 1, color);\n this.solid(x, y + 18, width, 1, color);\n } else if (style === 3) {\n for (let dx = 0; dx < width; dx++) {\n this.solid(x + dx, y + 17 + Math.round(Math.sin((x + dx) * Math.PI / 4)), 1, 1, color);\n }\n } else if (style === 4 || style === 5) {\n const step = style === 4 ? 2 : 5;\n const segment = style === 4 ? 1 : 3;\n for (let dx = 0; dx < width; dx += step) this.solid(x + dx, y + 18, Math.min(segment, width - dx), 1, color);\n }\n }\n\n render(cells: readonly (TerminalCell | undefined)[], metadata: FrameMetadata, blinkOn: boolean) {\n const start = performance.now();\n this.quadCount = 0;\n this.batches = [];\n const placements = metadata.placements.map((placement, order) => ({\n placement,\n order,\n z: placement.kind === \"sixel\" ? -1 : placement.z,\n })).sort((a, b) => a.z - b.z || a.order - b.order);\n for (const item of placements) if (item.z < -1073741824) this.placement(item.placement);\n for (let i = 0; i < cells.length; i++) {\n const cell = cells[i];\n if (!cell) continue;\n this.solid((i % this.columns) * CELL_WIDTH, Math.floor(i / this.columns) * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT, rgba(cell.background));\n }\n for (const item of placements) if (item.z >= -1073741824 && item.z < 0) this.placement(item.placement);\n for (let i = 0; i < cells.length; i++) {\n const cell = cells[i];\n if (!cell || !cell.width || (cell.attributes & 64) || ((cell.attributes & 16) && !blinkOn)) continue;\n const x = (i % this.columns) * CELL_WIDTH;\n const y = Math.floor(i / this.columns) * CELL_HEIGHT;\n const width = Math.min(cell.width * CELL_WIDTH, this.width - x);\n const foreground = rgba(cell.foreground);\n const glyph = this.glyphs.get(glyphKey(cell));\n if (glyph) {\n const tint: Vector4 = glyph.colored ? (cell.attributes & 2 ? [0.5, 0.5, 0.5, 1] : WHITE) : foreground;\n this.quad(this.atlas, x, y, cell.width * CELL_WIDTH, CELL_HEIGHT,\n tint, glyph.colored ? 2 : 1, [glyph.u0, glyph.v0, glyph.u1, glyph.v1]);\n }\n // Reverse and dim are already reflected in server-projected colors.\n this.decorations(cell, x, y, width, foreground);\n }\n for (const item of placements) if (item.z >= 0) this.placement(item.placement);\n const cursor = metadata.cursor;\n const cursorBlink = cursor.shape === 0 || cursor.shape % 2 === 1;\n if (cursor.visible && (!cursorBlink || blinkOn) && cursor.x >= 0 && cursor.x < this.columns && cursor.y >= 0 && cursor.y < this.rows) {\n const cell = cells[cursor.y * this.columns + cursor.x];\n const color = rgba(cell?.foreground ?? 0xffffffff);\n const x = cursor.x * CELL_WIDTH;\n const y = cursor.y * CELL_HEIGHT;\n if (cursor.shape === 3 || cursor.shape === 4) this.solid(x, y + 18, CELL_WIDTH, 2, color);\n else if (cursor.shape === 5 || cursor.shape === 6) this.solid(x, y, 2, CELL_HEIGHT, color);\n else {\n color[3] *= 0.55;\n this.solid(x, y, CELL_WIDTH, CELL_HEIGHT, color);\n }\n }\n const usedBytes = this.quadCount * STRIDE * 4;\n if (!this.instanceBuffer || usedBytes > this.instanceBufferBytes) {\n this.instanceBuffer?.destroy();\n this.instanceBufferBytes = Math.max(256, this.instances.byteLength);\n this.instanceBuffer = this.device.createBuffer({\n size: this.instanceBufferBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n if (usedBytes) this.device.queue.writeBuffer(this.instanceBuffer, 0, this.instances, 0, this.quadCount * STRIDE);\n const encoder = this.device.createCommandEncoder();\n const base = rgba(metadata.defaultBackground ?? cells[0]?.background ?? 0xff000000);\n const pass = encoder.beginRenderPass({\n colorAttachments: [{\n view: this.context.getCurrentTexture().createView(),\n clearValue: { r: base[0], g: base[1], b: base[2], a: 1 },\n loadOp: \"clear\",\n storeOp: \"store\",\n }],\n });\n pass.setPipeline(this.pipeline);\n pass.setVertexBuffer(0, this.instanceBuffer);\n for (const batch of this.batches) {\n pass.setBindGroup(0, batch.resource.bindGroup);\n pass.draw(6, batch.count, 0, batch.start);\n }\n pass.end();\n this.device.queue.submit([encoder.finish()]);\n return { cpuMs: performance.now() - start, quads: this.quadCount, drawCalls: this.batches.length };\n }\n\n metrics() {\n return {\n fontFamily: this.font.family,\n rasterScale: this.scale,\n backingScale: this.backingScale,\n backingWidth: this.canvas.width,\n backingHeight: this.canvas.height,\n imageCount: this.images.size,\n textureBytes: this.textureBytes,\n atlasGlyphs: this.glyphs.size,\n atlasBytes: this.atlas.width * this.atlas.height * 4,\n atlasRebuilds: this.atlasRebuilds,\n imageUploadBytes: this.imageUploadBytes,\n imagePayloadBytes: this.imagePayloadBytes,\n glyphUploadBytes: this.glyphUploadBytes,\n instanceBufferBytes: this.instanceBufferBytes,\n };\n }\n\n async idle() {\n await this.device.queue.onSubmittedWorkDone();\n }\n\n dispose() {\n this.disposed = true;\n for (const image of this.images.values()) image.texture.destroy();\n this.images.clear();\n this.atlas?.texture.destroy();\n this.instanceBuffer?.destroy();\n this.uniform?.destroy();\n this.font?.dispose();\n this.fontMetrics.clear();\n this.context.unconfigure();\n this.device.destroy();\n }\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { MouseTrackingMode, SelectionMode, TerminalPoint, TerminalSelection } from "./types.js";
|
|
2
|
+
import type { CellPosition } from "./wire-types.js";
|
|
3
|
+
export interface GestureState {
|
|
4
|
+
tracking: MouseTrackingMode;
|
|
5
|
+
historical?: boolean;
|
|
6
|
+
readOnly?: boolean;
|
|
7
|
+
selection?: Pick<TerminalSelection, "status" | "mode" | "canExtend">;
|
|
8
|
+
}
|
|
9
|
+
export type GestureStart = {
|
|
10
|
+
owner: "app";
|
|
11
|
+
} | {
|
|
12
|
+
owner: "local";
|
|
13
|
+
mode: SelectionMode;
|
|
14
|
+
extend: boolean;
|
|
15
|
+
};
|
|
16
|
+
type PointEvent = Pick<MouseEvent, "clientX" | "clientY" | "shiftKey" | "altKey" | "ctrlKey">;
|
|
17
|
+
export declare function cellPoint(event: PointEvent, bounds: Pick<DOMRect, "left" | "top" | "width" | "height">, columns: number, rows: number, clamp?: boolean): CellPosition | null;
|
|
18
|
+
export declare class WheelAccumulator {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
reset(): void;
|
|
22
|
+
take(event: Pick<WheelEvent, "deltaMode" | "deltaX" | "deltaY">, bounds: Pick<DOMRect, "height">, rows: number): TerminalPoint;
|
|
23
|
+
}
|
|
24
|
+
/** Ownership and granularity are latched, independent of subsequent modifiers. */
|
|
25
|
+
export declare class SelectionGesture {
|
|
26
|
+
owner: "local" | "app" | null;
|
|
27
|
+
mode: SelectionMode;
|
|
28
|
+
endpoint: TerminalPoint | null;
|
|
29
|
+
begin(event: Pick<MouseEvent, "button" | "shiftKey" | "altKey" | "detail">, point: TerminalPoint, { tracking, historical, readOnly, selection }: GestureState): GestureStart | null;
|
|
30
|
+
move(point: TerminalPoint): TerminalPoint | null;
|
|
31
|
+
scrollPoint(point: TerminalPoint): TerminalPoint | undefined;
|
|
32
|
+
wheelOwner(event: Pick<MouseEvent, "shiftKey">, { tracking, historical, readOnly }: GestureState): "local" | "app";
|
|
33
|
+
end(): void;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=selection-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-input.d.ts","sourceRoot":"","sources":["../src/selection-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACrG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;CACtE;AACD,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AACvG,KAAK,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;AAE9F,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC,EACrG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,YAAY,GAAG,IAAI,CAUnE;AAED,qBAAa,gBAAgB;IAC3B,CAAC,SAAK;IACN,CAAC,SAAK;IACN,KAAK;IACL,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa;CAY/H;AAED,kFAAkF;AAClF,qBAAa,gBAAgB;IAC3B,KAAK,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,CAAQ;IACrC,IAAI,EAAE,aAAa,CAAe;IAClC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAQ;IACtC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC,EAAE,KAAK,EAAE,aAAa,EAC9F,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,YAAY,GAAG,YAAY,GAAG,IAAI;IAYnF,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,IAAI;IAKhD,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS;IAK5D,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,YAAY,GAAG,OAAO,GAAG,KAAK;IAGlH,GAAG;CACJ"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export function cellPoint(event, bounds, columns, rows, clamp = false) {
|
|
2
|
+
if (!(bounds.width > 0) || !(bounds.height > 0))
|
|
3
|
+
return null;
|
|
4
|
+
const x = Math.floor((event.clientX - bounds.left) * columns / bounds.width);
|
|
5
|
+
const y = Math.floor((event.clientY - bounds.top) * rows / bounds.height);
|
|
6
|
+
if (!clamp && (x < 0 || y < 0 || x >= columns || y >= rows))
|
|
7
|
+
return null;
|
|
8
|
+
return {
|
|
9
|
+
x: Math.max(0, Math.min(columns - 1, x)),
|
|
10
|
+
y: Math.max(0, Math.min(rows - 1, y)),
|
|
11
|
+
shift: !!event.shiftKey, alt: !!event.altKey, ctrl: !!event.ctrlKey
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export class WheelAccumulator {
|
|
15
|
+
x = 0;
|
|
16
|
+
y = 0;
|
|
17
|
+
reset() { this.x = this.y = 0; }
|
|
18
|
+
take(event, bounds, rows) {
|
|
19
|
+
const cellHeight = bounds.height / rows;
|
|
20
|
+
if (!(cellHeight > 0))
|
|
21
|
+
return { x: 0, y: 0 };
|
|
22
|
+
const unit = event.deltaMode === 1 ? 1 : event.deltaMode === 2 ? rows : 1 / cellHeight;
|
|
23
|
+
this.x += event.deltaX * unit;
|
|
24
|
+
this.y += event.deltaY * unit;
|
|
25
|
+
const x = Math.trunc(this.x);
|
|
26
|
+
const y = Math.trunc(this.y);
|
|
27
|
+
this.x -= x;
|
|
28
|
+
this.y -= y;
|
|
29
|
+
return { x: Math.max(-32, Math.min(32, x)), y: Math.max(-32, Math.min(32, y)) };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Ownership and granularity are latched, independent of subsequent modifiers. */
|
|
33
|
+
export class SelectionGesture {
|
|
34
|
+
owner = null;
|
|
35
|
+
mode = "character";
|
|
36
|
+
endpoint = null;
|
|
37
|
+
begin(event, point, { tracking, historical, readOnly, selection }) {
|
|
38
|
+
if (this.owner)
|
|
39
|
+
return null;
|
|
40
|
+
const local = historical || readOnly || !tracking || event.shiftKey;
|
|
41
|
+
if (local && event.button !== 0)
|
|
42
|
+
return null;
|
|
43
|
+
this.owner = local ? "local" : "app";
|
|
44
|
+
if (!local)
|
|
45
|
+
return { owner: "app" };
|
|
46
|
+
const extend = !!event.shiftKey && !!selection && ["valid", "pending"].includes(selection.status) && selection.canExtend !== false;
|
|
47
|
+
this.mode = extend && selection ? selection.mode : event.altKey ? "rectangle"
|
|
48
|
+
: event.detail >= 3 ? "line" : event.detail === 2 ? "word" : "character";
|
|
49
|
+
this.endpoint = { x: point.x, y: point.y };
|
|
50
|
+
return { owner: this.owner, mode: this.mode, extend };
|
|
51
|
+
}
|
|
52
|
+
move(point) {
|
|
53
|
+
if (this.owner !== "local")
|
|
54
|
+
return null;
|
|
55
|
+
this.endpoint = { x: point.x, y: point.y };
|
|
56
|
+
return { ...this.endpoint };
|
|
57
|
+
}
|
|
58
|
+
scrollPoint(point) {
|
|
59
|
+
if (this.owner !== "local")
|
|
60
|
+
return undefined;
|
|
61
|
+
// A wheel cannot widen a rectangle; only actual pointer movement can.
|
|
62
|
+
return { x: this.mode === "rectangle" && this.endpoint ? this.endpoint.x : point.x, y: point.y };
|
|
63
|
+
}
|
|
64
|
+
wheelOwner(event, { tracking, historical, readOnly }) {
|
|
65
|
+
return this.owner ?? (historical || readOnly || !tracking || event.shiftKey ? "local" : "app");
|
|
66
|
+
}
|
|
67
|
+
end() { this.owner = null; }
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=selection-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-input.js","sourceRoot":"","sources":["../src/selection-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MouseTrackingMode, SelectionMode, TerminalPoint, TerminalSelection } from \"./types.js\";\nimport type { CellPosition } from \"./wire-types.js\";\n\nexport interface GestureState {\n tracking: MouseTrackingMode;\n historical?: boolean;\n readOnly?: boolean;\n selection?: Pick<TerminalSelection, \"status\" | \"mode\" | \"canExtend\">;\n}\nexport type GestureStart = { owner: \"app\" } | { owner: \"local\"; mode: SelectionMode; extend: boolean };\ntype PointEvent = Pick<MouseEvent, \"clientX\" | \"clientY\" | \"shiftKey\" | \"altKey\" | \"ctrlKey\">;\n\nexport function cellPoint(event: PointEvent, bounds: Pick<DOMRect, \"left\" | \"top\" | \"width\" | \"height\">,\n columns: number, rows: number, clamp = false): CellPosition | null {\n if (!(bounds.width > 0) || !(bounds.height > 0)) return null;\n const x = Math.floor((event.clientX - bounds.left) * columns / bounds.width);\n const y = Math.floor((event.clientY - bounds.top) * rows / bounds.height);\n if (!clamp && (x < 0 || y < 0 || x >= columns || y >= rows)) return null;\n return {\n x: Math.max(0, Math.min(columns - 1, x)),\n y: Math.max(0, Math.min(rows - 1, y)),\n shift: !!event.shiftKey, alt: !!event.altKey, ctrl: !!event.ctrlKey\n };\n}\n\nexport class WheelAccumulator {\n x = 0;\n y = 0;\n reset() { this.x = this.y = 0; }\n take(event: Pick<WheelEvent, \"deltaMode\" | \"deltaX\" | \"deltaY\">, bounds: Pick<DOMRect, \"height\">, rows: number): TerminalPoint {\n const cellHeight = bounds.height / rows;\n if (!(cellHeight > 0)) return { x: 0, y: 0 };\n const unit = event.deltaMode === 1 ? 1 : event.deltaMode === 2 ? rows : 1 / cellHeight;\n this.x += event.deltaX * unit;\n this.y += event.deltaY * unit;\n const x = Math.trunc(this.x);\n const y = Math.trunc(this.y);\n this.x -= x;\n this.y -= y;\n return { x: Math.max(-32, Math.min(32, x)), y: Math.max(-32, Math.min(32, y)) };\n }\n}\n\n/** Ownership and granularity are latched, independent of subsequent modifiers. */\nexport class SelectionGesture {\n owner: \"local\" | \"app\" | null = null;\n mode: SelectionMode = \"character\";\n endpoint: TerminalPoint | null = null;\n begin(event: Pick<MouseEvent, \"button\" | \"shiftKey\" | \"altKey\" | \"detail\">, point: TerminalPoint,\n { tracking, historical, readOnly, selection }: GestureState): GestureStart | null {\n if (this.owner) return null;\n const local = historical || readOnly || !tracking || event.shiftKey;\n if (local && event.button !== 0) return null;\n this.owner = local ? \"local\" : \"app\";\n if (!local) return { owner: \"app\" };\n const extend = !!event.shiftKey && !!selection && [\"valid\", \"pending\"].includes(selection.status) && selection.canExtend !== false;\n this.mode = extend && selection ? selection.mode : event.altKey ? \"rectangle\"\n : event.detail >= 3 ? \"line\" : event.detail === 2 ? \"word\" : \"character\";\n this.endpoint = { x: point.x, y: point.y };\n return { owner: this.owner, mode: this.mode, extend };\n }\n move(point: TerminalPoint): TerminalPoint | null {\n if (this.owner !== \"local\") return null;\n this.endpoint = { x: point.x, y: point.y };\n return { ...this.endpoint };\n }\n scrollPoint(point: TerminalPoint): TerminalPoint | undefined {\n if (this.owner !== \"local\") return undefined;\n // A wheel cannot widen a rectangle; only actual pointer movement can.\n return { x: this.mode === \"rectangle\" && this.endpoint ? this.endpoint.x : point.x, y: point.y };\n }\n wheelOwner(event: Pick<MouseEvent, \"shiftKey\">, { tracking, historical, readOnly }: GestureState): \"local\" | \"app\" {\n return this.owner ?? (historical || readOnly || !tracking || event.shiftKey ? \"local\" : \"app\");\n }\n end() { this.owner = null; }\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RunTerminalAction, SelectionRange, SelectionUIState, TerminalGeometry, TerminalSize, WebTerminalOptions } from "./types.js";
|
|
2
|
+
export declare function sameSelectionUIState(a: SelectionUIState | undefined, b: SelectionUIState): boolean;
|
|
3
|
+
export declare function selectionRectangles(ranges: readonly SelectionRange[], geometry: TerminalGeometry, canvasSize: TerminalSize): Readonly<{
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}>[];
|
|
9
|
+
/** Owns UI notification/default rendering, not terminal selection or clipboard state. */
|
|
10
|
+
export declare class SelectionUI {
|
|
11
|
+
#private;
|
|
12
|
+
constructor({ element, overlay, button, signal, getState, runAction, onSelectionUI, reportError }: {
|
|
13
|
+
element: HTMLDivElement;
|
|
14
|
+
overlay: HTMLDivElement;
|
|
15
|
+
button: HTMLButtonElement;
|
|
16
|
+
signal: AbortSignal;
|
|
17
|
+
getState: () => SelectionUIState;
|
|
18
|
+
runAction: RunTerminalAction;
|
|
19
|
+
onSelectionUI?: WebTerminalOptions["onSelectionUI"];
|
|
20
|
+
reportError: (error: unknown) => void;
|
|
21
|
+
});
|
|
22
|
+
refresh(force?: boolean): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=selection-ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-ui.d.ts","sourceRoot":"","sources":["../src/selection-ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAC7C,gBAAgB,EAAE,gBAAgB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAY3F,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,gBAAgB,GAAG,SAAS,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAQlG;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY;;;;;KAO1H;AAED,yFAAyF;AACzF,qBAAa,WAAW;;gBAaV,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,EAAE;QACjG,OAAO,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QACjG,QAAQ,EAAE,MAAM,gBAAgB,CAAC;QAAC,SAAS,EAAE,iBAAiB,CAAC;QAC/D,aAAa,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAAC,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;KAC5F;IA4BD,OAAO,CAAC,KAAK,UAAQ;CAqCtB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { isRecord } from "./validation.js";
|
|
2
|
+
const selectionFields = ["status", "mode", "requestId", "active", "pending", "canExtend",
|
|
3
|
+
"text", "message", "copying", "copyError"];
|
|
4
|
+
const viewportFields = ["available", "following", "pending", "generation", "buffer",
|
|
5
|
+
"top", "liveTop", "totalRows", "requestId"];
|
|
6
|
+
const geometryFields = ["columns", "rows", "cellWidth", "cellHeight", "mouseTracking"];
|
|
7
|
+
const rangeFields = ["row", "startColumn", "endColumn"];
|
|
8
|
+
const equalFields = (a, b, fields) => fields.every(field => a?.[field] === b?.[field]);
|
|
9
|
+
export function sameSelectionUIState(a, b) {
|
|
10
|
+
return !!a && a.connected === b.connected && a.readOnly === b.readOnly &&
|
|
11
|
+
equalFields(a.selection, b.selection, selectionFields) &&
|
|
12
|
+
equalFields(a.viewport, b.viewport, viewportFields) &&
|
|
13
|
+
equalFields(a.geometry, b.geometry, geometryFields) &&
|
|
14
|
+
equalFields(a.canvasSize, b.canvasSize, ["width", "height"]) &&
|
|
15
|
+
a.selection.ranges.length === b.selection.ranges.length &&
|
|
16
|
+
a.selection.ranges.every((range, index) => equalFields(range, b.selection.ranges[index], rangeFields));
|
|
17
|
+
}
|
|
18
|
+
export function selectionRectangles(ranges, geometry, canvasSize) {
|
|
19
|
+
const width = canvasSize.width / geometry.columns;
|
|
20
|
+
const height = canvasSize.height / geometry.rows;
|
|
21
|
+
return ranges.map(range => Object.freeze({
|
|
22
|
+
left: range.startColumn * width, top: range.row * height,
|
|
23
|
+
width: (range.endColumn - range.startColumn) * width, height
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
/** Owns UI notification/default rendering, not terminal selection or clipboard state. */
|
|
27
|
+
export class SelectionUI {
|
|
28
|
+
#element;
|
|
29
|
+
#overlay;
|
|
30
|
+
#button;
|
|
31
|
+
#signal;
|
|
32
|
+
#getState;
|
|
33
|
+
#runAction;
|
|
34
|
+
#reportError;
|
|
35
|
+
#previous;
|
|
36
|
+
#notification;
|
|
37
|
+
#queued = false;
|
|
38
|
+
#force = false;
|
|
39
|
+
constructor({ element, overlay, button, signal, getState, runAction, onSelectionUI, reportError }) {
|
|
40
|
+
this.#element = element;
|
|
41
|
+
this.#overlay = overlay;
|
|
42
|
+
this.#button = button;
|
|
43
|
+
this.#signal = signal;
|
|
44
|
+
this.#getState = getState;
|
|
45
|
+
this.#runAction = runAction;
|
|
46
|
+
this.#reportError = reportError;
|
|
47
|
+
if (onSelectionUI) {
|
|
48
|
+
element.addEventListener("selectionui", event => {
|
|
49
|
+
if (!this.#notification || event !== this.#notification)
|
|
50
|
+
return;
|
|
51
|
+
const snapshot = this.#previous;
|
|
52
|
+
try {
|
|
53
|
+
const result = onSelectionUI(this.#notification);
|
|
54
|
+
if (result !== undefined) {
|
|
55
|
+
if (isRecord(result) && typeof result.then === "function")
|
|
56
|
+
Promise.resolve(result).catch(error => {
|
|
57
|
+
if (!signal.aborted && this.#previous === snapshot)
|
|
58
|
+
reportError(error);
|
|
59
|
+
});
|
|
60
|
+
throw new TypeError("onSelectionUI must finish synchronously; use preventDefault() and signal for UI ownership");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
reportError(error);
|
|
66
|
+
}
|
|
67
|
+
}, { signal });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
refresh(force = false) {
|
|
71
|
+
this.#force ||= force;
|
|
72
|
+
if (this.#queued || this.#signal.aborted)
|
|
73
|
+
return;
|
|
74
|
+
this.#queued = true;
|
|
75
|
+
// Coalesce geometry and history from the same presented frame before notifying the host.
|
|
76
|
+
queueMicrotask(() => {
|
|
77
|
+
this.#queued = false;
|
|
78
|
+
if (this.#signal.aborted)
|
|
79
|
+
return;
|
|
80
|
+
const state = this.#getState();
|
|
81
|
+
const force = this.#force;
|
|
82
|
+
this.#force = false;
|
|
83
|
+
if (!force && sameSelectionUIState(this.#previous, state))
|
|
84
|
+
return;
|
|
85
|
+
const snapshot = Object.freeze({
|
|
86
|
+
...state,
|
|
87
|
+
selection: Object.freeze({ ...state.selection,
|
|
88
|
+
ranges: Object.freeze(state.selection.ranges.map(range => Object.freeze({ ...range }))) }),
|
|
89
|
+
viewport: Object.freeze({ ...state.viewport, rowIds: Object.freeze([...(state.viewport.rowIds ?? [])]) }),
|
|
90
|
+
geometry: Object.freeze({ ...state.geometry }),
|
|
91
|
+
canvasSize: Object.freeze({ ...state.canvasSize })
|
|
92
|
+
});
|
|
93
|
+
this.#previous = snapshot;
|
|
94
|
+
const detail = Object.freeze({
|
|
95
|
+
...snapshot, overlay: this.#overlay, signal: this.#signal, runAction: this.#runAction,
|
|
96
|
+
rects: Object.freeze(selectionRectangles(snapshot.selection.ranges, snapshot.geometry, snapshot.canvasSize))
|
|
97
|
+
});
|
|
98
|
+
const event = new CustomEvent("selectionui", { cancelable: true, detail });
|
|
99
|
+
this.#notification = event;
|
|
100
|
+
this.#reportError(null);
|
|
101
|
+
this.#element.dispatchEvent(event);
|
|
102
|
+
if (this.#signal.aborted)
|
|
103
|
+
return;
|
|
104
|
+
const selection = snapshot.selection;
|
|
105
|
+
this.#button.hidden = event.defaultPrevented || ["none", "unavailable"].includes(selection.status);
|
|
106
|
+
this.#button.disabled = !snapshot.connected || selection.status !== "valid" || selection.copying;
|
|
107
|
+
const label = selection.copying ? "Copying\u2026" : "Copy";
|
|
108
|
+
if (this.#button.textContent !== label)
|
|
109
|
+
this.#button.textContent = label;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=selection-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-ui.js","sourceRoot":"","sources":["../src/selection-ui.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RunTerminalAction, SelectionRange, SelectionUIDetail, SelectionUIEvent,\n SelectionUIState, TerminalGeometry, TerminalSize, WebTerminalOptions } from \"./types.js\";\nimport { isRecord } from \"./validation.js\";\n\nconst selectionFields = [\"status\", \"mode\", \"requestId\", \"active\", \"pending\", \"canExtend\",\n \"text\", \"message\", \"copying\", \"copyError\"] as const;\nconst viewportFields = [\"available\", \"following\", \"pending\", \"generation\", \"buffer\",\n \"top\", \"liveTop\", \"totalRows\", \"requestId\"] as const;\nconst geometryFields = [\"columns\", \"rows\", \"cellWidth\", \"cellHeight\", \"mouseTracking\"] as const;\nconst rangeFields = [\"row\", \"startColumn\", \"endColumn\"] as const;\nconst equalFields = <T>(a: T | undefined, b: T | undefined, fields: readonly (keyof T)[]) =>\n fields.every(field => a?.[field] === b?.[field]);\n\nexport function sameSelectionUIState(a: SelectionUIState | undefined, b: SelectionUIState): boolean {\n return !!a && a.connected === b.connected && a.readOnly === b.readOnly &&\n equalFields(a.selection, b.selection, selectionFields) &&\n equalFields(a.viewport, b.viewport, viewportFields) &&\n equalFields(a.geometry, b.geometry, geometryFields) &&\n equalFields(a.canvasSize, b.canvasSize, [\"width\", \"height\"]) &&\n a.selection.ranges.length === b.selection.ranges.length &&\n a.selection.ranges.every((range, index) => equalFields(range, b.selection.ranges[index], rangeFields));\n}\n\nexport function selectionRectangles(ranges: readonly SelectionRange[], geometry: TerminalGeometry, canvasSize: TerminalSize) {\n const width = canvasSize.width / geometry.columns;\n const height = canvasSize.height / geometry.rows;\n return ranges.map(range => Object.freeze({\n left: range.startColumn * width, top: range.row * height,\n width: (range.endColumn - range.startColumn) * width, height\n }));\n}\n\n/** Owns UI notification/default rendering, not terminal selection or clipboard state. */\nexport class SelectionUI {\n #element: HTMLDivElement;\n #overlay: HTMLDivElement;\n #button: HTMLButtonElement;\n #signal: AbortSignal;\n #getState: () => SelectionUIState;\n #runAction: RunTerminalAction;\n #reportError: (error: unknown) => void;\n #previous: SelectionUIState | undefined;\n #notification: SelectionUIEvent | undefined;\n #queued = false;\n #force = false;\n\n constructor({ element, overlay, button, signal, getState, runAction, onSelectionUI, reportError }: {\n element: HTMLDivElement; overlay: HTMLDivElement; button: HTMLButtonElement; signal: AbortSignal;\n getState: () => SelectionUIState; runAction: RunTerminalAction;\n onSelectionUI?: WebTerminalOptions[\"onSelectionUI\"]; reportError: (error: unknown) => void;\n }) {\n this.#element = element;\n this.#overlay = overlay;\n this.#button = button;\n this.#signal = signal;\n this.#getState = getState;\n this.#runAction = runAction;\n this.#reportError = reportError;\n if (onSelectionUI) {\n element.addEventListener(\"selectionui\", event => {\n if (!this.#notification || event !== this.#notification) return;\n const snapshot = this.#previous;\n try {\n const result: unknown = onSelectionUI(this.#notification);\n if (result !== undefined) {\n if (isRecord(result) && typeof result.then === \"function\") Promise.resolve(result).catch(error => {\n if (!signal.aborted && this.#previous === snapshot) reportError(error);\n });\n throw new TypeError(\"onSelectionUI must finish synchronously; use preventDefault() and signal for UI ownership\");\n }\n } catch (error) {\n event.preventDefault();\n reportError(error);\n }\n }, { signal });\n }\n }\n\n refresh(force = false) {\n this.#force ||= force;\n if (this.#queued || this.#signal.aborted) return;\n this.#queued = true;\n // Coalesce geometry and history from the same presented frame before notifying the host.\n queueMicrotask(() => {\n this.#queued = false;\n if (this.#signal.aborted) return;\n const state = this.#getState();\n const force = this.#force;\n this.#force = false;\n if (!force && sameSelectionUIState(this.#previous, state)) return;\n const snapshot: SelectionUIState = Object.freeze({\n ...state,\n selection: Object.freeze({ ...state.selection,\n ranges: Object.freeze(state.selection.ranges.map(range => Object.freeze({ ...range }))) }),\n viewport: Object.freeze({ ...state.viewport, rowIds: Object.freeze([...(state.viewport.rowIds ?? [])]) }),\n geometry: Object.freeze({ ...state.geometry }),\n canvasSize: Object.freeze({ ...state.canvasSize })\n });\n this.#previous = snapshot;\n const detail = Object.freeze({\n ...snapshot, overlay: this.#overlay, signal: this.#signal, runAction: this.#runAction,\n rects: Object.freeze(selectionRectangles(snapshot.selection.ranges, snapshot.geometry, snapshot.canvasSize))\n });\n const event = new CustomEvent<SelectionUIDetail>(\"selectionui\", { cancelable: true, detail });\n this.#notification = event;\n this.#reportError(null);\n this.#element.dispatchEvent(event);\n if (this.#signal.aborted) return;\n const selection = snapshot.selection;\n this.#button.hidden = event.defaultPrevented || [\"none\", \"unavailable\"].includes(selection.status);\n this.#button.disabled = !snapshot.connected || selection.status !== \"valid\" || selection.copying;\n const label = selection.copying ? \"Copying\\u2026\" : \"Copy\";\n if (this.#button.textContent !== label) this.#button.textContent = label;\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Resolve caller-relative URLs before sending the configuration to the worker. */
|
|
2
|
+
export declare function normalizeFont(font?: TerminalFont, baseUrl?: string): NormalizedFont;
|
|
3
|
+
/** Use the rendering context's FontFaceSet; a worker cannot inherit page fonts. */
|
|
4
|
+
export declare function loadFont(configuration: TerminalFont): Promise<LoadedFont>;
|
|
5
|
+
/** Fit one font-wide advance and line box to the authoritative cell dimensions. */
|
|
6
|
+
export declare function measureFont(raster: OffscreenCanvasRenderingContext2D, cssFamily: string, attributes: number, scale: number, cellWidth: number, cellHeight: number): FontMetrics;
|
|
7
|
+
import type { TerminalFont, TerminalFontFace } from "./types.js";
|
|
8
|
+
export interface NormalizedFont {
|
|
9
|
+
family: string;
|
|
10
|
+
faces: Required<TerminalFontFace>[];
|
|
11
|
+
}
|
|
12
|
+
export interface LoadedFont {
|
|
13
|
+
family: string;
|
|
14
|
+
cssFamily: string;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
17
|
+
export interface FontMetrics {
|
|
18
|
+
font: string;
|
|
19
|
+
xScale: number;
|
|
20
|
+
yScale: number;
|
|
21
|
+
baseline: number;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=terminal-font.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-font.d.ts","sourceRoot":"","sources":["../src/terminal-font.ts"],"names":[],"mappings":"AAGA,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,OAAO,SAAkB,GAAG,cAAc,CA2B5F;AAED,mFAAmF;AACnF,wBAAsB,QAAQ,CAAC,aAAa,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CA6B/E;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,MAAM,EAAE,iCAAiC,EAAE,SAAS,EAAE,MAAM,EACtF,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAcvF;AACD,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGjE,MAAM,WAAW,cAAc;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAA;CAAE;AACvF,MAAM,WAAW,UAAU;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAAE;AAClF,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const defaultFontUrl = new URL("./fonts/cascadia-mono-nf/CascadiaMonoNF.woff2", import.meta.url).href;
|
|
2
|
+
const genericFamilies = new Set(["monospace", "serif", "sans-serif", "system-ui"]);
|
|
3
|
+
/** Resolve caller-relative URLs before sending the configuration to the worker. */
|
|
4
|
+
export function normalizeFont(font, baseUrl = import.meta.url) {
|
|
5
|
+
font ??= { family: "Cascadia Mono NF", faces: [{ url: defaultFontUrl, weight: "200 700" }] };
|
|
6
|
+
if (typeof font !== "object" || Array.isArray(font) ||
|
|
7
|
+
typeof font.family !== "string" || !font.family.trim() || font.family.length > 256 ||
|
|
8
|
+
/[\u0000-\u001f\u007f]/u.test(font.family)) {
|
|
9
|
+
throw new TypeError("font.family must be a single, nonempty font family name");
|
|
10
|
+
}
|
|
11
|
+
const faces = font.faces ?? [];
|
|
12
|
+
if (!Array.isArray(faces) || faces.length > 16)
|
|
13
|
+
throw new TypeError("font.faces must contain at most 16 font sources");
|
|
14
|
+
return {
|
|
15
|
+
family: font.family.trim(),
|
|
16
|
+
faces: faces.map(face => {
|
|
17
|
+
if (!face || typeof face.url !== "string" || !face.url.trim()) {
|
|
18
|
+
throw new TypeError("Each font face requires a URL");
|
|
19
|
+
}
|
|
20
|
+
for (const field of ["weight", "style"]) {
|
|
21
|
+
if (face[field] !== undefined && (typeof face[field] !== "string" || face[field].length > 64)) {
|
|
22
|
+
throw new TypeError(`Font face ${field} must be a CSS descriptor string`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
url: new URL(face.url, baseUrl).href,
|
|
27
|
+
weight: face.weight ?? "400",
|
|
28
|
+
style: face.style ?? "normal"
|
|
29
|
+
};
|
|
30
|
+
})
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Use the rendering context's FontFaceSet; a worker cannot inherit page fonts. */
|
|
34
|
+
export async function loadFont(configuration) {
|
|
35
|
+
const { family, faces } = normalizeFont(configuration);
|
|
36
|
+
const scope = globalThis;
|
|
37
|
+
const fontSet = "fonts" in scope && isFontSet(scope.fonts)
|
|
38
|
+
? scope.fonts : globalThis.document?.fonts;
|
|
39
|
+
if (!fontSet || typeof FontFace !== "function") {
|
|
40
|
+
throw new Error("Terminal font loading requires the CSS Font Loading API in the rendering context");
|
|
41
|
+
}
|
|
42
|
+
const generic = genericFamilies.has(family.toLowerCase());
|
|
43
|
+
const cssFamily = generic ? family.toLowerCase() : JSON.stringify(family);
|
|
44
|
+
if (generic && faces.length)
|
|
45
|
+
throw new TypeError("A generic font family cannot have downloadable faces");
|
|
46
|
+
const sources = faces.length ? faces : generic ? [] : [{ local: family }];
|
|
47
|
+
const loaded = [];
|
|
48
|
+
for (const source of sources) {
|
|
49
|
+
try {
|
|
50
|
+
const face = new FontFace(family, "local" in source ? `local(${JSON.stringify(source.local)})` : `url(${JSON.stringify(source.url)})`, { weight: source.weight ?? "400", style: source.style ?? "normal" });
|
|
51
|
+
loaded.push(await face.load());
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new Error(`Could not load terminal font "${family}" from ${"url" in source ? source.url : "local fonts"}`, { cause: error });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const face of loaded)
|
|
58
|
+
fontSet.add(face);
|
|
59
|
+
return {
|
|
60
|
+
family, cssFamily,
|
|
61
|
+
dispose() { for (const face of loaded)
|
|
62
|
+
fontSet.delete(face); }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** Fit one font-wide advance and line box to the authoritative cell dimensions. */
|
|
66
|
+
export function measureFont(raster, cssFamily, attributes, scale, cellWidth, cellHeight) {
|
|
67
|
+
const font = `${attributes & 4 ? "italic " : ""}${attributes & 1 ? "bold " : ""}${16 * scale}px ${cssFamily}`;
|
|
68
|
+
raster.font = font;
|
|
69
|
+
raster.textBaseline = "alphabetic";
|
|
70
|
+
raster.textAlign = "left";
|
|
71
|
+
const metrics = raster.measureText("M");
|
|
72
|
+
const lineHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
|
|
73
|
+
if (!Number.isFinite(metrics.width) || metrics.width <= 0 ||
|
|
74
|
+
!Number.isFinite(lineHeight) || lineHeight <= 0) {
|
|
75
|
+
throw new Error(`Invalid terminal font metrics for ${cssFamily}`);
|
|
76
|
+
}
|
|
77
|
+
const xScale = cellWidth * scale / metrics.width;
|
|
78
|
+
const yScale = cellHeight * scale / lineHeight;
|
|
79
|
+
return { font, xScale, yScale, baseline: metrics.fontBoundingBoxAscent * yScale };
|
|
80
|
+
}
|
|
81
|
+
import { isRecord } from "./validation.js";
|
|
82
|
+
function isFontSet(value) {
|
|
83
|
+
return isRecord(value) && typeof value.add === "function" && typeof value.delete === "function";
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=terminal-font.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-font.js","sourceRoot":"","sources":["../src/terminal-font.ts"],"names":[],"mappings":"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","sourcesContent":["const defaultFontUrl = new URL(\"./fonts/cascadia-mono-nf/CascadiaMonoNF.woff2\", import.meta.url).href;\nconst genericFamilies = new Set([\"monospace\", \"serif\", \"sans-serif\", \"system-ui\"]);\n\n/** Resolve caller-relative URLs before sending the configuration to the worker. */\nexport function normalizeFont(font?: TerminalFont, baseUrl = import.meta.url): NormalizedFont {\n font ??= { family: \"Cascadia Mono NF\", faces: [{ url: defaultFontUrl, weight: \"200 700\" }] };\n if (typeof font !== \"object\" || Array.isArray(font) ||\n typeof font.family !== \"string\" || !font.family.trim() || font.family.length > 256 ||\n /[\\u0000-\\u001f\\u007f]/u.test(font.family)) {\n throw new TypeError(\"font.family must be a single, nonempty font family name\");\n }\n const faces = font.faces ?? [];\n if (!Array.isArray(faces) || faces.length > 16) throw new TypeError(\"font.faces must contain at most 16 font sources\");\n return {\n family: font.family.trim(),\n faces: faces.map(face => {\n if (!face || typeof face.url !== \"string\" || !face.url.trim()) {\n throw new TypeError(\"Each font face requires a URL\");\n }\n for (const field of [\"weight\", \"style\"] as const) {\n if (face[field] !== undefined && (typeof face[field] !== \"string\" || face[field].length > 64)) {\n throw new TypeError(`Font face ${field} must be a CSS descriptor string`);\n }\n }\n return {\n url: new URL(face.url, baseUrl).href,\n weight: face.weight ?? \"400\",\n style: face.style ?? \"normal\"\n };\n })\n };\n}\n\n/** Use the rendering context's FontFaceSet; a worker cannot inherit page fonts. */\nexport async function loadFont(configuration: TerminalFont): Promise<LoadedFont> {\n const { family, faces } = normalizeFont(configuration);\n const scope: object = globalThis;\n const fontSet = \"fonts\" in scope && isFontSet(scope.fonts)\n ? scope.fonts : globalThis.document?.fonts;\n if (!fontSet || typeof FontFace !== \"function\") {\n throw new Error(\"Terminal font loading requires the CSS Font Loading API in the rendering context\");\n }\n const generic = genericFamilies.has(family.toLowerCase());\n const cssFamily = generic ? family.toLowerCase() : JSON.stringify(family);\n if (generic && faces.length) throw new TypeError(\"A generic font family cannot have downloadable faces\");\n const sources: (TerminalFontFace | { local: string; weight?: string; style?: string })[] =\n faces.length ? faces : generic ? [] : [{ local: family }];\n const loaded: FontFace[] = [];\n for (const source of sources) {\n try {\n const face = new FontFace(family,\n \"local\" in source ? `local(${JSON.stringify(source.local)})` : `url(${JSON.stringify(source.url)})`,\n { weight: source.weight ?? \"400\", style: source.style ?? \"normal\" });\n loaded.push(await face.load());\n } catch (error) {\n throw new Error(`Could not load terminal font \"${family}\" from ${\"url\" in source ? source.url : \"local fonts\"}`, { cause: error });\n }\n }\n for (const face of loaded) fontSet.add(face);\n return {\n family, cssFamily,\n dispose() { for (const face of loaded) fontSet.delete(face); }\n };\n}\n\n/** Fit one font-wide advance and line box to the authoritative cell dimensions. */\nexport function measureFont(raster: OffscreenCanvasRenderingContext2D, cssFamily: string,\n attributes: number, scale: number, cellWidth: number, cellHeight: number): FontMetrics {\n const font = `${attributes & 4 ? \"italic \" : \"\"}${attributes & 1 ? \"bold \" : \"\"}${16 * scale}px ${cssFamily}`;\n raster.font = font;\n raster.textBaseline = \"alphabetic\";\n raster.textAlign = \"left\";\n const metrics = raster.measureText(\"M\");\n const lineHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;\n if (!Number.isFinite(metrics.width) || metrics.width <= 0 ||\n !Number.isFinite(lineHeight) || lineHeight <= 0) {\n throw new Error(`Invalid terminal font metrics for ${cssFamily}`);\n }\n const xScale = cellWidth * scale / metrics.width;\n const yScale = cellHeight * scale / lineHeight;\n return { font, xScale, yScale, baseline: metrics.fontBoundingBoxAscent * yScale };\n}\nimport type { TerminalFont, TerminalFontFace } from \"./types.js\";\nimport { isRecord } from \"./validation.js\";\n\nexport interface NormalizedFont { family: string; faces: Required<TerminalFontFace>[] }\nexport interface LoadedFont { family: string; cssFamily: string; dispose(): void }\nexport interface FontMetrics { font: string; xScale: number; yScale: number; baseline: number }\n\nfunction isFontSet(value: unknown): value is Pick<FontFaceSet, \"add\" | \"delete\"> {\n return isRecord(value) && typeof value.add === \"function\" && typeof value.delete === \"function\";\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const MIN_FONT_SIZE = 8;
|
|
2
|
+
export declare const MAX_FONT_SIZE = 32;
|
|
3
|
+
export declare function dimensions(columns: number, rows: number): TerminalGrid;
|
|
4
|
+
export declare function normalizeSizing(sizing?: TerminalSizing, previousFontSize?: number): TerminalSizingState;
|
|
5
|
+
export declare function requestedGrid(size: TerminalSize, geometry: TerminalGeometry, sizing: TerminalSizingState): TerminalGrid | null;
|
|
6
|
+
export declare function fittedScale(size: TerminalSize, geometry: TerminalGeometry, isPrimary: boolean, sizing: TerminalSizingState): number;
|
|
7
|
+
import type { TerminalGeometry, TerminalGrid, TerminalSize, TerminalSizing, TerminalSizingState } from "./types.js";
|
|
8
|
+
//# sourceMappingURL=terminal-sizing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-sizing.d.ts","sourceRoot":"","sources":["../src/terminal-sizing.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,aAAa,KAAK,CAAC;AAGhC,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAMtE;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAE,cAAiC,EAAE,gBAAgB,SAAmB,GAAG,mBAAmB,CAWnI;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,GAAG,YAAY,GAAG,IAAI,CAQ9H;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAKnI;AACD,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
|