fix(export): enable proper file downloads and fix empty PNG export

This commit is contained in:
syntaxbullet
2026-02-09 22:50:25 +01:00
parent ea05b814b4
commit 8dae3578b1
5 changed files with 40 additions and 13 deletions

View File

@@ -223,14 +223,14 @@ import Tooltip from "../components/Tooltip.astro";
<TuiButton
id="btn-copy-text"
label="TXT"
title="Copy Text"
description="Copy raw ASCII text to clipboard."
title="Save as Text"
description="Download raw ASCII text file."
/>
<TuiButton
id="btn-copy-html"
label="HTML"
title="Copy HTML"
description="Copy colored HTML span elements to clipboard."
title="Save as HTML"
description="Download colored HTML file."
/>
</div>
</div>

View File

@@ -417,11 +417,27 @@ export class AsciiController {
// ============= Export =============
savePNG(): void {
const wasShowing = this.zoomState.showMagnifier;
// 1. Force hide magnifier for clean export
if (wasShowing) {
this.zoomState.showMagnifier = false;
this.requestRender('uniforms');
// Force synchronous render
this.renderFrame();
}
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
AsciiExporter.downloadPNG(this.canvas, `ascii-art-${timestamp}.png`);
// 2. Restore state
if (wasShowing) {
this.zoomState.showMagnifier = true;
this.requestRender('uniforms');
}
}
async copyText(): Promise<void> {
saveText(): void {
if (!this.cachedGrid.imgEl) return;
const text = AsciiExporter.generateText(
this.cachedGrid.imgEl,
@@ -429,10 +445,11 @@ export class AsciiController {
this.cachedGrid.widthCols,
Math.floor(this.cachedGrid.heightRows)
);
await AsciiExporter.copyToClipboard(text);
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
AsciiExporter.downloadText(text, `ascii-art-${timestamp}.txt`);
}
async copyHTML(): Promise<void> {
saveHTML(): void {
if (!this.cachedGrid.imgEl) return;
const html = AsciiExporter.generateHTML(
this.cachedGrid.imgEl,
@@ -440,7 +457,8 @@ export class AsciiController {
this.cachedGrid.widthCols,
Math.floor(this.cachedGrid.heightRows)
);
await AsciiExporter.copyToClipboard(html);
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
AsciiExporter.downloadText(html, `ascii-art-${timestamp}.html`);
}
// ============= Utilities =============

View File

@@ -8,6 +8,15 @@ export class AsciiExporter {
link.click();
}
static downloadText(content: string, filename: string) {
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
URL.revokeObjectURL(link.href);
}
static async copyToClipboard(text: string): Promise<void> {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text);

View File

@@ -308,9 +308,9 @@ export class UIBindings {
const btnCopyText = document.getElementById('btn-copy-text');
if (btnCopyText) {
const handler = async (e: Event) => {
const handler = (e: Event) => {
e.stopPropagation();
await this.controller.copyText();
this.controller.saveText();
};
this.buttonHandlers.set('btn-copy-text', handler);
btnCopyText.addEventListener('click', handler);
@@ -318,9 +318,9 @@ export class UIBindings {
const btnCopyHtml = document.getElementById('btn-copy-html');
if (btnCopyHtml) {
const handler = async (e: Event) => {
const handler = (e: Event) => {
e.stopPropagation();
await this.controller.copyHTML();
this.controller.saveHTML();
};
this.buttonHandlers.set('btn-copy-html', handler);
btnCopyHtml.addEventListener('click', handler);

View File

@@ -46,7 +46,7 @@ export class WebGLAsciiRenderer {
private lastImage: HTMLImageElement | null;
constructor(_canvas: HTMLCanvasElement) {
const gl = _canvas.getContext('webgl', { antialias: false });
const gl = _canvas.getContext('webgl', { antialias: false, preserveDrawingBuffer: true });
if (!gl) {
throw new Error('WebGL not supported');
}