New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

assetgraph-sprite

Package Overview
Dependencies
Maintainers
2
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

assetgraph-sprite - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

20

lib/packers/horizontal.js

@@ -1,12 +0,10 @@

var extend = require('lodash.assign');
exports.pack = function (imageInfos) {
var previousRightPadding = 0,
packingData = {
width: 0,
height: 0,
imageInfos: []
};
imageInfos.forEach(function (existingImageInfo) {
var imageInfo = extend({}, existingImageInfo);
let previousRightPadding = 0;
const packingData = {
width: 0,
height: 0,
imageInfos: []
};
for (const existingImageInfo of imageInfos) {
const imageInfo = {...existingImageInfo};
packingData.width += Math.max(previousRightPadding, imageInfo.padding[3]);

@@ -19,4 +17,4 @@ imageInfo.x = packingData.width;

packingData.imageInfos.push(imageInfo);
});
}
return packingData;
};
// Install getters for all packers in this directory:
require('fs').readdirSync(__dirname).forEach(function (fileName) {
for (const fileName of require('fs').readdirSync(__dirname)) {
if (/\.js$/.test(fileName) && fileName !== 'index.js') {
exports.__defineGetter__(fileName.replace(/\.js$/, ''), function () {
return require('./' + fileName);
Object.defineProperty(exports, fileName.replace(/\.js$/, ''), {
get: () => require('./' + fileName)
});
}
});
}

@@ -10,4 +10,2 @@ /*

var extend = require('lodash.assign');
function findCoords(node, width, height) {

@@ -66,15 +64,15 @@ // If we are not at a leaf then go deeper

config = config || {};
var root = {
x: 0,
y: 0,
width: config.maxWidth || 999999,
height: config.maxHeight || 999999
};
const root = {
x: 0,
y: 0,
width: config.maxWidth || 999999,
height: config.maxHeight || 999999
};
// Sort by area, descending:
imageInfos.sort(function (a, b) {
return (b.width * b.height) - (a.width * a.height);
});
imageInfos.sort(
(a, b) => (b.width * b.height) - (a.width * a.height)
);
var packingData = {
const packingData = {
imageInfos: [],

@@ -85,9 +83,9 @@ width: 0,

imageInfos.forEach(function (existingImageInfo) {
var imageInfo = extend({}, existingImageInfo);
if (imageInfo.padding && imageInfo.padding.some(function (v) {return v > 0;})) {
for (const existingImageInfo of imageInfos) {
const imageInfo = {...existingImageInfo};
if (imageInfo.padding && imageInfo.padding.some(v => v > 0)) {
throw new Error('jimScott.pack: Sprite padding not supported');
}
// Perform the search
var coords = findCoords(root, imageInfo.width, imageInfo.height);
const coords = findCoords(root, imageInfo.width, imageInfo.height);
// If fitted then recalculate the used dimensions

@@ -100,6 +98,6 @@ if (coords) {

}
extend(imageInfo, coords);
Object.assign(imageInfo, coords);
packingData.imageInfos.push(imageInfo);
});
}
return packingData;
};

@@ -1,7 +0,7 @@

var packers = ['./horizontal', './vertical', './jimScott'].map(require);
const packers = ['./horizontal', './vertical', './jimScott'].map(require);
exports.pack = function (imageInfos) {
var bestPacking;
packers.forEach(function (packer) {
var packing;
exports.pack = imageInfos => {
let bestPacking;
for (const packer of packers) {
let packing;
try {

@@ -11,3 +11,3 @@ packing = packer.pack(imageInfos);

// The Jim Scott packer doesn't support sprite padding, just skip to the next packer if we get an exception.
return;
continue;
}

@@ -17,4 +17,4 @@ if (!bestPacking || (packing.width * packing.height) < (bestPacking.width * bestPacking.height)) {

}
});
}
return bestPacking;
};

@@ -1,12 +0,11 @@

var extend = require('lodash.assign');
exports.pack = function (imageInfos) {
let previousBottomPadding = 0;
const packingData = {
width: 0,
height: 0,
imageInfos: []
};
exports.pack = function (imageInfos) {
var previousBottomPadding = 0,
packingData = {
width: 0,
height: 0,
imageInfos: []
};
imageInfos.forEach(function (existingImageInfo) {
var imageInfo = extend({}, existingImageInfo);
for (const existingImageInfo of imageInfos) {
const imageInfo = {...existingImageInfo};
packingData.height += Math.max(previousBottomPadding, imageInfo.padding[0]);

@@ -19,4 +18,4 @@ imageInfo.y = packingData.height;

packingData.imageInfos.push(imageInfo);
});
}
return packingData;
};

@@ -1,9 +0,5 @@

var URL = require('url'),
queryString = require('querystring'),
extend = require('lodash.assign'),
values = require('lodash.values'),
seq = require('seq'),
passError = require('passerror'),
packers = require('./packers'),
Canvas;
const queryString = require('querystring');
const { promisify } = require('util');
const packers = require('./packers');
let Canvas;

@@ -16,39 +12,40 @@ try {

function getProperties(container, propertyName) {
return container.nodes.filter(function (node) {
return node.prop === propertyName;
});
return container.nodes.filter(
node => node.prop === propertyName
);
}
function getCanvasImageFromImageAsset(imageAsset, cb) {
var canvasImage = new Canvas.Image();
canvasImage.onerror = function (err) {
process.nextTick(function () {
async function getCanvasImageFromImageAsset(imageAsset) {
const canvasImage = new Canvas.Image();
await new Promise((resolve, reject) => {
canvasImage.onerror = err => {
err.message += ' (' + imageAsset.urlOrDescription + ')';
cb(err);
});
};
canvasImage.onload = function () {
process.nextTick(function () {
cb(null, canvasImage);
});
};
canvasImage.src = imageAsset.rawSrc;
reject(err);
};
canvasImage.onload = resolve;
canvasImage.src = imageAsset.rawSrc;
});
return canvasImage;
}
function getImageAssetFromCanvas(canvas, assetType, assetGraph, cb) {
async function getImageAssetFromCanvas(canvas, assetType, assetGraph) {
if (assetType === 'Png') {
canvas.toBuffer(passError(cb, function (pngBuffer) {
cb(null, new assetGraph.Png({
rawSrc: pngBuffer
}));
}));
const rawSrc = await promisify(cb => canvas.toBuffer(cb))();
return {
type: 'Png',
rawSrc
};
} else {
var jpegChunks = [];
canvas.createJPEGStream().on('data', function (chunk) {
jpegChunks.push(chunk);
}).on('end', function () {
cb(null, new assetGraph.Jpeg({
rawSrc: Buffer.concat(jpegChunks)
}));
}).on('error', cb);
const rawSrc = await promisify(cb => {
const jpegChunks = [];
canvas.createJPEGStream().on('data', function (chunk) {
jpegChunks.push(chunk);
})
.on('end', () => cb(null, Buffer.concat(jpegChunks)))
.on('error', cb);
})();
return {
type: 'Jpeg',
rawSrc
};
}

@@ -81,9 +78,9 @@ }

return padding.map(function (size) {
return Math.max(size, Math.max(asset.devicePixelRatio) - 1);
});
return padding.map(
size => Math.max(size, Math.max(asset.devicePixelRatio) - 1)
);
}
function getRelationSpriteInfoFromIncomingRelation(incomingRelation) {
var parsedQueryString = queryString.parse(incomingRelation.href.match(/\?([^#]*)/)[1]);
const parsedQueryString = queryString.parse(incomingRelation.href.match(/\?([^#]*)/)[1]);
return {

@@ -98,8 +95,10 @@ groupName: parsedQueryString.sprite || 'default',

function extractInfoFromCssRule(cssRule, propertyNamePrefix) {
var info = {};
cssRule.walkDecls(function (decl) {
if (!propertyNamePrefix || decl.prop.indexOf(propertyNamePrefix) === 0) {
var keyName = decl.prop.substr(propertyNamePrefix.length).replace(/-([a-z])/g, function ($0, $1) {
return $1.toUpperCase();
});
const info = {};
cssRule.walkDecls(decl => {
if (!propertyNamePrefix || decl.prop.startsWith(propertyNamePrefix)) {
const keyName = decl.prop
.substr(propertyNamePrefix.length)
.replace(
/-([a-z])/g, ($0, $1) => $1.toUpperCase()
);
info[keyName] = decl.value.replace(/^([\'\"])(.*)\1$/, '$2');

@@ -112,27 +111,27 @@ }

module.exports = function () {
return function spriteBackgroundImages(assetGraph, cb) {
module.exports = () => {
return async function spriteBackgroundImages(assetGraph) {
if (!Canvas) {
assetGraph.emit('warn', new Error('assetgraph-sprite: Canvas not found, skipping'));
return cb();
assetGraph.warn(new Error('assetgraph-sprite: Canvas not found, skipping'));
return;
}
// Waiting for https://github.com/LearnBoost/node-canvas/issues/52
var cairoVersion = Canvas.cairoVersion.split('.').map(function (str) {
return parseInt(str, 10);
});
const cairoVersion = Canvas.cairoVersion.split('.').map(
str => parseInt(str, 10)
);
if (cairoVersion[0] < 1 || cairoVersion[1] < 10) {
assetGraph.emit('warn', new Error('assetgraph-sprite: Cannot create sprites due to missing canvas.getContext("2d").drawImage() support. Please compile node-canvas with Cairo version 1.10.0 or above.'));
return cb();
assetGraph.warn(new Error('assetgraph-sprite: Cannot create sprites due to missing canvas.getContext("2d").drawImage() support. Please compile node-canvas with Cairo version 1.10.0 or above.'));
return;
}
var spriteGroups = {};
const spriteGroups = {};
// Find sprite annotated images and create a data structure with their information
assetGraph.findRelations({type: 'CssImage', to: {isImage: true}, href: /\?(?:|[^#]*&)sprite(?:[=&#]|$)/}).forEach(function (relation) {
var relationSpriteInfo = getRelationSpriteInfoFromIncomingRelation(relation),
spriteGroup = (spriteGroups[relationSpriteInfo.groupName] = spriteGroups[relationSpriteInfo.groupName] || {
imageInfosById: {}
}),
imageInfo = spriteGroup.imageInfosById[relationSpriteInfo.asset.id];
for (const relation of assetGraph.findRelations({type: 'CssImage', to: {isImage: true}, href: /\?(?:|[^#]*&)sprite(?:[=&#]|$)/})) {
const relationSpriteInfo = getRelationSpriteInfoFromIncomingRelation(relation);
const spriteGroup = (spriteGroups[relationSpriteInfo.groupName] = spriteGroups[relationSpriteInfo.groupName] || {
imageInfosById: {}
});
const imageInfo = spriteGroup.imageInfosById[relationSpriteInfo.asset.id];
if (!imageInfo) {

@@ -147,9 +146,9 @@ relationSpriteInfo.incomingRelations = [relation];

}
});
}
var redefinitionErrors = {};
const redefinitionErrors = {};
// Extract sprite grouping information va -sprite- prefixed properties in stylesheets
assetGraph.findAssets({type: 'Css'}).forEach(function (cssAsset) {
cssAsset.eachRuleInParseTree(function (cssRule) {
for (const cssAsset of assetGraph.findAssets({type: 'Css', isLoaded: true})) {
cssAsset.eachRuleInParseTree(cssRule => {
if (cssRule.type !== 'rule') {

@@ -159,6 +158,6 @@ return;

if (getProperties(cssRule, '-sprite-selector-for-group').length > 0) {
var spriteInfo = extractInfoFromCssRule(cssRule, '-sprite-'),
spriteGroupName = spriteInfo.selectorForGroup;
const spriteInfo = extractInfoFromCssRule(cssRule, '-sprite-');
const spriteGroupName = spriteInfo.selectorForGroup;
if (spriteInfo.location) {
var matchLocation = spriteInfo.location.match(/^url\((['"]|)(.*?)\1\)$/);
const matchLocation = spriteInfo.location.match(/^url\((['"]|)(.*?)\1\)$/);
if (matchLocation) {

@@ -168,3 +167,3 @@ spriteInfo.location = matchLocation[2];

}
var group = spriteGroups[spriteGroupName];
const group = spriteGroups[spriteGroupName];
if (group) {

@@ -176,6 +175,6 @@ if (!Array.isArray(group.placeHolders)) {

if (group.placeHolders.length > 0) {
var err;
let err;
if (Object.keys(group.placeHolders[0]).every(function (key) {
if (['asset', 'cssRule'].indexOf(key) !== -1) {
if (Object.keys(group.placeHolders[0]).every(key => {
if (['asset', 'cssRule'].includes(key)) {
return true;

@@ -191,18 +190,20 @@ }

group.placeHolders.push(extend(spriteInfo, {
group.placeHolders.push({
...spriteInfo,
asset: cssAsset,
cssRule: cssRule
}));
cssRule
});
} else {
err = new Error('assetgraph-sprite: Multiple differing definitions of ' + spriteGroupName + ' sprite.\nThis is most likely an error.');
err = new Error(`assetgraph-sprite: Multiple differing definitions of ${spriteGroupName} sprite.\nThis is most likely an error.`);
err.asset = cssAsset;
assetGraph.emit('warn', err);
assetGraph.warn(err);
}
} else {
group.placeHolders.push(extend(spriteInfo, {
group.placeHolders.push({
...spriteInfo,
asset: cssAsset,
cssRule: cssRule
}));
cssRule
});
}

@@ -213,262 +214,260 @@

});
});
}
Object.keys(redefinitionErrors).forEach(function (spriteGroupName) {
var message = [
'assetgraph-sprite: Multiple identical definitions of ' + spriteGroupName + ' sprite.',
for (const spriteGroupName of Object.keys(redefinitionErrors)) {
const message = [
`assetgraph-sprite: Multiple identical definitions of ${spriteGroupName} sprite.`,
'This might happen if you duplicate CSS using a preprocessor.',
redefinitionErrors[spriteGroupName].map(function (asset) {
return '\t' + asset.urlOrDescription;
}).join('\n')
...redefinitionErrors[spriteGroupName].map(
asset => ' ' + asset.urlOrDescription
)
].join('\n');
var err = new Error(message);
const err = new Error(message);
assetGraph.emit('info', err);
});
assetGraph.info(err);
}
seq(Object.keys(spriteGroups))
.seqEach(function (spriteGroupName) {
var callback = this,
spriteGroup = spriteGroups[spriteGroupName],
imageInfos = values(spriteGroup.imageInfosById),
spriteInfo = spriteGroup.placeHolders && spriteGroup.placeHolders[0] || {},
packingData;
for (const spriteGroupName of Object.keys(spriteGroups)) {
const spriteGroup = spriteGroups[spriteGroupName];
let imageInfos = Object.values(spriteGroup.imageInfosById);
const spriteInfo = spriteGroup.placeHolders && spriteGroup.placeHolders[0] || {};
seq(imageInfos)
.parMap(function (imageInfo) {
getCanvasImageFromImageAsset(imageInfo.asset, function (err, canvasImage) {
// For some reason parMap swallows errors!
// Rewrite to use promises or async and get rid of this:
if (err) {
callback(err);
} else {
this(null, canvasImage);
}
}.bind(this));
})
.seqEach(function (canvasImage, i) {
extend(imageInfos[i], {
canvasImage: canvasImage,
width: canvasImage.width,
height: canvasImage.height
});
setImmediate(this);
})
.seq(function () {
var packerName = {
'jim-scott': 'jimScott',
horizontal: 'horizontal',
vertical: 'vertical'
}[spriteInfo.packer] || 'tryAll';
const canvasImages = await Promise.all(imageInfos.map(
imageInfo => getCanvasImageFromImageAsset(imageInfo.asset)
));
for (const [i, imageInfo] of imageInfos.entries()) {
const canvasImage = canvasImages[i];
Object.assign(imageInfo, {
canvasImage,
width: canvasImage.width,
height: canvasImage.height
});
}
packingData = packers[packerName].pack(imageInfos);
const packerName = {
'jim-scott': 'jimScott',
horizontal: 'horizontal',
vertical: 'vertical'
}[spriteInfo.packer] || 'tryAll';
var canvas = new Canvas(packingData.width, packingData.height),
ctx = canvas.getContext('2d');
const packingData = packers[packerName].pack(imageInfos);
const canvas = new Canvas(packingData.width, packingData.height);
const ctx = canvas.getContext('2d');
imageInfos = packingData.imageInfos;
if ('backgroundColor' in spriteInfo) {
ctx.fillStyle = spriteInfo.backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
imageInfos.forEach(function (imageInfo) {
ctx.drawImage(imageInfo.canvasImage, imageInfo.x, imageInfo.y, imageInfo.width, imageInfo.height);
});
getImageAssetFromCanvas(canvas, /^jpe?g$/.test(spriteInfo.imageFormat) ? 'Jpeg' : 'Png', assetGraph, this);
})
.seq(function (spriteAsset) {
var baseUrl = assetGraph.root,
href = ['sprite', spriteGroupName, imageInfos.length, spriteAsset.id].join('-') + spriteAsset.defaultExtension;
if ('backgroundColor' in spriteInfo) {
ctx.fillStyle = spriteInfo.backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
if (Array.isArray(spriteGroup.placeHolders)) {
var location = spriteGroup.placeHolders[0].location;
imageInfos = packingData.imageInfos;
for (const imageInfo of imageInfos) {
ctx.drawImage(
imageInfo.canvasImage,
imageInfo.x,
imageInfo.y,
imageInfo.width,
imageInfo.height
);
}
const spriteImageType = /^jpe?g$/.test(spriteInfo.imageFormat) ? 'Jpeg' : 'Png';
const spriteAssetConfig = await getImageAssetFromCanvas(canvas, spriteImageType, assetGraph);
if (location) {
if (/^[?#]/.test(location)) {
href += location;
} else {
href = location;
let fileName = `sprite-${spriteGroupName}-${imageInfos.length}${assetGraph[spriteImageType].prototype.defaultExtension}`;
if (Array.isArray(spriteGroup.placeHolders)) {
let location = spriteGroup.placeHolders[0].location;
if (location) {
let href;
if (/^\?/.test(location)) {
href = fileName + location;
} else {
href = location;
}
spriteAssetConfig.url = assetGraph.resolveUrl(
assetGraph.root,
href
);
}
}
if (!spriteAssetConfig.url) {
spriteAssetConfig.fileName = fileName;
}
const spriteAsset = assetGraph.addAsset(spriteAssetConfig);
if (Array.isArray(spriteGroup.placeHolders)) {
for (const spriteInfo of spriteGroup.placeHolders) {
const cssRule = spriteInfo.cssRule;
let propertyName;
let propertyNode;
let tokenNumber;
for (const candidatePropertyName of ['background-image', 'background']) {
const decls = getProperties(cssRule, candidatePropertyName);
if (!propertyName && decls.length > 0) {
propertyName = candidatePropertyName;
var propertyValue = decls[0].value;
if (propertyValue === '!important') {
// Hack so that an existing value of "!important" will DTRT
decls[0].important = true;
propertyValue = 'url(...)';
} else if (/^\s*$/.test(propertyValue)) {
propertyValue = 'url(...)';
} else {
const existingUrlTokens = propertyValue.match(assetGraph.CssImage.prototype.tokenRegExp);
if (existingUrlTokens) {
tokenNumber = existingUrlTokens.length;
}
propertyValue += ' url(...)';
}
decls[0].value = propertyValue;
}
}
if (propertyName) {
propertyNode = getProperties(cssRule, propertyName)[0];
} else {
cssRule.append('background-image: url(...)');
propertyNode = cssRule.last;
}
// I can't see why the ordering of CssImage relations should be significant...
const relation = spriteInfo.asset.addRelation({
type: 'CssImage',
node: cssRule,
to: spriteAsset,
propertyName,
propertyNode,
tokenNumber
}, 'last');
relation.refreshHref();
spriteInfo.cssRule.walkDecls(decl => {
if (['-sprite-selector-for-group', '-sprite-packer', '-sprite-image-format', '-sprite-background-color', '-sprite-important'].includes(decl.prop)) {
decl.remove();
}
});
spriteAsset.url = URL.resolve(baseUrl, href);
assetGraph.addAsset(spriteAsset);
if (Array.isArray(spriteGroup.placeHolders)) {
spriteGroup.placeHolders.forEach(function (spriteInfo) {
var cssRule = spriteInfo.cssRule,
relation = new assetGraph.CssImage({
node: cssRule,
to: spriteAsset
});
// If background-size is set, we should update it, The correct size is now the size of the sprite:
const backgroundSizeDecls = getProperties(spriteInfo.cssRule, 'background-size');
if (backgroundSizeDecls.length > 0) {
backgroundSizeDecls[0].value = packingData.width + 'px ' + packingData.height + 'px';
}
}
}
[ 'background-image', 'background' ].forEach(function (propertyName) {
var decls = getProperties(cssRule, propertyName);
if (!relation.propertyName && decls.length > 0) {
relation.propertyName = propertyName;
var propertyValue = decls[0].value;
if (propertyValue === '!important') {
// Hack so that an existing value of "!important" will DTRT
decls[0].important = true;
propertyValue = 'url(...)';
} else if (/^\s*$/.test(propertyValue)) {
propertyValue = 'url(...)';
} else {
var existingUrlTokens = propertyValue.match(relation.tokenRegExp);
if (existingUrlTokens) {
relation.tokenNumber = existingUrlTokens.length;
}
propertyValue += ' url(...)';
}
decls[0].value = propertyValue;
}
});
if (relation.propertyName) {
relation.propertyNode = getProperties(cssRule, relation.propertyName)[0];
} else {
cssRule.append('background-image: url(...)');
relation.propertyNode = cssRule.last;
}
// I can't see why the ordering of CssImage relations should be significant...
spriteInfo.asset.addRelation(relation, 'last');
relation.refreshHref();
spriteInfo.cssRule.walkDecls(function (decl) {
if (['-sprite-selector-for-group', '-sprite-packer', '-sprite-image-format', '-sprite-background-color', '-sprite-important'].indexOf(decl.prop) !== -1) {
decl.remove();
}
});
for (const imageInfo of imageInfos) {
for (const incomingRelation of imageInfo.incomingRelations) {
incomingRelation.from.markDirty();
const relationSpriteInfo = getRelationSpriteInfoFromIncomingRelation(incomingRelation);
const node = incomingRelation.node;
const existingBackgroundPositionDecls = getProperties(node, 'background-position');
const existingBackgroundDecls = getProperties(node, 'background');
const offsets = [
Math.round(imageInfo.x / imageInfo.asset.devicePixelRatio), // FIXME: Rounding issues?
Math.round(imageInfo.y / imageInfo.asset.devicePixelRatio)
];
let backgroundOffsetsWereUpdated = false;
let existingOffsets;
if (existingBackgroundDecls.length > 0) {
// Warn if there's more than one?
const backgroundTokens = existingBackgroundDecls[0].value.split(/\s+/);
const positionTokenIndices = [];
existingOffsets = [];
for (const [i, existingBackgroundValueToken] of backgroundTokens.entries()) {
if (/^(?:-?\d+px|0)$/i.test(existingBackgroundValueToken)) {
positionTokenIndices.push(i);
existingOffsets.push(parseInt(existingBackgroundValueToken, 10));
}
}
if (existingOffsets.length === 2) {
// Patch up the existing background property by replacing the old offsets with corrected ones:
for (let [i, offset] of offsets.entries()) {
offset -= existingOffsets[i];
backgroundTokens.splice(positionTokenIndices[i], 1, offset ? -offset + 'px' : '0');
}
// If background-size is set, we should update it, The correct size is now the size of the sprite:
var backgroundSizeDecls = getProperties(spriteInfo.cssRule, 'background-size');
if (backgroundSizeDecls.length > 0) {
backgroundSizeDecls[0].value = packingData.width + 'px ' + packingData.height + 'px';
}
});
existingBackgroundDecls[0].value = backgroundTokens.join(' ');
backgroundOffsetsWereUpdated = true;
}
imageInfos.forEach(function (imageInfo) {
imageInfo.incomingRelations.forEach(function (incomingRelation) {
incomingRelation.from.markDirty();
var relationSpriteInfo = getRelationSpriteInfoFromIncomingRelation(incomingRelation),
node = incomingRelation.node,
existingBackgroundPositionDecls = getProperties(node, 'background-position'),
existingBackgroundDecls = getProperties(node, 'background'),
backgroundOffsetsWereUpdated = false,
offsets = [
Math.round(imageInfo.x / imageInfo.asset.devicePixelRatio), // FIXME: Rounding issues?
Math.round(imageInfo.y / imageInfo.asset.devicePixelRatio)
],
existingOffsets;
if (existingBackgroundDecls.length > 0) {
// Warn if there's more than one?
var backgroundTokens = existingBackgroundDecls[0].value.split(/\s+/),
positionTokenIndices = [];
existingOffsets = [];
backgroundTokens.forEach(function (existingBackgroundValueToken, i) {
if (/^(?:-?\d+px|0)$/i.test(existingBackgroundValueToken)) {
positionTokenIndices.push(i);
existingOffsets.push(parseInt(existingBackgroundValueToken, 10));
}
});
if (existingOffsets.length === 2) {
// Patch up the existing background property by replacing the old offsets with corrected ones:
offsets.forEach(function (offset, i) {
offset -= existingOffsets[i];
backgroundTokens.splice(positionTokenIndices[i], 1, offset ? -offset + 'px' : '0');
});
}
existingBackgroundDecls[0].value = backgroundTokens.join(' ');
backgroundOffsetsWereUpdated = true;
}
}
if (!backgroundOffsetsWereUpdated) {
// There was no 'background' property, or it didn't contain something that looked like offsets.
// Create or update the background-position property instead:
let backgroundPositionImportant = false;
if (existingBackgroundPositionDecls.length === 1) {
// FIXME: Silently ignores other units than px
backgroundPositionImportant = existingBackgroundPositionDecls[0].value === '!important' || existingBackgroundPositionDecls[0].important;
if (!backgroundOffsetsWereUpdated) {
// There was no 'background' property, or it didn't contain something that looked like offsets.
// Create or update the background-position property instead:
var backgroundPositionImportant = false;
if (existingBackgroundPositionDecls.length === 1) {
// FIXME: Silently ignores other units than px
backgroundPositionImportant = existingBackgroundPositionDecls[0].value === '!important' || existingBackgroundPositionDecls[0].important;
if (existingBackgroundPositionDecls[0].value !== '!important') {
existingOffsets = existingBackgroundPositionDecls[0].value.split(' ').map(function (item) {
return parseInt(item, 10);
});
if (existingOffsets.length !== 2 || isNaN(existingOffsets[0]) || isNaN(existingOffsets[1])) {
var err = new Error('WARNING: trying to sprite ' + imageInfo.asset.url + ' with background-position: ' + existingBackgroundPositionDecls[0].value);
assetGraph.emit('warn', err);
} else {
offsets[0] -= existingOffsets[0];
offsets[1] -= existingOffsets[1];
}
}
}
var newBackgroundPositionValue = offsets.map(function (item) {
return item ? -item + 'px' : '0';
}).join(' ');
if (existingBackgroundPositionDecls.length > 0) {
existingBackgroundPositionDecls[0].value = newBackgroundPositionValue;
existingBackgroundPositionDecls[0].important = backgroundPositionImportant;
} else {
node.append('background-position: ' + newBackgroundPositionValue + (backgroundPositionImportant ? ' !important' : ''));
}
if (existingBackgroundPositionDecls[0].value !== '!important') {
existingOffsets = existingBackgroundPositionDecls[0].value.split(' ').map(
item => parseInt(item, 10)
);
if (existingOffsets.length !== 2 || isNaN(existingOffsets[0]) || isNaN(existingOffsets[1])) {
const err = new Error('WARNING: trying to sprite ' + imageInfo.asset.url + ' with background-position: ' + existingBackgroundPositionDecls[0].value);
assetGraph.warn(err);
} else {
offsets[0] -= existingOffsets[0];
offsets[1] -= existingOffsets[1];
}
}
}
const newBackgroundPositionValue = offsets.map(
item => item ? -item + 'px' : '0'
).join(' ');
if (existingBackgroundPositionDecls.length > 0) {
existingBackgroundPositionDecls[0].value = newBackgroundPositionValue;
existingBackgroundPositionDecls[0].important = backgroundPositionImportant;
} else {
node.append('background-position: ' + newBackgroundPositionValue + (backgroundPositionImportant ? ' !important' : ''));
}
}
node.walkDecls(function (decl) {
if (['-sprite-group', '-sprite-padding', '-sprite-no-group-selector', '-sprite-important'].indexOf(decl.prop) !== -1) {
decl.remove();
}
});
node.walkDecls(decl => {
if (['-sprite-group', '-sprite-padding', '-sprite-no-group-selector', '-sprite-important'].includes(decl.prop)) {
decl.remove();
}
});
// Background-sizes change when spriting, upadte appropriately
if (imageInfo.asset.devicePixelRatio === 1) {
// Device pixel ratio is default. Remove property and let the defaults rule
getProperties(incomingRelation.node, 'background-size').forEach(function (backgroundSizeDecl) {
backgroundSizeDecl.remove();
});
} else {
// Device pixel ratio is non-default, Set it explicitly with the ratio applied
var dpr = incomingRelation.to.devicePixelRatio;
// Background-sizes change when spriting, upadte appropriately
if (imageInfo.asset.devicePixelRatio === 1) {
// Device pixel ratio is default. Remove property and let the defaults rule
for (const backgroundSizeDecl of getProperties(incomingRelation.node, 'background-size')) {
backgroundSizeDecl.remove();
}
} else {
// Device pixel ratio is non-default, Set it explicitly with the ratio applied
const dpr = incomingRelation.to.devicePixelRatio;
// TODO: Figure out if rounding might become a problem
var width = packingData.width / dpr;
var height = packingData.height / dpr;
var existingBackgroundSizeDecls = getProperties(incomingRelation.node, 'background-size');
if (existingBackgroundSizeDecls.length > 0) {
existingBackgroundSizeDecls[0].value = width + 'px ' + height + 'px';
} else {
incomingRelation.node.append('background-size: ' + width + 'px ' + height + 'px');
}
}
// TODO: Figure out if rounding might become a problem
const width = packingData.width / dpr;
const height = packingData.height / dpr;
const existingBackgroundSizeDecls = getProperties(incomingRelation.node, 'background-size');
if (existingBackgroundSizeDecls.length > 0) {
existingBackgroundSizeDecls[0].value = `${width}px ${height}px`;
} else {
incomingRelation.node.append(`background-size: ${width}px ${height}px`);
}
}
if (relationSpriteInfo.noGroup || !spriteGroup.placeHolders) {
// The user specified that this selector needs its own background-image/background
// property pointing at the sprite rather than relying on the Html elements also being
// matched by the sprite group's "main" selector, which would have been preferable.
var relation = new assetGraph.CssImage({
node: incomingRelation.node,
propertyNode: incomingRelation.propertyNode,
to: spriteAsset
});
incomingRelation.from.addRelation(relation, 'before', incomingRelation);
relation.refreshHref();
incomingRelation.remove();
} else {
incomingRelation.detach();
}
if (relationSpriteInfo.noGroup || !spriteGroup.placeHolders) {
// The user specified that this selector needs its own background-image/background
// property pointing at the sprite rather than relying on the Html elements also being
// matched by the sprite group's "main" selector, which would have been preferable.
const relation = incomingRelation.from.addRelation({
type: 'CssImage',
node: incomingRelation.node,
propertyNode: incomingRelation.propertyNode,
to: spriteAsset
}, 'before', incomingRelation);
relation.refreshHref();
incomingRelation.remove();
} else {
incomingRelation.detach();
}
// Remove the original image if it has become an orphan:
if (!assetGraph.findRelations({to: incomingRelation.to}).length) {
assetGraph.removeAsset(incomingRelation.to);
}
});
});
callback();
})['catch'](callback);
})
.seq(function () {
cb();
})['catch'](cb);
// Remove the original image if it has become an orphan:
if (!assetGraph.findRelations({to: incomingRelation.to}).length) {
assetGraph.removeAsset(incomingRelation.to);
}
}
}
}
};
};

@@ -5,3 +5,3 @@ {

"repository": "git://github.com/One-com/assetgraph-sprite.git",
"version": "2.0.0",
"version": "3.0.0",
"maintainers": [

@@ -23,8 +23,2 @@ {

],
"dependencies": {
"lodash.assign": "4.2.0",
"lodash.values": "4.3.0",
"passerror": "1.1.1",
"seq": "0.3.5"
},
"optionalDependencies": {

@@ -34,6 +28,7 @@ "canvas": "1.6.5"

"devDependencies": {
"assetgraph": "^3.0.0",
"assetgraph": "4.0.0",
"coveralls": "^2.11.6",
"eslint": "4.16.0",
"eslint-config-onelint": "3.0.0",
"istanbul": "^0.4.2",
"jshint": "^2.9.1",
"lodash.pluck": "3.1.2",

@@ -48,3 +43,3 @@ "mocha": "^3.0.0",

"scripts": {
"lint": "jshint .",
"lint": "eslint .",
"test": "npm run lint && mocha",

@@ -51,0 +46,0 @@ "coverage": "istanbul cover _mocha",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc