├── Color Copier.sketchplugin └── Contents │ └── Sketch │ ├── hex.cocoascript │ ├── hsb.cocoascript │ ├── hsl.cocoascript │ ├── hsla.cocoascript │ ├── manifest.json │ ├── rgb.cocoascript │ ├── rgba.cocoascript │ └── utility.js └── README.md /Color Copier.sketchplugin/Contents/Sketch/hex.cocoascript: -------------------------------------------------------------------------------- 1 | @import 'utility.js' 2 | 3 | var copyHexFill = function(context) { 4 | var selection = context.selection 5 | 6 | if (checkLayerCount(selection.count())) { 7 | var layer = selection[0] 8 | 9 | if (checkFill(layer)) { 10 | var selectedColor = getColor("fill", layer) 11 | var hex = selectedColor.hexValue().toString() 12 | 13 | clipboard.set(hex) 14 | 15 | var doc = context.document 16 | doc.showMessage("Fill color HEX [ " + hex + " ] copied to clipboard.") 17 | } 18 | } 19 | } 20 | 21 | var copyHexBorder = function(context) { 22 | var selection = context.selection 23 | 24 | if (checkLayerCount(selection.count())) { 25 | var layer = selection[0] 26 | 27 | if (checkBorder(layer)) { 28 | var selectedColor = getColor("border", layer) 29 | var hex = selectedColor.hexValue().toString() 30 | 31 | clipboard.set(hex) 32 | 33 | var doc = context.document 34 | doc.showMessage("Border color HEX [ " + hex + " ] copied to clipboard.") 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/hsb.cocoascript: -------------------------------------------------------------------------------- 1 | @import 'utility.js' 2 | 3 | var copyHsbFill = function(context) { 4 | var selection = context.selection 5 | 6 | if (checkLayerCount(selection.count())) { 7 | var layer = selection[0] 8 | 9 | if (checkFill(layer)) { 10 | var selectedColor = getColor("fill", layer) 11 | 12 | var hue = Math.round(selectedColor.hue() * 360) 13 | var saturation = Math.round(selectedColor.saturation() * 100) 14 | var brightness = Math.round(selectedColor.brightness() * 100) 15 | 16 | clipboard.set(hue + ", " + saturation + ", " + brightness) 17 | 18 | var doc = context.document 19 | doc.showMessage("Fill color HSB [ " 20 | + hue + ", " 21 | + saturation + ", " 22 | + brightness + " ] copied to clipboard.") 23 | } 24 | } 25 | } 26 | 27 | var copyHsbBorder = function(context) { 28 | var selection = context.selection 29 | 30 | if (checkLayerCount(selection.count())) { 31 | var layer = selection[0] 32 | 33 | if (checkBorder(layer)) { 34 | var selectedColor = getColor("border", layer) 35 | 36 | var hue = Math.round(selectedColor.hue() * 360) 37 | var saturation = Math.round(selectedColor.saturation() * 100) 38 | var brightness = Math.round(selectedColor.brightness() * 100) 39 | 40 | clipboard.set(hue + ", " + saturation + ", " + brightness) 41 | 42 | var doc = context.document 43 | doc.showMessage("Border color HSB [ " 44 | + hue + ", " 45 | + saturation + ", " 46 | + brightness + " ] copied to clipboard.") 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/hsl.cocoascript: -------------------------------------------------------------------------------- 1 | @import 'utility.js' 2 | 3 | var copyHslFill = function(context) { 4 | var selection = context.selection 5 | 6 | if (checkLayerCount(selection.count())) { 7 | var layer = selection[0] 8 | 9 | if (checkFill(layer)) { 10 | var selectedColor = getColor("fill", layer) 11 | 12 | // http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c 13 | var red = selectedColor.red() 14 | var green = selectedColor.green() 15 | var blue = selectedColor.blue() 16 | 17 | var max = Math.max(red, blue, green) 18 | var min = Math.min(red, blue, green) 19 | 20 | var hue 21 | var saturation 22 | var lightness = (max + min) / 2 23 | 24 | if (max === min) { 25 | hue = 0 26 | saturation = 0 27 | } else { 28 | var d = max - min 29 | saturation = lightness > 0.5 ? d / (2 - max - min) : d / (max + min) 30 | 31 | if (max === red) { 32 | hue = (green - blue) / d + (green < blue ? 6 : 0); 33 | } else if (max === green) { 34 | hue = (blue - red) / d + 2; 35 | } else if (max === blue) { 36 | hue = (red - green) / d + 4; 37 | } 38 | 39 | hue /= 6 40 | hue *= 360 41 | saturation *= 100 42 | lightness = Math.round(lightness * 100) 43 | } 44 | 45 | clipboard.set(hue + ", " + saturation + ", " + lightness) 46 | 47 | var doc = context.document 48 | doc.showMessage("Fill color HSL [ " 49 | + hue + ", " 50 | + saturation + ", " 51 | + lightness + " ] copied to clipboard.") 52 | } 53 | } 54 | } 55 | 56 | var copyHslBorder = function(context) { 57 | var selection = context.selection 58 | 59 | if (checkLayerCount(selection.count())) { 60 | var layer = selection[0] 61 | 62 | if (checkBorder(layer)) { 63 | var selectedColor = getColor("border", layer) 64 | 65 | // http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c 66 | var red = selectedColor.red() 67 | var green = selectedColor.green() 68 | var blue = selectedColor.blue() 69 | 70 | var max = Math.max(red, blue, green) 71 | var min = Math.min(red, blue, green) 72 | 73 | var hue 74 | var saturation 75 | var lightness = (max + min) / 2 76 | 77 | if (max === min) { 78 | hue = 0 79 | saturation = 0 80 | } else { 81 | var d = max - min 82 | saturation = lightness > 0.5 ? d / (2 - max - min) : d / (max + min) 83 | 84 | if (max === red) { 85 | hue = (green - blue) / d + (green < blue ? 6 : 0); 86 | } else if (max === green) { 87 | hue = (blue - red) / d + 2; 88 | } else if (max === blue) { 89 | hue = (red - green) / d + 4; 90 | } 91 | 92 | hue /= 6 93 | hue *= 360 94 | saturation *= 100 95 | lightness = Math.round(lightness * 100) 96 | } 97 | 98 | clipboard.set(hue + ", " + saturation + ", " + lightness) 99 | 100 | var doc = context.document 101 | doc.showMessage("Border color HSL [ " 102 | + hue + ", " 103 | + saturation + ", " 104 | + lightness + " ] copied to clipboard.") 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/hsla.cocoascript: -------------------------------------------------------------------------------- 1 | @import 'utility.js' 2 | 3 | var copyHslaFill = function(context) { 4 | var selection = context.selection 5 | 6 | if (checkLayerCount(selection.count())) { 7 | var layer = selection[0] 8 | 9 | if (checkFill(layer)) { 10 | var selectedColor = getColor("fill", layer) 11 | 12 | // http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c 13 | var red = selectedColor.red() 14 | var green = selectedColor.green() 15 | var blue = selectedColor.blue() 16 | 17 | var max = Math.max(red, blue, green) 18 | var min = Math.min(red, blue, green) 19 | 20 | var hue 21 | var saturation 22 | var lightness = (max + min) / 2 23 | var alpha = +selectedColor.alpha().toFixed(2) 24 | 25 | if (max === min) { 26 | hue = 0 27 | saturation = 0 28 | } else { 29 | var d = max - min 30 | saturation = lightness > 0.5 ? d / (2 - max - min) : d / (max + min) 31 | 32 | if (max === red) { 33 | hue = (green - blue) / d + (green < blue ? 6 : 0); 34 | } else if (max === green) { 35 | hue = (blue - red) / d + 2; 36 | } else if (max === blue) { 37 | hue = (red - green) / d + 4; 38 | } 39 | 40 | hue /= 6 41 | hue *= 360 42 | saturation *= 100 43 | lightness = Math.round(lightness * 100) 44 | } 45 | 46 | clipboard.set(hue + ", " + saturation + ", " + lightness + ", " + alpha) 47 | 48 | var doc = context.document 49 | doc.showMessage("Fill color HSLA [ " 50 | + hue + ", " 51 | + saturation + ", " 52 | + lightness + " , " 53 | + alpha + " ] copied to clipboard.") 54 | } 55 | } 56 | } 57 | 58 | var copyHslaBorder = function(context) { 59 | var selection = context.selection 60 | 61 | if (checkLayerCount(selection.count())) { 62 | var layer = selection[0] 63 | 64 | if (checkBorder(layer)) { 65 | var selectedColor = getColor("border", layer) 66 | 67 | // http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c 68 | var red = selectedColor.red() 69 | var green = selectedColor.green() 70 | var blue = selectedColor.blue() 71 | 72 | var max = Math.max(red, blue, green) 73 | var min = Math.min(red, blue, green) 74 | 75 | var hue 76 | var saturation 77 | var lightness = (max + min) / 2 78 | var alpha = selectedColor.alpha() 79 | 80 | if (max === min) { 81 | hue = 0 82 | saturation = 0 83 | } else { 84 | var d = max - min 85 | saturation = lightness > 0.5 ? d / (2 - max - min) : d / (max + min) 86 | 87 | if (max === red) { 88 | hue = (green - blue) / d + (green < blue ? 6 : 0); 89 | } else if (max === green) { 90 | hue = (blue - red) / d + 2; 91 | } else if (max === blue) { 92 | hue = (red - green) / d + 4; 93 | } 94 | 95 | hue /= 6 96 | hue *= 360 97 | saturation *= 100 98 | lightness = Math.round(lightness * 100) 99 | } 100 | 101 | clipboard.set(hue + ", " + saturation + ", " + lightness + ", " + alpha) 102 | 103 | var doc = context.document 104 | doc.showMessage("Border color HSLA [ " 105 | + hue + ", " 106 | + saturation + ", " 107 | + lightness + " , " 108 | + alpha + " ] copied to clipboard.") 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Color Copier", 3 | "description": "Quickly copy the RGB, RGBA, HSB, HSL, HSLA, or HEX values for fill or border.", 4 | "author": "Michael Fouquet", 5 | "authorEmail": "michael.fouquet@me.com", 6 | "homepage": "https://github.com/mfouquet/color-copier", 7 | "version" : "2.1", 8 | "compatibleVersion": 3, 9 | "identifier" : "com.mfouquet.sketch.color-copier", 10 | "commands" : [ 11 | { 12 | "name" : "Fill", 13 | "identifier" : "rgb-fill", 14 | "script" : "rgb.cocoascript", 15 | "handler" : "copyRgbFill", 16 | "shortcut" : "", 17 | }, 18 | { 19 | "name" : "Border", 20 | "identifier" : "rgb-border", 21 | "script" : "rgb.cocoascript", 22 | "handler" : "copyRgbBorder", 23 | "shortcut" : "", 24 | }, 25 | { 26 | "name" : "Fill", 27 | "identifier" : "rgba-fill", 28 | "script" : "rgba.cocoascript", 29 | "handler" : "copyRgbaFill", 30 | "shortcut" : "", 31 | }, 32 | { 33 | "name" : "Border", 34 | "identifier" : "rgba-border", 35 | "script" : "rgba.cocoascript", 36 | "handler" : "copyRgbaBorder", 37 | "shortcut" : "", 38 | }, 39 | { 40 | "name" : "Fill", 41 | "identifier" : "hsb-fill", 42 | "script" : "hsb.cocoascript", 43 | "handler" : "copyHsbFill", 44 | "shortcut" : "", 45 | }, 46 | { 47 | "name" : "Border", 48 | "identifier" : "hsb-border", 49 | "script" : "hsb.cocoascript", 50 | "handler" : "copyHsbBorder", 51 | "shortcut" : "", 52 | }, 53 | { 54 | "name" : "Fill", 55 | "identifier" : "hsl-fill", 56 | "script" : "hsl.cocoascript", 57 | "handler" : "copyHslFill", 58 | "shortcut" : "", 59 | }, 60 | { 61 | "name" : "Border", 62 | "identifier" : "hsl-border", 63 | "script" : "hsl.cocoascript", 64 | "handler" : "copyHslBorder", 65 | "shortcut" : "", 66 | }, 67 | { 68 | "name" : "Fill", 69 | "identifier" : "hsla-fill", 70 | "script" : "hsla.cocoascript", 71 | "handler" : "copyHslaFill", 72 | "shortcut" : "", 73 | }, 74 | { 75 | "name" : "Border", 76 | "identifier" : "hsla-border", 77 | "script" : "hsla.cocoascript", 78 | "handler" : "copyHslaBorder", 79 | "shortcut" : "", 80 | }, 81 | { 82 | "name" : "Fill", 83 | "identifier" : "hex-fill", 84 | "script" : "hex.cocoascript", 85 | "handler" : "copyHexFill", 86 | "shortcut" : "", 87 | }, 88 | { 89 | "name" : "Border", 90 | "identifier" : "hex-border", 91 | "script" : "hex.cocoascript", 92 | "handler" : "copyHexBorder", 93 | "shortcut" : "", 94 | }, 95 | ], 96 | "menu" : { 97 | "items" : [ 98 | { 99 | "title": "RGB", 100 | "items": [ 101 | "rgb-fill", 102 | "rgb-border", 103 | ] 104 | }, 105 | { 106 | "title": "RGBA", 107 | "items": [ 108 | "rgba-fill", 109 | "rgba-border", 110 | ] 111 | }, 112 | { 113 | "title": "HSB", 114 | "items": [ 115 | "hsb-fill", 116 | "hsb-border", 117 | ] 118 | }, 119 | { 120 | "title": "HSL", 121 | "items": [ 122 | "hsl-fill", 123 | "hsl-border", 124 | ] 125 | }, 126 | { 127 | "title": "HSLA", 128 | "items": [ 129 | "hsla-fill", 130 | "hsla-border", 131 | ] 132 | }, 133 | { 134 | "title": "HEX", 135 | "items": [ 136 | "hex-fill", 137 | "hex-border", 138 | ] 139 | } 140 | ], 141 | "title" : "Color Copier" 142 | }, 143 | } 144 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/rgb.cocoascript: -------------------------------------------------------------------------------- 1 | @import 'utility.js' 2 | 3 | var copyRgbFill = function(context) { 4 | var selection = context.selection 5 | 6 | if (checkLayerCount(selection.count())) { 7 | var layer = selection[0] 8 | 9 | if (checkFill(layer)) { 10 | var selectedColor = getColor("fill", layer) 11 | 12 | var red = Math.round(selectedColor.red() * 255) 13 | var green = Math.round(selectedColor.green() * 255) 14 | var blue = Math.round(selectedColor.blue() * 255) 15 | 16 | clipboard.set(red + ", " + green + ", " + blue) 17 | 18 | var doc = context.document 19 | doc.showMessage("Fill color RGB [ " 20 | + red + ", " 21 | + green + ", " 22 | + blue + " ] copied to clipboard.") 23 | } 24 | } 25 | } 26 | 27 | var copyRgbBorder = function(context) { 28 | var selection = context.selection 29 | 30 | if (checkLayerCount(selection.count())) { 31 | var layer = selection[0] 32 | 33 | if (checkBorder(layer)) { 34 | var selectedColor = getColor("border", layer) 35 | 36 | var red = Math.round(selectedColor.red() * 255) 37 | var green = Math.round(selectedColor.green() * 255) 38 | var blue = Math.round(selectedColor.blue() * 255) 39 | 40 | clipboard.set(red + ", " + green + ", " + blue) 41 | 42 | var doc = context.document 43 | doc.showMessage("Border color RGB [ " 44 | + red + ", " 45 | + green + ", " 46 | + blue + " ] copied to clipboard.") 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/rgba.cocoascript: -------------------------------------------------------------------------------- 1 | @import 'utility.js' 2 | 3 | var copyRgbaFill = function(context) { 4 | var selection = context.selection 5 | 6 | if (checkLayerCount(selection.count())) { 7 | var layer = selection[0] 8 | 9 | if (checkFill(layer)) { 10 | var selectedColor = getColor("fill", layer) 11 | 12 | var red = Math.round(selectedColor.red() * 255) 13 | var green = Math.round(selectedColor.green() * 255) 14 | var blue = Math.round(selectedColor.blue() * 255) 15 | var alpha = +selectedColor.alpha().toFixed(2) 16 | 17 | clipboard.set(red + ", " + green + ", " + blue + ", " + alpha) 18 | 19 | var doc = context.document 20 | doc.showMessage("Fill color RGBA [ " 21 | + red + ", " 22 | + green + ", " 23 | + blue + ", " 24 | + alpha + " ] copied to clipboard.") 25 | } 26 | } 27 | } 28 | 29 | var copyRgbaBorder = function(context) { 30 | var selection = context.selection 31 | 32 | if (checkLayerCount(selection.count())) { 33 | var layer = selection[0] 34 | 35 | if (checkBorder(layer)) { 36 | var selectedColor = getColor("border", layer) 37 | 38 | var red = Math.round(selectedColor.red() * 255) 39 | var green = Math.round(selectedColor.green() * 255) 40 | var blue = Math.round(selectedColor.blue() * 255) 41 | var alpha = +selectedColor.alpha().toFixed(2) 42 | 43 | clipboard.set(red + ", " + green + ", " + blue + ", " + alpha) 44 | 45 | var doc = context.document 46 | doc.showMessage("Border color RGBA [ " 47 | + red + ", " 48 | + green + ", " 49 | + blue + ", " 50 | + alpha + " ] copied to clipboard.") 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Color Copier.sketchplugin/Contents/Sketch/utility.js: -------------------------------------------------------------------------------- 1 | var app = NSApplication.sharedApplication() 2 | 3 | var checkLayerCount = function(selectionCount) { 4 | var isOneLayerSelected = false 5 | 6 | switch (selectionCount) { 7 | case 0: 8 | app.displayDialog_withTitle("You must select a layer first.", "Color Copier") 9 | break 10 | 11 | case 1: 12 | isOneLayerSelected = true 13 | break 14 | 15 | default: 16 | app.displayDialog_withTitle("Only one layer can be selected.", "Color Copier") 17 | break 18 | } 19 | 20 | return isOneLayerSelected 21 | } 22 | 23 | var checkFill = function(layer) { 24 | var isFillPresent = false 25 | 26 | if (layer.style().fills().count() > 0 || (layer instanceof MSTextLayer)) { 27 | isFillPresent = true 28 | } else { 29 | app.displayDialog_withTitle("No fill on this object.", "Color Copier") 30 | } 31 | 32 | return isFillPresent 33 | } 34 | 35 | var checkBorder = function(layer) { 36 | var isBorderPresent = false 37 | 38 | if (layer.style().borders().count() > 0) { 39 | isBorderPresent = true 40 | } else { 41 | app.displayDialog_withTitle("No border on this object.", "Color Copier") 42 | } 43 | 44 | return isBorderPresent 45 | } 46 | 47 | var getColor = function(selectionType, layer) { 48 | var color 49 | 50 | if (selectionType === "fill") { 51 | if (layer instanceof MSTextLayer) { 52 | color = layer.textColor() 53 | } else { 54 | color = layer.style().fills().firstObject().color() 55 | } 56 | } else { 57 | color = layer.style().borders().firstObject().color() 58 | } 59 | 60 | return color 61 | } 62 | 63 | // JSTalk clipboard 64 | // https://gist.github.com/uhunkler/5465857 65 | var clipboard = { 66 | pasteBoard : null, 67 | init : function() { 68 | this.pasteBoard = NSPasteboard.generalPasteboard(); 69 | }, 70 | set : function( text ) { 71 | if( typeof text === 'undefined' ) return null; 72 | 73 | if( !this.pasteBoard ) 74 | this.init(); 75 | 76 | this.pasteBoard.declareTypes_owner( [ NSPasteboardTypeString ], null ); 77 | this.pasteBoard.setString_forType( text, NSPasteboardTypeString ); 78 | 79 | return true; 80 | }, 81 | get : function() { 82 | if( !this.pasteBoard ) 83 | this.init(); 84 | 85 | var text = this.pasteBoard.stringForType( NSPasteboardTypeString ); 86 | 87 | return text.toString(); 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Color Copier Sketch Plugin 2 | 3 | This plugin allows you to quickly copy the RGB, RGBA, HSB, HSL, HSLA or HEX values for both the 4 | fill and border colors. 5 | 6 | ##Installation 7 | 1. Download the plugin and double-click to install. 8 | 9 | ##Usage 10 | No more and no less than one layer can be selected. You can have any type of 11 | shape or text selected. 12 | 13 | Upon selecting an option from the menu, the info will immediately be copied to your clipboard. 14 | --------------------------------------------------------------------------------