├── .gitignore ├── README.md └── json-parser.sketchplugin └── Contents └── Sketch ├── manifest.json └── script.cocoascript /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sketch JSON Parser 2 | ================= 3 | #### Replaces layer values in groups with JSON data 4 | 5 | ### Setup 6 | 1. Download/Clone this repo 7 | 2. Run json-parser.sketchplugin 8 | 9 | ### Example 10 | #####1. Say you have a group that looks like this: 11 | ![Layer Group Example](http://i.imgur.com/wKPFRdu.png) 12 | 13 | #####2. And a JSON array that looks like this: 14 | ``` 15 | [{ 16 | "img": "http://i.imgur.com/IBZMRic.png", 17 | "title": "Holabila", 18 | "date": { 19 | "formatted": "25 Jan 2015", 20 | "time_ago": "5 min ago" 21 | }, 22 | "name": "Koen Vendrik" 23 | }, 24 | { 25 | "img": "/Users/joeytribbiani/Desktop/350.png", 26 | "title": "Bilahola", 27 | "date": { 28 | "formatted": "28 Feb 2015", 29 | "time_ago": "2 days ago" 30 | }, 31 | "name": "Jaer Pollux" 32 | }] 33 | ``` 34 | 35 | #####3. Now include JSON path variables in your layer names like this: 36 | ![Path Variables Example](http://i.imgur.com/JsnUwv2.png) 37 | 38 | #####4. Duplicate the group as many times as you want and select the groups 39 | (in this case probably two times as you have two items in the array) 40 | 41 | #####5. Run the plugin and paste in the JSON when prompted 42 | ![Prompt](http://i.imgur.com/sO4JCwi.png) 43 | 44 | #####6. Voila! The plugin replaced all layer values with data from the JSON 45 | ![Woah GIF](http://www.reactiongifs.com/wp-content/gallery/omg/RDJ_Woah.gif) 46 | -------------------------------------------------------------------------------- /json-parser.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "json-parser", 3 | "description": "Replaces layer values in groups with JSON data", 4 | "author" : "Koen Vendrik", 5 | "homepage": "http://github.com/kvendrik/sketch-json-parser", 6 | "version" : 1.0, 7 | "identifier" : "com.example.sketch.3a59b701-baab-45cc-a80e-8e785f03428b", 8 | "updateURL": "https://github.com/kvendrik/sketch-json-parser", 9 | "compatibleVersion": 3.3, 10 | "bundleVersion": 1, 11 | "commands" : [ 12 | { 13 | "script" : "script.cocoascript", 14 | "handler" : "onRun", 15 | "shortcut" : "", 16 | "name" : "Run", 17 | "identifier" : "run" 18 | } 19 | ], 20 | "menu" : { 21 | "items" : [ 22 | "run" 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /json-parser.sketchplugin/Contents/Sketch/script.cocoascript: -------------------------------------------------------------------------------- 1 | /** 2 | * context passed by Sketch 3 | * [jsonObj] optional js object param for debug data 4 | */ 5 | var onRun = function(context, jsonObj) { 6 | 7 | //define helpers 8 | var utils = { 9 | 10 | getValByPath: function(path, json){ 11 | var pieces = path.split('.'), 12 | currPath = json; 13 | 14 | for(var i = 0; i < pieces.length; i++){ 15 | var val = pieces[i]; 16 | if(currPath[val] == undefined){ 17 | return undefined; 18 | } else { 19 | currPath = currPath[val]; 20 | } 21 | } 22 | 23 | return currPath; 24 | }, 25 | 26 | parseLayer: function(layer, json){ 27 | var self = this; 28 | var parseIndividualLayer = function(MSLayer){ 29 | var tagMatch = MSLayer.name().match(/\$([^\s]+)/), 30 | tagVal, 31 | val; 32 | 33 | if(tagMatch != null && tagMatch[1]){ 34 | tagVal = tagMatch[1].trim(); 35 | } else { 36 | return; 37 | } 38 | 39 | val = self.getValByPath(tagVal, json); 40 | if(typeof val == 'undefined') return; 41 | 42 | switch(MSLayer.class()){ 43 | case MSTextLayer: 44 | MSLayer.setStringValue(String(val)); 45 | MSLayer.adjustFrameToFit(); 46 | break; 47 | case MSBitmapLayer: 48 | var isUrl = new RegExp('http(s)?\:\/\/.+').test(val), 49 | fileManager = [NSFileManager defaultManager], 50 | img; 51 | 52 | if(isUrl){ 53 | img = NSImage.alloc().initWithContentsOfURL(NSURL.URLWithString(val)); 54 | } else { 55 | //check if image exists 56 | if(fileManager.fileExistsAtPath(val)){ 57 | img = NSImage.alloc().initWithContentsOfFile(val); 58 | } 59 | } 60 | 61 | if(img){ 62 | MSLayer.setConstrainProportions(false); 63 | MSLayer.setRawImage_convertColourspace_collection(img, false, doc.documentData().images()); 64 | MSLayer.frame().setWidth(img.size().width); 65 | MSLayer.frame().setHeight(img.size().height); 66 | MSLayer.setConstrainProportions(true); 67 | } else { 68 | log('Image file '+val+' not found'); 69 | } 70 | 71 | break; 72 | } 73 | }; 74 | 75 | if(layer.class() == 'MSLayerGroup'){ 76 | //if is group 77 | var layers = layer.children(), 78 | layersCount = layers.count(); 79 | 80 | for(var i = 0; i < layersCount; i++){ 81 | parseIndividualLayer(layers[i]); 82 | } 83 | } else { 84 | //if is layer 85 | parseIndividualLayer(layer); 86 | } 87 | } 88 | 89 | }; 90 | 91 | //get global vars 92 | var doc = context.document, 93 | app = [NSApplication sharedApplication]; 94 | 95 | //get selected layers 96 | var selectedLayers = context.selection, 97 | selectedCount = selectedLayers.count(); 98 | 99 | //check if layers are selected 100 | if(selectedCount == 0) { 101 | [app displayDialog:"No layers are selected."] 102 | return; 103 | } 104 | 105 | //get JSON by user input 106 | var jsonStr = jsonObj ? JSON.stringify(jsonObj) : [doc askForUserInput:"Enter the JSON you'd like to use" initialValue:""], 107 | json; 108 | 109 | //if input is an array, make valid json 110 | if(jsonStr.indexOf('[') == 0){ 111 | jsonStr = '{ "__sketchJsonArray": '+jsonStr+' }'; 112 | } 113 | 114 | //attempt to parse json 115 | try { 116 | json = JSON.parse(jsonStr); 117 | } catch(e){ 118 | [app displayDialog:"Whoops, looks like that's not valid JSON."] 119 | return; 120 | } 121 | 122 | //check if json is an array 123 | if(json.__sketchJsonArray){ 124 | //is an array 125 | var dataArr = json.__sketchJsonArray; 126 | 127 | //loop selected layers 128 | for(var i = 0; i < selectedCount; i++){ 129 | var currLayer = selectedLayers[i], 130 | currObj = dataArr[i]; 131 | 132 | if(currObj){ 133 | utils.parseLayer(currLayer, currObj); 134 | } 135 | } 136 | } else { 137 | //single object 138 | //loop selected layers 139 | for(var i = 0; i < selectedCount; i++){ 140 | utils.parseLayer(selectedLayers[i], json); 141 | } 142 | } 143 | 144 | }; 145 | --------------------------------------------------------------------------------