025
LVL 01 — WAVE DEFENDER SESSION 025 DAY 25

EXPORT FIX

🎫 PIXELCRAFT-013
🐛 Bug | 🔵 Easy | Priority: 🟠 High

Clicking Export downloads a file named "undefined.png" instead of using the original filename with "_edited" suffix.
CONCEPTS.UNLOCKED
" "
Strings
Text data type, declared with "quotes", 'quotes', or `backticks`. Strings are immutable — every method returns a new string, never modifies the original.
String Methods
.slice(), .split(), .join(), .replace(), .includes(), .indexOf(), .toLowerCase() — the essential toolkit for parsing, building, and transforming text.
${}
Template Literals
`${variable} some text ${expression}` — embed variables and expressions inside strings using backticks. Cleaner than concatenation with +.
📅
The Date Object
new Date() creates a timestamp. .toISOString() gives "2026-02-18T..." — .slice(0, 10) extracts just the date. Useful for naming, sorting, and logging.
💾
Canvas Export: toBlob()
canvas.toBlob(callback, mimeType) converts the canvas to a downloadable file. Combined with URL.createObjectURL() and a hidden <a> link, it triggers a download.
🧹
Filename Sanitization
Filenames can contain characters that break on different operating systems: / \ : * ? " < > |. A sanitizer removes or replaces these to produce safe, portable filenames.
HANDS-ON.TASKS
01
Trace the Bug

The filename variable is never stored when uploading. The export function reads currentFileName but it was never assigned → undefined → "undefined.png".

This is one of the most common JavaScript bugs: using a variable that was declared but never assigned a value. typeof undefined === "undefined" — it becomes part of the filename string.
02
Fix: Save Filename on Upload
let currentFileName = 'untitled'; fileInput.addEventListener('change', (event) => { const file = event.target.files[0]; currentFileName = file.name; // "vacation.jpg" // ... rest of upload logic });
Default value 'untitled' handles the edge case where someone pastes or drags an image without a filename. Defensive defaults prevent undefined.
03
Parse & Build the Export Name
function generateExportName(originalName, format = 'png') { const dotIndex = originalName.lastIndexOf('.'); const name = dotIndex > 0 ? originalName.slice(0, dotIndex) : originalName; const now = new Date(); const date = now.toISOString().slice(0, 10); // "2026-02-18" return `${name}_edited_${date}.${format}`; } // "vacation.jpg" → "vacation_edited_2026-02-18.png"
MethodWhat It DoesExample
.lastIndexOf('.')Finds last dot position"photo.raw.jpg" → 9
.slice(0, dotIndex)Extracts name without extension"photo.raw"
.toISOString()Date as standard string"2026-02-18T..."
.slice(0, 10)First 10 characters"2026-02-18"
04
Implement the Export
exportBtn.addEventListener('click', () => { const exportName = generateExportName(currentFileName, 'png'); canvas.toBlob((blob) => { const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = exportName; link.click(); URL.revokeObjectURL(url); showToast(`Exported as ${exportName}`, 'success'); }, 'image/png'); });
canvas.toBlob() is async (callback pattern, like FileReader). URL.createObjectURL creates a temporary URL for the blob. URL.revokeObjectURL frees the memory after download starts.
05
Handle Edge Cases
Edge CaseProblemSolution
"file.name.with.dots.jpg"Multiple dotslastIndexOf finds last dot
"my vacation photo.png"Spaces in nameReplace with underscores
"résumé.png"Accented charactersAllow or transliterate
No extensiondotIndex === -1Use full name as base
06
Build a Filename Sanitizer

Remove characters that break on different operating systems:

function sanitizeFilename(name) { return name .replace(/[\/\\:*?"<>|]/g, '') // Remove illegal chars .replace(/\s+/g, '_') // Spaces → underscores .replace(/_+/g, '_') // Collapse multiple _ .trim(); }
07
Close the Ticket
git switch -c bugfix/PIXELCRAFT-013-export-filename git add src/scripts/ git commit -m "Fix export filename and add sanitizer (PIXELCRAFT-013)" git push origin bugfix/PIXELCRAFT-013-export-filename # PR → Review → Merge → Close ticket ✅
CS.DEEP-DIVE

Strings as arrays of characters.

Internally, "hello" is stored as character codes: [104, 101, 108, 108, 111] in UTF-16 encoding.

// String methods are array operations:

.indexOf()    → linear search through chars
.slice()      → creates a sub-array
.split()      → creates a new array from string
.replace()    → pattern match and substitute

// Understanding strings as arrays helps
// predict performance and edge cases.

// This connects back to Session 1:
// everything in the computer is numbers
// — even text.
"Export Pro"
[A] Add a format selector: let users choose between PNG, JPEG (with quality slider 0–100), and WebP. Change the toBlob MIME type and file extension accordingly.
[B] Show a preview of the export: file size estimate, dimensions, format. Display in a modal before confirming the download.
[C] Build a string manipulation playground in the console: take "Hello, World!" and use only string methods to transform it into "dlrow_olleh" (lowercase, reversed, spaces to underscores).
REF.MATERIAL
ARTICLE
Mozilla Developer Network
The definitive String reference: every method, every property, with examples. Bookmark alongside Array and Object.
STRINGSMDNREFERENCE
VIDEO
Web Dev Simplified
Practical walkthrough of the most-used string methods: slice, split, replace, includes, template literals, and common patterns.
STRINGSPRACTICAL
ARTICLE
Mozilla Developer Network
Complete reference for canvas export: toBlob, toDataURL, quality parameter, supported MIME types.
CANVASEXPORTBLOB
ARTICLE
javascript.info
In-depth string tutorial: quotes, template literals, special characters, searching, extracting, and comparing. Interactive examples.
STRINGSINTERACTIVE
VIDEO
Programming with Mosh
The Date object explained: creating dates, formatting, parsing, calculating differences, and the ISO 8601 standard.
DATETIME
// LEAVE EXCITED BECAUSE
The full user pipeline works: Upload → Edit → Export with correct filename. PixelCraft is a functional image editor. Users could actually USE this.