├── .DS_Store ├── ColorPalette.swift ├── README.md ├── SwiftColorPalette.sketchplugin ├── .DS_Store └── Contents │ └── Sketch │ ├── library.cocoascript │ ├── manifest.json │ └── script.cocoascript └── demo.gif /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahitheper/SwiftColorPalette/a3cb3965334e8cfed5474121b93844c1c8b2d6f9/.DS_Store -------------------------------------------------------------------------------- /ColorPalette.swift: -------------------------------------------------------------------------------- 1 | enum ColorPalette { 2 | 3 | static let lightGrayColor = UIColor(red:0.737, green: 0.769, blue: 0.792, alpha: 1.000) 4 | 5 | static let blueColor = UIColor(red:0.353, green: 0.510, blue: 0.647, alpha: 1.000) 6 | 7 | static let grayColor = UIColor(red:0.373, green: 0.373, blue: 0.376, alpha: 1.000) 8 | 9 | static let panelColor = UIColor(red:0.212, green: 0.227, blue: 0.267, alpha: 1.000) 10 | 11 | static let secondaryColor = UIColor(red:0.141, green: 0.220, blue: 0.282, alpha: 1.000) 12 | 13 | static let primaryColor = UIColor(red:0.129, green: 0.133, blue: 0.145, alpha: 1.000) 14 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Swift Color Palette 2 | ============================= 3 | 4 | A SketchApp plugin that making color palette an enum in other words generates Swift Color Theme files from your Sketch documents. 5 | 6 | Swift Color Palette plugin inspired by [**@NatashaTheRobot**](https://github.com/NatashaTheRobot) 's [blog post](https://www.natashatherobot.com/swift-enum-no-cases/) 7 | 8 | Installation 9 | ============================= 10 | 11 | [Download](https://github.com/nahitheper/SwiftColorPalette/archive/master.zip) and extract the contents of this repository. Then double-click the `SwiftColorPalette.sketchplugin` bundle to install the plugin. 12 | In [Sketch Toolbox](http://sketchtoolbox.com), search for 'Swift Color Palette' and tap Install. 13 | 14 | Short Demo 15 | ============================= 16 | 17 | Swift Color Palette 18 | 19 | Usage 20 | ============================= 21 | * Rename color palette layer(s) 22 | * Select a layer(s) 23 | * Run using ```Plugins > Menu > Swift Color Palette``` 24 | * Select a Export File (optional) or you can choose copy to clipboard. 25 | * Click OK. 26 | 27 | Example Code 28 | ============================= 29 | ```swift 30 | enum ColorPalette { 31 | static let lightGrayColor = UIColor(red:0.737, green: 0.769, blue: 0.792, alpha: 1.000) 32 | static let blueColor = UIColor(red:0.353, green: 0.510, blue: 0.647, alpha: 1.000) 33 | static let grayColor = UIColor(red:0.373, green: 0.373, blue: 0.376, alpha: 1.000) 34 | static let panelColor = UIColor(red:0.212, green: 0.227, blue: 0.267, alpha: 1.000) 35 | static let secondaryColor = UIColor(red:0.141, green: 0.220, blue: 0.282, alpha: 1.000) 36 | static let primaryColor = UIColor(red:0.129, green: 0.133, blue: 0.145, alpha: 1.000) 37 | } 38 | ``` 39 | 40 | Feedback 41 | ========= 42 | 43 | If you have any questions, find a bug, or have ideas for ways to improve the plugin, ping me on twitter: @nahitheper 44 | 45 | 46 | -------------------------------------------------------------------------------- /SwiftColorPalette.sketchplugin/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahitheper/SwiftColorPalette/a3cb3965334e8cfed5474121b93844c1c8b2d6f9/SwiftColorPalette.sketchplugin/.DS_Store -------------------------------------------------------------------------------- /SwiftColorPalette.sketchplugin/Contents/Sketch/library.cocoascript: -------------------------------------------------------------------------------- 1 | var SketchLib = { 2 | // Adds a new layer as a child of `container` with the given type 3 | // Valid types are 'group', 'text', 'image' and 'rectangle' 4 | // parameters is an optional dictionary containing zero or more of the 5 | // following keys: 6 | // name (a string) 7 | // rect (an NSRect) 8 | // color (an MSColor) 9 | // returns the newly created layer 10 | "addLayer": function (container, type, parameters) { 11 | var layer = container.addLayerOfType(type); 12 | if (typeof(parameters.name) !== 'undefined') layer.name = parameters.name; 13 | if (typeof(parameters.rect) !== 'undefined') layer.rect = parameters.rect; 14 | if (typeof(parameters.color) !== 'undefined') { 15 | this.util.setFillColor(layer, parameters.color); 16 | } 17 | return layer; 18 | }, 19 | // Adds a new group (MSLayerGroup) as a child of `container` 20 | // See `addLayer` for a discussion of `parameters` 21 | // returns the newly created group 22 | "addLayerGroup": function (container, parameters) { 23 | return this.addLayer(container, "group", parameters); 24 | }, 25 | // Adds a new text layer (MSTextLayer) as a child of `container` 26 | // In addition to the keys described in `addLayer`, `parameters` may also 27 | // contain the following keys: 28 | // text (a string) 29 | // fontSize (a number) 30 | // returns the newly created text layer 31 | "addTextLayer": function (container, parameters) { 32 | var textLayer = this.addLayer(container, "text", parameters); 33 | if (typeof(parameters.text) !== 'undefined') { 34 | textLayer.stringValue = parameters.text; 35 | if (typeof(parameters.name) == 'undefined') { 36 | textLayer.name = parameters.text; 37 | } 38 | } 39 | if (typeof(parameters.fontSize) !== 'undefined') textLayer.fontSize = parameters.fontSize; 40 | textLayer.adjustFrameToFit(); 41 | return textLayer; 42 | }, 43 | // Adds a new bitmap layer (MSBitmapLayer) as a child of `container` 44 | // In addition to the keys described in `addLayer`, `parameters` may also 45 | // contain the following keys: 46 | // imageData (MSImageData) 47 | // image (NSImage) 48 | // url (NSURL) 49 | // returns the newly created bitmap layer 50 | "addImageLayer": function (container, parameters) { 51 | var imageLayer = this.addLayer(container, "image", parameters); 52 | var imageData = parameters.imageData; 53 | var image = null; 54 | 55 | if (typeof(imageData) === 'undefined') { 56 | var image = parameters.image; 57 | if (typeof(image) !== 'undefined') { 58 | imageData = this.util.imageDataFromImage(container, image); 59 | } else { 60 | var url = parameters.url; 61 | if (typeof(url) !== 'undefined' && url !== null) { 62 | imageData = this.util.imageDataFromURL(container, url); 63 | } 64 | if (typeof(imageData) !== 'undefined') { 65 | image = imageData.image(); 66 | } 67 | } 68 | } 69 | 70 | if (typeof(image) !== 'undefined' && image !== null) { 71 | var originalImageSize = [image size]; 72 | var fill = [[[imageLayer style] fills] addNewStylePart]; 73 | [fill setIsEnabled:false]; 74 | [imageLayer setConstrainProportions:false]; 75 | [imageLayer setImage:[MSImageProxy proxyWithImageData:imageData]]; 76 | var rect = CGRectZero; 77 | rect.size = originalImageSize; 78 | [imageLayer setRect:rect]; 79 | [imageLayer setConstrainProportions:true]; 80 | } 81 | return imageLayer; 82 | }, 83 | // Adds a new shape group (MSShapeGroup) as a child of `container` 84 | // containing a rectangle path 85 | // See `addLayer` for a discussion of `parameters` 86 | // returns the newly created shape group 87 | "addShapeLayer": function (container, parameters) { 88 | return this.addLayer(container, "rectangle", parameters); 89 | }, 90 | "util": { 91 | // Returns an MSImageData object for `image` (NSImage) 92 | "imageDataFromImage": function(container, image) { 93 | var imageCollection = [[container documentData] images]; 94 | return [imageCollection addNSImage:image convertColourspace:false]; 95 | }, 96 | 97 | // Returns an MSImageData object for `url` (NSURL) 98 | "imageDataFromURL": function(container, url) { 99 | var image = [[NSImage alloc] initWithContentsOfURL:url]; 100 | var imageData = undefined; 101 | if (typeof(image) !== 'undefined') { 102 | imageData = this.imageDataFromImage(container, image); 103 | } 104 | return imageData; 105 | }, 106 | 107 | // Centers `layer` at `point`. If point is not specified `layer` 108 | // is centered at the origin (0,0) 109 | "centerLayer": function(layer, point) { 110 | var center = (typeof(point) !== 'undefined') ? point : CGPointMake(0,0); 111 | var rect = [layer rect]; 112 | rect.origin.x = center.x-(CGRectGetWidth(rect)/2.0); 113 | rect.origin.y = center.y-(CGRectGetHeight(rect)/2.0); 114 | [layer setRect:rect]; 115 | }, 116 | 117 | // Sets the fill color for `layer` to `color` (MSColor) 118 | "setFillColor": function(layer, color) { 119 | var fill = [[[layer style] fills] addNewStylePart]; 120 | [fill setColor: color]; 121 | } 122 | } 123 | }; -------------------------------------------------------------------------------- /SwiftColorPalette.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "author" : "Nahit Rüştü Heper", 3 | "commands" : [ 4 | { 5 | "script" : "script.cocoascript", 6 | "handler" : "onRun", 7 | "shortcut" : "", 8 | "name" : "Swift Color Palette !", 9 | "identifier" : "swiftColorPalette" 10 | } 11 | ], 12 | "menu": { 13 | "isRoot": true, 14 | "items": [ 15 | "swiftColorPalette" 16 | ] 17 | }, 18 | "identifier" : "com.example.sketch.swiftColorPalette", 19 | "version" : "1.0", 20 | "description" : "Sketch Plugin using export UIColor values from within Color Palette", 21 | "authorEmail" : "nahitheper@gmail.com", 22 | "name" : "Swift Color Palette" 23 | } 24 | -------------------------------------------------------------------------------- /SwiftColorPalette.sketchplugin/Contents/Sketch/script.cocoascript: -------------------------------------------------------------------------------- 1 | @import "library.cocoascript"; 2 | var onRun = function(context) { 3 | 4 | var documentName = context.document.displayName(); 5 | var selectedLayers = context.selection; 6 | var selectedCount = selectedLayers.count(); 7 | var str = ""; 8 | 9 | if (selectedCount == 0) { 10 | showMessage("No layers are selected.").runModal(); 11 | } else { 12 | // Show dialog 13 | var alert = createDialog(); 14 | var options = alertResponse(alert,alert.runModal()); 15 | 16 | if (options.include){ 17 | str = writeText(selectedLayers,true); 18 | }else{ 19 | str = writeText(selectedLayers,false); 20 | } 21 | 22 | if (options.exportFile){ 23 | var savedFile = writeTextToFile(str); 24 | if (savedFile){ 25 | showMessage("File saved.").runModal(); 26 | }else{ 27 | showMessage("File not saved.").runModal(); 28 | } 29 | }else{ 30 | copyToclipBoard(str); 31 | } 32 | } 33 | }; 34 | 35 | function convertUIColor(color) { 36 | var red = color.red().toFixed(3).toString(); 37 | var green = color.green().toFixed(3).toString(); 38 | var blue = color.blue().toFixed(3).toString(); 39 | var alpha = color.alpha().toFixed(3).toString(); 40 | 41 | return "UIColor(red:"+red+", green: "+green+", blue: "+blue+", alpha: "+alpha+")"; 42 | } 43 | 44 | function makeEnumCaseName(string){ 45 | return string.charAt(0).toLowerCase() + string.substr(1) 46 | } 47 | 48 | function writeText(selectedLayers,includeComments){ 49 | 50 | var newLine = "\n"; 51 | var textString = ""; 52 | if (includeComments) { 53 | textString += "// Generated automatically by Swift Color Palette." 54 | textString += newLine 55 | textString += "// https://github.com/nahitheper/SwiftColorPalette" 56 | textString += newLine 57 | } 58 | textString += "import UIKit" 59 | textString += newLine 60 | textString += "enum ColorPalette {" 61 | 62 | for (var i = 0; i < selectedLayers.count(); i++) { 63 | var layer = selectedLayers[i]; 64 | textString += newLine 65 | textString += newLine 66 | textString += " static let "+makeEnumCaseName(layer.name())+" = " + convertUIColor(layer.style().fills().firstObject().color()) 67 | } 68 | 69 | textString += newLine 70 | textString += "}" 71 | return textString; 72 | } 73 | 74 | function copyToclipBoard(text){ 75 | var pasteBoard = NSPasteboard.generalPasteboard(); 76 | pasteBoard.clearContents() 77 | pasteBoard.writeObjects([text]); 78 | showMessage("Successfully copied to clipboard.").runModal(); 79 | } 80 | 81 | function writeTextToFile(text) { 82 | 83 | var openPanel = [NSOpenPanel openPanel] 84 | [openPanel setCanChooseDirectories:true] 85 | [openPanel setCanChooseFiles:false] 86 | [openPanel setCanCreateDirectories:false] 87 | [openPanel setDirectoryURL:[NSURL fileURLWithPath:"~/Documents/"]] 88 | [openPanel setTitle:"Choose a file"] 89 | [openPanel setPrompt:"Choose"] 90 | [openPanel runModal] 91 | var directory = [openPanel filename]; 92 | var path = directory + "/ColorPalette.swift"; 93 | 94 | var result = false; 95 | if (typeof path !== 'string') 96 | return result; 97 | var nsstring = NSString.stringWithUTF8String(text); 98 | result = [nsstring writeToFile:path atomically:1 encoding:NSUTF8StringEncoding error:null]; 99 | if (!result) { 100 | result = false; 101 | } else { 102 | result = true; 103 | } 104 | return result; 105 | } 106 | 107 | function alertResponse(alert, code) { 108 | if (code == "1000") { 109 | return { 110 | exportFile: alert.viewAtIndex(0).state() 111 | //include: alert.viewAtIndex(1).state() 112 | } 113 | } 114 | return null; 115 | } 116 | 117 | function createCheckbox(checkBoxLabel) { 118 | var checkbox = NSButton.alloc().initWithFrame( NSMakeRect( 0, 0, 300, 18 ) ); 119 | checkbox.setButtonType( NSSwitchButton ); 120 | checkbox.setTitle( checkBoxLabel ); 121 | checkbox.setTag( checkBoxLabel ); 122 | checkbox.setState( false ); 123 | 124 | return checkbox; 125 | } 126 | 127 | function createDialog(){ 128 | var alert = COSAlertWindow.new(); 129 | alert.setMessageText("Swift Color Palette"); 130 | alert.setInformativeText("Choose your options. Export file or copy to clipboard ?"); 131 | var exportFileChecBox = createCheckbox("Export file"); 132 | var includeHex = createCheckbox("Include Hex codes with comment."); 133 | alert.addAccessoryView(exportFileChecBox); 134 | //alert.addAccessoryView(includeHex); 135 | alert.addButtonWithTitle('OK'); 136 | alert.addButtonWithTitle('Cancel'); 137 | 138 | return alert; 139 | } 140 | 141 | function showMessage(informationText){ 142 | var alert = COSAlertWindow.new(); 143 | 144 | alert.setMessageText("Swift Color Palette"); 145 | alert.setInformativeText(informationText); 146 | alert.addButtonWithTitle('OK'); 147 | 148 | return alert; 149 | } -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahitheper/SwiftColorPalette/a3cb3965334e8cfed5474121b93844c1c8b2d6f9/demo.gif --------------------------------------------------------------------------------