const fs = require('fs');
const lib = require('../');
/**
* This class represents the sketch file and all this content.
*
* @property {JSZip} repo - The instance of JSZip containing the raw data
* @property {Node} document - The document data
* @property {Node} meta - The meta data
* @property {Node} user - The user data
* @property {Page[]} pages - Array with all pages of the document
* @property {Page|undefined} symbolsPage - The "Symbols" page if exists
* @property {Node[]} localSymbols - Array with all local symbols (symbols stored in any page of the document)
* @property {Node[]} foreignSymbols - Array with all foreign symbols used in the document (symbols loaded from libraries)
* @property {SharedStyle[]} sharedStyles - Array with all shared styles of the document
* @property {SharedStyle[]} textStyles - Array with all text styles of the document
* @property {Node[]} colors - Array with the document color palette
* @property {Node[]} gradients - Array with the document gradients palette
*/
class Sketch {
constructor(repo, document, meta, user, pages) {
this._class = 'sketch';
this.repo = repo;
this.document = lib.create(this, document);
this.meta = lib.create(this, meta);
this.user = lib.create(this, user);
this.pages = pages.map(page => lib.create(this, page));
this.queue = null;
}
get symbolsPage() {
return this.pages.find(page => page.name === 'Symbols');
}
get localSymbols() {
return this.pages
.map(page => page.getAll('symbolMaster'))
.reduce((symbols, currentPage) => symbols.concat(currentPage));
}
get foreignSymbols() {
return this.document.foreignSymbols.map(symbol => symbol.symbolMaster);
}
get sharedStyles() {
return this.document.layerStyles.objects;
}
get textStyles() {
return this.document.layerTextStyles.objects;
}
get colors() {
return this.document.assets.colors;
}
get gradients() {
return this.document.assets.gradients;
}
/**
* Execute a plugin with the sketch
* @param {function} plugin The plugin to execute
* @return {this}
*/
use(plugin) {
if (this.queue) {
this.queue.then(() => plugin.run(this));
} else {
this.queue = plugin.run(this);
}
return this;
}
/**
* Save the document as a sketch file
* @example
* ns.read('input.sketch').then((sketch) => {
*
* //modify the sketch data
*
* return sketch.save('output.sketch')
* })
* @param {string} file - The file path
* @return {this}
*/
save(file) {
if (!this.queue) {
this.queue = this.save(file);
} else {
this.queue.then(() => {
const pagesFolder = this.repo.folder('pages');
this.document.pages = this.pages.map(page => {
this.repo.file(
`pages/${page.do_objectID}.json`,
JSON.stringify(page)
);
return {
_class: 'MSJSONFileReference',
_ref_class: 'MSImmutablePage',
_ref: `pages/${page.do_objectID}`
};
});
this.repo.file('document.json', JSON.stringify(this.document));
this.repo.file('meta.json', JSON.stringify(this.meta));
this.repo.file('user.json', JSON.stringify(this.user));
return new Promise((resolve, reject) => {
this.repo
.generateNodeStream({
type: 'nodebuffer',
streamFiles: true,
compression: 'DEFLATE'
})
.pipe(fs.createWriteStream(file))
.on('finish', () => {
resolve(file);
})
.on('error', err => {
reject(err);
});
});
});
}
return this;
}
}
module.exports = Sketch;