I sent emails to the developer email address and never got responses. So I’ll post here in hopes that someone will have a method to figure out what’s going wrong…
On Mar 11, 2025, at 11:29 AM, Timothy Martin wrote:
I’m managing a Sketch Library that we have stored in Git and we decided to use a workflow that involves unzipping the file for storage for more efficient usage of Git, instead of relying on Git LFS.
Anyway, in that process I noticed that any update causes the entire JSON file to be replaced, and I believe that’s because they are minified. I used `js-beautify` after unzipping to create a human readable version of the JSON files, and assumed the software wouldn’t care. But if I rezip them up Sketch complains when trying to open the file with the following alert:
Furthermore, if i re-minify them it doesn’t seem to fix the error. So the process of beautifying must be doing something that Sketch isn’t happy about. I was wondering if there’s a way I could find out what’s causing this error?
I used `js-beautify` after unzipping to create a human readable version of the JSON files, and assumed the software wouldn’t care. But if I rezip them up Sketch complains when trying to open the file with the following alert:
This doesn’t seem right, I wonder what else in your setup/design files themselves could affect the resulting file. I’ve tried to recreate this workflow using the following Node script:
beautify-sketch.js
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const beautify = require('js-beautify');
function beautifySketchFile(inputFile) {
const outputFile = inputFile.replace('.sketch', '-beautiful.sketch');
const tempDir = './temp-sketch-extract';
try {
// Clean up any existing temp directory
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
console.log('Extracting Sketch file...');
fs.mkdirSync(tempDir, { recursive: true });
// Unzip the sketch file
execSync(`unzip -q "${inputFile}" -d "${tempDir}"`);
console.log('Beautifying JSON files...');
// Find all JSON files recursively
function findJSONFiles(dir) {
const files = [];
const items = fs.readdirSync(dir, { withFileTypes: true });
for (const item of items) {
const fullPath = path.join(dir, item.name);
if (item.isDirectory()) {
files.push(...findJSONFiles(fullPath));
} else if (item.isFile() && item.name.endsWith('.json')) {
files.push(fullPath);
}
}
return files;
}
const jsonFiles = findJSONFiles(tempDir);
// Beautify each JSON file
for (const jsonFile of jsonFiles) {
try {
const content = fs.readFileSync(jsonFile, 'utf8');
const beautified = beautify(content, {
indent_size: 2,
space_in_empty_paren: true
});
fs.writeFileSync(jsonFile, beautified, 'utf8');
console.log(`Beautified: ${path.relative(tempDir, jsonFile)}`);
} catch (error) {
console.warn(`Warning: Could not beautify ${jsonFile}: ${error.message}`);
}
}
console.log('Repackaging Sketch file...');
// Change to temp directory and zip contents
process.chdir(tempDir);
execSync(`zip -r "../${outputFile}" .`);
process.chdir('..');
// Clean up temp directory
fs.rmSync(tempDir, { recursive: true, force: true });
console.log(`Created beautified Sketch file: ${outputFile}`);
} catch (error) {
console.error('Error:', error.message);
// Clean up on error
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
process.exit(1);
}
}
// Check if input file is provided
const inputFile = process.argv[2] || 'document.sketch';
if (!fs.existsSync(inputFile)) {
console.error(`File not found: ${inputFile}`);
process.exit(1);
}
if (!inputFile.endsWith('.sketch')) {
console.error('Input file must be a .sketch file');
process.exit(1);
}
console.log(`Beautifying Sketch file: ${inputFile}`);
beautifySketchFile(inputFile);
Calling it with
node beautify-sketch.js document.sketch
produces a valid Sketch document with beautified internals that opens without issues for me.