├── .DS_Store ├── Image Replacer.sketchplugin └── Contents │ └── Sketch │ ├── Replace.cocoascript │ ├── manifest.json │ └── scripts │ └── utility.js ├── README.md └── license.txt /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iansilber/sketch-image-replace/0f609b355eec483d023754154f248b56392f8305/.DS_Store -------------------------------------------------------------------------------- /Image Replacer.sketchplugin/Contents/Sketch/Replace.cocoascript: -------------------------------------------------------------------------------- 1 | @import "scripts/utility.js"; 2 | 3 | // Primary method. Pulls a collection of randomly selected images from a user-configured directory. 4 | var onRun = function(context) { 5 | 6 | var directory = [[NSUserDefaults standardUserDefaults] objectForKey:"directory"] 7 | 8 | if (directory == null) { 9 | var alert = [[NSAlert alloc] init] 10 | [alert setMessageText:"Setup"] 11 | [alert setInformativeText:"Choose a directory containing images. You can change this at any time by going to Image Replace > Settings."] 12 | [alert addButtonWithTitle:'Continue...'] 13 | var responseCode = [alert runModal] 14 | 15 | this.resetDefaultDirectory(context) 16 | directory = [[NSUserDefaults standardUserDefaults] objectForKey:"directory"] 17 | } 18 | 19 | getFilesAndReplace(directory, context) 20 | } 21 | 22 | var replaceWithPicker = function(context) { 23 | 24 | var panel = showFileBrowserAndRequireDirectory(false); 25 | 26 | if (panel.response == NSFileHandlingPanelOKButton) { 27 | var thePanel = panel.panel; 28 | var isDirectory = false; 29 | var firstURL = [[thePanel URLs] objectAtIndex:0]; 30 | var firstURLPath = [NSString stringWithFormat:@"%@", firstURL]; 31 | 32 | //directory 33 | if ([firstURLPath hasSuffix:@"/"]) { 34 | getFilesAndReplace([firstURL path], context) 35 | 36 | //files 37 | } else { 38 | var imageFileNames = [] 39 | var loop = [[thePanel URLs] objectEnumerator]; 40 | while (url = [loop nextObject]) { 41 | imageFileNames.push([url path]); 42 | } 43 | replaceWithImages(imageFileNames, context); 44 | } 45 | } 46 | } 47 | 48 | // Reset the default directory. 49 | var resetDefaultDirectory = function(context) { 50 | 51 | var panel = showFileBrowserAndRequireDirectory(true) 52 | 53 | if (panel.response == NSFileHandlingPanelOKButton) { 54 | var thePanel = panel.panel 55 | var selectedDirectory = [[thePanel URLs] objectAtIndex:0]; 56 | [[NSUserDefaults standardUserDefaults] setObject:[selectedDirectory path] forKey:"directory"] 57 | var target = [[[NSURL fileURLWithPath:[selectedDirectory path]] URLByStandardizingPath] URLByResolvingSymlinksInPath] 58 | } 59 | 60 | var app = [NSApplication sharedApplication]; 61 | var doc = context.document 62 | [doc showMessage:"The default directory has been set"] 63 | } 64 | 65 | -------------------------------------------------------------------------------- /Image Replacer.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "author" : "", 3 | "commands" : [ 4 | { 5 | "name" : "Replace", 6 | "handler" : "onRun", 7 | "script" : "Replace.cocoascript", 8 | "shortcut" : "cmd shift i", 9 | "identifier" : "image replace" 10 | }, 11 | { 12 | "name" : "Choose Manually", 13 | "handler" : "replaceWithPicker", 14 | "script" : "Replace.cocoascript", 15 | "shortcut" : "cmd ctrl shift i", 16 | "identifier" : "image directory replace" 17 | }, 18 | { 19 | "name" : "Reset Default Directory", 20 | "handler": "resetDefaultDirectory", 21 | "script": "Replace.cocoascript", 22 | "shortcut" : "", 23 | "identifier" : "reset" 24 | } 25 | ], 26 | "menu": { 27 | "items": [ 28 | "image replace", 29 | "image directory replace", 30 | "reset" 31 | ] 32 | }, 33 | "identifier" : "com.iansilber.image-replace", 34 | "version" : "1.1", 35 | "description" : "", 36 | "authorEmail" : "iansilber@gmail.com", 37 | "name" : "Image Replace" 38 | } -------------------------------------------------------------------------------- /Image Replacer.sketchplugin/Contents/Sketch/scripts/utility.js: -------------------------------------------------------------------------------- 1 | function shuffle(array) { 2 | var currentIndex = array.count(), temporaryValue, randomIndex ; 3 | 4 | // While there remain elements to shuffle... 5 | while (0 !== currentIndex) { 6 | 7 | // Pick a remaining element... 8 | randomIndex = Math.floor(Math.random() * currentIndex); 9 | currentIndex -= 1; 10 | 11 | // And swap it with the current element. 12 | temporaryValue = array[currentIndex]; 13 | array[currentIndex] = array[randomIndex]; 14 | array[randomIndex] = temporaryValue; 15 | } 16 | 17 | return array; 18 | } 19 | 20 | function showFileBrowserAndRequireDirectory(requireDirectory) { 21 | var fileTypes = [NSArray arrayWithArray:["png", "jpg", "gif", "jpeg"]]; 22 | var panel = [NSOpenPanel openPanel]; 23 | var imageFileNames = []; 24 | if (requireDirectory == true) { 25 | [panel setCanChooseFiles:false]; 26 | } else { 27 | [panel setCanChooseFiles:true]; 28 | } 29 | 30 | [panel setCanChooseDirectories:true]; 31 | [panel setAllowsMultipleSelection:true]; // yes if more than one dir is allowed 32 | [panel setAllowedFileTypes:fileTypes]; 33 | 34 | var response = [panel runModal]; 35 | return {response: response, panel: panel} 36 | } 37 | 38 | function replaceWithImages(images, context) { 39 | selection = context.selection; 40 | for(var i = 0; i < [selection count]; i++) { 41 | var data = [NSData dataWithContentsOfFile:images[i]] 42 | var image = [[MSImageData alloc] initWithData:data sha:nil]; 43 | var layer = selection[i]; 44 | if ([layer class] == MSShapeGroup) { 45 | 46 | var fill = layer.style().fills().firstObject() 47 | [fill setFillType:4] 48 | [fill setImage:image] 49 | layer.style().fills().firstObject().setPatternFillType(1); 50 | } 51 | } 52 | if([selection count] == 0) [doc showMessage:'Select at least one vector shape'];; 53 | 54 | } 55 | 56 | function getFilesAndReplace(directory, context) { 57 | var fileTypes = [NSArray arrayWithArray:["png", "PNG", "jpg", "JPG", "jpeg", "JPEG", "gif", "GIF"]]; 58 | var fileManager = [NSFileManager defaultManager]; 59 | var files = [fileManager contentsOfDirectoryAtPath:directory error:nil]; 60 | var imageFileNames = [[files filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"pathExtension IN %@", fileTypes]] mutableCopy] 61 | var count = imageFileNames.count(); 62 | 63 | if (count == 0) { 64 | var doc = context.document 65 | [doc showMessage:"The directory does not contain any images"] 66 | } else { 67 | 68 | shuffle(imageFileNames); 69 | for (var i = 0; i < context.selection.count(); i++) { 70 | imageFileNames[i] = directory + "/" + imageFileNames[i]; 71 | } 72 | replaceWithImages(imageFileNames, context); 73 | if(context.selection.count() == 0) [doc showMessage:'Select at least one vector shape']; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image Replace for Sketch 2 | 3 | [Download Sketch Image Replacer](https://github.com/iansilber/sketch-image-replace/archive/master.zip) 4 | 5 | A quick way to replace one or more vector shapes with an image from a directory of your choosing. 6 | 7 | This plugin was derived from Content Generator. The main difference is that with Image Replace, images can be stored anywhere on your computer, as opposed to having to be stored in the plugin directory. 8 | 9 | This plugin has three commands: 10 | 11 | * **Replace (shift + cmd + i):** Fills selected shapes with images from a folder you choose. After choosing the first time, it won't ask again. Reset it using the Settings command. 12 | * **Choose Manually (Ctrl + shift + cmd + i):** Same as above but lets you choose the folder each time 13 | * **Reset Default Directory:** change the directory used for the Replace command 14 | 15 | [![Demo video](http://img.youtube.com/vi/77KUm7uDPmY/0.jpg)](https://www.youtube.com/watch?v=77KUm7uDPmY) 16 | 17 | 18 | [Download Sketch Image Replacer](https://github.com/iansilber/sketch-image-replace/archive/master.zip) 19 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ian Silber 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 | --------------------------------------------------------------------------------