Skip to content

Instantly share code, notes, and snippets.

@andershaig
Created April 17, 2012 21:44
Show Gist options
  • Save andershaig/2409272 to your computer and use it in GitHub Desktop.
Save andershaig/2409272 to your computer and use it in GitHub Desktop.
Create CSS3 code from Photoshop layers
/* Copyright 2012 - Minim Group - http://minim.co/ */
// Enable double-clicking from Finder/Explorer
#target photoshop
app.bringToFront();
// ### Document Variables
var doc_layers = app.activeDocument.layers;
var num_layers = doc_layers.length;
// ### Effect Variables
var dropShadow = {};
var stroke = {};
var gradient = {};
// ### Output Variables
var output = ''; // TEMP
var css;
var html;
cTID = function(s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
sTID = function(s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
xTID = function(s) {
if (s.constructor == Number) {
return s;
}
if (s.constructor == String) {
if (s.length != 4) return sTID(s);
try { return cTID(s); } catch (e) { return sTID(s); }
}
throw "Bad typeid: " + s;
};
// ### Main Function
function main() {
//createDialog();
getLayerEffects();
//generateCSS();
outputFile();
}
// ### Helper Functions
function createDialog() {
var ui = "dialog { \
text:'Main Dialog Text', \
alignChildren: 'fill', \
mainPanel: Panel { \
orientation: 'column', \
text:'Select Layers', \
alignChildren: 'fill', \
helpText:StaticText { \
text:'Which layer would you like to convert and export?', \
properties:{scrolling:undefined,multiline:undefined} \
}, \
selectLayers:DropDownList { properties:{name:'layerList'} } \
}, \
gButtons: Group { \
orientation: 'row', \
cancelBtn:Button { text:'Cancel', orientation: 'column', alignment: 'left', properties:{name:'cancel'} }, \
continueBtn:Button { text:'Select Layers', orientation: 'column', alignment: 'right', properties:{name:'select'} } \
} \
}";
var win = new Window (ui); // new window object with UI resource
win.center(); // move to center before
var ret = win.show(); // dialog display
/*
if (1 == ret) { // if "Open" button clicked.
}
*/
}
function getLayerEffects() {
// Get Effect Helpers
function getDropShadow() {
var dropShadowDesc = effectDesc.getObjectValue(cTID("DrSh"));
dropShadow.enabled = dropShadowDesc .getBoolean( cTID( "enab" ));
dropShadow.blendMode = typeIDToStringID(dropShadowDesc .getEnumerationValue(cTID( "Md " )));
var shadowColorDesc = dropShadowDesc .getObjectValue(cTID( "Clr " ));
var shadowColorMode = typeIDToCharID(dropShadowDesc .getObjectType(cTID( "Clr " )));
dropShadow.color = new SolidColor();
switch ( shadowColorMode ){
case 'Grsc':
dropShadow.color.gray.gray = shadowColorDesc.getDouble(cTID('Gry '));
break;
case 'RGBC':
dropShadow.color.rgb.red = shadowColorDesc.getDouble(cTID('Rd '));
dropShadow.color.rgb.green = shadowColorDesc.getDouble(cTID('Grn '));
dropShadow.color.rgb.blue = shadowColorDesc.getDouble(cTID('Bl '));
break;
case 'CMYC':
dropShadow.color.cmyk.cyan = shadowColorDesc.getDouble(cTID('Cyn '));
dropShadow.color.cmyk.magenta = shadowColorDesc.getDouble(cTID('Mgnt'));
dropShadow.color.cmyk.yellow = shadowColorDesc.getDouble(cTID('Ylw '));
dropShadow.color.cmyk.black = shadowColorDesc.getDouble(cTID('Blck'));
break;
case 'LbCl':
dropShadow.color.lab.l = shadowColorDesc.getDouble(cTID('Lmnc'));
dropShadow.color.lab.a = shadowColorDesc.getDouble(cTID('A '));
dropShadow.color.lab.b = shadowColorDesc.getDouble(cTID('B '));
break;
}
dropShadow.opacity = dropShadowDesc .getDouble(cTID("Opct"));
dropShadow.useGlobalAngle = dropShadowDesc .getBoolean(cTID("uglg"));
dropShadow.localLightingAngle = dropShadowDesc .getDouble( cTID("lagl"));
dropShadow.distance = dropShadowDesc .getDouble( cTID("Dstn"));
dropShadow.spread = dropShadowDesc .getDouble( cTID("Ckmt"));
dropShadow.blur = dropShadowDesc .getDouble( cTID("blur"));
dropShadow.noise = dropShadowDesc .getDouble( cTID("Nose"));
dropShadow.antialias = dropShadowDesc .getBoolean( cTID( "AntA" ));
dropShadow.knockout = dropShadowDesc .getBoolean( sTID("layerConceals"));
var contourDesc = dropShadowDesc .getObjectValue( cTID("TrnS"), cTID("ShpC") );
if( contourDesc.hasKey(cTID("Nm ")) ) {
dropShadow.contourName = localize(contourDesc.getString( cTID("Nm ")));
}else{
dropShadow.contourName = 'custom';
}
}
function getStroke() {
var strokeDesc = effectDesc.getObjectValue(cTID("FrFX"));
stroke.enabled = strokeDesc .getBoolean( cTID("enab"));
stroke.frameStyle = typeIDToStringID(strokeDesc .getEnumerationValue(cTID("Styl")));
stroke.frameFill = typeIDToStringID(strokeDesc .getEnumerationValue(cTID("PntT")));
stroke.blendMode = typeIDToStringID(strokeDesc .getEnumerationValue(cTID("Md ")));
var strokeColorDesc = strokeDesc .getObjectValue(cTID("Clr "));
var strokeColorMode = typeIDToCharID(strokeDesc .getObjectType(cTID("Clr ")));
stroke.color = new SolidColor();
switch ( strokeColorMode ){
case 'Grsc':
stroke.color.gray.gray = strokeColorDesc.getDouble(cTID('Gry '));
break;
case 'RGBC':
stroke.color.rgb.red = strokeColorDesc.getDouble(cTID('Rd '));
stroke.color.rgb.green = strokeColorDesc.getDouble(cTID('Grn '));
stroke.color.rgb.blue = strokeColorDesc.getDouble(cTID('Bl '));
break;
case 'CMYC':
stroke.color.cmyk.cyan = strokeColorDesc.getDouble(cTID('Cyn '));
stroke.color.cmyk.magenta = strokeColorDesc.getDouble(cTID('Mgnt'));
stroke.color.cmyk.yellow = strokeColorDesc.getDouble(cTID('Ylw '));
stroke.color.cmyk.black = strokeColorDesc.getDouble(cTID('Blck'));
break;
case 'LbCl':
stroke.color.lab.l = strokeColorDesc.getDouble(cTID('Lmnc'));
stroke.color.lab.a = strokeColorDesc.getDouble(cTID('A '));
stroke.color.lab.b = strokeColorDesc.getDouble(cTID('B '));
break;
}
stroke.opacity = strokeDesc .getDouble(cTID("Opct"));
stroke.size = strokeDesc .getDouble(cTID("Sz "));
}
// Generate CSS Helpers
function setDropShadowCSS() {
// Simple Vars
var ds;
var dsVal;
var dsClr;
var blur = dropShadow.blur + 'px ';
var spread = dropShadow.spread + 'px ';
var red = Math.round(dropShadow.color.rgb.red);
var green = Math.round(dropShadow.color.rgb.green);
var blue = Math.round(dropShadow.color.rgb.blue);
var o = dropShadow.opacity / 100;
// Round to nearest 45 degrees (in future do more to calculate)
var a = dropShadow.localLightingAngle;
var d = dropShadow.distance;
var ra = Math.round (a / 45) * 45;
var distance;
if (ra === 0) {
distance = (-d) + 'px 0 ';
} else if (ra === 45) {
distance = (-d) + 'px ' + d + 'px ';
} else if (ra === 90) {
distance = '0 ' + d + 'px ';
} else if (ra === 135) {
distance = d + 'px ' + d + 'px ';
} else if (ra === 180 || ra === -180) {
distance = d + 'px 0 ';
} else if (ra === -135) {
distance = d + 'px ' + (-d) + 'px ';
} else if (ra === -90) {
distance = '0 ' + (-d) + 'px ';
} else if (ra === -45) {
distance = (-d) + 'px ' + (-d) + 'px ';
} else {
// Couldn't figure out angle
}
dsVal = distance + blur + spread;
dsClr = 'rgba(' + red + ',' + green + ',' + blue + ',' + o + ')';
ds = 'box-shadow: ' + dsVal + dsClr + ';\n';
output += ds;
}
function setStrokeCSS() {
// Simple Vars
var s;
var sClr;
var size = stroke.size + 'px ';
var red = Math.round(stroke.color.rgb.red);
var green = Math.round(stroke.color.rgb.green);
var blue = Math.round(stroke.color.rgb.blue);
var o = stroke.opacity / 100;
sClr = 'rgba(' + red + ',' + green + ',' + blue + ',' + o + ')';
s = 'border: ' + size + 'solid ' + sClr + ';\n';
//if (stroke.frameStyle === 'insetFrame') {
//}
output += s;
}
// Effect Names To Array
var ref = new ActionReference();
ref.putEnumerated( cTID("Lyr "), cTID("Ordn"), cTID("Trgt") );
var desc = executeActionGet(ref);
if (desc.hasKey(sTID('layerEffects'))) {
var effects = [];
var effectDesc = desc.getObjectValue( sTID('layerEffects'));
// first key is scale so skip and start with 1
for (var effect = 1; effect < effectDesc.count; effect++) {
var effect_name = typeIDToStringID(effectDesc.getKey(effect));
if (effect_name === 'dropShadow') {
// Drop Shadow / Box Shadow
getDropShadow();
setDropShadowCSS();
//output += 'Effect name is ' + effect_name + '\n';
} else if (effect_name === 'gradientFill') {
// Gradient
//gradient_obj = getGradientSettings();
//output += 'Effect name is ' + effect_name + '\n';
} else if (effect_name === 'frameFX') {
// Stroke / Border
getStroke();
setStrokeCSS();
//output += 'Effect name is ' + effect_name + '\n';
} else {
// do nothing
}
}
}
}
function generateCSS() {
// TODO - Templating?
}
// ### Output Function
function outputFile(){
var mySavefile = File.saveDialog("Filename...","*.html");
if (!mySavefile) {return};
if (mySavefile.exists) {
if(! confirm("There is already a file with that name.\nDo you want to overwrite?")){return false;};
}
var fileRef = new File(mySavefile);
flag = fileRef.open ("w","","");
if (flag)
{
fileRef.writeln('<!DOCTYPE html>');
fileRef.writeln('<html lang="en">');
fileRef.writeln('<head>');
fileRef.writeln('<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />');
fileRef.writeln('<meta http-equiv="Content-Script-Type" content="text/javascript" />');
fileRef.writeln('<title>Template</title>');
fileRef.writeln('</head>');
fileRef.writeln('<style><!--');
fileRef.writeln(output);
fileRef.writeln('--></style>');
fileRef.writeln('<body>');
fileRef.writeln('HTML will go here.');
fileRef.writeln('</body>');
fileRef.writeln('</html>');
}
fileRef.close();
}
// ### Make That Magic Happen
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment