-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimplePSDtoHTML.jsx
More file actions
387 lines (349 loc) · 17.2 KB
/
Copy pathsimplePSDtoHTML.jsx
File metadata and controls
387 lines (349 loc) · 17.2 KB
1
// enable double clicking from the Macintosh Finder or the Windows Explorer#target photoshop///////////////////////////////////////// Глобальные переменные ////////////////////////////////////////var docRef = activeDocument; //Активный документvar docWidth = docRef.width.value; //Ширина документа var docHeight = docRef.height.value; //Высота документаvar docName = app.activeDocument.fullName.toString().replace(".psd",""); // Имя текущего документаvar mySourceFilePath = app.activeDocument.path; // Путь к текущему файлуvar TAB = " "; // Отступ для HTML/CSSvar uId = 0; // Уникальный идентификатор объектовvar html = "", css = ""; // HTML/CSS текст///////////////////////////////////////// Текстовые константы ////////////////////////////////////////var strAlertDocumentMustBeOpened = "Должен быть открыт по крайней мере один документ!";var strAlertCantWriteFile = "Не могу записать файл:"; var strAllOk = "Все готово!";///////////////////////////////////////// Функции ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Function: saveFileOnDisk// Usage: Сохраняет текстовые данные в файл. Имя берется от основного файла// Input: Текстовые данные data + расширение для файла ext// Return: нет///////////////////////////////////////////////////////////////////////////////function saveFileOnDisk(data, ext){ var csvFile, output; try{ csvFile = File(docName + "."+ ext); if(csvFile.exists){ csvFile.remove(); } csvFile = new File(docName + "."+ ext); if (csvFile !== ''){ output = csvFile.open('w'); if(output !== false){ if(csvFile.write(data)){ csvFile.close(); } else{ alert(strAlertCantWriteFile + ' ' + docName + "."+ ext + "\n" + csvFile.error); } } } } catch(err){ alert(strAlertCantWriteFile + ' ' + docName + "."+ ext + "\n" + err); }}///////////////////////////////////////////////////////////////////////////////// Function: saveImage// Usage: Сохраняет изображение в формате PNG/JPG// Input: ссылка на слой с изображением// Return: нет///////////////////////////////////////////////////////////////////////////////function saveImage(img){ var filePathName = mySourceFilePath +"/"+ img.fileNam, saveOptions = new ExportOptionsSaveForWeb(), deltaX, deltaY, layerRef; if(img.x2){ img.link.resize(50, 50); // ToDo: Сохранить начальное состояние документа и восстановить в конце! layerRef = duplicateElement(img.link); } else{ layerRef = duplicateElement(img.link); } if(img.type == 'jpg'){ saveOptions.format = SaveDocumentType.JPEG; // Сохраняем в формате JPEG saveOptions.quality = 90; saveOptions.includeProfile = false; saveOptions.interlaced = 0; saveOptions.optimized = true; } else{ saveOptions.format = SaveDocumentType.PNG; // Или PNG saveOptions.PNG8 = false; saveOptions.transparency = true; saveOptions.interlaced = false; saveOptions.includeProfile = false; } app.activeDocument.exportDocument(new File( filePathName ), ExportType.SAVEFORWEB, saveOptions ); app.activeDocument.close( SaveOptions.DONOTSAVECHANGES ); if(img.x2){ img.link.resize(200, 200); }}///////////////////////////////////////////////////////////////////////////////// Function: duplicateElement// Usage: Копирует слой в новый документ// Input: Ссылка на слой, который дублируем// Return: ссылка на скопированный слой в новом документе///////////////////////////////////////////////////////////////////////////////function duplicateElement( obj ){ var w = parseInt (obj.bounds[2]) - parseInt (obj.bounds[0]), h = parseInt (obj.bounds[3]) - parseInt (obj.bounds[1]), layerRef, from = app.activeDocument, objOpacity = obj.opacity, objFillOpacity = obj.fillOpacity, // Сохраняем текущую прозрачность документа to = app.documents.add(w, h, 72, "tmp", NewDocumentMode.RGB, DocumentFill.TRANSPARENT); app.activeDocument = from; obj.opacity = 100; obj.fillOpacity = 100; layerRef = obj.duplicate(to, ElementPlacement.PLACEBEFORE.beforeLayer); // копируем слой в новый документ obj.opacity = objOpacity; // Восстановим значение прозрачности для элемента obj.fillOpacity = objFillOpacity; app.activeDocument = to; if(layerRef.bounds[0] !== 0 || layerRef.bounds[1] !== 0) { // если элемент съехал относительно начала координат layerRef.translate(new UnitValue (-layerRef.bounds[0], "px"), new UnitValue (-layerRef.bounds[1], "px")); } return layerRef; }///////////////////////////////////////////////////////////////////////////////// Function: writeHTMLFiles// Usage: Записываем все слои с изображениями в файлы и создаем соответствующие HTML/CSS// Input: Дерево объектов и значение отступа// Return: нет///////////////////////////////////////////////////////////////////////////////function writeHTMLFiles(tree, tab){ var leaf, node; tab = tab || TAB; for(leaf in tree){ if(tree[leaf].type){ node = tree[leaf]; ///////////// Секция CSS //////////////////////////// css += '.' + node.name + '{\n'; css += " position : absolute;\n"; css += " width:" + node.width + "px;\n"; css += " height:" + node.height + "px;\n"; css += " top:" + node.y + "px;\n"; css += " left:" + node.x + "px;\n"; css += " opacity: " + node.opacity.toFixed(2) + ";\n"; if(node.rotate || node.scale){ css +=" -webkit-transform: rotate(" + (node.rotate ? node.rotate : 0) + "deg) scale(" + (node.scale ? node.scale : 1) + ");\n"; css +=" -moz-transform: rotate(" + (node.rotate ? node.rotate : 0) + "deg) scale(" + (node.scale ? node.scale : 1) + ");\n"; css +=" -ms-transform: rotate(" + (node.rotate ? node.rotate : 0) + "deg) scale(" + (node.scale ? node.scale : 1) + ");\n"; css +=" -o-transform: rotate(" + (node.rotate ? node.rotate : 0) + "deg) scale(" + (node.scale ? node.scale : 1) + ");\n"; css +=" transform: rotate(" + (node.rotate ? node.rotate : 0) + "deg) scale(" + (node.scale ? node.scale : 1) + ");\n"; } css += "}\n\n"; ///////////// Конец секции CSS //////////////////////// if(node.type == "div"){ html += tab + '<div class="' + node.name + ' ' + node.type + '">\n'; writeHTMLFiles(node, tab+TAB); html += tab + '</div>\n'; } else{ saveImage(node); html += tab + '<img src="' + node.fileName + '" width="' + node.width + '" height="' + node.height + '" class="' + node.name + ' ' + node.type + '">\n'; } } }}///////////////////////////////////////////////////////////////////////////////// Function: parseLayerSet// Usage: Заполняем значения для группы слоев// Input: ссылка на слой-группу// Return: заполненная структура данных///////////////////////////////////////////////////////////////////////////////function parseLayerSet(layer){ var result = {}; result = parseLayerName(layer.name); result.type = "div"; result.x = parseInt(layer.bounds[0]); result.y = parseInt(layer.bounds[1]); result.width = parseInt (layer.bounds[2]) - parseInt (layer.bounds[0]); result.height = parseInt (layer.bounds[3]) - parseInt (layer.bounds[1]); return result;}///////////////////////////////////////////////////////////////////////////////// Function: parseArtLayer// Usage: Заполняем значения для слоя с изображением// Input: Ссылка на арт-слой// Return: заполненная структура данных///////////////////////////////////////////////////////////////////////////////function parseArtLayer(layer){ var result = {}; result = parseLayerName(layer.name); result.fileName = "img/" + result.name + "." + result.type; result.x = parseInt(layer.bounds[0]); result.y = parseInt(layer.bounds[1]); result.width = parseInt (layer.bounds[2]) - parseInt (layer.bounds[0]); result.height = parseInt (layer.bounds[3]) - parseInt (layer.bounds[1]); return result;}///////////////////////////////////////////////////////////////////////////////// Function: createDocTree// Usage: Строим рекурсивно дерево объектов из слоев// Input: obj - ссылка на слой фотошопа// node - ссылка на узел выстраивомого дерева// dx, dy - относительное смещение слоя// Return: нет///////////////////////////////////////////////////////////////////////////////function createDocTree(obj, node, dx, dy){ var i; for(i = obj.layers.length; i--; ){ obj.layers[i].name = obj.layers[i].name.replace(/[\/\\\*\?\^]*/g, ""); obj.layers[i].name = obj.layers[i].name.replace(/ ([0-9]+)/,"$1"); if(obj.layers[i].typename == "LayerSet"){ node[obj.layers[i].name] = parseLayerSet(obj.layers[i]); createDocTree(obj.layers[i], node[obj.layers[i].name], node[obj.layers[i].name].x, node[obj.layers[i].name].y); } else if(obj.layers[i].typename == "ArtLayer" && obj.layers[i].kind == LayerKind.NORMAL){ // Только обычные слои слои! node[obj.layers[i].name] = parseArtLayer(obj.layers[i]); } else{ continue; } node[obj.layers[i].name].uId = uId++; node[obj.layers[i].name].link = obj.layers[i]; node[obj.layers[i].name].isVisible = obj.layers[i].visible; node[obj.layers[i].name].x -= dx; node[obj.layers[i].name].y -= dy; if(node[obj.layers[i].name].x2){ node[obj.layers[i].name].scale = 2 * (node[obj.layers[i].name].scale? node[obj.layers[i].name].scale : 1); } node[obj.layers[i].name].opacity = ((obj.layers[i].fillOpacity ? obj.layers[i].fillOpacity : 100) * obj.layers[i].opacity)/10000; } }///////////////////////////////////////////////////////////////////////////////// Function: transliterate// Usage: Вспомогательная функция. Переводит русские символы в латинские// Input: text - текстовый элемент, engToRus - флаг направления транслитерации// Return: переведенный текст///////////////////////////////////////////////////////////////////////////////var transliterate = (function() { var rus = "щ ш ч ц ю я ё ж ъ ы э а б в г д е з и й к л м н о п р с т у ф х ь".split(/ +/g), eng = "shh sh ch cz yu ya yo zh `` y' e` a b v g d e z i j k l m n o p r s t u f x `".split(/ +/g); return function(text, engToRus) { var i; for(i = 0; i < rus.length; i++) { text = text.split(engToRus ? eng[i] : rus[i]).join(engToRus ? rus[i] : eng[i]); text = text.split(engToRus ? eng[i].toUpperCase() : rus[i].toUpperCase()).join(engToRus ? rus[i].toUpperCase() : eng[i].toUpperCase()); } return text; } })();///////////////////////////////////////////////////////////////////////////////// Function: parseLayerName// Usage: Разбираем имя слоя. По умолчанию сохраняем в PNG! Проверяет уникальность имени. Ключи:// rotate(NN) - Поворот в градусах// scale(NN) - Масштабирование в процентак// factor(NN) - Масштабирование// jpg, jpeg - Сохранять в JPEG// 2x, x2 - Уменьшаем картинку в два раза// Input: Ссылка на элемент, который дублируем// Return: <none>///////////////////////////////////////////////////////////////////////////////var parseLayerName = (function(){ var names = {}; return function(name){ var splitName = [], result = {}, i; name = name.replace(/_/g, " "); while(~name.indexOf(" ")){ // убираем лишние пробелы в имени слоя name = name.replace(/ /g, " "); } if(~name.search(/[А-яЁё]/)){ name = transliterate(name, false); } splitName = name.toLowerCase().split(" "); // Разбиваем имя на компоненты result.type = "png"; result.name = splitName[0]; if(~result.name.search(/^[0-9-]/)){ result.name = "_" + result.name; } if(result.name in names){ result.name += "_" + uId; } names[result.name] = true; for(i = 0; i < splitName.length; i++){ if(~splitName[i].indexOf("rotate")){ result.rotate = splitName[i].match(/[0-9]+/)[0]; } else if((~splitName[i].indexOf("scale")) || (~splitName[i].indexOf("factor"))){ if(~splitName[i].indexOf(".")){ result.scale = splitName[i].match(/[0-9]+.?(?:[0-9]+)/)[0] + ""; } else { result.scale = splitName[i].match(/[0-9]+/)[0]/100 + ""; } } else if((~splitName[i].indexOf("jpg")) || (~splitName[i].indexOf("jpeg"))){ result.type = "jpg"; } else if((~splitName[i].indexOf("x2")) || (~splitName[i].indexOf("2x"))){ result.x2 = true; } } return result; }})();///////////////////////////////////////////////////////////////////////////////// Function: main// Usage: Основная функция// Input: нет// Return: нет///////////////////////////////////////////////////////////////////////////////function main(){// секция переменных var layerRef, result, docTree = {}, originalUnit, deltaX = 0, deltaY= 0, //смещение начала координат. По умолчанию совпадает с началом координат документа folder, i; //////////////////////////////////////////////////////////////////////////////// if ( app.documents.length <= 0 ) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert( strAlertDocumentMustBeOpened ); } return 'cancel'; // Выходим, возвращаем 'cancel' } // Запомним текущие настройки линеек originalUnit = preferences.rulerUnit; app.preferences.rulerUnits = Units.PIXELS; for(i = docRef.layers.length; i--; ){ if(docRef.layers[i].name.toLowerCase().indexOf ("bg")+1){ deltaX = parseInt ( docRef.layers[i].bounds[0]); deltaY = parseInt ( docRef.layers[i].bounds[1]); i = 0; } } createDocTree (docRef, docTree, deltaX, deltaY); folder= new Folder(mySourceFilePath + '/img/'); if (!folder.exists){ folder.create(); } writeHTMLFiles(docTree, TAB); saveFileOnDisk(html, "html"); saveFileOnDisk(css, "css"); //Восстановим настройки линеек preferences.rulerUnit = originalUnit; app.beep(); alert(strAllOk); return 'ok'; }///////////////////////////////////////// Поехали!!! ////////////////////////////////////////main();