├── screenshot.png ├── .jshintrc ├── LICENSE.txt ├── README.md ├── Illustrator ├── Export Layout Folder.jsx └── Export Layout.jsx └── Photoshop └── Export Layer Coordinates Photoshop.jsx /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bronzehedwick/Adobe-Export-Scripts/HEAD/screenshot.png -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "es5" : true, 3 | "browser" : false, 4 | "curly": true, 5 | "debug": false, 6 | "devel": false, 7 | "eqeqeq": true, 8 | "eqnull": true, 9 | "evil": true, 10 | "forin": false, 11 | "immed": false, 12 | "laxbreak": false, 13 | "newcap": true, 14 | "noarg": true, 15 | "noempty": false, 16 | "nonew": false, 17 | "onevar": true, 18 | "plusplus": false, 19 | "regexp": false, 20 | "undef": true, 21 | "sub": false, 22 | "strict": false, 23 | "predef": [ 24 | "app", 25 | "SaveOptions", 26 | "Folder", 27 | "alert", 28 | "preferences", 29 | "fileLineFeed" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Christopher DeLuca 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Adobe-Export-Scripts 2 | ==================== 3 | ### 4 | License: [MIT][1] 5 | Blame: Chris DeLuca & Sean Orelli 6 | ### 7 | 8 | Photoshop and Illustrator scripts. These scripts have been tested with Illustrator CS4/5 and Photoshop CS5. 9 | 10 | There are two Illustrator scripts: 11 | * Export PNGs from groups 12 | * Export layout coordinates 13 | 14 | ![Illustrator script code screenshot](https://raw.githubusercontent.com/bronzehedwick/Adobe-Export-Scripts/master/screenshot.png) 15 | 16 | The PNG export differs from other export scripts I have found in that it exports groups only, instead of all elements. This way you can group all the PNGs you want exported. The script will only use the top level group (so it won't export nested groups) and trims the PNG with as little white space as possible. 17 | 18 | The export layout script is possibly more interesting. It exports the coordinates of all elements on the stage in valid JSON format. This can be interpreted by other code to lay out the contents of a screen, forming a working pipeline between the art department and programming. Ultimately, this is one piece in an automated process using a build server. 19 | 20 | The Photoshop script is very young, and needs an overhaul to compete with the Illustrator scripts. 21 | 22 | Installation 23 | -------------------- 24 | 1. Copy script to 25 | - **Mac:** `~/Applications/Adobe Illustrator CS#/Presets/en\_US/Scripts/` 26 | - **Win:** `C:\Program Files\Adobe\Adobe Illustrator CS#\Presets\en\_US\Scripts\` 27 | 2. Restart Illustrator or Photoshop 28 | 3. Choose `File > Scripts > [Name of Script]` 29 | 30 | [1]:http://www.opensource.org/licenses/MIT 31 | -------------------------------------------------------------------------------- /Illustrator/Export Layout Folder.jsx: -------------------------------------------------------------------------------- 1 | // Export Layout Folder - Adobe Illustrator Script 2 | // Description: Runs Export Layout on the contents of a folder 3 | // Requirements: Adobe Illustrator CS4 or greater 4 | // Version: 1.0-beta1 5 | // =============================================================================== 6 | // Installation: 7 | // 1. Place script in 8 | // Mac: '~/Applications/Adobe Illustrator CS#/Presets/Scripts/' 9 | // Win: 'C:\Program Files\Adobe\Adobe Illustrator CS#\Presets\en_US\Scripts\' 10 | // 2. Restart Illustrator 11 | // 3. Choose File > Scripts > Export Layout Folder 12 | // =============================================================================== 13 | /* 14 | 15 | This script runs the Export Layout script on all ai and eps files in a folder. 16 | Export Layout must be installed (as above) for this script to function. 17 | 18 | */ 19 | 20 | /*_______________________________ 21 | Enables double-click launching from 22 | the Mac Finder or Windows Explorer 23 | _______________________________*/ 24 | #target illustrator 25 | 26 | /*________________ 27 | 28 | Detect OS 29 | _________________*/ 30 | var os; 31 | if ( $.os.search(/windows/i) !== -1 ) { 32 | os = "Windows" 33 | } 34 | else { 35 | os = "Macintosh" 36 | } 37 | 38 | /*_______________ 39 | 40 | Set path to script 41 | _______________*/ 42 | if ( os === "Windows" ) { 43 | var scriptsPath = app.path + "/Presets/en_US/Scripts/Export%20Layout.jsx"; 44 | } 45 | else { 46 | var scriptsPath = app.path + "/Presets.localized/en_US/Scripts/Export%20Layout.jsx"; 47 | } 48 | 49 | var scriptFile = File(scriptsPath); 50 | var script; 51 | var docRef; 52 | 53 | /*__________________________ 54 | 55 | Load the Export Layout script 56 | __________________________*/ 57 | function executeScript() { 58 | scriptFile.open('r'); 59 | script = scriptFile.read(); 60 | scriptFile.close(); 61 | 62 | eval(script); 63 | } 64 | 65 | /*_________________________ 66 | 67 | Traverse files in selected folder 68 | _________________________*/ 69 | function traverseFiles() { 70 | for ( var i = 0; i < fileList.length; i++ ) { 71 | openFile(fileList[i]); 72 | } 73 | } 74 | 75 | /*__________________________ 76 | 77 | Open the file and process it 78 | __________________________*/ 79 | function openFile(filename) { 80 | docRef = app.open(filename); 81 | executeScript(); 82 | docRef.close(SaveOptions.DONOTSAVECHANGES); 83 | } 84 | 85 | /*_____________________________ 86 | 87 | Check if Export Layout is installed, 88 | then run functions 89 | ______________________________*/ 90 | if ( scriptFile.exists === true ) { 91 | var inputFolder = Folder.selectDialog( "Please select top level folder to process"); 92 | 93 | var fileList = inputFolder.getFiles("*.eps"); 94 | traverseFiles(); 95 | 96 | var fileList = inputFolder.getFiles("*.ai"); 97 | traverseFiles(); 98 | } 99 | else { 100 | alert("Export Layout is not installed!\n\nPlease copy Export Layout.jsx into\n\n" + scriptsPath + "\n\nand run this script again", "Script not installed"); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /Photoshop/Export Layer Coordinates Photoshop.jsx: -------------------------------------------------------------------------------- 1 | // Export Layer Coordinates - Adobe Photoshop Script 2 | // Description: Export x and y coordinates to comma seperated .txt file 3 | // Requirements: Adobe Photoshop CS5 (have not tested on CS4) 4 | // Version: 1.0-beta1.1, 8/31/2011 5 | // Author: Chris DeLuca 6 | // Company: Playmatics 7 | // =============================================================================== 8 | // Installation: 9 | // 1. Place script in 10 | // Mac: '~/Applications/Adobe Photoshop CS#/Presets/Scripts/' 11 | // Win: 'C:\Program Files\Adobe\Adobe Photoshop CS#\Presets\Scripts\' 12 | // 2. Restart Photoshop 13 | // 3. Choose File > Scripts > Export Layer Coordinates Photoshop 14 | // =============================================================================== 15 | 16 | // Enables double-click launching from the Mac Finder or Windows Explorer 17 | #target photoshop 18 | 19 | // Bring application forward 20 | app.bringToFront(); 21 | 22 | // Set active Document variable and decode name for output 23 | var docRef = app.activeDocument; 24 | var docName = decodeURI(activeDocument.name); 25 | 26 | // Define pixels as unit of measurement 27 | var defaultRulerUnits = preferences.rulerUnits; 28 | preferences.rulerUnits = Units.PIXELS; 29 | 30 | // Define variable for the number of layers in the active document 31 | var layerNum = app.activeDocument.artLayers.length; 32 | 33 | // Define variable for the active layer in the active document 34 | var layerRef = app.activeDocument.activeLayer; 35 | 36 | // Define varibles for x and y of layers 37 | var x = layerRef.bounds[0].value; 38 | var y = layerRef.bounds[1].value; 39 | var coords = ""; 40 | 41 | // Loop to iterate through all layers 42 | function recurseLayers(currLayers) { 43 | for ( var i = 0; i < currLayers.layers.length; i++ ) { 44 | layerRef = currLayers.layers[i]; 45 | x = layerRef.bounds[0].value; 46 | y = layerRef.bounds[1].value; 47 | coords += layerRef.name + "," + x + "," + y + "\n"; 48 | 49 | //test if it's a layer set 50 | if ( isLayerSet(currLayers.layers[i]) ) { 51 | recurseLayers(currLayers.layers[i]); 52 | } 53 | } 54 | } 55 | 56 | //a test for a layer set 57 | function isLayerSet(layer) { 58 | try { 59 | if ( layer.layers.length > 0 ) { 60 | return true; 61 | } 62 | } 63 | 64 | catch(err) { 65 | return false; 66 | } 67 | } 68 | 69 | // Ask the user for the folder to export to 70 | var FPath = Folder.selectDialog("Save exported coordinates to"); 71 | 72 | // Detect line feed type 73 | if ( $.os.search(/windows/i) !== -1 ) { 74 | fileLineFeed = "Windows"; 75 | } 76 | else { 77 | fileLineFeed = "Macintosh"; 78 | } 79 | 80 | // Export to txt file 81 | function writeFile(info) { 82 | try { 83 | var f = new File(FPath + "/" + docName + ".txt"); 84 | f.remove(); 85 | f.open('a'); 86 | f.lineFeed = fileLineFeed; 87 | f.write(info); 88 | f.close(); 89 | } 90 | catch(e){} 91 | } 92 | 93 | // Run the functions 94 | recurseLayers(docRef); 95 | preferences.rulerUnits = defaultRulerUnits; // Set preferences back to user 's defaults 96 | writeFile(coords); 97 | 98 | // Show results 99 | if ( FPath == null ) { 100 | alert("Export aborted", "Canceled"); 101 | } 102 | else { 103 | alert("Exported " + layerNum + " layer's coordinates to " + FPath + "/" + docName + ".txt " + "using " + fileLineFeed + " line feeds.", "Success!"); 104 | } 105 | 106 | -------------------------------------------------------------------------------- /Illustrator/Export Layout.jsx: -------------------------------------------------------------------------------- 1 | // Export Layout - Adobe Illustrator Script 2 | // Description: Export x and y coordinates to JSON 3 | // Requirements: Adobe Illustrator CS4 or greater 4 | // Version: 1.0-beta8 5 | // =============================================================================== 6 | // Installation: 7 | // 1. Place script in 8 | // Mac: '~/Applications/Adobe Illustrator CS#/Presets/Scripts/' 9 | // Win: 'C:\Program Files\Adobe\Adobe Illustrator CS#\Presets\en_US\Scripts\' 10 | // 2. Restart Illustrator 11 | // 3. Choose File > Scripts > Export Layout 12 | // =============================================================================== 13 | /* 14 | 15 | This script will output a JSON tree representing the content. 16 | Layers , Groups, and PageItems are arranged in a tree, 17 | those with #tags in the name are labeled as UI elements 18 | @tags are used to specifiy alignment to the parent 19 | All coordinates are absolute 20 | 21 | 22 | */ 23 | 24 | // Enables double-click launching from the Mac Finder or Windows Explorer 25 | #target illustrator 26 | 27 | // Set active Document variable and decode name for output 28 | // Define the rect bounds of the artboard 29 | var document = app.activeDocument; 30 | var documentName = decodeURI(activeDocument.name); 31 | //var colorSpace = document.DocumentColorSpace.RGB; 32 | var dX = document.artboards[0].artboardRect[0]; 33 | var dY = document.artboards[0].artboardRect[3]; 34 | var dX2 = document.artboards[0].artboardRect[2]; 35 | var dY2 = document.artboards[0].artboardRect[1]; 36 | 37 | // Layer variables 38 | var layerNum = 0; 39 | 40 | // Tag variables 41 | var nameO = []; // is strings without tags 42 | var id = []; // $identifier 43 | var type = []; // #type 44 | var align = []; /* @align */ 45 | var attach = []; // %attach 46 | var variable = []; // &variable 47 | 48 | // Define varible for object position 49 | var output = ""; 50 | 51 | // Automatically indent JSON output 52 | var tabCount = 0; 53 | 54 | // PNG option variables 55 | var options = new ExportOptionsPNG24(); 56 | options.antiAliasing = true; 57 | options.transparency = true; 58 | options.artBoardClipping = true; 59 | var pngNum = 0; 60 | 61 | // Color variables 62 | fillColor = []; 63 | strokeColor = []; 64 | 65 | // Text variables 66 | var fontFamily = []; 67 | var fontStyle = []; 68 | var fontSize = []; 69 | var fontJustification = []; 70 | var fontFillColor = []; 71 | var fontStrokeColor = []; 72 | var fontStrokeWeight = []; 73 | //~ var kerning = []; 74 | //~ var kerningMethod = []; 75 | var tracking = []; 76 | var leading = []; 77 | var textContent = []; 78 | 79 | 80 | /*____________________________________ 81 | 82 | Tab 83 | 84 | adds to output the given string with current indentation 85 | ____________________________________*/ 86 | function tab(s) { 87 | for ( var t = 0; t< tabCount; t++ ) { 88 | output += " "; 89 | } 90 | 91 | if ( s !== 'undefined' ) { 92 | output += s; 93 | } 94 | } 95 | 96 | /*____________________________________ 97 | 98 | Process Document 99 | 100 | Prints Names of all the sublayers 101 | and the items on the layers 102 | ____________________________________*/ 103 | function processDocument(D) { 104 | tab("{\n"); 105 | tabCount+=1; 106 | 107 | tab("\"Document\":\""+D.name+"\",\n"); 108 | tab("\"Date\":\""+new Date()+"\",\n"); 109 | tab("\"x\":\""+Math.round(dX)+"\",\n"); 110 | tab("\"y\":\""+Math.round(dY)+"\",\n"); 111 | tab("\"w\":\""+(dX2-dX)+"\",\n"); 112 | tab("\"h\":\""+(dY2-dY)+"\",\n"); 113 | 114 | //Maybe here we rasterize the index list of pageObject 115 | //traversePageItems(layer); 116 | tab("\"children\":\n"); 117 | tab("[\n"); 118 | 119 | traverseLayers(D); 120 | tab("]\n"); 121 | 122 | tabCount-=1; 123 | tab("}\n"); 124 | } 125 | /*______________________ 126 | 127 | Translate Tag 128 | ________________________*/ 129 | function translateTag(t) { 130 | if ( t === "#btn" ) { 131 | return "button"; 132 | } 133 | 134 | if ( t === "btn" ) { 135 | return "button"; 136 | } 137 | 138 | if ( t === "#btnToggle" ) { 139 | return "toggle"; 140 | } 141 | 142 | if ( t === "btnToggle" ) { 143 | return "toggle"; 144 | } 145 | 146 | if ( t === "#icon" ) { 147 | return "image"; 148 | } 149 | 150 | if ( t === "icon" ) { 151 | return "image"; 152 | } 153 | 154 | if ( t === "#txt" ) { 155 | return "text"; 156 | } 157 | 158 | if ( t === "txt" ) { 159 | return "text"; 160 | } 161 | 162 | if ( t === "#text" ) { 163 | return "text"; 164 | } 165 | 166 | if ( t === "#valueBar" ) { 167 | return "valueBar"; 168 | } 169 | 170 | if ( t === "#fillingBar" ) { 171 | return "fillingBar"; 172 | } 173 | 174 | if ( t === "#rectangle" ) { 175 | return "rectangle"; 176 | } 177 | 178 | if ( t === "#bg" ) { 179 | return "rectangle"; 180 | } 181 | 182 | if ( t === "bg" ) { 183 | return "rectangle"; 184 | } 185 | 186 | return t; 187 | } 188 | /*__________________________________________ 189 | 190 | Number Of Visible Pages 191 | __________________________________________*/ 192 | function numberOfVisiblePageItems(layer) { 193 | num = 0; 194 | for ( var i =0; i max ) { 284 | max = newMax; 285 | } 286 | } 287 | } 288 | 289 | W = max - getX(layer); 290 | 291 | for ( var i = 0; i < layer.layers.length; i++ ) { 292 | L = layer.layers[i]; 293 | if ( L.visible ) { 294 | newW = getW(L); 295 | if ( newW > W ) { 296 | W = newW; 297 | } 298 | } 299 | } 300 | 301 | return Math.round(W); 302 | } 303 | 304 | /*__________________________________________ 305 | 306 | Get H 307 | __________________________________________*/ 308 | function getH(layer) { 309 | H = 0; 310 | max = 0; 311 | 312 | for ( var i = 0; i < layer.pageItems.length; i++ ) { 313 | item = layer.pageItems[i]; 314 | newMax = item.position[1]-dY; 315 | 316 | if ( !item.hidden ) { 317 | if ( newMax > max ) { 318 | max = newMax; 319 | } 320 | } 321 | } 322 | 323 | H = max - getY(layer); 324 | 325 | for ( var i = 0; i < layer.layers.length; i++ ) { 326 | L = layer.layers[i]; 327 | if ( L.visible ) { 328 | newH = getH(L); 329 | if ( newH > H ) { 330 | H = newH; 331 | } 332 | } 333 | } 334 | 335 | return Math.round(H); 336 | } 337 | 338 | /*____________________________________ 339 | 340 | Process Layer 341 | 342 | Prints Names of all the sublayers 343 | and the items on the layers 344 | ____________________________________*/ 345 | function processLayer(layer) { 346 | tabCount=tabCount+1; 347 | layerNum++; 348 | 349 | //Set tag arrays to none so non present tags won't come up undefined 350 | id[this.layer] = "NONE"; 351 | type[this.layer] = layer.typename; 352 | align[this.layer] = "NONE"; 353 | attach[this.layer] = "NONE"; 354 | variable[this.layer] = "NONE"; 355 | 356 | //Parse Tags from the name, set type 357 | //This could be in a separate function(s) 358 | var layerName = layer.name.split (" "); 359 | check = 0; 360 | // loop through layer name that was split into an array 361 | for ( var ii = 0; ii < layerName.length; ii++ ) { 362 | // Gather Name 363 | if ( layerName[ii].indexOf("$") == -1 && 364 | layerName[ii].indexOf("#") == -1 && 365 | layerName[ii].indexOf("@") == -1 && 366 | layerName[ii].indexOf("%") == -1 && 367 | layerName[ii].indexOf("&") == -1 ) 368 | nameO[this.layer] = layerName[ii]; 369 | else if ( ii === layer.name.length ) { 370 | nameO[this.layer] = "NONE"; 371 | } 372 | 373 | // Check for ID tag 374 | if ( layerName[ii].indexOf("$") !== -1 ) { 375 | id[this.layer] = layerName[ii].toLowerCase().slice(1); 376 | id[this.layer]=translateTag(id[this.layer]); 377 | check = 1; 378 | } 379 | else if ( ii === layer.name.length && check === 0 ) { 380 | id[this.layer] = "layer"; 381 | check = 0; 382 | } 383 | 384 | // Check for type tag 385 | if ( layerName[ii].indexOf("#") !== -1 ) { 386 | type[this.layer] = layerName[ii].toLowerCase().slice(1); 387 | type[this.layer]=translateTag(type[this.layer]); 388 | check = 1; 389 | } 390 | else if ( check === 0 && ii === layerName.length ) { 391 | type[this.layer] = layer.typename; 392 | type[this.layer] = translateTag(type[this.layer]); 393 | check = 0; 394 | } 395 | 396 | // Check for align tag 397 | if ( layerName[ii].indexOf("@") !== -1 ) { 398 | align[this.layer] = layerName[ii].toUpperCase().slice(1); 399 | align[this.layer]=translateTag(align[this.layer]); 400 | } 401 | else if ( ii === layerName.length ) { 402 | align[this.layer] = "NONE"; 403 | } 404 | 405 | // Check for attach tag 406 | if ( layerName[ii].indexOf("%") !== -1 ) { 407 | attach[this.layer] = layerName[ii].toLowerCase().slice(1); 408 | attach[this.layer]=translateTag(attach[this.layer]); 409 | } 410 | else if ( ii === layerName.length ) { 411 | attach[this.layer] = "NONE"; 412 | } 413 | 414 | // Check for variable tag 415 | if ( layerName[ii].indexOf("&") !== -1 ) { 416 | variable[this.layer] = layerName[ii].toLowerCase().slice(1); 417 | variable[this.layer]=translateTag(variable[this.layer]); 418 | } 419 | else if ( ii === layerName.length ) { 420 | variable[this.layer] = "NONE"; 421 | } 422 | } 423 | 424 | if ( layer.visible ) { 425 | //Visible Layer 426 | tab("\"name\":\""+nameO[this.layer]+"\",\n"); 427 | tab("\"id\":\""+id[this.layer]+"\",\n"); 428 | tab("\"type\":\""+type[this.layer]+"\",\n"); 429 | tab("\"align\":\""+align[this.layer]+"\",\n"); 430 | tab("\"attach\":\""+attach[this.layer]+"\",\n"); 431 | tab("\"variable\":\""+variable[this.layer]+"\",\n"); 432 | tab("\"x\":\"" + getX(layer) +"\",\n"); 433 | tab("\"y\":\"" + getY(layer) +"\",\n"); 434 | tab("\"w\":\"" + getW(layer) +"\",\n"); 435 | tab("\"h\":\"" + getH(layer) +"\",\n"); 436 | tab("\"children\":\n"); 437 | tab("[\n"); 438 | 439 | //Print Page Items out as Children 440 | traversePageItems(layer); 441 | 442 | if ( numberOfVisiblePageItems(layer) > 0 ) { 443 | if ( numberOfVisibleSubLayers(layer) > 0 ) { 444 | tab(",\n"); 445 | } 446 | } 447 | 448 | //Print Layers out as Children 449 | traverseLayers(layer); 450 | tab("]\n"); 451 | 452 | tabCount = tabCount -1; 453 | } 454 | else { 455 | //Invisible Layer 456 | tab("\"name\":\""+"HIDDEN LAYER"+"\",\n"); 457 | tab("\"type\":\""+"HIDDEN LAYER "+ type[this.layer]+"\"\n"); 458 | tabCount = tabCount -1; 459 | } 460 | 461 | } 462 | 463 | /*____________________________________ 464 | 465 | Traverse Children 466 | 467 | go through layers 468 | ____________________________________*/ 469 | function traverseLayers(parent) { 470 | if ( parent.layers.length > 0 ) { 471 | tabCount = tabCount + 1; 472 | 473 | for ( var ii = 0; ii < parent.layers.length; ii++ ) { 474 | //Open layer '{' 475 | child = parent.layers[ii]; 476 | tab("{\n"); 477 | 478 | processLayer(child); 479 | 480 | // last child close '}' 481 | // not last child comma '},' 482 | if ( ii === parent.layers.length - 1 ) { 483 | tab("}\n"); 484 | } 485 | else { 486 | tab("},\n"); 487 | } 488 | } 489 | 490 | tabCount = tabCount - 1; 491 | } 492 | } 493 | 494 | /*_________________________________ 495 | 496 | Parse Name 497 | _________________________________*/ 498 | function parseName(child, i) { 499 | if ( child.name.length <= 0 ) { 500 | //Reset tag arrays so children won't inherit parent's values 501 | nameO[i] = "NONE"; 502 | id[i] = "NONE"; 503 | type[i] = child.typename; 504 | align[i] = "NONE"; 505 | attach[i] = "NONE"; 506 | variable[i] = "NONE"; 507 | } 508 | else { 509 | childName = child.name.split(" "); 510 | var check = 0; 511 | var nameBox = []; 512 | 513 | for ( var ii = 0; ii < childName.length; ii++ ) { 514 | // loop through child name that was split into an array to pick out tags 515 | // Gather name 516 | if ( childName[ii].indexOf("$") === -1 && 517 | childName[ii].indexOf("#") === -1 && 518 | childName[ii].indexOf("@") === -1 && 519 | childName[ii].indexOf("%") === -1 && 520 | childName[ii].indexOf("&") === -1 ) { 521 | nameO[i] = childName[ii]; 522 | check = 1; 523 | } 524 | else if ( check === 0 ) { 525 | nameO[i] = "NONE"; 526 | } 527 | 528 | // Check for ID tag 529 | if ( childName[ii].indexOf("$") !== -1 ) { 530 | id[i] = childName[ii].toLowerCase().slice(1); 531 | id[i]=translateTag(id[i]); 532 | } 533 | else if ( ii === child.name.length ) { 534 | id[i] = "NONE"; 535 | } 536 | 537 | // Check for type tag 538 | if ( childName[ii].indexOf("#") !== -1 ) { 539 | type[i] = childName[ii].toLowerCase().slice(1); 540 | type[i] = translateTag(type[i]); 541 | } 542 | else if (ii === childName.length) { 543 | type[i] = child.typename; 544 | type[i] = translateTag(type[i]); 545 | } 546 | 547 | // Check for align tag 548 | if ( childName[ii].indexOf("@") !== -1 ) { 549 | align[i] = childName[ii].toUpperCase().slice(1); 550 | align[i]=translateTag(align[i]); 551 | } 552 | else if ( ii === childName.length ) { 553 | align[i] = "NONE"; 554 | } 555 | 556 | // Check for align tag 557 | if ( childName[ii].indexOf("%") !== -1 ) { 558 | attach[i] = childName[ii].toLowerCase().slice(1); 559 | attach[i]=translateTag(attach[i]); 560 | } 561 | else if ( ii === childName.length ) { 562 | attach[i] = "NONE"; 563 | } 564 | 565 | // Check for variable tag 566 | if ( childName[ii].indexOf("&") !== -1 ) { 567 | variable[i] = childName[ii].toLowerCase().slice(1); 568 | variable[i]=translateTag(variable[i]); 569 | } 570 | else if ( ii === childName.length ) { 571 | variable[i] = "NONE"; 572 | } 573 | } 574 | } 575 | 576 | // Check if element is Placed Item 577 | if ( child.typename === "PlacedItem" ) { 578 | nameO[i] = "No Linked PlacedItem"; 579 | } 580 | 581 | // Check if element is Path Item 582 | // then add color information 583 | if ( child.typename === "PathItem" ) { 584 | fillColor[i] = child.fillColor; 585 | strokeColor[i] = child.strokeColor; 586 | } 587 | 588 | // Check if element is TextFrame 589 | // then add font information 590 | if ( child.typename === "TextFrame" ) { 591 | fontFamily[i] = child.textRange.characterAttributes.textFont.family; 592 | fontStyle[i] = child.textRange.characterAttributes.textFont.style; 593 | fontSize[i] = child.textRange.characterAttributes.size; 594 | fontJustification[i] = child.textRange.paragraphAttributes.justification; 595 | tracking[i] = child.textRange.characterAttributes.tracking; 596 | fontFillColor[i] = child.textRange.characterAttributes.fillColor; 597 | fontStrokeColor[i] = child.textRange.characterAttributes.strokeColor; 598 | fontStrokeWeight[i] = child.textRange.characterAttributes.strokeWeight; 599 | leading[i] = child.textRange.characterAttributes.leading; 600 | textContent[i] = child.textRange.contents; 601 | } 602 | } 603 | /*_________________________________ 604 | 605 | Process Page Item 606 | _________________________________*/ 607 | function processPageItem(child, i) { 608 | var cX = child.position[0]; 609 | var cY = child.position[1]; 610 | 611 | var X = Math.round(cX - dX); 612 | var Y = Math.round((cY - dY)- child.height); 613 | var W = Math.round(child.width); 614 | var H = Math.round(child.height); 615 | parseName(child, i); 616 | 617 | tab("\"name\":\"" + nameO[i] + "\",\n"); 618 | tab("\"id\":\"" + id[i] + "\",\n"); 619 | tab("\"type\":\"" + type[i] + "\",\n"); 620 | tab("\"align\":\"" + align[i] + "\",\n"); 621 | tab("\"attach\":\"" + attach[i] + "\",\n"); 622 | tab("\"variable\":\"" + variable[i] + "\",\n"); 623 | 624 | // Output color information for PathItems 625 | if ( child.typename === "PathItem" ) { 626 | // Fill Colors 627 | if ( fillColor[i].typename === "RGBColor" ) { 628 | tab("\"fill color type\":\"" + fillColor[i].typename + "\",\n"); 629 | tab("\"fill r\":\"" + fillColor[i].red + "\",\n"); 630 | tab("\"fill g\":\"" + fillColor[i].green + "\",\n"); 631 | tab("\"fill b\":\"" + fillColor[i].blue + "\",\n"); 632 | tab("\"fill a\":\"" + child.opacity + "\",\n"); 633 | } 634 | else if ( fillColor[i].typename === "GrayColor" ) { 635 | tab("\"fill color type\":\"" + fillColor[i].typename + "\",\n"); 636 | tab("\"fill gray\":\"" + fillColor[i].gray + "\",\n"); 637 | tab("\"fill a\":\"" + child.opacity + "\",\n"); 638 | } 639 | else if ( fillColor[i].typename === "GradientColor" ) { 640 | tab("\"fill color type\":\"" + fillColor[i].typename + "\"" + ",\n"); 641 | } 642 | else if ( fillColor[i].typename === "NoColor" ) { 643 | tab("\"fill color type\":\"" + fillColor[i].typename + "\"" + "\",\n"); 644 | } 645 | 646 | // Stroke Colors 647 | if ( strokeColor[i].typename === "RGBColor" ) { 648 | tab("\"stroke color type\":\"" + strokeColor[i].typename + "\",\n"); 649 | tab("\"stroke r\":\"" + strokeColor[i].red + "\",\n"); 650 | tab("\"stroke g\":\"" + strokeColor[i].green + "\",\n"); 651 | tab("\"stroke b\":\"" + strokeColor[i].blue + "\",\n"); 652 | tab("\"stroke a\":\"" + child.opacity + "\",\n"); 653 | } 654 | else if ( strokeColor[i].typename === "GrayColor" ) { 655 | tab("\"stroke color type\":\"" + strokeColor[i].typename + "\",\n"); 656 | tab("\"stroke gray\":\"" + strokeColor[i].gray + "\",\n"); 657 | tab("\"stroke a\":\"" + child.opacity + "\",\n"); 658 | } 659 | else if ( strokeColor[i].typename === "GradientColor" ) { 660 | tab("\"stroke color type\":\"" + strokeColor[i].typename + "\"" + ",\n"); 661 | } 662 | else if ( strokeColor[i].typename === "NoColor" ) { 663 | tab("\"stroke color type\":\"" + strokeColor[i].typename + "\"" + ",\n"); 664 | } 665 | } 666 | 667 | // Output font information for TextFrames 668 | if ( child.typename === "TextFrame" ) { 669 | tab("\"font family\":\"" + fontFamily[i] + "\"" + ",\n"); 670 | tab("\"font style\":\"" + fontStyle[i] + "\"" + ",\n"); 671 | tab("\"font size\":\"" + fontSize[i] + "\"" + ",\n"); 672 | tab("\"font stroke weight\":\"" + fontStrokeWeight[i] + "\"" + ",\n"); 673 | var justify = String(fontJustification[i]); 674 | justify = justify.split(".")[1]; 675 | tab("\"paragraph justification\":\"" + justify.toLowerCase() + "\"" + ",\n"); 676 | tab("\"tracking\":\"" + tracking[i] + "\"" + ",\n"); 677 | tab("\"leading\":\"" + leading[i] + "\"" + ",\n"); 678 | 679 | // Font Fill Colors 680 | if ( fontFillColor[i].typename === "RGBColor" ) { 681 | tab("\"font fill color type\":\"" + fontFillColor[i].typename + "\",\n"); 682 | tab("\"font fill r\":\"" + fontFillColor[i].red + "\",\n"); 683 | tab("\"font fill g\":\"" + fontFillColor[i].green + "\",\n"); 684 | tab("\"font fill b\":\"" + fontFillColor[i].blue + "\",\n"); 685 | tab("\"font fill a\":\"" + child.opacity + "\",\n"); 686 | } 687 | else if ( fontFillColor[i].typename === "GrayColor" ) { 688 | tab("\"font fill color type\":\"" + fontFillColor[i].typename + "\",\n"); 689 | tab("\"font fill gray\":\"" + fontFillColor[i].gray + "\",\n"); 690 | tab("\"font fill a\":\"" + child.opacity + "\",\n"); 691 | } 692 | else if ( fontFillColor[i].typename === "GradientColor" ) { 693 | tab("\"font fill color type\":\"" + fontFillColor[i].typename + "\"" + ",\n"); 694 | } 695 | else if ( fontFillColor[i].typename === "NoColor" ) { 696 | tab("\"font fill color type\":\"" + fontFillColor[i].typename + "\"" + "\",\n"); 697 | } 698 | 699 | // Font Stroke Colors 700 | if ( fontStrokeColor[i].typename === "RGBColor" ) { 701 | tab("\"font stroke color type\":\"" + fontStrokeColor[i].typename + "\",\n"); 702 | tab("\"font stroke r\":\"" + fontStrokeColor[i].red + "\",\n"); 703 | tab("\"font stroke g\":\"" + fontStrokeColor[i].green + "\",\n"); 704 | tab("\"font stroke b\":\"" + fontStrokeColor[i].blue + "\",\n"); 705 | tab("\"font stroke a\":\"" + child.opacity + "\",\n"); 706 | } 707 | else if ( fontStrokeColor[i].typename === "GrayColor" ) { 708 | tab("\"font stroke color type\":\"" + fontStrokeColor[i].typename + "\",\n"); 709 | tab("\"font stroke gray\":\"" + fontStrokeColor[i].gray + "\",\n"); 710 | tab("\"font stroke a\":\"" + child.opacity + "\",\n"); 711 | } 712 | else if ( fontStrokeColor[i].typename === "GradientColor" ) { 713 | tab("\"font stroke color type\":\"" + fontStrokeColor[i].typename + "\"" + ",\n"); 714 | } 715 | else if ( fontStrokeColor[i].typename === "NoColor" ) { 716 | tab("\"font stroke color type\":\"" + fontStrokeColor[i].typename + "\"" + "\",\n"); 717 | } 718 | 719 | tab("\"text content\":\"" + textContent[i] + "\"" + ",\n"); 720 | } 721 | tab("\"x\":\"" + X + "\",\n"); 722 | tab("\"y\":\"" + Y + "\",\n"); 723 | tab("\"w\":\"" + W + "\",\n"); 724 | tab("\"h\":\"" + H + "\",\n"); 725 | /*________________________ 726 | 727 | Export PNGs 728 | ________________________*/ 729 | if ( type[i] === "image" || type[i] === "icon" || type[i] === "button" ) { 730 | var png = new File(FPath.fsName+"/"+childName+".png"); 731 | var scratchDoc = app.documents.add(DocumentColorSpace.RGB, child.width, child.height); 732 | scratchDoc.pageOrigin = [0,0]; 733 | child.duplicate(scratchDoc, ElementPlacement.PLACEATEND); 734 | var item = scratchDoc.activeLayer.pageItems[0]; 735 | item.translate(-item.position[0], -item.position[1] + child.height); 736 | scratchDoc.exportFile(png,ExportType.PNG24,options); 737 | scratchDoc.close(SaveOptions.DONOTSAVECHANGES); 738 | pngNum++; 739 | } 740 | 741 | if ( child.typename === "GroupItem" ) { 742 | tab("\"children\":\n"); 743 | tab("[\n"); 744 | traversePageItems (child); 745 | tab("]\n"); 746 | } 747 | } 748 | 749 | /*____________________________________ 750 | 751 | traverse Page Items 752 | ____________________________________*/ 753 | function traversePageItems(layer) { 754 | tabCount=tabCount+1; 755 | layerNum++; 756 | var offset; //switch between names with and without #types, set to 1 or 0 757 | 758 | for ( var i = 0; i < layer.pageItems.length; i++ ) { 759 | child = layer.pageItems[i]; 760 | if ( !child.hidden ) { 761 | tab("{\n"); 762 | tabCount++; 763 | 764 | processPageItem(child), i; 765 | 766 | tabCount-=1; 767 | if ( i === layer.pageItems.length - 1 ) { 768 | tab("}\n"); 769 | } 770 | else { 771 | tab("},\n"); 772 | } 773 | } 774 | } 775 | tabCount = tabCount - 1; 776 | } 777 | 778 | /*_________________________ 779 | 780 | Write File 781 | _________________________*/ 782 | function writeFile(info) { 783 | try { 784 | var f = new File(FPath + "/" + documentName + ".txt"); 785 | f.open('w'); 786 | f.lineFeed = fileLineFeed; 787 | f.write(info); 788 | f.close(); 789 | } 790 | catch(e){} 791 | } 792 | 793 | // Ask the user for the folder to export to 794 | var FPath = Folder.selectDialog("Save exported coordinates and PNGs to") ; 795 | 796 | //------------------------------------------------------------------------------------------- 797 | // Detect line feed type 798 | if ( $.os.search(/windows/i) !== -1 ) { 799 | fileLineFeed = "Windows"; 800 | } 801 | else { 802 | fileLineFeed = "Macintosh"; 803 | } 804 | 805 | // Run the functions 806 | processDocument(document); 807 | writeFile(output); 808 | 809 | // Export document PNG 810 | var docPng = new File(FPath.fsName+"/"+documentName+".png"); 811 | document.exportFile(docPng, ExportType.PNG24); 812 | pngNum++; 813 | 814 | // Show results 815 | if ( FPath === null ) { 816 | alert ("Export aborted", "Canceled"); 817 | } 818 | else { 819 | alert( "Exported " + 820 | layerNum + 821 | " layer's coordinates and " + 822 | pngNum + 823 | " PNGs to " + 824 | translateTag(FPath), 825 | "Success!"); 826 | } 827 | 828 | --------------------------------------------------------------------------------