├── .gitignore
├── README.md
├── assets
└── icon.png
├── package-lock.json
├── package.json
├── sketch-tokenizer.sketchplugin
└── Contents
│ ├── Resources
│ └── icon.png
│ └── Sketch
│ ├── get-base-border-color.js
│ ├── get-base-border-color.js.map
│ ├── get-base-fill-color.js
│ ├── get-base-fill-color.js.map
│ ├── get-border-color.js
│ ├── get-border-color.js.map
│ ├── get-color-variable.js
│ ├── get-color-variable.js.map
│ ├── get-fill-color.js
│ ├── get-fill-color.js.map
│ ├── get-token-background-color-input.js
│ ├── get-token-background-color-input.js.map
│ ├── get-token-border-color-input.js
│ ├── get-token-border-color-input.js.map
│ ├── import-base-colors-decisions-file.js
│ ├── import-base-colors-decisions-file.js.map
│ ├── import-base-colors.js
│ ├── import-base-colors.js.map
│ ├── import-decisions-file.js
│ ├── import-decisions-file.js.map
│ ├── import-token-backgrounds-decisions-file.js
│ ├── import-token-backgrounds-decisions-file.js.map
│ ├── import-token-borders-decisions-file.js
│ ├── import-token-borders-decisions-file.js.map
│ ├── manifest.json
│ ├── my-command.js
│ └── my-command.js.map
└── src
├── border-color.js
├── converters
└── colors.js
├── decisions
├── backgrounds.json
├── base-colors.json
└── borders.json
├── example.sketch
├── manifest.json
├── menu-identify
├── base-colors
│ ├── get-base-border-color.js
│ └── get-base-fill-color.js
└── tokens
│ ├── background
│ └── get-token-background-color-input.js
│ └── border
│ └── get-token-border-color-input.js
├── menu-import
├── import-base-colors-decisions-file.js
├── import-token-backgrounds-decisions-file.js
└── import-token-borders-decisions-file.js
└── utils.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # build artifacts
2 | plugin.sketchplugin
3 |
4 | # npm
5 | node_modules
6 | .npm
7 | npm-debug.log
8 |
9 | # mac
10 | .DS_Store
11 |
12 | # WebStorm
13 | .idea
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # sketch-tokenizer
2 |
3 |
4 |
5 | > Maps your hardcoded colors values to actual design tokens and adds a label to your layout.
6 |
7 | If you work with design tokens in your project, one of the issues you might face is receiving layouts and having to inspecting them to find out which design token corresponds to certain HEX value.
8 |
9 | That's time consuming, and would be really good to receive such layouts with some "text labels" indicating which design token applies to certain color.
10 |
11 | This plugin comes to make both Designers and Developers's lives easier: you provide a file with your main colors and their variations, and the plugin will take care of mapping those to design tokens.
12 |
13 | **TLDR;:** Designers hands over screens with the `design tokens` developers should use for certain elements. That means: no more time wasted on inspecting hardcoded values.
14 |
15 | ## Demo
16 |
17 |
18 |
19 | ## Usage
20 |
21 | 1. Provide a JSON file with your project's [decision base colors](https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421)
22 |
23 | ```json
24 | // variations are based on the color`s lightness channel
25 | // (E.g color(var(--color-green), lightness(25%)))
26 | {
27 | "baseColors": {
28 | "green": {
29 | "default": "#00b39e",
30 | "25": "25%",
31 | "40": "40%",
32 | "85": "85%",
33 | "95": "95%"
34 | },
35 | "white": {
36 | "default": "#ffffff"
37 | },
38 | "navy": {
39 | "default": "#213c45",
40 | "30": "30%",
41 | "40": "40%",
42 | "98": "98%"
43 | }
44 | }
45 | }
46 | ```
47 |
48 | 2. Import this file on `Plugins > Tokenizer > Import base colors file...`
49 |
50 |
51 |
52 | 3. Select an object in the Artboard
53 |
54 | 4. Go to `Plugins > Tokenizer > Get color variable > Fill Color` or `Border Color`
55 |
56 | 5. 🎉 The corresponding design token to that label will be applied to the Artboard
57 |
58 | ## Future updates
59 |
60 | - Implement actual design tokens (not only base colors)
61 | - Tones for text
62 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lufego/sketch-tokenizer/7c5bedccaae1467e98063b011c1f15a734c5ab79/assets/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sketch-tokenizer",
3 | "version": "0.1.0",
4 | "engines": {
5 | "sketch": ">=3.0"
6 | },
7 | "skpm": {
8 | "name": "sketch-tokenizer",
9 | "manifest": "src/manifest.json",
10 | "main": "sketch-tokenizer.sketchplugin",
11 | "assets": [
12 | "assets/**/*"
13 | ]
14 | },
15 | "scripts": {
16 | "build": "skpm-build",
17 | "watch": "skpm-build --watch",
18 | "start": "skpm-build --watch --run",
19 | "postinstall": "npm run build && skpm-link"
20 | },
21 | "devDependencies": {
22 | "@skpm/builder": "^0.5.2"
23 | },
24 | "author": "lufego ",
25 | "dependencies": {
26 | "fs": "0.0.1-security",
27 | "path": "^0.12.7",
28 | "requirejs": "^2.3.5",
29 | "sketch": "^0.2.0",
30 | "yaml-js": "^0.2.3"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lufego/sketch-tokenizer/7c5bedccaae1467e98063b011c1f15a734c5ab79/sketch-tokenizer.sketchplugin/Contents/Resources/icon.png
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/get-border-color.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/get-border-color.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/get-border-color.js":
95 | /*!*********************************!*\
96 | !*** ./src/get-border-color.js ***!
97 | \*********************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | var Utils = __webpack_require__(/*! ./utils.js */ "./src/utils.js"); // My plugin (command shift s)
104 |
105 |
106 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
107 | var selection = context.selection;
108 | context.document.showMessage('Plugin 🏃');
109 |
110 | if (selection.length == 0) {
111 | return context.document.showMessage('🗝🌈: Please select an object');
112 | } // if its a text
113 |
114 |
115 | if (selection[0] instanceof MSTextLayer) {
116 | return context.document.showMessage('❌: Please use `Tokenizer > Get Tone` for texts');
117 | }
118 |
119 | var colorMapping = Utils.getBaseColorsVariablesMapping();
120 | var currentSelectedColor = Utils.getBorderHexColor(selection).toString().toUpperCase();
121 | var color = colorMapping["#" + currentSelectedColor];
122 |
123 | var callback = function callback() {
124 | return getBorderColorVariable(selection, color);
125 | }; // checks if color belongs to UI Kit, if not returns an error
126 |
127 |
128 | Utils.colorChecker(color, callback);
129 | });
130 |
131 | function getBorderColorVariable(selection, text) {
132 | // gets the position of selection
133 | var x = selection[0].frame().x();
134 | var selectedElementWidth = selection[0].frame().width();
135 | var midY = selection[0].frame().midY();
136 | var position = {
137 | x: x,
138 | y: midY - 30,
139 | width: selectedElementWidth
140 | };
141 | Utils.insertTokenText(position, 'Token', 'Border color: ', text, true);
142 | }
143 |
144 | /***/ }),
145 |
146 | /***/ "./src/utils.js":
147 | /*!**********************!*\
148 | !*** ./src/utils.js ***!
149 | \**********************/
150 | /*! exports provided: insertTokenText, createQuoteLine, createTextLayer, getTokenVariable, getFillHexColor, getBorderHexColor, getRGBColor, getHexValueFromColorVariable, colorChecker, getBaseColorsVariablesMapping */
151 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
152 |
153 | "use strict";
154 | __webpack_require__.r(__webpack_exports__);
155 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "insertTokenText", function() { return insertTokenText; });
156 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createQuoteLine", function() { return createQuoteLine; });
157 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextLayer", function() { return createTextLayer; });
158 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTokenVariable", function() { return getTokenVariable; });
159 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getFillHexColor", function() { return getFillHexColor; });
160 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBorderHexColor", function() { return getBorderHexColor; });
161 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRGBColor", function() { return getRGBColor; });
162 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHexValueFromColorVariable", function() { return getHexValueFromColorVariable; });
163 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "colorChecker", function() { return colorChecker; });
164 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBaseColorsVariablesMapping", function() { return getBaseColorsVariablesMapping; });
165 | var quoteColor = {
166 | r: 1,
167 | g: 0.369,
168 | b: 0.941,
169 | a: 1
170 | }; // UI Creators
171 |
172 | function insertTokenText(_ref, layerName, title, text) {
173 | var x = _ref.x,
174 | y = _ref.y,
175 | width = _ref.width;
176 | var isBorder = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
177 | var textWithToken = createTextLayer(layerName, title + text); // pass the position to the text layer to be inserted
178 |
179 | textWithToken.frame().x = x + width + 100;
180 | textWithToken.frame().midY = y; // pass the position to quote line
181 |
182 | createQuoteLine(x, y, width, isBorder); // add the layer to the artboar
183 |
184 | context.document.currentPage().addLayers([textWithToken]);
185 | }
186 | function createQuoteLine(x, y, elementWidth, isBorder) {
187 | // if its a border, we want the quote line to touch it, otherwise touch fill
188 | var touchOffset = isBorder ? 0 : 5; // if its a border, we want the quote line to start from the same point as fill quoted line
189 |
190 | var startPointOffset = isBorder ? 30 : 0;
191 | var path = NSBezierPath.bezierPath();
192 | path.moveToPoint(NSMakePoint(x + elementWidth - touchOffset, y + startPointOffset));
193 | path.lineToPoint(NSMakePoint(x + elementWidth + 90, y));
194 | var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));
195 | var border = shape.style().addStylePartOfType(1);
196 | border.color = MSColor.colorWithRGBADictionary(quoteColor);
197 | border.thickness = 1;
198 | context.document.currentPage().addLayers([shape]);
199 | }
200 | function createTextLayer(name, stringValue) {
201 | var textLayer = MSTextLayer.new();
202 | textLayer.stringValue = stringValue;
203 | textLayer.name = name;
204 | textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));
205 | return textLayer;
206 | } // Token getters
207 |
208 | function getTokenVariable(colorsMap, wholeObject, property, component, hexColor) {
209 | if (!colorsMap) {
210 | return context.document.showMessage('✋🏻❌: Please load a decisions base colors file before continuing');
211 | }
212 |
213 | if (!wholeObject) {
214 | return context.document.showMessage("\u270B\uD83C\uDFFB\u274C: Please load a decisions token file for ".concat(property, " before continuing"));
215 | }
216 |
217 | var prefix = '--token'; // if property has `-`, splits it
218 |
219 | var hasDash = /-/;
220 | var propertyPrefix = hasDash.test(property) ? property.split('-') : property; // gets the color from selected element
221 |
222 | var selectedColor = colorsMap[hexColor].replace('--color-', '');
223 | var states;
224 | var propertyName;
225 |
226 | if (propertyPrefix instanceof Array) {
227 | states = wholeObject['token'][propertyPrefix[0]][propertyPrefix[1]][component];
228 | propertyName = "".concat(propertyPrefix[0], "-").concat(propertyPrefix[1]);
229 | } else {
230 | states = wholeObject['token'][propertyPrefix][component];
231 | propertyName = propertyPrefix;
232 | }
233 |
234 | var selectedState = Object.keys(states).find(function (state) {
235 | return states[state] == selectedColor;
236 | });
237 | return "".concat(prefix, "-").concat(propertyName, "-").concat(component, "-").concat(selectedState);
238 | } // Base color getters
239 |
240 | function getFillHexColor(selection) {
241 | var layer = context.selection[0];
242 | var selectedColor = getRGBColor('fill', layer);
243 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
244 | return colorHex;
245 | }
246 | function getBorderHexColor(selection) {
247 | var layer = context.selection[0];
248 | var selectedColor = getRGBColor('border', layer);
249 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
250 | return colorHex;
251 | }
252 | function getRGBColor(type, layer) {
253 | var color;
254 |
255 | if (type === 'fill') {
256 | if (layer instanceof MSTextLayer) {
257 | color = layer.textColor();
258 | } else {
259 | color = layer.style().fills().firstObject().color();
260 | }
261 | } else {
262 | color = layer.style().borders().firstObject().color();
263 | }
264 |
265 | return color;
266 | }
267 | function getHexValueFromColorVariable(colorVar, baseColorsVariablesMap) {
268 | var colorVarWithPrefix = "--color-".concat(colorVar);
269 | return Object.keys(baseColorsVariablesMap).find(function (hexVal) {
270 | if (baseColorsVariablesMap[hexVal] == colorVarWithPrefix) return hexVal;
271 | });
272 | } // Checkers
273 |
274 | function colorChecker(color, callback) {
275 | if (typeof color === 'undefined') {
276 | return context.document.showMessage('🎨🚫: Non UI Kit color. Please make sure to use a valid color');
277 | } else {
278 | return callback();
279 | }
280 | } // General scripts
281 |
282 | function getBaseColorsVariablesMapping() {
283 | // Gets the json data stored in global state
284 | var threadDictionary = NSThread.mainThread().threadDictionary();
285 | var importedBaseColors = threadDictionary.importedBaseColors;
286 | if (!importedBaseColors) return context.document.showMessage('🗃👎🏻 No file imported. Please import your base colors file in `Import base colors file...`');
287 | var colorNames = {}; // gets default color variables
288 |
289 | Object.keys(importedBaseColors).map(function (colorGroupName) {
290 | // console.log('colorGroupName', colorGroupName)
291 | var colorGroup = importedBaseColors[colorGroupName];
292 | var colorDefaultName = colorGroup.default;
293 | colorNames[colorDefaultName.toString().toUpperCase()] = '--color-' + colorGroupName; // console.log('colorGroup.default', colorGroup.default);
294 |
295 | Object.keys(colorGroup).forEach(function (variation) {
296 | // filters out default values
297 | if (variation !== 'default') {
298 | var variationName = colorGroup[variation];
299 | var variationNameWithoutPercetageSign = variationName.toString().replace('%', ''); // console.log('colorGroup.default', colorGroup.default)
300 |
301 | colorNames[transformColorLightness(colorGroup.default, variationNameWithoutPercetageSign).toUpperCase()] = '--color-' + colorGroupName + '-' + variation;
302 | }
303 | });
304 | });
305 | return colorNames;
306 | } // Color converters
307 |
308 | function transformColorLightness(hex, lightness) {
309 | var hslColor = hexToHsl(hex, lightness);
310 | var hexColor = hslToHex(hslColor);
311 | console.log('hexColor', hexColor);
312 | return hexColor;
313 | }
314 |
315 | function hexToHsl(hex, lightness) {
316 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
317 | var r = parseInt(result[1], 16);
318 | var g = parseInt(result[2], 16);
319 | var b = parseInt(result[3], 16);
320 | r /= 255, g /= 255, b /= 255;
321 | var max = Math.max(r, g, b),
322 | min = Math.min(r, g, b);
323 | var h,
324 | s,
325 | l = (max + min) / 2;
326 |
327 | if (max == min) {
328 | h = s = 0; // achromatic
329 | } else {
330 | var d = max - min;
331 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
332 |
333 | switch (max) {
334 | case r:
335 | h = (g - b) / d + (g < b ? 6 : 0);
336 | break;
337 |
338 | case g:
339 | h = (b - r) / d + 2;
340 | break;
341 |
342 | case b:
343 | h = (r - g) / d + 4;
344 | break;
345 | }
346 |
347 | h /= 6;
348 | }
349 |
350 | h = Math.round(360 * h);
351 | s = s * 100;
352 | s = Math.round(s);
353 | l = l * 100;
354 | l = lightness ? lightness : Math.round(l);
355 | return [h, s, l];
356 | }
357 |
358 | function hslToHex(hsl) {
359 | var rgbColor = hslToRgb(hsl[0], hsl[1], hsl[2]);
360 | var r = rgbColor[0];
361 | var g = rgbColor[1];
362 | var b = rgbColor[2]; // console.log('rgb', r, g, b)
363 |
364 | return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
365 | }
366 |
367 | function hslToRgb(h, s, l) {
368 | var m1, m2, hue;
369 | s = s / 100;
370 | l = l / 100;
371 | var r, g, b;
372 | if (s == 0) r = g = b = l * 255;else {
373 | m2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
374 | m1 = 2 * l - m2;
375 | hue = h / 360;
376 | r = hue2rgb(m1, m2, hue + 1 / 3);
377 | g = hue2rgb(m1, m2, hue);
378 | b = hue2rgb(m1, m2, hue - 1 / 3);
379 | }
380 |
381 | function multiplyBy255(num) {
382 | return num * 255;
383 | }
384 |
385 | if (r < 1 || g < 1 || b < 1) {
386 | r = multiplyBy255(r);
387 | g = multiplyBy255(g);
388 | b = multiplyBy255(b);
389 | }
390 |
391 | console.log('rgb', Math.round(r), Math.round(g), Math.round(b));
392 | return [Math.round(r), Math.round(g), Math.round(b)];
393 | }
394 |
395 | function hue2rgb(m1, m2, hue) {
396 | if (hue < 0) hue += 1;
397 | if (hue > 1) hue -= 1;
398 | if (hue < 1 / 6) return m1 + (m2 - m1) * 6 * hue;
399 | if (hue < 1 / 2) return m2;
400 | if (hue < 2 / 3) return m1 + (m2 - m1) * (2 / 3 - hue) * 6;
401 | return m1;
402 | }
403 |
404 | /***/ })
405 |
406 | /******/ });
407 | if (key === 'default' && typeof exports === 'function') {
408 | exports(context);
409 | } else {
410 | exports[key](context);
411 | }
412 | }
413 | that['onRun'] = __skpm_run.bind(this, 'default')
414 |
415 | //# sourceMappingURL=get-border-color.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/get-border-color.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/get-border-color.js","webpack://exports/./src/utils.js"],"names":["Utils","require","context","selection","document","showMessage","length","MSTextLayer","colorMapping","getBaseColorsVariablesMapping","currentSelectedColor","getBorderHexColor","toString","toUpperCase","color","callback","getBorderColorVariable","colorChecker","text","x","frame","selectedElementWidth","width","midY","position","y","insertTokenText","quoteColor","r","g","b","a","layerName","title","isBorder","textWithToken","createTextLayer","createQuoteLine","currentPage","addLayers","elementWidth","touchOffset","startPointOffset","path","NSBezierPath","bezierPath","moveToPoint","NSMakePoint","lineToPoint","shape","MSShapeGroup","shapeWithBezierPath","MSPath","pathWithBezierPath","border","style","addStylePartOfType","MSColor","colorWithRGBADictionary","thickness","name","stringValue","textLayer","new","setTextColor","getTokenVariable","colorsMap","wholeObject","property","component","hexColor","prefix","hasDash","propertyPrefix","test","split","selectedColor","replace","states","propertyName","Array","selectedState","Object","keys","find","state","getFillHexColor","layer","getRGBColor","colorHex","immutableModelObject","hexValue","type","textColor","fills","firstObject","borders","getHexValueFromColorVariable","colorVar","baseColorsVariablesMap","colorVarWithPrefix","hexVal","threadDictionary","NSThread","mainThread","importedBaseColors","colorNames","map","colorGroup","colorGroupName","colorDefaultName","default","forEach","variation","variationName","variationNameWithoutPercetageSign","transformColorLightness","hex","lightness","hslColor","hexToHsl","hslToHex","console","log","result","exec","parseInt","max","Math","min","h","s","l","d","round","hsl","rgbColor","hslToRgb","slice","m1","m2","hue","hue2rgb","multiplyBy255","num"],"mappings":"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","file":"get-border-color.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/get-border-color.js\");\n","const Utils = require('./utils.js')\n\n// My plugin (command shift s)\nexport default function(context) {\n var selection = context.selection;\n context.document.showMessage('Plugin 🏃');\n\n if (selection.length == 0) {\n return context.document.showMessage('🗝🌈: Please select an object');\n }\n // if its a text\n if (selection[0] instanceof MSTextLayer) {\n return context.document.showMessage('❌: Please use `Tokenizer > Get Tone` for texts');\n }\n \n const colorMapping = Utils.getBaseColorsVariablesMapping()\n const currentSelectedColor = Utils.getBorderHexColor(selection).toString().toUpperCase();\n \n \n const color = colorMapping[\"#\" + currentSelectedColor];\n \n const callback = () => getBorderColorVariable(selection, color);\n\n // checks if color belongs to UI Kit, if not returns an error\n Utils.colorChecker(color, callback)\n}\n\n\n\n\nfunction getBorderColorVariable(selection, text) {\n // gets the position of selection\n var x = selection[0].frame().x();\n var selectedElementWidth = selection[0].frame().width();\n var midY =selection[0].frame().midY();\n\n const position = {\n x, y: midY - 30, width: selectedElementWidth\n }\n Utils.insertTokenText(position, 'Token', 'Border color: ', text, true)\n}\n","const quoteColor = { r: 1, g: 0.369, b: 0.941, a: 1 };\n\n// UI Creators\n\nexport function insertTokenText(\n { x, y, width },\n layerName,\n title,\n text,\n isBorder = false\n) {\n const textWithToken = createTextLayer(layerName, title + text);\n // pass the position to the text layer to be inserted\n textWithToken.frame().x = x + width + 100;\n textWithToken.frame().midY = y;\n\n // pass the position to quote line\n createQuoteLine(x, y, width, isBorder);\n\n // add the layer to the artboar\n context.document.currentPage().addLayers([textWithToken]);\n}\n\nexport function createQuoteLine(x, y, elementWidth, isBorder) {\n // if its a border, we want the quote line to touch it, otherwise touch fill\n const touchOffset = isBorder ? 0 : 5;\n\n // if its a border, we want the quote line to start from the same point as fill quoted line\n const startPointOffset = isBorder ? 30 : 0;\n var path = NSBezierPath.bezierPath();\n path.moveToPoint(\n NSMakePoint(x + elementWidth - touchOffset, y + startPointOffset)\n );\n path.lineToPoint(NSMakePoint(x + elementWidth + 90, y));\n\n var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));\n var border = shape.style().addStylePartOfType(1);\n border.color = MSColor.colorWithRGBADictionary(quoteColor);\n border.thickness = 1;\n\n context.document.currentPage().addLayers([shape]);\n}\n\nexport function createTextLayer(name, stringValue) {\n var textLayer = MSTextLayer.new();\n textLayer.stringValue = stringValue;\n textLayer.name = name;\n textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));\n return textLayer;\n}\n\n// Token getters\n\nexport function getTokenVariable(\n colorsMap,\n wholeObject,\n property,\n component,\n hexColor\n) {\n if (!colorsMap) {\n return context.document.showMessage(\n '✋🏻❌: Please load a decisions base colors file before continuing'\n );\n }\n\n if (!wholeObject) {\n return context.document.showMessage(\n `✋🏻❌: Please load a decisions token file for ${property} before continuing`\n );\n }\n\n const prefix = '--token';\n\n // if property has `-`, splits it\n const hasDash = /-/;\n const propertyPrefix = hasDash.test(property)\n ? property.split('-')\n : property;\n\n // gets the color from selected element\n const selectedColor = colorsMap[hexColor].replace('--color-', '');\n\n let states;\n let propertyName;\n if (propertyPrefix instanceof Array) {\n states =\n wholeObject['token'][propertyPrefix[0]][propertyPrefix[1]][component];\n propertyName = `${propertyPrefix[0]}-${propertyPrefix[1]}`;\n } else {\n states = wholeObject['token'][propertyPrefix][component];\n propertyName = propertyPrefix;\n }\n\n const selectedState = Object.keys(states).find(\n state => states[state] == selectedColor\n );\n\n return `${prefix}-${propertyName}-${component}-${selectedState}`;\n}\n\n// Base color getters\n\nexport function getFillHexColor(selection) {\n var layer = context.selection[0];\n var selectedColor = getRGBColor('fill', layer);\n var colorHex = selectedColor\n .immutableModelObject()\n .hexValue()\n .toString();\n return colorHex;\n}\n\nexport function getBorderHexColor(selection) {\n var layer = context.selection[0];\n var selectedColor = getRGBColor('border', layer);\n var colorHex = selectedColor\n .immutableModelObject()\n .hexValue()\n .toString();\n return colorHex;\n}\n\nexport function getRGBColor(type, layer) {\n var color;\n\n if (type === 'fill') {\n if (layer instanceof MSTextLayer) {\n color = layer.textColor();\n } else {\n color = layer\n .style()\n .fills()\n .firstObject()\n .color();\n }\n } else {\n color = layer\n .style()\n .borders()\n .firstObject()\n .color();\n }\n\n return color;\n}\n\nexport function getHexValueFromColorVariable(colorVar, baseColorsVariablesMap) {\n const colorVarWithPrefix = `--color-${colorVar}`;\n return Object.keys(baseColorsVariablesMap).find(hexVal => {\n if (baseColorsVariablesMap[hexVal] == colorVarWithPrefix) return hexVal;\n });\n}\n\n// Checkers\n\nexport function colorChecker(color, callback) {\n if (typeof color === 'undefined') {\n return context.document.showMessage(\n '🎨🚫: Non UI Kit color. Please make sure to use a valid color'\n );\n } else {\n return callback();\n }\n}\n\n// General scripts\n\nexport function getBaseColorsVariablesMapping() {\n // Gets the json data stored in global state\n let threadDictionary = NSThread.mainThread().threadDictionary();\n let importedBaseColors = threadDictionary.importedBaseColors;\n if (!importedBaseColors)\n return context.document.showMessage(\n '🗃👎🏻 No file imported. Please import your base colors file in `Import base colors file...`'\n );\n\n const colorNames = {};\n // gets default color variables\n Object.keys(importedBaseColors).map(colorGroupName => {\n // console.log('colorGroupName', colorGroupName)\n const colorGroup = importedBaseColors[colorGroupName];\n const colorDefaultName = colorGroup.default;\n colorNames[colorDefaultName.toString().toUpperCase()] =\n '--color-' + colorGroupName;\n\n // console.log('colorGroup.default', colorGroup.default);\n\n Object.keys(colorGroup).forEach(variation => {\n // filters out default values\n if (variation !== 'default') {\n const variationName = colorGroup[variation];\n const variationNameWithoutPercetageSign = variationName\n .toString()\n .replace('%', '');\n // console.log('colorGroup.default', colorGroup.default)\n colorNames[\n transformColorLightness(\n colorGroup.default,\n variationNameWithoutPercetageSign\n ).toUpperCase()\n ] =\n '--color-' + colorGroupName + '-' + variation;\n }\n });\n });\n return colorNames;\n}\n\n// Color converters\n\nfunction transformColorLightness(hex, lightness) {\n const hslColor = hexToHsl(hex, lightness);\n const hexColor = hslToHex(hslColor);\n console.log('hexColor', hexColor);\n return hexColor;\n}\n\nfunction hexToHsl(hex, lightness) {\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\n var r = parseInt(result[1], 16);\n var g = parseInt(result[2], 16);\n var b = parseInt(result[3], 16);\n\n (r /= 255), (g /= 255), (b /= 255);\n var max = Math.max(r, g, b),\n min = Math.min(r, g, b);\n var h,\n s,\n l = (max + min) / 2;\n\n if (max == min) {\n h = s = 0; // achromatic\n } else {\n var d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n\n h = Math.round(360 * h);\n s = s * 100;\n s = Math.round(s);\n l = l * 100;\n l = lightness ? lightness : Math.round(l);\n\n return [h, s, l];\n}\n\nfunction hslToHex(hsl) {\n const rgbColor = hslToRgb(hsl[0], hsl[1], hsl[2]);\n const r = rgbColor[0];\n const g = rgbColor[1];\n const b = rgbColor[2];\n\n // console.log('rgb', r, g, b)\n\n return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);\n}\n\nfunction hslToRgb(h, s, l) {\n var m1, m2, hue;\n s = s / 100;\n l = l / 100;\n var r, g, b;\n\n if (s == 0) r = g = b = l * 255;\n else {\n m2 = l < 0.5 ? l * (1 + s) : l + s - l * s;\n m1 = 2 * l - m2;\n hue = h / 360;\n\n r = hue2rgb(m1, m2, hue + 1 / 3);\n g = hue2rgb(m1, m2, hue);\n b = hue2rgb(m1, m2, hue - 1 / 3);\n }\n\n function multiplyBy255(num) {\n return num * 255;\n }\n\n if (r < 1 || g < 1 || b < 1) {\n r = multiplyBy255(r);\n g = multiplyBy255(g);\n b = multiplyBy255(b);\n }\n\n console.log('rgb', Math.round(r), Math.round(g), Math.round(b));\n\n return [Math.round(r), Math.round(g), Math.round(b)];\n}\n\nfunction hue2rgb(m1, m2, hue) {\n if (hue < 0) hue += 1;\n if (hue > 1) hue -= 1;\n if (hue < 1 / 6) return m1 + (m2 - m1) * 6 * hue;\n if (hue < 1 / 2) return m2;\n if (hue < 2 / 3) return m1 + (m2 - m1) * (2 / 3 - hue) * 6;\n return m1;\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/get-color-variable.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/get-color-variable.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/get-color-variable.js":
95 | /*!***********************************!*\
96 | !*** ./src/get-color-variable.js ***!
97 | \***********************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | // My plugin (command shift s)
104 | var colorVariables = {
105 | baseColors: {
106 | green: {
107 | default: "#14B39D",
108 | 25: "#0B8171",
109 | 40: "#19CCB3",
110 | 85: "#B4FFF6",
111 | 95: "#E6FFFC"
112 | },
113 | white: {
114 | default: "#FFFFFF"
115 | },
116 | navy: {
117 | default: "#1D3D45",
118 | 30: "#2E5768",
119 | 40: "#407A8B",
120 | 95: "#EEF4F6",
121 | 98: "#F9FBFB"
122 | },
123 | blue: {
124 | default: "#0090E0",
125 | 95: "#B2E3FF",
126 | 98: "#E5F6FF"
127 | },
128 | gray: {
129 | default: "#CCCCCC",
130 | 60: "#999999",
131 | 90: "#E6E6E6",
132 | 95: "#F2F2F2"
133 | },
134 | orange: {
135 | default: "#F1690E",
136 | 95: "#FEF0E7"
137 | },
138 | red: {
139 | default: "#E50051",
140 | 95: "#FFE5EE"
141 | },
142 | purple: {
143 | default: "#B26DFF"
144 | },
145 | black: {
146 | default: "#181818"
147 | }
148 | }
149 | };
150 | var quoteColor = {
151 | r: 1,
152 | g: 0.369,
153 | b: 0.941,
154 | a: 1
155 | };
156 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
157 | var selection = context.selection;
158 | context.document.showMessage('Plugin 🏃');
159 |
160 | if (selection.length == 0) {
161 | return context.document.showMessage('🗝🌈: Please select an object');
162 | }
163 |
164 | var colorMapping = getColorVariablesMapping(colorVariables);
165 | var currentSelectedColor = getFillHexColor(selection).toString().toUpperCase(); // if its a text
166 | // if (selection[0] instanceof MSTextLayer) {
167 | // const lay = createTextLayer('tone', 'tone: ' + 'NEGATIVE');
168 | // // gets the position of selection
169 | // var midX=context.selection[0].frame().midX();
170 | // var midY=context.selection[0].frame().midY();
171 | //
172 | // // pass the position to the text layer to be inserter
173 | // lay.frame().midX = midX;
174 | // lay.frame().midY = midY;
175 | // return context.document.currentPage().addLayers([lay]);
176 | // }
177 |
178 | var text = colorMapping["#" + currentSelectedColor]; // if its a shape
179 |
180 | getFillColorVariable(selection, text);
181 | });
182 |
183 | function insertTokenText(_ref, layerName, title, text) {
184 | var x = _ref.x,
185 | y = _ref.y,
186 | width = _ref.width;
187 | var textWithToken = createTextLayer(layerName, title + text); // pass the position to the text layer to be inserted
188 |
189 | textWithToken.frame().x = x + width + 100;
190 | textWithToken.frame().midY = y; // pass the position to quote line
191 |
192 | createQuoteLine(x, y, width); // add the layer to the artboar
193 |
194 | context.document.currentPage().addLayers([textWithToken]);
195 | }
196 |
197 | function getFillColorVariable(selection, text) {
198 | // gets the position of selection
199 | var x = selection[0].frame().x();
200 | var selectedElementWidth = selection[0].frame().width();
201 | var midY = selection[0].frame().midY();
202 | var position = {
203 | x: x,
204 | y: midY,
205 | width: selectedElementWidth
206 | };
207 | insertTokenText(position, 'Token', 'Fill color: ', text);
208 | }
209 |
210 | function createQuoteLine(x, y, elementWidth) {
211 | var path = NSBezierPath.bezierPath();
212 | path.moveToPoint(NSMakePoint(x + elementWidth - 5, y));
213 | path.lineToPoint(NSMakePoint(x + elementWidth + 90, y));
214 | var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));
215 | var border = shape.style().addStylePartOfType(1);
216 | border.color = MSColor.colorWithRGBADictionary(quoteColor);
217 | border.thickness = 1;
218 | context.document.currentPage().addLayers([shape]);
219 | }
220 |
221 | function getFillHexColor(selection) {
222 | var layer = context.selection[0];
223 | var selectedColor = getFillRGBColor("fill", layer);
224 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
225 | return colorHex;
226 | }
227 |
228 | function getFillRGBColor(type, layer) {
229 | var color;
230 |
231 | if (type === "fill") {
232 | if (layer instanceof MSTextLayer) {
233 | color = layer.textColor();
234 | } else {
235 | color = layer.style().fills().firstObject().color();
236 | }
237 | } else {
238 | color = layer.style().borders().firstObject().color();
239 | }
240 |
241 | return color;
242 | } // Hex to Color - helper function
243 |
244 |
245 | var hexToColor = function hexToColor(hex, alpha) {
246 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex),
247 | red = parseInt(result[1], 16) / 255,
248 | green = parseInt(result[2], 16) / 255,
249 | blue = parseInt(result[3], 16) / 255,
250 | alpha = typeof alpha !== 'undefined' ? alpha : 1;
251 | return NSColor.colorWithCalibratedRed_green_blue_alpha(red, green, blue, alpha);
252 | };
253 |
254 | function createTextLayer(name, stringValue) {
255 | var textLayer = MSTextLayer.new();
256 | textLayer.stringValue = stringValue;
257 | textLayer.name = name;
258 | textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));
259 | return textLayer;
260 | }
261 |
262 | function getColorVariablesMapping(variables) {
263 | var obj = variables.baseColors;
264 | var colorNames = {}; // gets default color variables
265 |
266 | Object.keys(obj).map(function (colorGroupName) {
267 | var colorGroup = obj[colorGroupName];
268 | colorNames[colorGroup.default] = '--color-' + colorGroupName;
269 | Object.keys(colorGroup).forEach(function (variation) {
270 | // filters out default values
271 | if (variation !== 'default') {
272 | colorNames[colorGroup[variation]] = '--color-' + colorGroupName + '-' + variation;
273 | }
274 | });
275 | });
276 | return colorNames;
277 | }
278 |
279 | /***/ })
280 |
281 | /******/ });
282 | if (key === 'default' && typeof exports === 'function') {
283 | exports(context);
284 | } else {
285 | exports[key](context);
286 | }
287 | }
288 | that['onRun'] = __skpm_run.bind(this, 'default')
289 |
290 | //# sourceMappingURL=get-color-variable.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/get-color-variable.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/get-color-variable.js"],"names":["colorVariables","baseColors","green","default","white","navy","blue","gray","orange","red","purple","black","quoteColor","r","g","b","a","context","selection","document","showMessage","length","colorMapping","getColorVariablesMapping","currentSelectedColor","getFillHexColor","toString","toUpperCase","text","getFillColorVariable","insertTokenText","layerName","title","x","y","width","textWithToken","createTextLayer","frame","midY","createQuoteLine","currentPage","addLayers","selectedElementWidth","position","elementWidth","path","NSBezierPath","bezierPath","moveToPoint","NSMakePoint","lineToPoint","shape","MSShapeGroup","shapeWithBezierPath","MSPath","pathWithBezierPath","border","style","addStylePartOfType","color","MSColor","colorWithRGBADictionary","thickness","layer","selectedColor","getFillRGBColor","colorHex","immutableModelObject","hexValue","type","MSTextLayer","textColor","fills","firstObject","borders","hexToColor","hex","alpha","result","exec","parseInt","NSColor","colorWithCalibratedRed_green_blue_alpha","name","stringValue","textLayer","new","setTextColor","variables","obj","colorNames","Object","keys","map","colorGroup","colorGroupName","forEach","variation"],"mappings":"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","file":"get-color-variable.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/get-color-variable.js\");\n","// My plugin (command shift s)\nconst colorVariables = {\n baseColors: {\n green: {\n default: \"#14B39D\",\n 25: \"#0B8171\",\n 40: \"#19CCB3\",\n 85: \"#B4FFF6\",\n 95: \"#E6FFFC\",\n },\n white: {\n default: \"#FFFFFF\"\n },\n navy: {\n default: \"#1D3D45\",\n 30: \"#2E5768\",\n 40: \"#407A8B\",\n 95: \"#EEF4F6\",\n 98 : \"#F9FBFB\"\n },\n blue: {\n default: \"#0090E0\",\n 95: \"#B2E3FF\",\n 98: \"#E5F6FF\"\n },\n gray: {\n default: \"#CCCCCC\",\n 60: \"#999999\",\n 90: \"#E6E6E6\",\n 95: \"#F2F2F2\"\n },\n orange: {\n default: \"#F1690E\",\n 95: \"#FEF0E7\"\n },\n red: {\n default: \"#E50051\",\n 95: \"#FFE5EE\"\n },\n purple: {\n default: \"#B26DFF\",\n },\n black: {\n default: \"#181818\",\n }\n }\n}\n\nconst quoteColor = {r: 1, g: 0.369, b: 0.941, a: 1}\n\nexport default function(context) {\n var selection = context.selection;\n context.document.showMessage('Plugin 🏃');\n\n if (selection.length == 0) {\n return context.document.showMessage('🗝🌈: Please select an object');\n }\n \n const colorMapping = getColorVariablesMapping(colorVariables)\n const currentSelectedColor = getFillHexColor(selection).toString().toUpperCase();\n \n // if its a text\n // if (selection[0] instanceof MSTextLayer) {\n // const lay = createTextLayer('tone', 'tone: ' + 'NEGATIVE');\n // // gets the position of selection\n // var midX=context.selection[0].frame().midX();\n // var midY=context.selection[0].frame().midY();\n // \n // // pass the position to the text layer to be inserter\n // lay.frame().midX = midX;\n // lay.frame().midY = midY;\n // return context.document.currentPage().addLayers([lay]);\n // }\n const text = colorMapping[\"#\" + currentSelectedColor];\n // if its a shape\n getFillColorVariable(selection, text)\n}\n\nfunction insertTokenText({x, y, width}, layerName, title, text) {\n const textWithToken = createTextLayer(layerName, title + text);\n // pass the position to the text layer to be inserted\n textWithToken.frame().x = x + width + 100;\n textWithToken.frame().midY = y;\n \n // pass the position to quote line\n createQuoteLine(x, y, width);\n\n // add the layer to the artboar\n context.document.currentPage().addLayers([textWithToken]);\n}\n\n\nfunction getFillColorVariable(selection, text) {\n // gets the position of selection\n var x = selection[0].frame().x();\n var selectedElementWidth = selection[0].frame().width();\n var midY =selection[0].frame().midY();\n\n const position = {\n x, y: midY, width: selectedElementWidth\n }\n insertTokenText(position, 'Token', 'Fill color: ', text)\n}\n\nfunction createQuoteLine(x, y, elementWidth) {\n var path = NSBezierPath.bezierPath();\n path.moveToPoint(NSMakePoint(x + elementWidth - 5, y));\n path.lineToPoint(NSMakePoint(x + elementWidth + 90, y));\n\n var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));\n var border = shape.style().addStylePartOfType(1);\n border.color = MSColor.colorWithRGBADictionary(quoteColor);\n border.thickness = 1;\n\n context.document.currentPage().addLayers([shape]);\n}\n\nfunction getFillHexColor(selection) {\n var layer = context.selection[0]\n var selectedColor = getFillRGBColor(\"fill\", layer)\n var colorHex = selectedColor.immutableModelObject().hexValue().toString()\n return colorHex\n}\n\nfunction getFillRGBColor (type, layer) {\n var color\n\n if (type === \"fill\") {\n if (layer instanceof MSTextLayer) {\n color = layer.textColor()\n } else {\n color = layer.style().fills().firstObject().color()\n }\n } else {\n color = layer.style().borders().firstObject().color()\n }\n\n return color\n}\n\n// Hex to Color - helper function\nvar hexToColor = function(hex, alpha) {\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex),\n red = parseInt(result[1], 16) / 255,\n green = parseInt(result[2], 16) / 255,\n blue = parseInt(result[3], 16) / 255,\n alpha = (typeof alpha !== 'undefined') ? alpha : 1;\n return NSColor.colorWithCalibratedRed_green_blue_alpha(red, green, blue, alpha)\n}\n\n\nfunction createTextLayer(name, stringValue) {\n var textLayer = MSTextLayer.new();\n textLayer.stringValue = stringValue\n textLayer.name = name\n textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor))\n return textLayer;\n}\n\nfunction getColorVariablesMapping(variables) {\n const obj = variables.baseColors\n const colorNames = {}\n // gets default color variables\n Object.keys(obj).map(colorGroupName => {\n const colorGroup = obj[colorGroupName]\n\n colorNames[colorGroup.default] = '--color-' + colorGroupName;\n\n Object.keys(colorGroup).forEach(variation => {\n // filters out default values\n if (variation !== 'default') {\n colorNames[colorGroup[variation]] = '--color-' + colorGroupName + '-' + variation;\n }\n })\n })\n\n return colorNames\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/get-fill-color.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/get-fill-color.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/get-fill-color.js":
95 | /*!*******************************!*\
96 | !*** ./src/get-fill-color.js ***!
97 | \*******************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | var Utils = __webpack_require__(/*! ./utils.js */ "./src/utils.js"); // My plugin (command shift s)
104 |
105 |
106 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
107 | var selection = context.selection;
108 | context.document.showMessage('Plugin 🏃');
109 |
110 | if (selection.length == 0) {
111 | return context.document.showMessage('🗝🌈: Please select an object');
112 | } // if its a text
113 |
114 |
115 | if (selection[0] instanceof MSTextLayer) {
116 | return context.document.showMessage('❌: Please use `Tokenizer > Get Tone` for texts');
117 | }
118 |
119 | var colorMapping = Utils.getBaseColorsVariablesMapping();
120 | console.log('colorMapping', colorMapping);
121 | var currentSelectedColor = Utils.getFillHexColor(selection).toString().toUpperCase();
122 | var color = colorMapping['#' + currentSelectedColor];
123 |
124 | var callback = function callback() {
125 | return getFillColorVariable(selection, color);
126 | }; // checks if color belongs to UI Kit, if not returns an error
127 |
128 |
129 | Utils.colorChecker(color, callback);
130 | });
131 |
132 | function getFillColorVariable(selection, text) {
133 | // gets the position of selection
134 | var x = selection[0].frame().x();
135 | var selectedElementWidth = selection[0].frame().width();
136 | var midY = selection[0].frame().midY();
137 | var position = {
138 | x: x,
139 | y: midY,
140 | width: selectedElementWidth
141 | };
142 | Utils.insertTokenText(position, 'Token', 'Fill color: ', text);
143 | }
144 |
145 | /***/ }),
146 |
147 | /***/ "./src/utils.js":
148 | /*!**********************!*\
149 | !*** ./src/utils.js ***!
150 | \**********************/
151 | /*! exports provided: insertTokenText, createQuoteLine, createTextLayer, getTokenVariable, getFillHexColor, getBorderHexColor, getRGBColor, getHexValueFromColorVariable, colorChecker, getBaseColorsVariablesMapping */
152 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
153 |
154 | "use strict";
155 | __webpack_require__.r(__webpack_exports__);
156 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "insertTokenText", function() { return insertTokenText; });
157 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createQuoteLine", function() { return createQuoteLine; });
158 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextLayer", function() { return createTextLayer; });
159 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTokenVariable", function() { return getTokenVariable; });
160 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getFillHexColor", function() { return getFillHexColor; });
161 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBorderHexColor", function() { return getBorderHexColor; });
162 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRGBColor", function() { return getRGBColor; });
163 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHexValueFromColorVariable", function() { return getHexValueFromColorVariable; });
164 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "colorChecker", function() { return colorChecker; });
165 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBaseColorsVariablesMapping", function() { return getBaseColorsVariablesMapping; });
166 | var quoteColor = {
167 | r: 1,
168 | g: 0.369,
169 | b: 0.941,
170 | a: 1
171 | }; // UI Creators
172 |
173 | function insertTokenText(_ref, layerName, title, text) {
174 | var x = _ref.x,
175 | y = _ref.y,
176 | width = _ref.width;
177 | var isBorder = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
178 | var textWithToken = createTextLayer(layerName, title + text); // pass the position to the text layer to be inserted
179 |
180 | textWithToken.frame().x = x + width + 100;
181 | textWithToken.frame().midY = y; // pass the position to quote line
182 |
183 | createQuoteLine(x, y, width, isBorder); // add the layer to the artboar
184 |
185 | context.document.currentPage().addLayers([textWithToken]);
186 | }
187 | function createQuoteLine(x, y, elementWidth, isBorder) {
188 | // if its a border, we want the quote line to touch it, otherwise touch fill
189 | var touchOffset = isBorder ? 0 : 5; // if its a border, we want the quote line to start from the same point as fill quoted line
190 |
191 | var startPointOffset = isBorder ? 30 : 0;
192 | var path = NSBezierPath.bezierPath();
193 | path.moveToPoint(NSMakePoint(x + elementWidth - touchOffset, y + startPointOffset));
194 | path.lineToPoint(NSMakePoint(x + elementWidth + 90, y));
195 | var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));
196 | var border = shape.style().addStylePartOfType(1);
197 | border.color = MSColor.colorWithRGBADictionary(quoteColor);
198 | border.thickness = 1;
199 | context.document.currentPage().addLayers([shape]);
200 | }
201 | function createTextLayer(name, stringValue) {
202 | var textLayer = MSTextLayer.new();
203 | textLayer.stringValue = stringValue;
204 | textLayer.name = name;
205 | textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));
206 | return textLayer;
207 | } // Token getters
208 |
209 | function getTokenVariable(colorsMap, wholeObject, property, component, hexColor) {
210 | if (!colorsMap) {
211 | return context.document.showMessage('✋🏻❌: Please load a decisions base colors file before continuing');
212 | }
213 |
214 | if (!wholeObject) {
215 | return context.document.showMessage("\u270B\uD83C\uDFFB\u274C: Please load a decisions token file for ".concat(property, " before continuing"));
216 | }
217 |
218 | var prefix = '--token'; // if property has `-`, splits it
219 |
220 | var hasDash = /-/;
221 | var propertyPrefix = hasDash.test(property) ? property.split('-') : property; // gets the color from selected element
222 |
223 | var selectedColor = colorsMap[hexColor].replace('--color-', '');
224 | var states;
225 | var propertyName;
226 |
227 | if (propertyPrefix instanceof Array) {
228 | states = wholeObject['token'][propertyPrefix[0]][propertyPrefix[1]][component];
229 | propertyName = "".concat(propertyPrefix[0], "-").concat(propertyPrefix[1]);
230 | } else {
231 | states = wholeObject['token'][propertyPrefix][component];
232 | propertyName = propertyPrefix;
233 | }
234 |
235 | var selectedState = Object.keys(states).find(function (state) {
236 | return states[state] == selectedColor;
237 | });
238 | return "".concat(prefix, "-").concat(propertyName, "-").concat(component, "-").concat(selectedState);
239 | } // Base color getters
240 |
241 | function getFillHexColor(selection) {
242 | var layer = context.selection[0];
243 | var selectedColor = getRGBColor('fill', layer);
244 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
245 | return colorHex;
246 | }
247 | function getBorderHexColor(selection) {
248 | var layer = context.selection[0];
249 | var selectedColor = getRGBColor('border', layer);
250 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
251 | return colorHex;
252 | }
253 | function getRGBColor(type, layer) {
254 | var color;
255 |
256 | if (type === 'fill') {
257 | if (layer instanceof MSTextLayer) {
258 | color = layer.textColor();
259 | } else {
260 | color = layer.style().fills().firstObject().color();
261 | }
262 | } else {
263 | color = layer.style().borders().firstObject().color();
264 | }
265 |
266 | return color;
267 | }
268 | function getHexValueFromColorVariable(colorVar, baseColorsVariablesMap) {
269 | var colorVarWithPrefix = "--color-".concat(colorVar);
270 | return Object.keys(baseColorsVariablesMap).find(function (hexVal) {
271 | if (baseColorsVariablesMap[hexVal] == colorVarWithPrefix) return hexVal;
272 | });
273 | } // Checkers
274 |
275 | function colorChecker(color, callback) {
276 | if (typeof color === 'undefined') {
277 | return context.document.showMessage('🎨🚫: Non UI Kit color. Please make sure to use a valid color');
278 | } else {
279 | return callback();
280 | }
281 | } // General scripts
282 |
283 | function getBaseColorsVariablesMapping() {
284 | // Gets the json data stored in global state
285 | var threadDictionary = NSThread.mainThread().threadDictionary();
286 | var importedBaseColors = threadDictionary.importedBaseColors;
287 | if (!importedBaseColors) return context.document.showMessage('🗃👎🏻 No file imported. Please import your base colors file in `Import base colors file...`');
288 | var colorNames = {}; // gets default color variables
289 |
290 | Object.keys(importedBaseColors).map(function (colorGroupName) {
291 | // console.log('colorGroupName', colorGroupName)
292 | var colorGroup = importedBaseColors[colorGroupName];
293 | var colorDefaultName = colorGroup.default;
294 | colorNames[colorDefaultName.toString().toUpperCase()] = '--color-' + colorGroupName; // console.log('colorGroup.default', colorGroup.default);
295 |
296 | Object.keys(colorGroup).forEach(function (variation) {
297 | // filters out default values
298 | if (variation !== 'default') {
299 | var variationName = colorGroup[variation];
300 | var variationNameWithoutPercetageSign = variationName.toString().replace('%', ''); // console.log('colorGroup.default', colorGroup.default)
301 |
302 | colorNames[transformColorLightness(colorGroup.default, variationNameWithoutPercetageSign).toUpperCase()] = '--color-' + colorGroupName + '-' + variation;
303 | }
304 | });
305 | });
306 | return colorNames;
307 | } // Color converters
308 |
309 | function transformColorLightness(hex, lightness) {
310 | var hslColor = hexToHsl(hex, lightness);
311 | var hexColor = hslToHex(hslColor);
312 | console.log('hexColor', hexColor);
313 | return hexColor;
314 | }
315 |
316 | function hexToHsl(hex, lightness) {
317 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
318 | var r = parseInt(result[1], 16);
319 | var g = parseInt(result[2], 16);
320 | var b = parseInt(result[3], 16);
321 | r /= 255, g /= 255, b /= 255;
322 | var max = Math.max(r, g, b),
323 | min = Math.min(r, g, b);
324 | var h,
325 | s,
326 | l = (max + min) / 2;
327 |
328 | if (max == min) {
329 | h = s = 0; // achromatic
330 | } else {
331 | var d = max - min;
332 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
333 |
334 | switch (max) {
335 | case r:
336 | h = (g - b) / d + (g < b ? 6 : 0);
337 | break;
338 |
339 | case g:
340 | h = (b - r) / d + 2;
341 | break;
342 |
343 | case b:
344 | h = (r - g) / d + 4;
345 | break;
346 | }
347 |
348 | h /= 6;
349 | }
350 |
351 | h = Math.round(360 * h);
352 | s = s * 100;
353 | s = Math.round(s);
354 | l = l * 100;
355 | l = lightness ? lightness : Math.round(l);
356 | return [h, s, l];
357 | }
358 |
359 | function hslToHex(hsl) {
360 | var rgbColor = hslToRgb(hsl[0], hsl[1], hsl[2]);
361 | var r = rgbColor[0];
362 | var g = rgbColor[1];
363 | var b = rgbColor[2]; // console.log('rgb', r, g, b)
364 |
365 | return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
366 | }
367 |
368 | function hslToRgb(h, s, l) {
369 | var m1, m2, hue;
370 | s = s / 100;
371 | l = l / 100;
372 | var r, g, b;
373 | if (s == 0) r = g = b = l * 255;else {
374 | m2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
375 | m1 = 2 * l - m2;
376 | hue = h / 360;
377 | r = hue2rgb(m1, m2, hue + 1 / 3);
378 | g = hue2rgb(m1, m2, hue);
379 | b = hue2rgb(m1, m2, hue - 1 / 3);
380 | }
381 |
382 | function multiplyBy255(num) {
383 | return num * 255;
384 | }
385 |
386 | if (r < 1 || g < 1 || b < 1) {
387 | r = multiplyBy255(r);
388 | g = multiplyBy255(g);
389 | b = multiplyBy255(b);
390 | }
391 |
392 | console.log('rgb', Math.round(r), Math.round(g), Math.round(b));
393 | return [Math.round(r), Math.round(g), Math.round(b)];
394 | }
395 |
396 | function hue2rgb(m1, m2, hue) {
397 | if (hue < 0) hue += 1;
398 | if (hue > 1) hue -= 1;
399 | if (hue < 1 / 6) return m1 + (m2 - m1) * 6 * hue;
400 | if (hue < 1 / 2) return m2;
401 | if (hue < 2 / 3) return m1 + (m2 - m1) * (2 / 3 - hue) * 6;
402 | return m1;
403 | }
404 |
405 | /***/ })
406 |
407 | /******/ });
408 | if (key === 'default' && typeof exports === 'function') {
409 | exports(context);
410 | } else {
411 | exports[key](context);
412 | }
413 | }
414 | that['onRun'] = __skpm_run.bind(this, 'default')
415 |
416 | //# sourceMappingURL=get-fill-color.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/get-fill-color.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/get-fill-color.js","webpack://exports/./src/utils.js"],"names":["Utils","require","context","selection","document","showMessage","length","MSTextLayer","colorMapping","getBaseColorsVariablesMapping","console","log","currentSelectedColor","getFillHexColor","toString","toUpperCase","color","callback","getFillColorVariable","colorChecker","text","x","frame","selectedElementWidth","width","midY","position","y","insertTokenText","quoteColor","r","g","b","a","layerName","title","isBorder","textWithToken","createTextLayer","createQuoteLine","currentPage","addLayers","elementWidth","touchOffset","startPointOffset","path","NSBezierPath","bezierPath","moveToPoint","NSMakePoint","lineToPoint","shape","MSShapeGroup","shapeWithBezierPath","MSPath","pathWithBezierPath","border","style","addStylePartOfType","MSColor","colorWithRGBADictionary","thickness","name","stringValue","textLayer","new","setTextColor","getTokenVariable","colorsMap","wholeObject","property","component","hexColor","prefix","hasDash","propertyPrefix","test","split","selectedColor","replace","states","propertyName","Array","selectedState","Object","keys","find","state","layer","getRGBColor","colorHex","immutableModelObject","hexValue","getBorderHexColor","type","textColor","fills","firstObject","borders","getHexValueFromColorVariable","colorVar","baseColorsVariablesMap","colorVarWithPrefix","hexVal","threadDictionary","NSThread","mainThread","importedBaseColors","colorNames","map","colorGroup","colorGroupName","colorDefaultName","default","forEach","variation","variationName","variationNameWithoutPercetageSign","transformColorLightness","hex","lightness","hslColor","hexToHsl","hslToHex","result","exec","parseInt","max","Math","min","h","s","l","d","round","hsl","rgbColor","hslToRgb","slice","m1","m2","hue","hue2rgb","multiplyBy255","num"],"mappings":"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","file":"get-fill-color.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/get-fill-color.js\");\n","const Utils = require('./utils.js');\n\n// My plugin (command shift s)\nexport default function(context) {\n var selection = context.selection;\n context.document.showMessage('Plugin 🏃');\n\n if (selection.length == 0) {\n return context.document.showMessage('🗝🌈: Please select an object');\n }\n // if its a text\n if (selection[0] instanceof MSTextLayer) {\n return context.document.showMessage(\n '❌: Please use `Tokenizer > Get Tone` for texts'\n );\n }\n\n const colorMapping = Utils.getBaseColorsVariablesMapping();\n console.log('colorMapping', colorMapping);\n const currentSelectedColor = Utils.getFillHexColor(selection)\n .toString()\n .toUpperCase();\n\n const color = colorMapping['#' + currentSelectedColor];\n\n const callback = () => getFillColorVariable(selection, color);\n\n // checks if color belongs to UI Kit, if not returns an error\n Utils.colorChecker(color, callback);\n}\n\nfunction getFillColorVariable(selection, text) {\n // gets the position of selection\n var x = selection[0].frame().x();\n var selectedElementWidth = selection[0].frame().width();\n var midY = selection[0].frame().midY();\n\n const position = {\n x,\n y: midY,\n width: selectedElementWidth\n };\n Utils.insertTokenText(position, 'Token', 'Fill color: ', text);\n}\n","const quoteColor = { r: 1, g: 0.369, b: 0.941, a: 1 };\n\n// UI Creators\n\nexport function insertTokenText(\n { x, y, width },\n layerName,\n title,\n text,\n isBorder = false\n) {\n const textWithToken = createTextLayer(layerName, title + text);\n // pass the position to the text layer to be inserted\n textWithToken.frame().x = x + width + 100;\n textWithToken.frame().midY = y;\n\n // pass the position to quote line\n createQuoteLine(x, y, width, isBorder);\n\n // add the layer to the artboar\n context.document.currentPage().addLayers([textWithToken]);\n}\n\nexport function createQuoteLine(x, y, elementWidth, isBorder) {\n // if its a border, we want the quote line to touch it, otherwise touch fill\n const touchOffset = isBorder ? 0 : 5;\n\n // if its a border, we want the quote line to start from the same point as fill quoted line\n const startPointOffset = isBorder ? 30 : 0;\n var path = NSBezierPath.bezierPath();\n path.moveToPoint(\n NSMakePoint(x + elementWidth - touchOffset, y + startPointOffset)\n );\n path.lineToPoint(NSMakePoint(x + elementWidth + 90, y));\n\n var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));\n var border = shape.style().addStylePartOfType(1);\n border.color = MSColor.colorWithRGBADictionary(quoteColor);\n border.thickness = 1;\n\n context.document.currentPage().addLayers([shape]);\n}\n\nexport function createTextLayer(name, stringValue) {\n var textLayer = MSTextLayer.new();\n textLayer.stringValue = stringValue;\n textLayer.name = name;\n textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));\n return textLayer;\n}\n\n// Token getters\n\nexport function getTokenVariable(\n colorsMap,\n wholeObject,\n property,\n component,\n hexColor\n) {\n if (!colorsMap) {\n return context.document.showMessage(\n '✋🏻❌: Please load a decisions base colors file before continuing'\n );\n }\n\n if (!wholeObject) {\n return context.document.showMessage(\n `✋🏻❌: Please load a decisions token file for ${property} before continuing`\n );\n }\n\n const prefix = '--token';\n\n // if property has `-`, splits it\n const hasDash = /-/;\n const propertyPrefix = hasDash.test(property)\n ? property.split('-')\n : property;\n\n // gets the color from selected element\n const selectedColor = colorsMap[hexColor].replace('--color-', '');\n\n let states;\n let propertyName;\n if (propertyPrefix instanceof Array) {\n states =\n wholeObject['token'][propertyPrefix[0]][propertyPrefix[1]][component];\n propertyName = `${propertyPrefix[0]}-${propertyPrefix[1]}`;\n } else {\n states = wholeObject['token'][propertyPrefix][component];\n propertyName = propertyPrefix;\n }\n\n const selectedState = Object.keys(states).find(\n state => states[state] == selectedColor\n );\n\n return `${prefix}-${propertyName}-${component}-${selectedState}`;\n}\n\n// Base color getters\n\nexport function getFillHexColor(selection) {\n var layer = context.selection[0];\n var selectedColor = getRGBColor('fill', layer);\n var colorHex = selectedColor\n .immutableModelObject()\n .hexValue()\n .toString();\n return colorHex;\n}\n\nexport function getBorderHexColor(selection) {\n var layer = context.selection[0];\n var selectedColor = getRGBColor('border', layer);\n var colorHex = selectedColor\n .immutableModelObject()\n .hexValue()\n .toString();\n return colorHex;\n}\n\nexport function getRGBColor(type, layer) {\n var color;\n\n if (type === 'fill') {\n if (layer instanceof MSTextLayer) {\n color = layer.textColor();\n } else {\n color = layer\n .style()\n .fills()\n .firstObject()\n .color();\n }\n } else {\n color = layer\n .style()\n .borders()\n .firstObject()\n .color();\n }\n\n return color;\n}\n\nexport function getHexValueFromColorVariable(colorVar, baseColorsVariablesMap) {\n const colorVarWithPrefix = `--color-${colorVar}`;\n return Object.keys(baseColorsVariablesMap).find(hexVal => {\n if (baseColorsVariablesMap[hexVal] == colorVarWithPrefix) return hexVal;\n });\n}\n\n// Checkers\n\nexport function colorChecker(color, callback) {\n if (typeof color === 'undefined') {\n return context.document.showMessage(\n '🎨🚫: Non UI Kit color. Please make sure to use a valid color'\n );\n } else {\n return callback();\n }\n}\n\n// General scripts\n\nexport function getBaseColorsVariablesMapping() {\n // Gets the json data stored in global state\n let threadDictionary = NSThread.mainThread().threadDictionary();\n let importedBaseColors = threadDictionary.importedBaseColors;\n if (!importedBaseColors)\n return context.document.showMessage(\n '🗃👎🏻 No file imported. Please import your base colors file in `Import base colors file...`'\n );\n\n const colorNames = {};\n // gets default color variables\n Object.keys(importedBaseColors).map(colorGroupName => {\n // console.log('colorGroupName', colorGroupName)\n const colorGroup = importedBaseColors[colorGroupName];\n const colorDefaultName = colorGroup.default;\n colorNames[colorDefaultName.toString().toUpperCase()] =\n '--color-' + colorGroupName;\n\n // console.log('colorGroup.default', colorGroup.default);\n\n Object.keys(colorGroup).forEach(variation => {\n // filters out default values\n if (variation !== 'default') {\n const variationName = colorGroup[variation];\n const variationNameWithoutPercetageSign = variationName\n .toString()\n .replace('%', '');\n // console.log('colorGroup.default', colorGroup.default)\n colorNames[\n transformColorLightness(\n colorGroup.default,\n variationNameWithoutPercetageSign\n ).toUpperCase()\n ] =\n '--color-' + colorGroupName + '-' + variation;\n }\n });\n });\n return colorNames;\n}\n\n// Color converters\n\nfunction transformColorLightness(hex, lightness) {\n const hslColor = hexToHsl(hex, lightness);\n const hexColor = hslToHex(hslColor);\n console.log('hexColor', hexColor);\n return hexColor;\n}\n\nfunction hexToHsl(hex, lightness) {\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\n var r = parseInt(result[1], 16);\n var g = parseInt(result[2], 16);\n var b = parseInt(result[3], 16);\n\n (r /= 255), (g /= 255), (b /= 255);\n var max = Math.max(r, g, b),\n min = Math.min(r, g, b);\n var h,\n s,\n l = (max + min) / 2;\n\n if (max == min) {\n h = s = 0; // achromatic\n } else {\n var d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n\n h = Math.round(360 * h);\n s = s * 100;\n s = Math.round(s);\n l = l * 100;\n l = lightness ? lightness : Math.round(l);\n\n return [h, s, l];\n}\n\nfunction hslToHex(hsl) {\n const rgbColor = hslToRgb(hsl[0], hsl[1], hsl[2]);\n const r = rgbColor[0];\n const g = rgbColor[1];\n const b = rgbColor[2];\n\n // console.log('rgb', r, g, b)\n\n return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);\n}\n\nfunction hslToRgb(h, s, l) {\n var m1, m2, hue;\n s = s / 100;\n l = l / 100;\n var r, g, b;\n\n if (s == 0) r = g = b = l * 255;\n else {\n m2 = l < 0.5 ? l * (1 + s) : l + s - l * s;\n m1 = 2 * l - m2;\n hue = h / 360;\n\n r = hue2rgb(m1, m2, hue + 1 / 3);\n g = hue2rgb(m1, m2, hue);\n b = hue2rgb(m1, m2, hue - 1 / 3);\n }\n\n function multiplyBy255(num) {\n return num * 255;\n }\n\n if (r < 1 || g < 1 || b < 1) {\n r = multiplyBy255(r);\n g = multiplyBy255(g);\n b = multiplyBy255(b);\n }\n\n console.log('rgb', Math.round(r), Math.round(g), Math.round(b));\n\n return [Math.round(r), Math.round(g), Math.round(b)];\n}\n\nfunction hue2rgb(m1, m2, hue) {\n if (hue < 0) hue += 1;\n if (hue > 1) hue -= 1;\n if (hue < 1 / 6) return m1 + (m2 - m1) * 6 * hue;\n if (hue < 1 / 2) return m2;\n if (hue < 2 / 3) return m1 + (m2 - m1) * (2 / 3 - hue) * 6;\n return m1;\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/import-base-colors-decisions-file.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/menu-import/import-base-colors-decisions-file.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/converters/colors.js":
95 | /*!**********************************!*\
96 | !*** ./src/converters/colors.js ***!
97 | \**********************************/
98 | /*! exports provided: transformColorLightness */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "transformColorLightness", function() { return transformColorLightness; });
104 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
105 |
106 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
107 |
108 | function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
109 |
110 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
111 |
112 | // Color converters
113 | function transformColorLightness(hex, lightness) {
114 | /* A bit of crazyness happening here;
115 | But this is the workflow from hsl_picker plugin to
116 | generate colors in sketch, so the same scheme is below */
117 | // HEXtoRGB => RgbToHsl => change light => HSLtoRGB => RGBtoHSL => HSLtoHEX
118 | var colorRgb = HEXtoRGB(hex);
119 | var colorHsl = RGBtoHSL(colorRgb, lightness);
120 | var colorRgbTransformed = HSLtoRGB(colorHsl);
121 | var colorHslTransformed = RGBtoHSL(colorRgbTransformed);
122 | var colorHex = HSLtoHEX(colorHslTransformed);
123 | return colorHex;
124 | }
125 |
126 | function HEXtoRGB(hex) {
127 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
128 | return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null;
129 | }
130 |
131 | function RGBtoHSL(_ref, lightness) {
132 | var _ref2 = _slicedToArray(_ref, 3),
133 | r = _ref2[0],
134 | g = _ref2[1],
135 | b = _ref2[2];
136 |
137 | r /= 255, g /= 255, b /= 255;
138 | var max = Math.max(r, g, b),
139 | min = Math.min(r, g, b);
140 | var h,
141 | s,
142 | l = (max + min) / 2;
143 |
144 | if (max == min) {
145 | h = s = 0; // achromatic
146 | } else {
147 | var d = max - min;
148 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
149 |
150 | switch (max) {
151 | case r:
152 | h = (g - b) / d + (g < b ? 6 : 0);
153 | break;
154 |
155 | case g:
156 | h = (b - r) / d + 2;
157 | break;
158 |
159 | case b:
160 | h = (r - g) / d + 4;
161 | break;
162 | }
163 |
164 | h /= 6;
165 | }
166 |
167 | return [Math.round(h * 360), Math.round(s * 100), lightness ? parseInt(lightness) : Math.round(l * 100)];
168 | }
169 |
170 | function HSLtoHEX(hsl) {
171 | var rgbColor = HSLtoRGB([hsl[0], hsl[1], hsl[2]]);
172 | var r = rgbColor[0];
173 | var g = rgbColor[1];
174 | var b = rgbColor[2]; // console.log('rgb', r, g, b)
175 |
176 | return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
177 | }
178 |
179 | function HSLtoRGB(_ref3) {
180 | var _ref4 = _slicedToArray(_ref3, 3),
181 | h = _ref4[0],
182 | s = _ref4[1],
183 | l = _ref4[2];
184 |
185 | var m1, m2, hue;
186 | s = s / 100;
187 | l = l / 100;
188 | var r, g, b;
189 | if (s == 0) r = g = b = l * 255;else {
190 | m2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
191 | m1 = 2 * l - m2;
192 | hue = h / 360;
193 | r = hue2rgb(m1, m2, hue + 1 / 3);
194 | g = hue2rgb(m1, m2, hue);
195 | b = hue2rgb(m1, m2, hue - 1 / 3);
196 | }
197 |
198 | function multiplyBy255(num) {
199 | return num * 255;
200 | }
201 |
202 | if (r < 1 || g < 1 || b < 1) {
203 | r = multiplyBy255(r);
204 | g = multiplyBy255(g);
205 | b = multiplyBy255(b);
206 | } // console.log('rgb', Math.round(r), Math.round(g), Math.round(b));
207 |
208 |
209 | return [Math.round(r), Math.round(g), Math.round(b)];
210 | } // Used inside HSLtoRGB function
211 |
212 |
213 | function hue2rgb(m1, m2, hue) {
214 | if (hue < 0) hue += 1;
215 | if (hue > 1) hue -= 1;
216 | if (hue < 1 / 6) return m1 + (m2 - m1) * 6 * hue;
217 | if (hue < 1 / 2) return m2;
218 | if (hue < 2 / 3) return m1 + (m2 - m1) * (2 / 3 - hue) * 6;
219 | return m1;
220 | }
221 |
222 | /***/ }),
223 |
224 | /***/ "./src/menu-import/import-base-colors-decisions-file.js":
225 | /*!**************************************************************!*\
226 | !*** ./src/menu-import/import-base-colors-decisions-file.js ***!
227 | \**************************************************************/
228 | /*! exports provided: default */
229 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
230 |
231 | "use strict";
232 | __webpack_require__.r(__webpack_exports__);
233 | var importFile = __webpack_require__(/*! ./../utils.js */ "./src/utils.js").importFile;
234 |
235 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
236 | var fileName = 'Base colors'; // the value global state will hold
237 |
238 | var objName = 'baseColors';
239 | importFile(fileName, objName);
240 | context.document.showMessage("\uD83D\uDCE9\uD83C\uDF89: File for ".concat(fileName, " imported! Ready to use!"));
241 | });
242 |
243 | /***/ }),
244 |
245 | /***/ "./src/utils.js":
246 | /*!**********************!*\
247 | !*** ./src/utils.js ***!
248 | \**********************/
249 | /*! exports provided: insertTokenText, insertIntoGroup, createQuoteLine, createTextLayer, getTokenVariable, getFillHexColor, getBorderHexColor, getRGBColor, getHexValueFromColorVariable, colorChecker, getBaseColorsVariablesMapping, importFile */
250 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
251 |
252 | "use strict";
253 | __webpack_require__.r(__webpack_exports__);
254 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "insertTokenText", function() { return insertTokenText; });
255 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "insertIntoGroup", function() { return insertIntoGroup; });
256 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createQuoteLine", function() { return createQuoteLine; });
257 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextLayer", function() { return createTextLayer; });
258 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTokenVariable", function() { return getTokenVariable; });
259 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getFillHexColor", function() { return getFillHexColor; });
260 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBorderHexColor", function() { return getBorderHexColor; });
261 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRGBColor", function() { return getRGBColor; });
262 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHexValueFromColorVariable", function() { return getHexValueFromColorVariable; });
263 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "colorChecker", function() { return colorChecker; });
264 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBaseColorsVariablesMapping", function() { return getBaseColorsVariablesMapping; });
265 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "importFile", function() { return importFile; });
266 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
267 |
268 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
269 |
270 | var ColorConverter = __webpack_require__(/*! ./converters/colors.js */ "./src/converters/colors.js");
271 |
272 | var quoteColor = {
273 | r: 1,
274 | g: 0.369,
275 | b: 0.941,
276 | a: 1
277 | };
278 | var lineHeight = 14;
279 | var lineWidth = 85; // UI Creators
280 |
281 | function insertTokenText(position, layerGroupName, title, text) {
282 | var isBorder = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
283 | var capitalizedTitle = title[0].toUpperCase() + title.slice(1);
284 | var textWithToken = createTextLayer("".concat(capitalizedTitle, ": ").concat(text));
285 | var quoteLine = createQuoteLine(position, isBorder); // var bounds = MSLayerGroup.groupBoundsForContainer(
286 | // MSLayerArray.arrayWithLayers([quoteLine, textWithToken])
287 | // );
288 |
289 | insertIntoGroup(layerGroupName, title, {
290 | text: textWithToken,
291 | line: quoteLine
292 | }, position, isBorder);
293 | }
294 | function insertIntoGroup(layerGroupName, property, layers, position, isBorder) {
295 | var groupLayer = MSLayerGroup.new(); // to simulate the heigt/width
296 |
297 | var bounds = MSLayerGroup.groupBoundsForContainer(MSLayerArray.arrayWithLayers([layers.line, layers.text])); // if its a border, we want the quote line to touch it, otherwise touch fill
298 |
299 | var touchOffset = isBorder ? 0 : 5; // if its a border TOKEN, we want the quote line to start from the same point as fill quoted line
300 |
301 | var startingPointOffset = isBorder ? lineHeight : 0; // spacing between line and text
302 |
303 | var spacing = 4; // moves the text a bit further from object
304 |
305 | layers.text.frame().x = lineWidth + spacing;
306 |
307 | if (isBorder) {
308 | layers.text.frame().y = -lineHeight;
309 | }
310 |
311 | groupLayer.name = "Token ".concat(property, " for ").concat(layerGroupName);
312 | groupLayer.layers = [layers.line, layers.text];
313 | groupLayer.resizeToFitChildrenWithOption(1);
314 | groupLayer.frame().x = position.x + position.width - touchOffset;
315 | groupLayer.frame().y = position.y + position.midY - bounds.size.height / 2 - startingPointOffset;
316 | var currentParentGroup = context.document.currentPage().currentArtboard() || context.document.currentPage();
317 | currentParentGroup.addLayers([groupLayer]);
318 | }
319 | function createQuoteLine(position, isBorder) {
320 | var lineHeightMidY = lineHeight / 2; // if its a border TOKEN, we want the quote line to start from the same point as fill quoted line
321 |
322 | var startingPointOffset = isBorder ? 15 : 0;
323 | var path = NSBezierPath.bezierPath();
324 | path.moveToPoint(NSMakePoint(lineWidth, lineHeightMidY - startingPointOffset));
325 | path.lineToPoint(NSMakePoint(0, lineHeightMidY));
326 | var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));
327 | var border = shape.style().addStylePartOfType(1);
328 | border.color = MSColor.colorWithRGBADictionary(quoteColor);
329 | border.thickness = 1;
330 | return shape;
331 | }
332 | function createTextLayer(stringValue) {
333 | var textLayer = MSTextLayer.new();
334 | textLayer.stringValue = stringValue;
335 | textLayer.name = 'Text';
336 | textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));
337 | return textLayer;
338 | } // Token getters
339 |
340 | function getTokenVariable(property, component, hexColor) {
341 | var baseColorsMap = getBaseColorsVariablesMapping();
342 | var prefix = '--token'; // if property has `-`, splits it
343 |
344 | var hasDash = /-/;
345 | var propertyPrefix = hasDash.test(property) ? property.split('-') : property;
346 | var states;
347 | var decisionsFile;
348 | var propertyName; // if the propery is passed with dash (E.g border-color)
349 |
350 | if (propertyPrefix instanceof Array) {
351 | decisionsFile = getDecisionsJson(propertyPrefix[0]);
352 |
353 | if (!decisionsFile) {
354 | return context.document.showMessage("\u270B\uD83C\uDFFB\u274C: Please load a decisions token file for ".concat(property, " before continuing"));
355 | }
356 |
357 | states = decisionsFile[propertyPrefix[1]][component];
358 | propertyName = "".concat(propertyPrefix[0], "-").concat(propertyPrefix[1]);
359 | } else {
360 | decisionsFile = getDecisionsJson(propertyPrefix);
361 |
362 | if (!decisionsFile) {
363 | return context.document.showMessage("\u270B\uD83C\uDFFB\u274C: Please load a decisions token file for ".concat(property, " before continuing"));
364 | }
365 |
366 | states = decisionsFile[propertyPrefix][component];
367 | propertyName = propertyPrefix;
368 | }
369 |
370 | if (!baseColorsMap) {
371 | return context.document.showMessage('✋🏻❌: Please load a decisions base colors file before continuing');
372 | } // gets the color from selected element
373 |
374 |
375 | var selectedColor = baseColorsMap[hexColor].replace('--color-', '');
376 | var selectedState = Object.keys(states).find(function (state) {
377 | return states[state] == selectedColor;
378 | });
379 |
380 | if (!selectedState) {
381 | return context.document.showMessage('🎨🚫: Non-recognized token color. Please make sure to use a valid color for this token');
382 | }
383 |
384 | return "".concat(prefix, "-").concat(propertyName, "-").concat(component, "-").concat(selectedState);
385 | } // Base color getters
386 |
387 | function getFillHexColor(selection) {
388 | var layer = context.selection[0];
389 | var selectedColor = getRGBColor('fill', layer);
390 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
391 | return colorHex;
392 | }
393 |
394 | function getDecisionsJson(object) {
395 | // Gets the json data stored in global state
396 | var threadDictionary = NSThread.mainThread().threadDictionary();
397 | var decisions = threadDictionary[object];
398 | return decisions;
399 | }
400 |
401 | function getBorderHexColor(selection) {
402 | var layer = context.selection[0];
403 | var selectedColor = getRGBColor('border', layer);
404 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
405 | return colorHex;
406 | }
407 | function getRGBColor(type, layer) {
408 | var color;
409 |
410 | if (type === 'fill') {
411 | if (layer instanceof MSTextLayer) {
412 | color = layer.textColor();
413 | } else {
414 | color = layer.style().fills().firstObject().color();
415 | }
416 | } else {
417 | color = layer.style().borders().firstObject().color();
418 | }
419 |
420 | return color;
421 | }
422 | function getHexValueFromColorVariable(colorVar, baseColorsVariablesMap) {
423 | var colorVarWithPrefix = "--color-".concat(colorVar);
424 | return Object.keys(baseColorsVariablesMap).find(function (hexVal) {
425 | if (baseColorsVariablesMap[hexVal] == colorVarWithPrefix) return hexVal;
426 | });
427 | } // Checkers
428 |
429 | function colorChecker(color, callback) {
430 | if (typeof color === 'undefined') {
431 | return context.document.showMessage('🎨🚫: Non UI Kit color. Please make sure to use a valid color');
432 | } else {
433 | return callback();
434 | }
435 | } // General scripts
436 |
437 | function getBaseColorsVariablesMapping() {
438 | // Gets the json data stored in global state
439 | var importedBaseColors = getDecisionsJson('baseColors');
440 | if (!importedBaseColors) return context.document.showMessage('🗃👎🏻 No file imported. Please import your base colors file in `Import base colors file...`');
441 | var colorNames = {}; // gets default color variables
442 |
443 | Object.keys(importedBaseColors).map(function (colorGroupName) {
444 | var colorGroup = importedBaseColors[colorGroupName];
445 | var colorDefaultName = colorGroup.default;
446 | colorNames[colorDefaultName.toString().toUpperCase()] = '--color-' + colorGroupName;
447 | Object.keys(colorGroup).forEach(function (variation) {
448 | // filters out default values
449 | if (variation !== 'default') {
450 | var variationName = colorGroup[variation];
451 | var variationNameWithoutPercetageSign = variationName.toString().replace('%', '');
452 | colorNames[ColorConverter.transformColorLightness(colorGroup.default, variationNameWithoutPercetageSign).toUpperCase()] = '--color-' + colorGroupName + '-' + variation;
453 | }
454 | });
455 | });
456 | return colorNames;
457 | } // importers
458 |
459 | function importFile(fileName, objName) {
460 | //ask for JSON file path, passing the last location if available
461 | var dataPath = askForJSON('lastJSONPath', fileName);
462 | if (!dataPath) return; //load json data
463 |
464 | var jsonData = loadJSONData(dataPath);
465 | if (!jsonData) return; //get root dir used when populating local images
466 |
467 | var jsonDir = NSString.stringWithString(dataPath).stringByDeletingLastPathComponent();
468 | var threadDictionary = NSThread.mainThread().threadDictionary();
469 | threadDictionary[objName] = _objectSpread({}, jsonData);
470 | }
471 |
472 | function askForJSON(path, fileName) {
473 | //create panel
474 | var panel = NSOpenPanel.openPanel(); //set panel properties
475 |
476 | panel.setTitle('Select JSON');
477 | panel.setMessage("Please select the JSON file for ".concat(fileName));
478 | panel.setPrompt('Select');
479 | panel.setCanCreateDirectories(false);
480 | panel.setCanChooseFiles(true);
481 | panel.setCanChooseDirectories(false);
482 | panel.setAllowsMultipleSelection(false);
483 | panel.setShowsHiddenFiles(false);
484 | panel.setExtensionHidden(false); //set initial panel path
485 |
486 | if (path) {
487 | panel.setDirectoryURL(NSURL.fileURLWithPath(path));
488 | } else {
489 | panel.setDirectoryURL(NSURL.fileURLWithPath('/Users/' + NSUserName()));
490 | } //show panel
491 |
492 |
493 | var pressedButton = panel.runModal();
494 |
495 | if (pressedButton == NSOKButton) {
496 | return panel.URL().path();
497 | }
498 | }
499 |
500 | function loadJSONData(path) {
501 | //load contents
502 | var contents = readFileAsText(path); //get data from JSON
503 |
504 | var data;
505 |
506 | try {
507 | data = JSON.parse(contents);
508 | } catch (e) {
509 | context.document.showMessage("There was an error parsing data. Please make sure it's valid.");
510 | return;
511 | }
512 |
513 | return data;
514 | }
515 |
516 | function readFileAsText(path) {
517 | return NSString.stringWithContentsOfFile_encoding_error(path, NSUTF8StringEncoding, false);
518 | }
519 |
520 | /***/ })
521 |
522 | /******/ });
523 | if (key === 'default' && typeof exports === 'function') {
524 | exports(context);
525 | } else {
526 | exports[key](context);
527 | }
528 | }
529 | that['onRun'] = __skpm_run.bind(this, 'default')
530 |
531 | //# sourceMappingURL=import-base-colors-decisions-file.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/import-base-colors.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/import-base-colors.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/import-base-colors.js":
95 | /*!***********************************!*\
96 | !*** ./src/import-base-colors.js ***!
97 | \***********************************/
98 | /*! exports provided: default, askForJSON, loadJSONData, readFileAsText */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "askForJSON", function() { return askForJSON; });
104 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "loadJSONData", function() { return loadJSONData; });
105 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readFileAsText", function() { return readFileAsText; });
106 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
107 |
108 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
109 |
110 | var baseColors;
111 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
112 | var selection = context.selection;
113 | context.document.showMessage('Plugin 🏃'); //ask for JSON file path, passing the last location if available
114 |
115 | var dataPath = askForJSON('lastJSONPath'); // console.log('dataPath', dataPath)
116 |
117 | if (!dataPath) return; //load json data
118 |
119 | var jsonData = loadJSONData(dataPath);
120 | if (!jsonData) return; //get root dir used when populating local images
121 |
122 | var jsonDir = NSString.stringWithString(dataPath).stringByDeletingLastPathComponent(); // console.log('jsonData', jsonData)
123 |
124 | var threadDictionary = NSThread.mainThread().threadDictionary();
125 | threadDictionary.importedBaseColors = _objectSpread({}, jsonData.baseColors);
126 | context.document.showMessage('📩🎉: File imported! Ready to use!');
127 | });
128 | function askForJSON(path) {
129 | //create panel
130 | var panel = NSOpenPanel.openPanel(); //set panel properties
131 |
132 | panel.setTitle("Select JSON");
133 | panel.setMessage("Please select the JSON file you'd like to use.");
134 | panel.setPrompt("Select");
135 | panel.setCanCreateDirectories(false);
136 | panel.setCanChooseFiles(true);
137 | panel.setCanChooseDirectories(false);
138 | panel.setAllowsMultipleSelection(false);
139 | panel.setShowsHiddenFiles(false);
140 | panel.setExtensionHidden(false); //set initial panel path
141 |
142 | if (path) {
143 | panel.setDirectoryURL(NSURL.fileURLWithPath(path));
144 | } else {
145 | panel.setDirectoryURL(NSURL.fileURLWithPath('/Users/' + NSUserName()));
146 | } //show panel
147 |
148 |
149 | var pressedButton = panel.runModal();
150 |
151 | if (pressedButton == NSOKButton) {
152 | return panel.URL().path();
153 | }
154 | }
155 | function loadJSONData(path) {
156 | //load contents
157 | var contents = readFileAsText(path); //get data from JSON
158 |
159 | var data;
160 |
161 | try {
162 | data = JSON.parse(contents);
163 | } catch (e) {
164 | context.document.showMessage("There was an error parsing data. Please make sure it's valid.");
165 | return;
166 | }
167 |
168 | return data;
169 | }
170 | function readFileAsText(path) {
171 | return NSString.stringWithContentsOfFile_encoding_error(path, NSUTF8StringEncoding, false);
172 | }
173 |
174 | /***/ })
175 |
176 | /******/ });
177 | if (key === 'default' && typeof exports === 'function') {
178 | exports(context);
179 | } else {
180 | exports[key](context);
181 | }
182 | }
183 | that['onRun'] = __skpm_run.bind(this, 'default')
184 |
185 | //# sourceMappingURL=import-base-colors.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/import-base-colors.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/import-base-colors.js"],"names":["baseColors","context","selection","document","showMessage","dataPath","askForJSON","jsonData","loadJSONData","jsonDir","NSString","stringWithString","stringByDeletingLastPathComponent","threadDictionary","NSThread","mainThread","importedBaseColors","path","panel","NSOpenPanel","openPanel","setTitle","setMessage","setPrompt","setCanCreateDirectories","setCanChooseFiles","setCanChooseDirectories","setAllowsMultipleSelection","setShowsHiddenFiles","setExtensionHidden","setDirectoryURL","NSURL","fileURLWithPath","NSUserName","pressedButton","runModal","NSOKButton","URL","contents","readFileAsText","data","JSON","parse","e","stringWithContentsOfFile_encoding_error","NSUTF8StringEncoding"],"mappings":"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","file":"import-base-colors.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/import-base-colors.js\");\n","let baseColors;\nexport default function(context) {\n var selection = context.selection;\n context.document.showMessage('Plugin 🏃');\n\n //ask for JSON file path, passing the last location if available\n let dataPath = askForJSON('lastJSONPath')\n // console.log('dataPath', dataPath)\n if (!dataPath) return\n\n //load json data\n let jsonData = loadJSONData(dataPath)\n if (!jsonData) return\n\n //get root dir used when populating local images\n let jsonDir = NSString.stringWithString(dataPath).stringByDeletingLastPathComponent()\n\n // console.log('jsonData', jsonData)\n\n let threadDictionary = NSThread.mainThread().threadDictionary();\n threadDictionary.importedBaseColors = {...jsonData.baseColors};\n\n context.document.showMessage('📩🎉: File imported! Ready to use!')\n}\n\nexport function askForJSON(path) {\n //create panel\n let panel = NSOpenPanel.openPanel()\n\n //set panel properties\n panel.setTitle(\"Select JSON\")\n panel.setMessage(\"Please select the JSON file you'd like to use.\")\n panel.setPrompt(\"Select\")\n panel.setCanCreateDirectories(false)\n panel.setCanChooseFiles(true)\n panel.setCanChooseDirectories(false)\n panel.setAllowsMultipleSelection(false)\n panel.setShowsHiddenFiles(false)\n panel.setExtensionHidden(false)\n\n //set initial panel path\n if (path) {\n panel.setDirectoryURL(NSURL.fileURLWithPath(path))\n }\n else {\n panel.setDirectoryURL(NSURL.fileURLWithPath('/Users/' + NSUserName()))\n }\n\n //show panel\n let pressedButton = panel.runModal()\n if (pressedButton == NSOKButton) {\n return panel.URL().path()\n }\n}\n\nexport function loadJSONData(path) {\n\n //load contents\n let contents = readFileAsText(path)\n\n //get data from JSON\n let data\n try {\n data = JSON.parse(contents)\n }\n catch (e) {\n context.document.showMessage(\"There was an error parsing data. Please make sure it's valid.\")\n return\n }\n\n return data\n}\n\nexport function readFileAsText(path) {\n return NSString.stringWithContentsOfFile_encoding_error(path, NSUTF8StringEncoding, false)\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/import-decisions-file.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/import-decisions-file.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/import-decisions-file.js":
95 | /*!**************************************!*\
96 | !*** ./src/import-decisions-file.js ***!
97 | \**************************************/
98 | /*! exports provided: default, askForJSON, loadJSONData, readFileAsText */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "askForJSON", function() { return askForJSON; });
104 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "loadJSONData", function() { return loadJSONData; });
105 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readFileAsText", function() { return readFileAsText; });
106 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
107 |
108 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
109 |
110 | var baseColors;
111 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
112 | var selection = context.selection;
113 | context.document.showMessage('Plugin 🏃'); //ask for JSON file path, passing the last location if available
114 |
115 | var dataPath = askForJSON('lastJSONPath'); // console.log('dataPath', dataPath)
116 |
117 | if (!dataPath) return; //load json data
118 |
119 | var jsonData = loadJSONData(dataPath);
120 | if (!jsonData) return; //get root dir used when populating local images
121 |
122 | var jsonDir = NSString.stringWithString(dataPath).stringByDeletingLastPathComponent(); // console.log('jsonData', jsonData)
123 |
124 | var threadDictionary = NSThread.mainThread().threadDictionary();
125 | threadDictionary.importedBaseColors = _objectSpread({}, jsonData.baseColors);
126 | context.document.showMessage('📩🎉: File imported! Ready to use!');
127 | });
128 | function askForJSON(path) {
129 | //create panel
130 | var panel = NSOpenPanel.openPanel(); //set panel properties
131 |
132 | panel.setTitle('Select JSON');
133 | panel.setMessage("Please select the JSON file you'd like to use.");
134 | panel.setPrompt('Select');
135 | panel.setCanCreateDirectories(false);
136 | panel.setCanChooseFiles(true);
137 | panel.setCanChooseDirectories(false);
138 | panel.setAllowsMultipleSelection(false);
139 | panel.setShowsHiddenFiles(false);
140 | panel.setExtensionHidden(false); //set initial panel path
141 |
142 | if (path) {
143 | panel.setDirectoryURL(NSURL.fileURLWithPath(path));
144 | } else {
145 | panel.setDirectoryURL(NSURL.fileURLWithPath('/Users/' + NSUserName()));
146 | } //show panel
147 |
148 |
149 | var pressedButton = panel.runModal();
150 |
151 | if (pressedButton == NSOKButton) {
152 | return panel.URL().path();
153 | }
154 | }
155 | function loadJSONData(path) {
156 | //load contents
157 | var contents = readFileAsText(path); //get data from JSON
158 |
159 | var data;
160 |
161 | try {
162 | data = JSON.parse(contents);
163 | } catch (e) {
164 | context.document.showMessage("There was an error parsing data. Please make sure it's valid.");
165 | return;
166 | }
167 |
168 | return data;
169 | }
170 | function readFileAsText(path) {
171 | return NSString.stringWithContentsOfFile_encoding_error(path, NSUTF8StringEncoding, false);
172 | }
173 |
174 | /***/ })
175 |
176 | /******/ });
177 | if (key === 'default' && typeof exports === 'function') {
178 | exports(context);
179 | } else {
180 | exports[key](context);
181 | }
182 | }
183 | that['onRun'] = __skpm_run.bind(this, 'default')
184 |
185 | //# sourceMappingURL=import-decisions-file.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/import-decisions-file.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/import-decisions-file.js"],"names":["baseColors","context","selection","document","showMessage","dataPath","askForJSON","jsonData","loadJSONData","jsonDir","NSString","stringWithString","stringByDeletingLastPathComponent","threadDictionary","NSThread","mainThread","importedBaseColors","path","panel","NSOpenPanel","openPanel","setTitle","setMessage","setPrompt","setCanCreateDirectories","setCanChooseFiles","setCanChooseDirectories","setAllowsMultipleSelection","setShowsHiddenFiles","setExtensionHidden","setDirectoryURL","NSURL","fileURLWithPath","NSUserName","pressedButton","runModal","NSOKButton","URL","contents","readFileAsText","data","JSON","parse","e","stringWithContentsOfFile_encoding_error","NSUTF8StringEncoding"],"mappings":"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","file":"import-decisions-file.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/import-decisions-file.js\");\n","let baseColors;\nexport default function(context) {\n var selection = context.selection;\n context.document.showMessage('Plugin 🏃');\n\n //ask for JSON file path, passing the last location if available\n let dataPath = askForJSON('lastJSONPath');\n // console.log('dataPath', dataPath)\n if (!dataPath) return;\n\n //load json data\n let jsonData = loadJSONData(dataPath);\n if (!jsonData) return;\n\n //get root dir used when populating local images\n let jsonDir = NSString.stringWithString(\n dataPath\n ).stringByDeletingLastPathComponent();\n\n // console.log('jsonData', jsonData)\n\n let threadDictionary = NSThread.mainThread().threadDictionary();\n threadDictionary.importedBaseColors = { ...jsonData.baseColors };\n\n context.document.showMessage('📩🎉: File imported! Ready to use!');\n}\n\nexport function askForJSON(path) {\n //create panel\n let panel = NSOpenPanel.openPanel();\n\n //set panel properties\n panel.setTitle('Select JSON');\n panel.setMessage(\"Please select the JSON file you'd like to use.\");\n panel.setPrompt('Select');\n panel.setCanCreateDirectories(false);\n panel.setCanChooseFiles(true);\n panel.setCanChooseDirectories(false);\n panel.setAllowsMultipleSelection(false);\n panel.setShowsHiddenFiles(false);\n panel.setExtensionHidden(false);\n\n //set initial panel path\n if (path) {\n panel.setDirectoryURL(NSURL.fileURLWithPath(path));\n } else {\n panel.setDirectoryURL(NSURL.fileURLWithPath('/Users/' + NSUserName()));\n }\n\n //show panel\n let pressedButton = panel.runModal();\n if (pressedButton == NSOKButton) {\n return panel.URL().path();\n }\n}\n\nexport function loadJSONData(path) {\n //load contents\n let contents = readFileAsText(path);\n\n //get data from JSON\n let data;\n try {\n data = JSON.parse(contents);\n } catch (e) {\n context.document.showMessage(\n \"There was an error parsing data. Please make sure it's valid.\"\n );\n return;\n }\n\n return data;\n}\n\nexport function readFileAsText(path) {\n return NSString.stringWithContentsOfFile_encoding_error(\n path,\n NSUTF8StringEncoding,\n false\n );\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "compatibleVersion": 3,
3 | "bundleVersion": 1,
4 | "icon": "icon.png",
5 | "commands": [
6 | {
7 | "name": "Fill color",
8 | "identifier": "base-fill-color",
9 | "shortcut": "ctrl shift w",
10 | "script": "get-base-fill-color.js"
11 | },
12 | {
13 | "name": "Border color",
14 | "identifier": "base-border-color",
15 | "shortcut": "ctrl shift b",
16 | "script": "get-base-border-color.js"
17 | },
18 | {
19 | "name": "Input",
20 | "identifier": "token-border-color-input",
21 | "script": "get-token-border-color-input.js"
22 | },
23 | {
24 | "name": "Input",
25 | "identifier": "token-background-color-input",
26 | "script": "get-token-background-color-input.js"
27 | },
28 | {
29 | "name": "Import base colors decisions file...",
30 | "identifier": "import-base-colors-decisions-file",
31 | "shortcut": "ctrl shift i",
32 | "script": "import-base-colors-decisions-file.js"
33 | },
34 | {
35 | "name": "Import borders decisions file...",
36 | "identifier": "import-token-borders-decisions-file",
37 | "script": "import-token-borders-decisions-file.js"
38 | },
39 | {
40 | "name": "Import backgrounds decisions file...",
41 | "identifier": "import-token-backgrounds-decisions-file",
42 | "script": "import-token-backgrounds-decisions-file.js"
43 | }
44 | ],
45 | "menu": {
46 | "title": "Tokenizer",
47 | "items": [
48 | {
49 | "title": "Load data",
50 | "items": [
51 | "import-base-colors-decisions-file",
52 | "import-token-borders-decisions-file",
53 | "import-token-backgrounds-decisions-file"
54 | ]
55 | },
56 | {
57 | "title": "Identify",
58 | "items": [
59 | {
60 | "title": "Base color",
61 | "items": [
62 | "base-fill-color",
63 | "base-border-color"
64 | ]
65 | },
66 | {
67 | "title": "Token",
68 | "items": [
69 | {
70 | "title": "Border color",
71 | "items": [
72 | "token-border-color-input"
73 | ]
74 | },
75 | {
76 | "title": "Background color",
77 | "items": [
78 | "token-background-color-input"
79 | ]
80 | }
81 | ]
82 | }
83 | ]
84 | }
85 | ]
86 | },
87 | "version": "0.1.0",
88 | "name": "sketch-tokenizer",
89 | "disableCocoaScriptPreprocessor": true,
90 | "appcast": "https://raw.githubusercontent.com//master/.appcast.xml",
91 | "author": "lufego",
92 | "authorEmail": "luis.gomes@commercetools.de"
93 | }
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/my-command.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/my-command.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/my-command.js":
95 | /*!***************************!*\
96 | !*** ./src/my-command.js ***!
97 | \***************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | // My plugin (command shift s)
104 | var colorVariables = {
105 | baseColors: {
106 | green: {
107 | default: "#14B39D",
108 | 25: "#0B8171",
109 | 40: "#19CCB3",
110 | 85: "#B4FFF6",
111 | 95: "#E6FFFC"
112 | },
113 | white: {
114 | default: "#FFFFFF"
115 | },
116 | navy: {
117 | default: "#1D3D45",
118 | 30: "#2E5768",
119 | 40: "#407A8B",
120 | 95: "#EEF4F6",
121 | 98: "#F9FBFB"
122 | },
123 | blue: {
124 | default: "#0090E0",
125 | 95: "#B2E3FF",
126 | 98: "#E5F6FF"
127 | },
128 | gray: {
129 | default: "#CCCCCC",
130 | 60: "#999999",
131 | 90: "#E6E6E6",
132 | 95: "#F2F2F2"
133 | },
134 | orange: {
135 | default: "#F1690E",
136 | 95: "#FEF0E7"
137 | },
138 | red: {
139 | default: "#E50051",
140 | 95: "#FFE5EE"
141 | },
142 | purple: {
143 | default: "#B26DFF"
144 | },
145 | black: {
146 | default: "#181818"
147 | }
148 | }
149 | };
150 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
151 | var selection = context.selection;
152 | context.document.showMessage('Plugin 🏃');
153 |
154 | if (selection.length == 0) {
155 | return context.document.showMessage('🗝🌈: Please select a layer');
156 | }
157 |
158 | if (selection[0] instanceof MSTextLayer) {
159 | var _lay = createTextLayer('tone', 'tone: ' + 'NEGATIVE'); // gets the position of selection
160 |
161 |
162 | var midX = context.selection[0].frame().midX();
163 | var midY = context.selection[0].frame().midY(); // pass the position to the text layer to be inserter
164 |
165 | _lay.frame().midX = midX;
166 | _lay.frame().midY = midY;
167 | return context.document.currentPage().addLayers([_lay]);
168 | }
169 |
170 | var colorMapping = getColorVariablesMapping(colorVariables);
171 | var currentSelectedColor = getFillHexColor(selection).toString().toUpperCase();
172 | var lay = createTextLayer('design', 'color: ' + colorMapping["#" + currentSelectedColor]); // gets the position of selection
173 |
174 | var midX = context.selection[0].frame().midX();
175 | var midY = context.selection[0].frame().midY(); // pass the position to the text layer to be inserter
176 |
177 | lay.frame().midX = midX;
178 | lay.frame().midY = midY; // add the layer to the artboar
179 |
180 | context.document.currentPage().addLayers([lay]);
181 | });
182 |
183 | function getFillHexColor(selection) {
184 | var layer = context.selection[0];
185 | var selectedColor = getFillRGBColor("fill", layer);
186 | var colorHex = selectedColor.immutableModelObject().hexValue().toString();
187 | return colorHex;
188 | }
189 |
190 | function getFillRGBColor(type, layer) {
191 | var color;
192 |
193 | if (type === "fill") {
194 | if (layer instanceof MSTextLayer) {
195 | color = layer.textColor();
196 | } else {
197 | color = layer.style().fills().firstObject().color();
198 | }
199 | } else {
200 | color = layer.style().borders().firstObject().color();
201 | }
202 |
203 | return color;
204 | } // Hex to Color - helper function
205 |
206 |
207 | var hexToColor = function hexToColor(hex, alpha) {
208 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex),
209 | red = parseInt(result[1], 16) / 255,
210 | green = parseInt(result[2], 16) / 255,
211 | blue = parseInt(result[3], 16) / 255,
212 | alpha = typeof alpha !== 'undefined' ? alpha : 1;
213 | return NSColor.colorWithCalibratedRed_green_blue_alpha(red, green, blue, alpha);
214 | };
215 |
216 | function createTextLayer(name, stringValue) {
217 | var textLayer = MSTextLayer.new();
218 | textLayer.stringValue = stringValue;
219 | textLayer.name = name;
220 | textLayer.setTextColor = hexToColor("CCCCCC");
221 | return textLayer;
222 | }
223 |
224 | function getColorVariablesMapping(variables) {
225 | var obj = variables.baseColors;
226 | var colorNames = {}; // gets default color variables
227 |
228 | Object.keys(obj).map(function (colorGroupName) {
229 | var colorGroup = obj[colorGroupName];
230 | colorNames[colorGroup.default] = '--color-' + colorGroupName;
231 | Object.keys(colorGroup).forEach(function (variation) {
232 | // filters out default values
233 | if (variation !== 'default') {
234 | colorNames[colorGroup[variation]] = '--color-' + colorGroupName + '-' + variation;
235 | }
236 | });
237 | });
238 | return colorNames;
239 | }
240 |
241 | /***/ })
242 |
243 | /******/ });
244 | if (key === 'default' && typeof exports === 'function') {
245 | exports(context);
246 | } else {
247 | exports[key](context);
248 | }
249 | }
250 | that['onRun'] = __skpm_run.bind(this, 'default')
251 |
252 | //# sourceMappingURL=my-command.js.map
--------------------------------------------------------------------------------
/sketch-tokenizer.sketchplugin/Contents/Sketch/my-command.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/my-command.js"],"names":["colorVariables","baseColors","green","default","white","navy","blue","gray","orange","red","purple","black","context","selection","document","showMessage","length","MSTextLayer","lay","createTextLayer","midX","frame","midY","currentPage","addLayers","colorMapping","getColorVariablesMapping","currentSelectedColor","getFillHexColor","toString","toUpperCase","layer","selectedColor","getFillRGBColor","colorHex","immutableModelObject","hexValue","type","color","textColor","style","fills","firstObject","borders","hexToColor","hex","alpha","result","exec","parseInt","NSColor","colorWithCalibratedRed_green_blue_alpha","name","stringValue","textLayer","new","setTextColor","variables","obj","colorNames","Object","keys","map","colorGroup","colorGroupName","forEach","variation"],"mappings":";;;;;;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;;AClFA;AAAA;AACA,IAAMA,iBAAiB;AACrBC,cAAY;AACVC,WAAO;AACLC,eAAS,SADJ;AAEL,UAAI,SAFC;AAGL,UAAI,SAHC;AAIL,UAAI,SAJC;AAKL,UAAI;AALC,KADG;AAQVC,WAAO;AACLD,eAAS;AADJ,KARG;AAWVE,UAAM;AACJF,eAAS,SADL;AAEJ,UAAI,SAFA;AAGJ,UAAI,SAHA;AAIJ,UAAI,SAJA;AAKJ,UAAK;AALD,KAXI;AAkBVG,UAAM;AACJH,eAAS,SADL;AAEJ,UAAI,SAFA;AAGJ,UAAI;AAHA,KAlBI;AAuBVI,UAAM;AACJJ,eAAS,SADL;AAEJ,UAAI,SAFA;AAGJ,UAAI,SAHA;AAIJ,UAAI;AAJA,KAvBI;AA6BVK,YAAQ;AACNL,eAAS,SADH;AAEN,UAAI;AAFE,KA7BE;AAiCVM,SAAK;AACHN,eAAS,SADN;AAEH,UAAI;AAFD,KAjCK;AAqCVO,YAAQ;AACNP,eAAS;AADH,KArCE;AAwCVQ,WAAO;AACLR,eAAS;AADJ;AAxCG;AADS,CAAvB;AA+CA,+DAAe,UAASS,OAAT,EAAkB;AAC/B,MAAIC,YAAYD,QAAQC,SAAxB;AACAD,UAAQE,QAAR,CAAiBC,WAAjB,CAA6B,WAA7B;;AAEA,MAAIF,UAAUG,MAAV,IAAoB,CAAxB,EAA2B;AACzB,WAAOJ,QAAQE,QAAR,CAAiBC,WAAjB,CAA6B,6BAA7B,CAAP;AACD;;AAED,MAAIF,UAAU,CAAV,aAAwBI,WAA5B,EAAyC;AACvC,QAAMC,OAAMC,gBAAgB,MAAhB,EAAwB,WAAW,UAAnC,CAAZ,CADuC,CAEvC;;;AACA,QAAIC,OAAKR,QAAQC,SAAR,CAAkB,CAAlB,EAAqBQ,KAArB,GAA6BD,IAA7B,EAAT;AACA,QAAIE,OAAKV,QAAQC,SAAR,CAAkB,CAAlB,EAAqBQ,KAArB,GAA6BC,IAA7B,EAAT,CAJuC,CAMvC;;AACAJ,SAAIG,KAAJ,GAAYD,IAAZ,GAAmBA,IAAnB;AACAF,SAAIG,KAAJ,GAAYC,IAAZ,GAAmBA,IAAnB;AACA,WAAOV,QAAQE,QAAR,CAAiBS,WAAjB,GAA+BC,SAA/B,CAAyC,CAACN,IAAD,CAAzC,CAAP;AACD;;AAED,MAAMO,eAAeC,yBAAyB1B,cAAzB,CAArB;AACA,MAAM2B,uBAAuBC,gBAAgBf,SAAhB,EAA2BgB,QAA3B,GAAsCC,WAAtC,EAA7B;AAGA,MAAMZ,MAAMC,gBAAgB,QAAhB,EAA0B,YAAYM,aAAa,MAAME,oBAAnB,CAAtC,CAAZ,CAxB+B,CA0B/B;;AACA,MAAIP,OAAKR,QAAQC,SAAR,CAAkB,CAAlB,EAAqBQ,KAArB,GAA6BD,IAA7B,EAAT;AACA,MAAIE,OAAKV,QAAQC,SAAR,CAAkB,CAAlB,EAAqBQ,KAArB,GAA6BC,IAA7B,EAAT,CA5B+B,CA8B/B;;AACAJ,MAAIG,KAAJ,GAAYD,IAAZ,GAAmBA,IAAnB;AACAF,MAAIG,KAAJ,GAAYC,IAAZ,GAAmBA,IAAnB,CAhC+B,CAkC/B;;AACAV,UAAQE,QAAR,CAAiBS,WAAjB,GAA+BC,SAA/B,CAAyC,CAACN,GAAD,CAAzC;AACD;;AAED,SAASU,eAAT,CAAyBf,SAAzB,EAAoC;AAClC,MAAIkB,QAAQnB,QAAQC,SAAR,CAAkB,CAAlB,CAAZ;AACA,MAAImB,gBAAgBC,gBAAgB,MAAhB,EAAwBF,KAAxB,CAApB;AACA,MAAIG,WAAWF,cAAcG,oBAAd,GAAqCC,QAArC,GAAgDP,QAAhD,EAAf;AACA,SAAOK,QAAP;AACD;;AAED,SAASD,eAAT,CAA0BI,IAA1B,EAAgCN,KAAhC,EAAuC;AACrC,MAAIO,KAAJ;;AAEA,MAAID,SAAS,MAAb,EAAqB;AACnB,QAAIN,iBAAiBd,WAArB,EAAkC;AAChCqB,cAAQP,MAAMQ,SAAN,EAAR;AACD,KAFD,MAEO;AACLD,cAAQP,MAAMS,KAAN,GAAcC,KAAd,GAAsBC,WAAtB,GAAoCJ,KAApC,EAAR;AACD;AACF,GAND,MAMO;AACLA,YAAQP,MAAMS,KAAN,GAAcG,OAAd,GAAwBD,WAAxB,GAAsCJ,KAAtC,EAAR;AACD;;AAED,SAAOA,KAAP;AACD,C,CAED;;;AACA,IAAIM,aAAa,SAAbA,UAAa,CAASC,GAAT,EAAcC,KAAd,EAAqB;AAClC,MAAIC,SAAS,4CAA4CC,IAA5C,CAAiDH,GAAjD,CAAb;AAAA,MACIpC,MAAMwC,SAASF,OAAO,CAAP,CAAT,EAAoB,EAApB,IAA0B,GADpC;AAAA,MAEI7C,QAAQ+C,SAASF,OAAO,CAAP,CAAT,EAAoB,EAApB,IAA0B,GAFtC;AAAA,MAGIzC,OAAO2C,SAASF,OAAO,CAAP,CAAT,EAAoB,EAApB,IAA0B,GAHrC;AAAA,MAIID,QAAS,OAAOA,KAAP,KAAiB,WAAlB,GAAiCA,KAAjC,GAAyC,CAJrD;AAKA,SAAOI,QAAQC,uCAAR,CAAgD1C,GAAhD,EAAqDP,KAArD,EAA4DI,IAA5D,EAAkEwC,KAAlE,CAAP;AACH,CAPD;;AAUA,SAAS3B,eAAT,CAAyBiC,IAAzB,EAA+BC,WAA/B,EAA4C;AACxC,MAAIC,YAAYrC,YAAYsC,GAAZ,EAAhB;AACAD,YAAUD,WAAV,GAAwBA,WAAxB;AACAC,YAAUF,IAAV,GAAiBA,IAAjB;AACAE,YAAUE,YAAV,GAAyBZ,WAAW,QAAX,CAAzB;AACA,SAAOU,SAAP;AACH;;AAED,SAAS5B,wBAAT,CAAkC+B,SAAlC,EAA6C;AAC3C,MAAMC,MAAMD,UAAUxD,UAAtB;AACA,MAAM0D,aAAa,EAAnB,CAF2C,CAG3C;;AACAC,SAAOC,IAAP,CAAYH,GAAZ,EAAiBI,GAAjB,CAAqB,0BAAkB;AACrC,QAAMC,aAAaL,IAAIM,cAAJ,CAAnB;AAEAL,eAAWI,WAAW5D,OAAtB,IAAiC,aAAa6D,cAA9C;AAEAJ,WAAOC,IAAP,CAAYE,UAAZ,EAAwBE,OAAxB,CAAgC,qBAAa;AAC3C;AACA,UAAIC,cAAc,SAAlB,EAA6B;AAC3BP,mBAAWI,WAAWG,SAAX,CAAX,IAAoC,aAAaF,cAAb,GAA8B,GAA9B,GAAoCE,SAAxE;AACD;AACF,KALD;AAMD,GAXD;AAaA,SAAOP,UAAP;AACD,C","file":"my-command.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/my-command.js\");\n","// My plugin (command shift s)\nconst colorVariables = {\n baseColors: {\n green: {\n default: \"#14B39D\",\n 25: \"#0B8171\",\n 40: \"#19CCB3\",\n 85: \"#B4FFF6\",\n 95: \"#E6FFFC\",\n },\n white: {\n default: \"#FFFFFF\"\n },\n navy: {\n default: \"#1D3D45\",\n 30: \"#2E5768\",\n 40: \"#407A8B\",\n 95: \"#EEF4F6\",\n 98 : \"#F9FBFB\"\n },\n blue: {\n default: \"#0090E0\",\n 95: \"#B2E3FF\",\n 98: \"#E5F6FF\"\n },\n gray: {\n default: \"#CCCCCC\",\n 60: \"#999999\",\n 90: \"#E6E6E6\",\n 95: \"#F2F2F2\"\n },\n orange: {\n default: \"#F1690E\",\n 95: \"#FEF0E7\"\n },\n red: {\n default: \"#E50051\",\n 95: \"#FFE5EE\"\n },\n purple: {\n default: \"#B26DFF\",\n },\n black: {\n default: \"#181818\",\n }\n }\n}\n\nexport default function(context) {\n var selection = context.selection;\n context.document.showMessage('Plugin 🏃');\n\n if (selection.length == 0) {\n return context.document.showMessage('🗝🌈: Please select a layer');\n }\n\n if (selection[0] instanceof MSTextLayer) {\n const lay = createTextLayer('tone', 'tone: ' + 'NEGATIVE');\n // gets the position of selection\n var midX=context.selection[0].frame().midX();\n var midY=context.selection[0].frame().midY();\n\n // pass the position to the text layer to be inserter\n lay.frame().midX = midX;\n lay.frame().midY = midY;\n return context.document.currentPage().addLayers([lay]);\n }\n\n const colorMapping = getColorVariablesMapping(colorVariables)\n const currentSelectedColor = getFillHexColor(selection).toString().toUpperCase();\n\n\n const lay = createTextLayer('design', 'color: ' + colorMapping[\"#\" + currentSelectedColor]);\n\n // gets the position of selection\n var midX=context.selection[0].frame().midX();\n var midY=context.selection[0].frame().midY();\n\n // pass the position to the text layer to be inserter\n lay.frame().midX = midX;\n lay.frame().midY = midY;\n\n // add the layer to the artboar\n context.document.currentPage().addLayers([lay]);\n}\n\nfunction getFillHexColor(selection) {\n var layer = context.selection[0]\n var selectedColor = getFillRGBColor(\"fill\", layer)\n var colorHex = selectedColor.immutableModelObject().hexValue().toString()\n return colorHex\n}\n\nfunction getFillRGBColor (type, layer) {\n var color\n\n if (type === \"fill\") {\n if (layer instanceof MSTextLayer) {\n color = layer.textColor()\n } else {\n color = layer.style().fills().firstObject().color()\n }\n } else {\n color = layer.style().borders().firstObject().color()\n }\n\n return color\n}\n\n// Hex to Color - helper function\nvar hexToColor = function(hex, alpha) {\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex),\n red = parseInt(result[1], 16) / 255,\n green = parseInt(result[2], 16) / 255,\n blue = parseInt(result[3], 16) / 255,\n alpha = (typeof alpha !== 'undefined') ? alpha : 1;\n return NSColor.colorWithCalibratedRed_green_blue_alpha(red, green, blue, alpha)\n}\n\n\nfunction createTextLayer(name, stringValue) {\n var textLayer = MSTextLayer.new();\n textLayer.stringValue = stringValue\n textLayer.name = name\n textLayer.setTextColor = hexToColor(\"CCCCCC\")\n return textLayer;\n}\n\nfunction getColorVariablesMapping(variables) {\n const obj = variables.baseColors\n const colorNames = {}\n // gets default color variables\n Object.keys(obj).map(colorGroupName => {\n const colorGroup = obj[colorGroupName]\n\n colorNames[colorGroup.default] = '--color-' + colorGroupName;\n\n Object.keys(colorGroup).forEach(variation => {\n // filters out default values\n if (variation !== 'default') {\n colorNames[colorGroup[variation]] = '--color-' + colorGroupName + '-' + variation;\n }\n })\n })\n\n return colorNames\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/src/border-color.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lufego/sketch-tokenizer/7c5bedccaae1467e98063b011c1f15a734c5ab79/src/border-color.js
--------------------------------------------------------------------------------
/src/converters/colors.js:
--------------------------------------------------------------------------------
1 | // Color converters
2 |
3 | export function transformColorLightness(hex, lightness) {
4 | /* A bit of crazyness happening here;
5 | But this is the workflow from hsl_picker plugin to
6 | generate colors in sketch, so the same scheme is below */
7 | // HEXtoRGB => RgbToHsl => change light => HSLtoRGB => RGBtoHSL => HSLtoHEX
8 |
9 | const colorRgb = HEXtoRGB(hex);
10 | const colorHsl = RGBtoHSL(colorRgb, lightness);
11 | const colorRgbTransformed = HSLtoRGB(colorHsl);
12 | const colorHslTransformed = RGBtoHSL(colorRgbTransformed);
13 | const colorHex = HSLtoHEX(colorHslTransformed);
14 | return colorHex;
15 | }
16 |
17 | function HEXtoRGB(hex) {
18 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
19 | return result
20 | ? [
21 | parseInt(result[1], 16),
22 | parseInt(result[2], 16),
23 | parseInt(result[3], 16)
24 | ]
25 | : null;
26 | }
27 |
28 | function RGBtoHSL([r, g, b], lightness) {
29 | (r /= 255), (g /= 255), (b /= 255);
30 | var max = Math.max(r, g, b),
31 | min = Math.min(r, g, b);
32 | var h,
33 | s,
34 | l = (max + min) / 2;
35 | if (max == min) {
36 | h = s = 0; // achromatic
37 | } else {
38 | var d = max - min;
39 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
40 | switch (max) {
41 | case r:
42 | h = (g - b) / d + (g < b ? 6 : 0);
43 | break;
44 | case g:
45 | h = (b - r) / d + 2;
46 | break;
47 | case b:
48 | h = (r - g) / d + 4;
49 | break;
50 | }
51 | h /= 6;
52 | }
53 | return [
54 | Math.round(h * 360),
55 | Math.round(s * 100),
56 | lightness ? parseInt(lightness) : Math.round(l * 100)
57 | ];
58 | }
59 |
60 | function HSLtoHEX(hsl) {
61 | const rgbColor = HSLtoRGB([hsl[0], hsl[1], hsl[2]]);
62 | const r = rgbColor[0];
63 | const g = rgbColor[1];
64 | const b = rgbColor[2];
65 |
66 | // console.log('rgb', r, g, b)
67 |
68 | return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
69 | }
70 |
71 | function HSLtoRGB([h, s, l]) {
72 | var m1, m2, hue;
73 | s = s / 100;
74 | l = l / 100;
75 | var r, g, b;
76 |
77 | if (s == 0) r = g = b = l * 255;
78 | else {
79 | m2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
80 | m1 = 2 * l - m2;
81 | hue = h / 360;
82 |
83 | r = hue2rgb(m1, m2, hue + 1 / 3);
84 | g = hue2rgb(m1, m2, hue);
85 | b = hue2rgb(m1, m2, hue - 1 / 3);
86 | }
87 |
88 | function multiplyBy255(num) {
89 | return num * 255;
90 | }
91 |
92 | if (r < 1 || g < 1 || b < 1) {
93 | r = multiplyBy255(r);
94 | g = multiplyBy255(g);
95 | b = multiplyBy255(b);
96 | }
97 |
98 | // console.log('rgb', Math.round(r), Math.round(g), Math.round(b));
99 |
100 | return [Math.round(r), Math.round(g), Math.round(b)];
101 | }
102 |
103 | // Used inside HSLtoRGB function
104 | function hue2rgb(m1, m2, hue) {
105 | if (hue < 0) hue += 1;
106 | if (hue > 1) hue -= 1;
107 | if (hue < 1 / 6) return m1 + (m2 - m1) * 6 * hue;
108 | if (hue < 1 / 2) return m2;
109 | if (hue < 2 / 3) return m1 + (m2 - m1) * (2 / 3 - hue) * 6;
110 | return m1;
111 | }
112 |
--------------------------------------------------------------------------------
/src/decisions/backgrounds.json:
--------------------------------------------------------------------------------
1 | {
2 | "color": {
3 | "input": {
4 | "pristine": "white",
5 | "disabled": "navy-98"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/decisions/base-colors.json:
--------------------------------------------------------------------------------
1 | {
2 | "green": {
3 | "25": "25%",
4 | "40": "40%",
5 | "85": "85%",
6 | "95": "95%",
7 | "default": "#00b39e"
8 | },
9 | "white": {
10 | "default": "#ffffff"
11 | },
12 | "navy": {
13 | "30": "30%",
14 | "40": "40%",
15 | "95": "95%",
16 | "98": "98%",
17 | "default": "#213c45"
18 | },
19 | "blue": {
20 | "95": "95%",
21 | "85": "85%",
22 | "default": "#078cdf"
23 | },
24 | "gray": {
25 | "60": "60%",
26 | "90": "90%",
27 | "95": "95%",
28 | "default": "#cccccc"
29 | },
30 | "orange": {
31 | "95": "95%",
32 | "default": "#f16d0e"
33 | },
34 | "red": {
35 | "95": "95%",
36 | "default": "#e60050"
37 | },
38 | "purple": {
39 | "default": "#b866ff"
40 | },
41 | "black": {
42 | "default": "#1a1a1a"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/decisions/borders.json:
--------------------------------------------------------------------------------
1 | {
2 | "color": {
3 | "input": {
4 | "pristine": "gray-60",
5 | "disabled": "gray",
6 | "readonly": "gray",
7 | "focus": "green",
8 | "error": "red",
9 | "warning": "orange"
10 | }
11 | },
12 | "radius": {
13 | "input": 6
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/example.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lufego/sketch-tokenizer/7c5bedccaae1467e98063b011c1f15a734c5ab79/src/example.sketch
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "compatibleVersion": 3,
3 | "bundleVersion": 1,
4 | "icon": "icon.png",
5 | "commands": [
6 | {
7 | "name": "Fill color",
8 | "identifier": "base-fill-color",
9 | "shortcut": "ctrl shift w",
10 | "script": "./menu-identify/base-colors/get-base-fill-color.js"
11 | },
12 | {
13 | "name": "Border color",
14 | "identifier": "base-border-color",
15 | "shortcut": "ctrl shift b",
16 | "script": "./menu-identify/base-colors/get-base-border-color.js"
17 | },
18 | {
19 | "name": "Input",
20 | "identifier": "token-border-color-input",
21 | "script": "./menu-identify/tokens/border/get-token-border-color-input.js"
22 | },
23 | {
24 | "name": "Input",
25 | "identifier": "token-background-color-input",
26 | "script":
27 | "./menu-identify/tokens/background/get-token-background-color-input.js"
28 | },
29 | {
30 | "name": "Import base colors decisions file...",
31 | "identifier": "import-base-colors-decisions-file",
32 | "shortcut": "ctrl shift i",
33 | "script": "./menu-import/import-base-colors-decisions-file.js"
34 | },
35 | {
36 | "name": "Import borders decisions file...",
37 | "identifier": "import-token-borders-decisions-file",
38 | "script": "./menu-import/import-token-borders-decisions-file.js"
39 | },
40 | {
41 | "name": "Import backgrounds decisions file...",
42 | "identifier": "import-token-backgrounds-decisions-file",
43 | "script": "./menu-import/import-token-backgrounds-decisions-file.js"
44 | }
45 | ],
46 | "menu": {
47 | "title": "Tokenizer",
48 | "items": [
49 | {
50 | "title": "Load data",
51 | "items": [
52 | "import-base-colors-decisions-file",
53 | "import-token-borders-decisions-file",
54 | "import-token-backgrounds-decisions-file"
55 | ]
56 | },
57 | {
58 | "title": "Identify",
59 | "items": [
60 | {
61 | "title": "Base color",
62 | "items": ["base-fill-color", "base-border-color"]
63 | },
64 | {
65 | "title": "Token",
66 | "items": [
67 | {
68 | "title": "Border color",
69 | "items": ["token-border-color-input"]
70 | },
71 | {
72 | "title": "Background color",
73 | "items": ["token-background-color-input"]
74 | }
75 | ]
76 | }
77 | ]
78 | }
79 | ]
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/menu-identify/base-colors/get-base-border-color.js:
--------------------------------------------------------------------------------
1 | const Utils = require('./../../utils.js');
2 |
3 | // My plugin (command shift s)
4 | export default function(context) {
5 | var selection = context.selection;
6 | context.document.showMessage('Plugin 🏃');
7 |
8 | if (selection.length == 0) {
9 | return context.document.showMessage('🗝🌈: Please select an object');
10 | }
11 | // if its a text
12 | if (selection[0] instanceof MSTextLayer) {
13 | return context.document.showMessage(
14 | '❌: Please use `Tokenizer > Get Tone` for texts'
15 | );
16 | }
17 |
18 | const colorMapping = Utils.getBaseColorsVariablesMapping();
19 | const currentSelectedColor = Utils.getBorderHexColor(selection)
20 | .toString()
21 | .toUpperCase();
22 |
23 | const color = colorMapping['#' + currentSelectedColor];
24 |
25 | const callback = () => getBorderColorVariable(selection, color);
26 |
27 | // checks if color belongs to UI Kit, if not returns an error
28 | Utils.colorChecker(color, callback);
29 | }
30 |
31 | function getBorderColorVariable(selection, text) {
32 | const position = {
33 | x: selection[0].absoluteRect().rulerX(),
34 | y: selection[0].absoluteRect().rulerY(),
35 | midY: selection[0].absoluteRect().height() / 2,
36 | width: selection[0].absoluteRect().width()
37 | };
38 |
39 | const layerName = String(selection[0].name());
40 |
41 | Utils.insertTokenText(position, layerName, 'border color', text, true);
42 | }
43 |
--------------------------------------------------------------------------------
/src/menu-identify/base-colors/get-base-fill-color.js:
--------------------------------------------------------------------------------
1 | const Utils = require('./../../utils.js');
2 |
3 | // My plugin (command shift s)
4 | export default function(context) {
5 | var selection = context.selection;
6 | context.document.showMessage('Plugin 🏃');
7 |
8 | if (selection.length == 0) {
9 | return context.document.showMessage('🗝🌈: Please select an object');
10 | }
11 | // if its a text
12 | if (selection[0] instanceof MSTextLayer) {
13 | return context.document.showMessage(
14 | '❌: Please use `Tokenizer > Get Tone` for texts'
15 | );
16 | }
17 |
18 | const colorMapping = Utils.getBaseColorsVariablesMapping();
19 | console.log('colorMapping', colorMapping);
20 | const currentSelectedColor = Utils.getFillHexColor(selection)
21 | .toString()
22 | .toUpperCase();
23 |
24 | const color = colorMapping['#' + currentSelectedColor];
25 |
26 | const callback = () => getFillColorVariable(selection, color);
27 |
28 | // checks if color belongs to UI Kit, if not returns an error
29 | Utils.colorChecker(color, callback);
30 | }
31 |
32 | function getFillColorVariable(selection, text) {
33 | const position = {
34 | x: selection[0].absoluteRect().rulerX(),
35 | y: selection[0].absoluteRect().rulerY(),
36 | midY: selection[0].absoluteRect().height() / 2,
37 | width: selection[0].absoluteRect().width()
38 | };
39 |
40 | const layerName = String(selection[0].name());
41 |
42 | Utils.insertTokenText(position, layerName, 'fill color', text);
43 | }
44 |
--------------------------------------------------------------------------------
/src/menu-identify/tokens/background/get-token-background-color-input.js:
--------------------------------------------------------------------------------
1 | const Utils = require('./../../../utils.js');
2 |
3 | // My plugin (command shift s)
4 | export default function(context) {
5 | var selection = context.selection;
6 | context.document.showMessage('Plugin 🏃');
7 |
8 | if (selection.length == 0) {
9 | return context.document.showMessage('🗝🌈: Please select an object');
10 | }
11 | // if its a text
12 | if (selection[0] instanceof MSTextLayer) {
13 | return context.document.showMessage(
14 | '❌: Please use `Tokenizer > Get Tone` for texts'
15 | );
16 | }
17 |
18 | const colorMapping = Utils.getBaseColorsVariablesMapping();
19 | // console.log('colorMapping', colorMapping);
20 | const currentSelectedColor = Utils.getFillHexColor(selection)
21 | .toString()
22 | .toUpperCase();
23 | const color = colorMapping[`#${currentSelectedColor}`];
24 |
25 | const callback = () =>
26 | insertTokenrVariable(selection, `#${currentSelectedColor}`);
27 |
28 | // checks if color belongs to UI Kit, if not returns an error
29 | Utils.colorChecker(color, callback);
30 | }
31 |
32 | function insertTokenrVariable(selection, hexColor) {
33 | const position = {
34 | x: selection[0].absoluteRect().rulerX(),
35 | y: selection[0].absoluteRect().rulerY(),
36 | midY: selection[0].absoluteRect().height() / 2,
37 | width: selection[0].absoluteRect().width()
38 | };
39 |
40 | const layerName = String(selection[0].name());
41 |
42 | const tokenText = Utils.getTokenVariable(
43 | 'background-color',
44 | 'input',
45 | hexColor
46 | );
47 |
48 | Utils.insertTokenText(
49 | position,
50 | layerName,
51 | 'token input background color',
52 | tokenText
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/src/menu-identify/tokens/border/get-token-border-color-input.js:
--------------------------------------------------------------------------------
1 | const Utils = require('./../../../utils.js');
2 |
3 | // My plugin (command shift s)
4 | export default function(context) {
5 | var selection = context.selection;
6 | context.document.showMessage('Plugin 🏃');
7 |
8 | if (selection.length == 0) {
9 | return context.document.showMessage('🗝🌈: Please select an object');
10 | }
11 | // if its a text
12 | if (selection[0] instanceof MSTextLayer) {
13 | return context.document.showMessage(
14 | '❌: Please use `Tokenizer > Get Tone` for texts'
15 | );
16 | }
17 |
18 | const colorMapping = Utils.getBaseColorsVariablesMapping();
19 | // console.log('colorMapping', colorMapping);
20 | const currentSelectedColor = Utils.getBorderHexColor(selection)
21 | .toString()
22 | .toUpperCase();
23 | const color = colorMapping[`#${currentSelectedColor}`];
24 |
25 | const callback = () =>
26 | insertTokenrVariable(selection, `#${currentSelectedColor}`);
27 |
28 | // checks if color belongs to UI Kit, if not returns an error
29 | Utils.colorChecker(color, callback);
30 | }
31 |
32 | function insertTokenrVariable(selection, hexColor) {
33 | const position = {
34 | x: selection[0].absoluteRect().rulerX(),
35 | y: selection[0].absoluteRect().rulerY(),
36 | midY: selection[0].absoluteRect().height() / 2,
37 | width: selection[0].absoluteRect().width()
38 | };
39 |
40 | const layerName = String(selection[0].name());
41 |
42 | const tokenText = Utils.getTokenVariable('border-color', 'input', hexColor);
43 |
44 | Utils.insertTokenText(
45 | position,
46 | layerName,
47 | 'token input border color',
48 | tokenText,
49 | true
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/src/menu-import/import-base-colors-decisions-file.js:
--------------------------------------------------------------------------------
1 | const importFile = require('./../utils.js').importFile;
2 |
3 | export default function(context) {
4 | const fileName = 'Base colors';
5 |
6 | // the value global state will hold
7 | const objName = 'baseColors';
8 |
9 | importFile(fileName, objName);
10 |
11 | context.document.showMessage(
12 | `📩🎉: File for ${fileName} imported! Ready to use!`
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/src/menu-import/import-token-backgrounds-decisions-file.js:
--------------------------------------------------------------------------------
1 | const importFile = require('./../utils.js').importFile;
2 |
3 | export default function(context) {
4 | const fileName = 'Background decisions';
5 |
6 | // the value global state will hold
7 | const objName = 'background';
8 |
9 | importFile(fileName, objName);
10 |
11 | context.document.showMessage(
12 | `📩🎉: File for ${fileName} imported! Ready to use!`
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/src/menu-import/import-token-borders-decisions-file.js:
--------------------------------------------------------------------------------
1 | const importFile = require('./../utils.js').importFile;
2 |
3 | export default function(context) {
4 | const fileName = 'Border decisions';
5 |
6 | // the value global state will hold
7 | const objName = 'border';
8 |
9 | importFile(fileName, objName);
10 |
11 | context.document.showMessage(
12 | `📩🎉: File for ${fileName} imported! Ready to use!`
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | const ColorConverter = require('./converters/colors.js');
2 |
3 | const quoteColor = { r: 1, g: 0.369, b: 0.941, a: 1 };
4 | const lineHeight = 14;
5 | const lineWidth = 85;
6 |
7 | // UI Creators
8 |
9 | export function insertTokenText(
10 | position,
11 | layerGroupName,
12 | title,
13 | text,
14 | isBorder = false
15 | ) {
16 | const capitalizedTitle = title[0].toUpperCase() + title.slice(1);
17 | const textWithToken = createTextLayer(`${capitalizedTitle}: ${text}`);
18 | const quoteLine = createQuoteLine(position, isBorder);
19 |
20 | // var bounds = MSLayerGroup.groupBoundsForContainer(
21 | // MSLayerArray.arrayWithLayers([quoteLine, textWithToken])
22 | // );
23 |
24 | insertIntoGroup(
25 | layerGroupName,
26 | title,
27 | { text: textWithToken, line: quoteLine },
28 | position,
29 | isBorder
30 | );
31 | }
32 |
33 | export function insertIntoGroup(
34 | layerGroupName,
35 | property,
36 | layers,
37 | position,
38 | isBorder
39 | ) {
40 | var groupLayer = MSLayerGroup.new();
41 |
42 | // to simulate the heigt/width
43 | var bounds = MSLayerGroup.groupBoundsForContainer(
44 | MSLayerArray.arrayWithLayers([layers.line, layers.text])
45 | );
46 |
47 | // if its a border, we want the quote line to touch it, otherwise touch fill
48 | const touchOffset = isBorder ? 0 : 5;
49 |
50 | // if its a border TOKEN, we want the quote line to start from the same point as fill quoted line
51 | const startingPointOffset = isBorder ? lineHeight : 0;
52 |
53 | // spacing between line and text
54 | const spacing = 4;
55 |
56 | // moves the text a bit further from object
57 | layers.text.frame().x = lineWidth + spacing;
58 | if (isBorder) {
59 | layers.text.frame().y = -lineHeight;
60 | }
61 |
62 | groupLayer.name = `Token ${property} for ${layerGroupName}`;
63 | groupLayer.layers = [layers.line, layers.text];
64 |
65 | groupLayer.resizeToFitChildrenWithOption(1);
66 | groupLayer.frame().x = position.x + position.width - touchOffset;
67 | groupLayer.frame().y =
68 | position.y + position.midY - bounds.size.height / 2 - startingPointOffset;
69 | var currentParentGroup =
70 | context.document.currentPage().currentArtboard() ||
71 | context.document.currentPage();
72 | currentParentGroup.addLayers([groupLayer]);
73 | }
74 |
75 | export function createQuoteLine(position, isBorder) {
76 | const lineHeightMidY = lineHeight / 2;
77 |
78 | // if its a border TOKEN, we want the quote line to start from the same point as fill quoted line
79 | const startingPointOffset = isBorder ? 15 : 0;
80 | var path = NSBezierPath.bezierPath();
81 | path.moveToPoint(
82 | NSMakePoint(lineWidth, lineHeightMidY - startingPointOffset)
83 | );
84 | path.lineToPoint(NSMakePoint(0, lineHeightMidY));
85 |
86 | var shape = MSShapeGroup.shapeWithBezierPath(MSPath.pathWithBezierPath(path));
87 | var border = shape.style().addStylePartOfType(1);
88 | border.color = MSColor.colorWithRGBADictionary(quoteColor);
89 | border.thickness = 1;
90 |
91 | return shape;
92 | }
93 |
94 | export function createTextLayer(stringValue) {
95 | var textLayer = MSTextLayer.new();
96 | textLayer.stringValue = stringValue;
97 | textLayer.name = 'Text';
98 | textLayer.setTextColor(MSColor.colorWithRGBADictionary(quoteColor));
99 | return textLayer;
100 | }
101 |
102 | // Token getters
103 |
104 | export function getTokenVariable(property, component, hexColor) {
105 | const baseColorsMap = getBaseColorsVariablesMapping();
106 | const prefix = '--token';
107 |
108 | // if property has `-`, splits it
109 | const hasDash = /-/;
110 | const propertyPrefix = hasDash.test(property)
111 | ? property.split('-')
112 | : property;
113 |
114 | let states;
115 | let decisionsFile;
116 | let propertyName;
117 |
118 | // if the propery is passed with dash (E.g border-color)
119 | if (propertyPrefix instanceof Array) {
120 | decisionsFile = getDecisionsJson(propertyPrefix[0]);
121 | if (!decisionsFile) {
122 | return context.document.showMessage(
123 | `✋🏻❌: Please load a decisions token file for ${property} before continuing`
124 | );
125 | }
126 | states = decisionsFile[propertyPrefix[1]][component];
127 | propertyName = `${propertyPrefix[0]}-${propertyPrefix[1]}`;
128 | } else {
129 | decisionsFile = getDecisionsJson(propertyPrefix);
130 | if (!decisionsFile) {
131 | return context.document.showMessage(
132 | `✋🏻❌: Please load a decisions token file for ${property} before continuing`
133 | );
134 | }
135 | states = decisionsFile[propertyPrefix][component];
136 | propertyName = propertyPrefix;
137 | }
138 |
139 | if (!baseColorsMap) {
140 | return context.document.showMessage(
141 | '✋🏻❌: Please load a decisions base colors file before continuing'
142 | );
143 | }
144 |
145 | // gets the color from selected element
146 | const selectedColor = baseColorsMap[hexColor].replace('--color-', '');
147 |
148 | const selectedState = Object.keys(states).find(
149 | state => states[state] == selectedColor
150 | );
151 |
152 | if (!selectedState) {
153 | return context.document.showMessage(
154 | '🎨🚫: Non-recognized token color. Please make sure to use a valid color for this token'
155 | );
156 | }
157 |
158 | return `${prefix}-${propertyName}-${component}-${selectedState}`;
159 | }
160 |
161 | // Base color getters
162 |
163 | export function getFillHexColor(selection) {
164 | var layer = context.selection[0];
165 | var selectedColor = getRGBColor('fill', layer);
166 | var colorHex = selectedColor
167 | .immutableModelObject()
168 | .hexValue()
169 | .toString();
170 | return colorHex;
171 | }
172 |
173 | function getDecisionsJson(object) {
174 | // Gets the json data stored in global state
175 | let threadDictionary = NSThread.mainThread().threadDictionary();
176 | let decisions = threadDictionary[object];
177 | return decisions;
178 | }
179 |
180 | export function getBorderHexColor(selection) {
181 | var layer = context.selection[0];
182 | var selectedColor = getRGBColor('border', layer);
183 | var colorHex = selectedColor
184 | .immutableModelObject()
185 | .hexValue()
186 | .toString();
187 | return colorHex;
188 | }
189 |
190 | export function getRGBColor(type, layer) {
191 | var color;
192 |
193 | if (type === 'fill') {
194 | if (layer instanceof MSTextLayer) {
195 | color = layer.textColor();
196 | } else {
197 | color = layer
198 | .style()
199 | .fills()
200 | .firstObject()
201 | .color();
202 | }
203 | } else {
204 | color = layer
205 | .style()
206 | .borders()
207 | .firstObject()
208 | .color();
209 | }
210 |
211 | return color;
212 | }
213 |
214 | export function getHexValueFromColorVariable(colorVar, baseColorsVariablesMap) {
215 | const colorVarWithPrefix = `--color-${colorVar}`;
216 | return Object.keys(baseColorsVariablesMap).find(hexVal => {
217 | if (baseColorsVariablesMap[hexVal] == colorVarWithPrefix) return hexVal;
218 | });
219 | }
220 |
221 | // Checkers
222 |
223 | export function colorChecker(color, callback) {
224 | if (typeof color === 'undefined') {
225 | return context.document.showMessage(
226 | '🎨🚫: Non UI Kit color. Please make sure to use a valid color'
227 | );
228 | } else {
229 | return callback();
230 | }
231 | }
232 |
233 | // General scripts
234 |
235 | export function getBaseColorsVariablesMapping() {
236 | // Gets the json data stored in global state
237 | const importedBaseColors = getDecisionsJson('baseColors');
238 |
239 | if (!importedBaseColors)
240 | return context.document.showMessage(
241 | '🗃👎🏻 No file imported. Please import your base colors file in `Import base colors file...`'
242 | );
243 |
244 | const colorNames = {};
245 | // gets default color variables
246 | Object.keys(importedBaseColors).map(colorGroupName => {
247 | const colorGroup = importedBaseColors[colorGroupName];
248 | const colorDefaultName = colorGroup.default;
249 | colorNames[colorDefaultName.toString().toUpperCase()] =
250 | '--color-' + colorGroupName;
251 |
252 | Object.keys(colorGroup).forEach(variation => {
253 | // filters out default values
254 | if (variation !== 'default') {
255 | const variationName = colorGroup[variation];
256 | const variationNameWithoutPercetageSign = variationName
257 | .toString()
258 | .replace('%', '');
259 | colorNames[
260 | ColorConverter.transformColorLightness(
261 | colorGroup.default,
262 | variationNameWithoutPercetageSign
263 | ).toUpperCase()
264 | ] =
265 | '--color-' + colorGroupName + '-' + variation;
266 | }
267 | });
268 | });
269 | return colorNames;
270 | }
271 |
272 | // importers
273 |
274 | export function importFile(fileName, objName) {
275 | //ask for JSON file path, passing the last location if available
276 | let dataPath = askForJSON('lastJSONPath', fileName);
277 | if (!dataPath) return;
278 |
279 | //load json data
280 | let jsonData = loadJSONData(dataPath);
281 | if (!jsonData) return;
282 |
283 | //get root dir used when populating local images
284 | let jsonDir = NSString.stringWithString(
285 | dataPath
286 | ).stringByDeletingLastPathComponent();
287 |
288 | let threadDictionary = NSThread.mainThread().threadDictionary();
289 | threadDictionary[objName] = { ...jsonData };
290 | }
291 |
292 | function askForJSON(path, fileName) {
293 | //create panel
294 | let panel = NSOpenPanel.openPanel();
295 |
296 | //set panel properties
297 | panel.setTitle('Select JSON');
298 | panel.setMessage(`Please select the JSON file for ${fileName}`);
299 | panel.setPrompt('Select');
300 | panel.setCanCreateDirectories(false);
301 | panel.setCanChooseFiles(true);
302 | panel.setCanChooseDirectories(false);
303 | panel.setAllowsMultipleSelection(false);
304 | panel.setShowsHiddenFiles(false);
305 | panel.setExtensionHidden(false);
306 |
307 | //set initial panel path
308 | if (path) {
309 | panel.setDirectoryURL(NSURL.fileURLWithPath(path));
310 | } else {
311 | panel.setDirectoryURL(NSURL.fileURLWithPath('/Users/' + NSUserName()));
312 | }
313 |
314 | //show panel
315 | let pressedButton = panel.runModal();
316 | if (pressedButton == NSOKButton) {
317 | return panel.URL().path();
318 | }
319 | }
320 |
321 | function loadJSONData(path) {
322 | //load contents
323 | let contents = readFileAsText(path);
324 |
325 | //get data from JSON
326 | let data;
327 | try {
328 | data = JSON.parse(contents);
329 | } catch (e) {
330 | context.document.showMessage(
331 | "There was an error parsing data. Please make sure it's valid."
332 | );
333 | return;
334 | }
335 |
336 | return data;
337 | }
338 |
339 | function readFileAsText(path) {
340 | return NSString.stringWithContentsOfFile_encoding_error(
341 | path,
342 | NSUTF8StringEncoding,
343 | false
344 | );
345 | }
346 |
--------------------------------------------------------------------------------