1
0
Fork 0
sass-spritemaker/lib/spritemaker.js

120 lines
3.3 KiB
JavaScript

/**
* Copyright (c) 2019-present Tomek Wójcik <contact@bthlabs.pl>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const Mustache = require('mustache');
const {PNG} = require('pngjs');
const URI = require('urijs');
const DEFAULT_OPTIONS = {
files: [],
output: 'sprite/',
urlPrefix: '/'
};
const spritemaker = (options) => {
options = Object.assign({}, DEFAULT_OPTIONS, options);
const images = [];
const bounds = {
width: 0,
height: 0
};
const spriteMap = [];
options.files.forEach((pattern, index) => {
glob.sync(pattern).forEach((imagePath, index) => {
const data = fs.readFileSync(imagePath);
const image = PNG.sync.read(data);
bounds.height += image.height;
if (image.width > bounds.width) {
bounds.width = image.width;
}
images.push([imagePath, image]);
});
});
const outputImage = new PNG({
height: bounds.height,
width: bounds.width
});
let currentDeltaY = 0;
images.forEach(([imagePath, image], index) => {
PNG.bitblt(
image, outputImage,
0, 0, image.width, image.height,
0, currentDeltaY
);
spriteMap.push({
name: path.basename(imagePath, '.png'),
rect: {
x: 0,
y: currentDeltaY * -1,
width: image.width,
height: image.height
}
});
currentDeltaY += image.height;
});
const hash = crypto.Hash('md5');
hash.update(outputImage.data);
const outputBasename = `sprite`;
const outputName = `${outputBasename}-${hash.digest('hex')}.png`;
const outbutBuffer = PNG.sync.write(outputImage, {
colorType: 6
});
fs.writeFileSync(
path.resolve(options.output, outputName), outbutBuffer
);
const template = fs.readFileSync(
path.resolve(__dirname, 'scss.mustache'), {encoding: 'utf-8'}
);
const context = {
bounds: bounds,
images: spriteMap,
url: path.join(options.urlPrefix, outputName)
};
const scss = Mustache.render(template, context);
const scssName = `${outputBasename}.scss`;
fs.writeFileSync(
path.resolve(options.output, scssName), scss
);
return [outputName, scssName];
};
module.exports = {
spritemaker: spritemaker
};