├── .eslintrc.yml ├── .gitignore ├── Escriba.sketchplugin └── Contents │ ├── Resources │ ├── icon.png │ └── icon_small.png │ └── Sketch │ ├── copy.js │ ├── manifest.json │ ├── paste.js │ └── settings.js ├── LICENSE ├── README.md ├── appcast.xml ├── assets ├── icon.png └── icon_small.png ├── images ├── InstallwithRunner.png ├── cover.png ├── pasteContent.gif ├── pasteLayerStyle.gif ├── pasteStyleAndContent.gif ├── pasteSymbol.gif ├── pasteTextStyle.gif ├── pasteall.gif └── settings.png ├── package-lock.json ├── package.json └── src ├── analytics.js ├── copy.js ├── create-alert-window.js ├── create-radio-buttons.js ├── manifest.json ├── paste.js └── settings.js /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | root: true 3 | extends: 4 | - airbnb-base 5 | - plugin:import/errors 6 | - prettier 7 | plugins: 8 | - no-not-accumulator-reassign 9 | - prettier 10 | env: 11 | node: true 12 | rules: 13 | no-not-accumulator-reassign/no-not-accumulator-reassign: [2, ['reduce'], {props: true}] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build artefacts 2 | plugin.sketchplugin/Contents/Sketch 3 | plugin.sketchplugin/Contents/Resources/_webpack_resources 4 | 5 | # npm 6 | node_modules 7 | .npm 8 | npm-debug.log 9 | 10 | # mac 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /Escriba.sketchplugin/Contents/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/Escriba.sketchplugin/Contents/Resources/icon.png -------------------------------------------------------------------------------- /Escriba.sketchplugin/Contents/Resources/icon_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/Escriba.sketchplugin/Contents/Resources/icon_small.png -------------------------------------------------------------------------------- /Escriba.sketchplugin/Contents/Sketch/copy.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, { 45 | /******/ configurable: false, 46 | /******/ enumerable: true, 47 | /******/ get: getter 48 | /******/ }); 49 | /******/ } 50 | /******/ }; 51 | /******/ 52 | /******/ // getDefaultExport function for compatibility with non-harmony modules 53 | /******/ __webpack_require__.n = function(module) { 54 | /******/ var getter = module && module.__esModule ? 55 | /******/ function getDefault() { return module['default']; } : 56 | /******/ function getModuleExports() { return module; }; 57 | /******/ __webpack_require__.d(getter, 'a', getter); 58 | /******/ return getter; 59 | /******/ }; 60 | /******/ 61 | /******/ // Object.prototype.hasOwnProperty.call 62 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 63 | /******/ 64 | /******/ // __webpack_public_path__ 65 | /******/ __webpack_require__.p = ""; 66 | /******/ 67 | /******/ // Load entry module and return exports 68 | /******/ return __webpack_require__(__webpack_require__.s = 0); 69 | /******/ }) 70 | /************************************************************************/ 71 | /******/ ([ 72 | /* 0 */ 73 | /***/ (function(module, exports, __webpack_require__) { 74 | 75 | "use strict"; 76 | 77 | 78 | Object.defineProperty(exports, "__esModule", { 79 | value: true 80 | }); 81 | exports.copySelected = copySelected; 82 | 83 | exports['default'] = function (context) { 84 | var selectedOverrides = context.document.documentData().selectedOverrides(); 85 | if (selectedOverrides.length == 1) { 86 | selectedOverrides.forEach(function (selectedOverride) { 87 | if (selectedOverride.includes('/')) { 88 | var tokens = selectedOverride.split('/'); 89 | var element = tokens[tokens.length - 1]; 90 | var tokensSplit = element.split('_'); 91 | var selectedOverrideId = tokensSplit[tokensSplit.length - 2]; 92 | (0, _analytics2['default'])(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 93 | copySelected(selectedOverrideId, context); 94 | } else { 95 | var tokens = selectedOverride.split('#'); 96 | var element = tokens[tokens.length - 1]; 97 | var tokensSplit = element.split('_'); 98 | var selectedOverrideId = tokensSplit[tokensSplit.length - 2]; 99 | (0, _analytics2['default'])(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 100 | copySelected(selectedOverrideId, context); 101 | } 102 | }); 103 | } 104 | if (selectedOverrides.length < 1) { 105 | UI.message('⚠️ Select one Symbol override to copy ⚠️'); 106 | (0, _analytics2['default'])(context, "Escriba UI", "No override selected to copy"); 107 | } 108 | if (selectedOverrides.length > 1) { 109 | UI.message('⚠️ You have selected more than one override, select only one Symbol override to copy ⚠️'); 110 | (0, _analytics2['default'])(context, "Escriba UI", "More than one override selected to copy"); 111 | } 112 | }; 113 | 114 | var _analytics = __webpack_require__(1); 115 | 116 | var _analytics2 = _interopRequireDefault(_analytics); 117 | 118 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 119 | 120 | var sketch = __webpack_require__(2); 121 | var doc = sketch.getSelectedDocument(); 122 | var selection = doc.selectedLayers.layers; 123 | var UI = __webpack_require__(3); 124 | var Settings = __webpack_require__(4); 125 | 126 | function copySelected(selectedOverrideId, context) { 127 | selection.forEach(function (layer) { 128 | layer.overrides.forEach(function (override) { 129 | if (selectedOverrideId == override.affectedLayer.id) { 130 | var string = override.value; 131 | 132 | var property = override.property; 133 | var settingName = ['settings' + String(property)]; 134 | Settings.setSessionVariable(settingName, string); 135 | (0, _analytics2['default'])(context, "Escriba Success", "Copy done", string); 136 | } 137 | }); 138 | }); 139 | } 140 | 141 | /***/ }), 142 | /* 1 */ 143 | /***/ (function(module, exports, __webpack_require__) { 144 | 145 | "use strict"; 146 | 147 | 148 | Object.defineProperty(exports, "__esModule", { 149 | value: true 150 | }); 151 | exports["default"] = googleAnalytics; 152 | function googleAnalytics(context, category, action, label, value) { 153 | var trackingID = "UA-128191866-1"; 154 | var uuidKey = "google.analytics.uuid"; 155 | var url = "https://www.google-analytics.com/collect?v=1"; 156 | var uuid = NSUserDefaults.standardUserDefaults().objectForKey(uuidKey); 157 | 158 | if (!uuid) { 159 | uuid = NSUUID.UUID().UUIDString(); 160 | NSUserDefaults.standardUserDefaults().setObject_forKey(uuid, uuidKey); 161 | } 162 | 163 | // Tracking ID 164 | url += "&tid=" + trackingID; 165 | // Source 166 | url += "&ds=sketch" + MSApplicationMetadata.metadata().appVersion; 167 | // Client ID 168 | url += "&cid=" + uuid; 169 | // pageview, screenview, event, transaction, item, social, exception, timing 170 | url += "&t=event"; 171 | // App Name 172 | url += "&an=" + encodeURI(context.plugin.name()); 173 | // App Version 174 | url += "&av=" + context.plugin.version(); 175 | // Event category 176 | url += "&ec=" + encodeURI(category); 177 | // Event action 178 | url += "&ea=" + encodeURI(action); 179 | // Event label 180 | if (label) { 181 | url += "&el=" + encodeURI(label); 182 | } 183 | // Event value 184 | if (value) { 185 | url += "&ev=" + encodeURI(value); 186 | } 187 | 188 | var session = NSURLSession.sharedSession(), 189 | task = session.dataTaskWithURL(NSURL.URLWithString(NSString.stringWithString(url))); 190 | task.resume(); 191 | } 192 | 193 | /***/ }), 194 | /* 2 */ 195 | /***/ (function(module, exports) { 196 | 197 | module.exports = require("sketch/dom"); 198 | 199 | /***/ }), 200 | /* 3 */ 201 | /***/ (function(module, exports) { 202 | 203 | module.exports = require("sketch/ui"); 204 | 205 | /***/ }), 206 | /* 4 */ 207 | /***/ (function(module, exports) { 208 | 209 | module.exports = require("sketch/settings"); 210 | 211 | /***/ }) 212 | /******/ ]); 213 | if (key === 'default' && typeof exports === 'function') { 214 | exports(context); 215 | } else { 216 | exports[key](context); 217 | } 218 | } 219 | that['onRun'] = __skpm_run.bind(this, 'default') 220 | -------------------------------------------------------------------------------- /Escriba.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "compatibleVersion": 53, 3 | "bundleVersion": 1, 4 | "icon": "icon.png", 5 | "appcast": "https://raw.githubusercontent.com/pausansol/escriba/master/appcast.xml", 6 | "commands": [ 7 | { 8 | "name": "Copy", 9 | "identifier": "copy-identifier", 10 | "shortcut": "ctrl command z", 11 | "script": "copy.js" 12 | }, 13 | { 14 | "name": "Paste", 15 | "identifier": "paste-identifier", 16 | "shortcut": "ctrl command x", 17 | "script": "paste.js" 18 | }, 19 | { 20 | "name": "Settings", 21 | "identifier": "settings-identifier", 22 | "script": "settings.js" 23 | } 24 | ], 25 | "menu": { 26 | "title": "Escriba", 27 | "items": [ 28 | "copy-identifier", 29 | "paste-identifier", 30 | "-", 31 | "settings-identifier" 32 | ] 33 | }, 34 | "version": "1.1.0", 35 | "description": "Copy & Paste overrides", 36 | "name": "Escriba", 37 | "disableCocoaScriptPreprocessor": true, 38 | "author": "Pausansol", 39 | "authorEmail": "pausansol@gmail.com" 40 | } -------------------------------------------------------------------------------- /Escriba.sketchplugin/Contents/Sketch/paste.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, { 45 | /******/ configurable: false, 46 | /******/ enumerable: true, 47 | /******/ get: getter 48 | /******/ }); 49 | /******/ } 50 | /******/ }; 51 | /******/ 52 | /******/ // getDefaultExport function for compatibility with non-harmony modules 53 | /******/ __webpack_require__.n = function(module) { 54 | /******/ var getter = module && module.__esModule ? 55 | /******/ function getDefault() { return module['default']; } : 56 | /******/ function getModuleExports() { return module; }; 57 | /******/ __webpack_require__.d(getter, 'a', getter); 58 | /******/ return getter; 59 | /******/ }; 60 | /******/ 61 | /******/ // Object.prototype.hasOwnProperty.call 62 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 63 | /******/ 64 | /******/ // __webpack_public_path__ 65 | /******/ __webpack_require__.p = ""; 66 | /******/ 67 | /******/ // Load entry module and return exports 68 | /******/ return __webpack_require__(__webpack_require__.s = 0); 69 | /******/ }) 70 | /************************************************************************/ 71 | /******/ ([ 72 | /* 0 */ 73 | /***/ (function(module, exports, __webpack_require__) { 74 | 75 | "use strict"; 76 | 77 | 78 | Object.defineProperty(exports, "__esModule", { 79 | value: true 80 | }); 81 | exports.pasteSelected = pasteSelected; 82 | 83 | exports['default'] = function (context) { 84 | var selectedOverrides = context.document.documentData().selectedOverrides(); 85 | if (selectedOverrides.length > 0) { 86 | selectedOverrides.forEach(function (selectedOverride) { 87 | if (selectedOverride.includes('/')) { 88 | var tokens = selectedOverride.split('/'); 89 | var element = tokens[tokens.length - 1]; 90 | var tokensSplit = element.split('_'); 91 | var selectedOverrideId = tokensSplit[tokensSplit.length - 2]; 92 | (0, _analytics2['default'])(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 93 | pasteSelected(selectedOverrideId, context); 94 | } else { 95 | var tokens = selectedOverride.split('#'); 96 | var element = tokens[tokens.length - 1]; 97 | var tokensSplit = element.split('_'); 98 | var selectedOverrideId = tokensSplit[tokensSplit.length - 2]; 99 | (0, _analytics2['default'])(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 100 | pasteSelected(selectedOverrideId, context); 101 | } 102 | }); 103 | } else { 104 | UI.message('⚠️ Select one Symbol override to paste ⚠️'); 105 | (0, _analytics2['default'])(context, "Escriba UI", "No override selected to paste"); 106 | } 107 | }; 108 | 109 | var _analytics = __webpack_require__(1); 110 | 111 | var _analytics2 = _interopRequireDefault(_analytics); 112 | 113 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 114 | 115 | var sketch = __webpack_require__(2); 116 | var doc = sketch.getSelectedDocument(); 117 | var selection = doc.selectedLayers.layers; 118 | var UI = __webpack_require__(3); 119 | var Settings = __webpack_require__(4); 120 | 121 | function pasteSelected(selectedOverrideId, context) { 122 | selection.forEach(function (layer) { 123 | layer.overrides.forEach(function (override) { 124 | if (selectedOverrideId == override.affectedLayer.id) { 125 | var property = override.property; 126 | var getseetting = ['Value' + String(property)]; 127 | var settingValue = Settings.settingForKey(getseetting.toString()); 128 | 129 | if (settingValue == 1 || undefined) { 130 | var settingName = ['settings' + String(property)]; 131 | var setting = Settings.sessionVariable(settingName); 132 | override.value = setting; 133 | (0, _analytics2['default'])(context, "Escriba Success", "Paste done", setting); 134 | } else { 135 | if (property == 'symbolID' || property == 'layerStyle') { 136 | UI.message('⚠️ ' + property + ' Copy&Paste is disabled, you can enable it in Escriba/Settings ⚠️'); 137 | } 138 | } 139 | } 140 | }); 141 | }); 142 | } 143 | 144 | /***/ }), 145 | /* 1 */ 146 | /***/ (function(module, exports, __webpack_require__) { 147 | 148 | "use strict"; 149 | 150 | 151 | Object.defineProperty(exports, "__esModule", { 152 | value: true 153 | }); 154 | exports["default"] = googleAnalytics; 155 | function googleAnalytics(context, category, action, label, value) { 156 | var trackingID = "UA-128191866-1"; 157 | var uuidKey = "google.analytics.uuid"; 158 | var url = "https://www.google-analytics.com/collect?v=1"; 159 | var uuid = NSUserDefaults.standardUserDefaults().objectForKey(uuidKey); 160 | 161 | if (!uuid) { 162 | uuid = NSUUID.UUID().UUIDString(); 163 | NSUserDefaults.standardUserDefaults().setObject_forKey(uuid, uuidKey); 164 | } 165 | 166 | // Tracking ID 167 | url += "&tid=" + trackingID; 168 | // Source 169 | url += "&ds=sketch" + MSApplicationMetadata.metadata().appVersion; 170 | // Client ID 171 | url += "&cid=" + uuid; 172 | // pageview, screenview, event, transaction, item, social, exception, timing 173 | url += "&t=event"; 174 | // App Name 175 | url += "&an=" + encodeURI(context.plugin.name()); 176 | // App Version 177 | url += "&av=" + context.plugin.version(); 178 | // Event category 179 | url += "&ec=" + encodeURI(category); 180 | // Event action 181 | url += "&ea=" + encodeURI(action); 182 | // Event label 183 | if (label) { 184 | url += "&el=" + encodeURI(label); 185 | } 186 | // Event value 187 | if (value) { 188 | url += "&ev=" + encodeURI(value); 189 | } 190 | 191 | var session = NSURLSession.sharedSession(), 192 | task = session.dataTaskWithURL(NSURL.URLWithString(NSString.stringWithString(url))); 193 | task.resume(); 194 | } 195 | 196 | /***/ }), 197 | /* 2 */ 198 | /***/ (function(module, exports) { 199 | 200 | module.exports = require("sketch/dom"); 201 | 202 | /***/ }), 203 | /* 3 */ 204 | /***/ (function(module, exports) { 205 | 206 | module.exports = require("sketch/ui"); 207 | 208 | /***/ }), 209 | /* 4 */ 210 | /***/ (function(module, exports) { 211 | 212 | module.exports = require("sketch/settings"); 213 | 214 | /***/ }) 215 | /******/ ]); 216 | if (key === 'default' && typeof exports === 'function') { 217 | exports(context); 218 | } else { 219 | exports[key](context); 220 | } 221 | } 222 | that['onRun'] = __skpm_run.bind(this, 'default') 223 | -------------------------------------------------------------------------------- /Escriba.sketchplugin/Contents/Sketch/settings.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, { 45 | /******/ configurable: false, 46 | /******/ enumerable: true, 47 | /******/ get: getter 48 | /******/ }); 49 | /******/ } 50 | /******/ }; 51 | /******/ 52 | /******/ // getDefaultExport function for compatibility with non-harmony modules 53 | /******/ __webpack_require__.n = function(module) { 54 | /******/ var getter = module && module.__esModule ? 55 | /******/ function getDefault() { return module['default']; } : 56 | /******/ function getModuleExports() { return module; }; 57 | /******/ __webpack_require__.d(getter, 'a', getter); 58 | /******/ return getter; 59 | /******/ }; 60 | /******/ 61 | /******/ // Object.prototype.hasOwnProperty.call 62 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 63 | /******/ 64 | /******/ // __webpack_public_path__ 65 | /******/ __webpack_require__.p = ""; 66 | /******/ 67 | /******/ // Load entry module and return exports 68 | /******/ return __webpack_require__(__webpack_require__.s = 0); 69 | /******/ }) 70 | /************************************************************************/ 71 | /******/ ([ 72 | /* 0 */ 73 | /***/ (function(module, exports, __webpack_require__) { 74 | 75 | "use strict"; 76 | 77 | 78 | Object.defineProperty(exports, "__esModule", { 79 | value: true 80 | }); 81 | 82 | exports['default'] = function (context) { 83 | (0, _analytics2['default'])(context, "Escriba settings", "Open"); 84 | 85 | // create the alertWindow UI 86 | var alertWindow = (0, _createAlertWindow2['default'])(context); 87 | 88 | // create the radioButtons 89 | // Create inputs 90 | 91 | // Create the main view 92 | var viewWidth = 400; 93 | var viewHeight = 210; 94 | var viewSpacer = 10; 95 | var layerStyleCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 125, viewWidth - viewSpacer, 20)); 96 | var textStyleCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 150, viewWidth / 2 - viewSpacer, 20)); 97 | var stringValueCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 175, viewWidth / 2 - viewSpacer, 20)); 98 | var symbolIDCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 200, viewWidth / 2 - viewSpacer, 20)); 99 | 100 | var layerStyleSetting = Settings.settingForKey('ValuelayerStyle'); 101 | var textStyleSetting = Settings.settingForKey('ValuetextStyle'); 102 | var stringValueSetting = Settings.settingForKey('ValuestringValue'); 103 | var symbolIDSetting = Settings.settingForKey('ValuesymbolID'); 104 | // Configure checkboxes 105 | 106 | layerStyleCheckbox.setButtonType(NSSwitchButton); 107 | layerStyleCheckbox.setBezelStyle(0); 108 | layerStyleCheckbox.setTitle("Layer Style"); 109 | if (layerStyleSetting == 1 || layerStyleSetting == undefined) { 110 | layerStyleCheckbox.setState(NSOnState); 111 | } else { 112 | layerStyleCheckbox.setState(NSOffState); 113 | } 114 | 115 | textStyleCheckbox.setButtonType(NSSwitchButton); 116 | textStyleCheckbox.setBezelStyle(0); 117 | textStyleCheckbox.setTitle("Text Style"); 118 | if (textStyleSetting == 1 || textStyleSetting == undefined) { 119 | textStyleCheckbox.setState(NSOnState); 120 | } else { 121 | textStyleCheckbox.setState(NSOffState); 122 | } 123 | 124 | stringValueCheckbox.setButtonType(NSSwitchButton); 125 | stringValueCheckbox.setBezelStyle(0); 126 | stringValueCheckbox.setTitle("Text content"); 127 | if (stringValueSetting == 1 || stringValueSetting == undefined) { 128 | stringValueCheckbox.setState(NSOnState); 129 | } else { 130 | stringValueCheckbox.setState(NSOffState); 131 | } 132 | 133 | symbolIDCheckbox.setButtonType(NSSwitchButton); 134 | symbolIDCheckbox.setBezelStyle(0); 135 | symbolIDCheckbox.setTitle("Symbol"); 136 | if (symbolIDSetting == 1 || symbolIDSetting == undefined) { 137 | symbolIDCheckbox.setState(NSOnState); 138 | } else { 139 | symbolIDCheckbox.setState(NSOffState); 140 | } 141 | 142 | //Adding inputs to the dialog 143 | alertWindow.addAccessoryView(layerStyleCheckbox); 144 | alertWindow.addAccessoryView(textStyleCheckbox); 145 | alertWindow.addAccessoryView(stringValueCheckbox); 146 | alertWindow.addAccessoryView(symbolIDCheckbox); 147 | 148 | alertWindow.addButtonWithTitle('Save'); 149 | alertWindow.addButtonWithTitle('Cancel'); 150 | 151 | if (alertWindow.runModal() == NSAlertFirstButtonReturn) { 152 | Settings.setSettingForKey('ValuelayerStyle', layerStyleCheckbox.state()); 153 | Settings.setSettingForKey('ValuetextStyle', textStyleCheckbox.state()); 154 | Settings.setSettingForKey('ValuestringValue', stringValueCheckbox.state()); 155 | Settings.setSettingForKey('ValuesymbolID', symbolIDCheckbox.state()); 156 | (0, _analytics2['default'])(context, "Escriba settings", "Save"); 157 | } 158 | }; 159 | 160 | var _createAlertWindow = __webpack_require__(1); 161 | 162 | var _createAlertWindow2 = _interopRequireDefault(_createAlertWindow); 163 | 164 | var _analytics = __webpack_require__(2); 165 | 166 | var _analytics2 = _interopRequireDefault(_analytics); 167 | 168 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 169 | 170 | var Settings = __webpack_require__(3); 171 | 172 | /***/ }), 173 | /* 1 */ 174 | /***/ (function(module, exports, __webpack_require__) { 175 | 176 | "use strict"; 177 | 178 | 179 | Object.defineProperty(exports, "__esModule", { 180 | value: true 181 | }); 182 | exports['default'] = createAlertWindow; 183 | function createAlertWindow(context) { 184 | var alertWindow = COSAlertWindow['new'](); 185 | 186 | alertWindow.setIcon(NSImage.alloc().initByReferencingFile(context.plugin.urlForResourceNamed('icon.png').path())); 187 | alertWindow.setMessageText('Escriba'); 188 | alertWindow.setInformativeText("Configure your Escriba preferences. What properties of overrides do you want to Copy&Paste?"); 189 | 190 | return alertWindow; 191 | } 192 | 193 | /***/ }), 194 | /* 2 */ 195 | /***/ (function(module, exports, __webpack_require__) { 196 | 197 | "use strict"; 198 | 199 | 200 | Object.defineProperty(exports, "__esModule", { 201 | value: true 202 | }); 203 | exports["default"] = googleAnalytics; 204 | function googleAnalytics(context, category, action, label, value) { 205 | var trackingID = "UA-128191866-1"; 206 | var uuidKey = "google.analytics.uuid"; 207 | var url = "https://www.google-analytics.com/collect?v=1"; 208 | var uuid = NSUserDefaults.standardUserDefaults().objectForKey(uuidKey); 209 | 210 | if (!uuid) { 211 | uuid = NSUUID.UUID().UUIDString(); 212 | NSUserDefaults.standardUserDefaults().setObject_forKey(uuid, uuidKey); 213 | } 214 | 215 | // Tracking ID 216 | url += "&tid=" + trackingID; 217 | // Source 218 | url += "&ds=sketch" + MSApplicationMetadata.metadata().appVersion; 219 | // Client ID 220 | url += "&cid=" + uuid; 221 | // pageview, screenview, event, transaction, item, social, exception, timing 222 | url += "&t=event"; 223 | // App Name 224 | url += "&an=" + encodeURI(context.plugin.name()); 225 | // App Version 226 | url += "&av=" + context.plugin.version(); 227 | // Event category 228 | url += "&ec=" + encodeURI(category); 229 | // Event action 230 | url += "&ea=" + encodeURI(action); 231 | // Event label 232 | if (label) { 233 | url += "&el=" + encodeURI(label); 234 | } 235 | // Event value 236 | if (value) { 237 | url += "&ev=" + encodeURI(value); 238 | } 239 | 240 | var session = NSURLSession.sharedSession(), 241 | task = session.dataTaskWithURL(NSURL.URLWithString(NSString.stringWithString(url))); 242 | task.resume(); 243 | } 244 | 245 | /***/ }), 246 | /* 3 */ 247 | /***/ (function(module, exports) { 248 | 249 | module.exports = require("sketch/settings"); 250 | 251 | /***/ }) 252 | /******/ ]); 253 | if (key === 'default' && typeof exports === 'function') { 254 | exports(context); 255 | } else { 256 | exports[key](context); 257 | } 258 | } 259 | that['onRun'] = __skpm_run.bind(this, 'default') 260 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Pablo Sanchez Soler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Overview 4 | Copy & Paste symbol overrides for Sketch 53. 5 | 6 | ## New in v1.1 7 | Added support for nested symbol overrides 8 | 9 | ## Install 10 | 11 | Two options: 12 | 13 | * Download and install the `Escriba.sketchplugin` zip file [here](https://github.com/Pausansol/Escriba/releases/download/v1.0.1/Escriba.sketchplugin.zip). 14 | 15 | * With Sketch Runner, just go to the `install` command and search for `Escriba`. Runner allows you to manage plugins and do much more to speed up your workflow in Sketch. 16 | 17 | 18 | 19 | ## How it works? 20 | 21 | It's simple: 22 | 23 | * Select an override and Copy `Control + Command + Z` 24 | 25 | * Select one or more overrides and Paste `Control + Command + X` 🙌 🎉 26 | 27 | 28 | It works with: 29 | 30 | Symbols 31 | 32 | 33 | 34 | layerStyles 35 | 36 | 37 | 38 | textStyles 39 | 40 | 41 | 42 | Text content 43 | 44 | 45 | 46 | Style and content at the same time 47 | 48 | 49 | 50 | Paste to one or more overrides 51 | 52 | 53 | 54 | Select your preferences in `Plugins/Escriba/Settings` menu: 55 | 56 | 57 | 58 | 59 | ## License 60 | Copyright (c) 2019 Pablo Sánchez (Pausansol). Logo by Héctor Sancho 61 | 62 | See [LICENSE.md](https://github.com/pausansol/escriba/blob/master/LICENSE.md) for further details. 63 | -------------------------------------------------------------------------------- /appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Escriba 5 | https://github.com/Pausansol/Escriba 6 | Escriba: copy and paste symbol overrides 7 | en 8 | 9 | Version 1.1.0 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/assets/icon.png -------------------------------------------------------------------------------- /assets/icon_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/assets/icon_small.png -------------------------------------------------------------------------------- /images/InstallwithRunner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/InstallwithRunner.png -------------------------------------------------------------------------------- /images/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/cover.png -------------------------------------------------------------------------------- /images/pasteContent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/pasteContent.gif -------------------------------------------------------------------------------- /images/pasteLayerStyle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/pasteLayerStyle.gif -------------------------------------------------------------------------------- /images/pasteStyleAndContent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/pasteStyleAndContent.gif -------------------------------------------------------------------------------- /images/pasteSymbol.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/pasteSymbol.gif -------------------------------------------------------------------------------- /images/pasteTextStyle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/pasteTextStyle.gif -------------------------------------------------------------------------------- /images/pasteall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/pasteall.gif -------------------------------------------------------------------------------- /images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pausansol/Escriba/7e5a6fd27cb564f546a06e5fc5e36e2e0611e8ab/images/settings.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "escriba", 3 | "version": "1.1.0", 4 | "description": "Copy & Paste overrides", 5 | "skpm": { 6 | "name": "Escriba", 7 | "manifest": "src/manifest.json", 8 | "main": "Escriba.sketchplugin", 9 | "assets": [ 10 | "assets/**/*" 11 | ] 12 | }, 13 | "scripts": { 14 | "build": "skpm-build", 15 | "watch": "skpm-build --watch", 16 | "start": "skpm-build --watch --run", 17 | "postinstall": "npm run build && skpm-link", 18 | "lint-staged": "lint-staged", 19 | "prettier:base": "prettier --single-quote --trailing-comma es5 --no-semi --write", 20 | "prettify": "npm run prettier:base \"./src/**/*.js\"" 21 | }, 22 | "devDependencies": { 23 | "@skpm/builder": "^0.4.2", 24 | "eslint": "^4.8.0", 25 | "eslint-config-airbnb-base": "^12.0.2", 26 | "eslint-config-prettier": "^2.6.0", 27 | "eslint-plugin-import": "^2.7.0", 28 | "eslint-plugin-no-not-accumulator-reassign": "^0.1.0", 29 | "eslint-plugin-prettier": "^2.3.1", 30 | "lint-staged": "^4.2.3", 31 | "pre-commit": "^1.2.2", 32 | "prettier": "^1.7.4" 33 | }, 34 | "pre-commit": [ 35 | "lint-staged" 36 | ], 37 | "lint-staged": { 38 | "*.js": [ 39 | "npm run prettier:base", 40 | "eslint --quiet --rule 'prettier/prettier: [\"error\", {\"trailingComma\": \"es5\", \"singleQuote\": true}]'", 41 | "git add" 42 | ] 43 | }, 44 | "author": "Pausansol " 45 | } 46 | -------------------------------------------------------------------------------- /src/analytics.js: -------------------------------------------------------------------------------- 1 | 2 | export default function googleAnalytics(context, category, action, label, value) { 3 | var trackingID = "UA-128191866-1"; 4 | var uuidKey = "google.analytics.uuid"; 5 | var url = "https://www.google-analytics.com/collect?v=1"; 6 | var uuid = NSUserDefaults.standardUserDefaults().objectForKey(uuidKey); 7 | 8 | if (!uuid) { 9 | uuid = NSUUID.UUID().UUIDString(); 10 | NSUserDefaults.standardUserDefaults().setObject_forKey(uuid,uuidKey); 11 | } 12 | 13 | // Tracking ID 14 | url += "&tid=" + trackingID; 15 | // Source 16 | url += "&ds=sketch" + MSApplicationMetadata.metadata().appVersion; 17 | // Client ID 18 | url += "&cid=" + uuid; 19 | // pageview, screenview, event, transaction, item, social, exception, timing 20 | url += "&t=event"; 21 | // App Name 22 | url += "&an=" + encodeURI(context.plugin.name()); 23 | // App Version 24 | url += "&av=" + context.plugin.version(); 25 | // Event category 26 | url += "&ec=" + encodeURI(category); 27 | // Event action 28 | url += "&ea=" + encodeURI(action); 29 | // Event label 30 | if (label) { 31 | url += "&el=" + encodeURI(label); 32 | } 33 | // Event value 34 | if (value) { 35 | url += "&ev=" + encodeURI(value); 36 | } 37 | 38 | var session = NSURLSession.sharedSession(), 39 | task = session.dataTaskWithURL(NSURL.URLWithString(NSString.stringWithString(url))); 40 | task.resume(); 41 | } 42 | -------------------------------------------------------------------------------- /src/copy.js: -------------------------------------------------------------------------------- 1 | import googleAnalytics from './analytics' 2 | 3 | var sketch = require('sketch/dom') 4 | const doc = sketch.getSelectedDocument() 5 | const selection = doc.selectedLayers.layers 6 | var UI = require('sketch/ui') 7 | var Settings = require('sketch/settings') 8 | 9 | export function copySelected (selectedOverrideId, context){ 10 | selection.forEach(function (layer) { 11 | layer.overrides.forEach(function (override){ 12 | if(selectedOverrideId == override.affectedLayer.id){ 13 | var string = override.value 14 | 15 | var property = override.property 16 | var settingName = [`settings${property}`] 17 | Settings.setSessionVariable(settingName, string) 18 | googleAnalytics(context, "Escriba Success", "Copy done", string); 19 | } 20 | }) 21 | }) 22 | } 23 | 24 | export default function(context) { 25 | const selectedOverrides = context.document.documentData().selectedOverrides(); 26 | if (selectedOverrides.length == 1){ 27 | selectedOverrides.forEach(function(selectedOverride){ 28 | if(selectedOverride.includes('/')){ 29 | var tokens = selectedOverride.split('/') 30 | var element = tokens[tokens.length-1] 31 | var tokensSplit = element.split('_') 32 | var selectedOverrideId = tokensSplit[tokensSplit.length-2] 33 | googleAnalytics(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 34 | copySelected(selectedOverrideId, context) 35 | 36 | } else { 37 | var tokens = selectedOverride.split('#') 38 | var element = tokens[tokens.length-1] 39 | var tokensSplit = element.split('_') 40 | var selectedOverrideId = tokensSplit[tokensSplit.length-2] 41 | googleAnalytics(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 42 | copySelected(selectedOverrideId, context) 43 | } 44 | }) 45 | } 46 | if (selectedOverrides.length < 1){ 47 | UI.message('⚠️ Select one Symbol override to copy ⚠️') 48 | googleAnalytics(context, "Escriba UI", "No override selected to copy"); 49 | } 50 | if (selectedOverrides.length > 1){ 51 | UI.message('⚠️ You have selected more than one override, select only one Symbol override to copy ⚠️') 52 | googleAnalytics(context, "Escriba UI", "More than one override selected to copy"); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/create-alert-window.js: -------------------------------------------------------------------------------- 1 | export default function createAlertWindow(context) { 2 | const alertWindow = COSAlertWindow.new() 3 | 4 | alertWindow.setIcon(NSImage.alloc().initByReferencingFile(context.plugin.urlForResourceNamed('icon.png').path())) 5 | alertWindow.setMessageText('Escriba') 6 | alertWindow.setInformativeText("Configure your Escriba preferences. What properties of overrides do you want to Copy&Paste?") 7 | 8 | return alertWindow 9 | } -------------------------------------------------------------------------------- /src/create-radio-buttons.js: -------------------------------------------------------------------------------- 1 | export default function createRadioButtons(options,selected,format,x,y) { 2 | var rows = options.length, 3 | columns = 1, 4 | buttonMatrixWidth = 300, 5 | buttonCellWidth = buttonMatrixWidth, 6 | x = (x) ? x : 0, 7 | y = (y) ? y : 0; 8 | 9 | if (format && format != 0) { 10 | rows = options.length / 2; 11 | columns = 2; 12 | buttonMatrixWidth = 300; 13 | buttonCellWidth = buttonMatrixWidth / columns; 14 | } 15 | 16 | var buttonCell = NSButtonCell.alloc().init(); 17 | 18 | buttonCell.setButtonType(NSRadioButton); 19 | 20 | var buttonMatrix = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns( 21 | NSMakeRect(x,y,buttonMatrixWidth,rows*24), 22 | NSRadioModeMatrix, 23 | buttonCell, 24 | rows, 25 | columns 26 | ); 27 | 28 | buttonMatrix.setCellSize(NSMakeSize(buttonCellWidth,24)); 29 | 30 | var i = 0 31 | 32 | for (i = 0; i < options.length; i++) { 33 | buttonMatrix.cells().objectAtIndex(i).setTitle(options[i]); 34 | buttonMatrix.cells().objectAtIndex(i).setTag(i); 35 | } 36 | 37 | buttonMatrix.selectCellAtRow_column(selected,0); 38 | 39 | return buttonMatrix; 40 | } -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "compatibleVersion": 53, 3 | "bundleVersion": 1, 4 | "icon": "icon.png", 5 | "appcast": "https://raw.githubusercontent.com/pausansol/escriba/master/appcast.xml", 6 | "commands": [ 7 | { 8 | "name": "Copy", 9 | "identifier": "copy-identifier", 10 | "shortcut": "ctrl command z", 11 | "script": "./copy.js" 12 | }, 13 | { 14 | "name": "Paste", 15 | "identifier": "paste-identifier", 16 | "shortcut": "ctrl command x", 17 | "script": "./paste.js" 18 | }, 19 | { 20 | "name": "Settings", 21 | "identifier": "settings-identifier", 22 | "script": "./settings.js" 23 | } 24 | ], 25 | "menu": { 26 | "title": "Escriba", 27 | "items": [ 28 | "copy-identifier", 29 | "paste-identifier", 30 | "-", 31 | "settings-identifier" 32 | ] 33 | } 34 | } -------------------------------------------------------------------------------- /src/paste.js: -------------------------------------------------------------------------------- 1 | import googleAnalytics from './analytics' 2 | 3 | var sketch = require('sketch/dom') 4 | const doc = sketch.getSelectedDocument() 5 | const selection = doc.selectedLayers.layers 6 | var UI = require('sketch/ui') 7 | var Settings = require('sketch/settings') 8 | 9 | export function pasteSelected(selectedOverrideId, context){ 10 | selection.forEach(function (layer) { 11 | layer.overrides.forEach(function (override){ 12 | if(selectedOverrideId == override.affectedLayer.id){ 13 | var property = override.property 14 | var getseetting = [`Value${property}`] 15 | var settingValue = Settings.settingForKey(getseetting.toString()) 16 | 17 | if(settingValue == 1 || undefined){ 18 | var settingName = [`settings${property}`] 19 | var setting = Settings.sessionVariable(settingName) 20 | override.value = setting 21 | googleAnalytics(context, "Escriba Success", "Paste done", setting) 22 | } else { 23 | if(property == 'symbolID' || property == 'layerStyle'){ 24 | UI.message('⚠️ ' + property + ' Copy&Paste is disabled, you can enable it in Escriba/Settings ⚠️') 25 | } 26 | } 27 | } 28 | }) 29 | }) 30 | } 31 | 32 | export default function(context){ 33 | const selectedOverrides = context.document.documentData().selectedOverrides(); 34 | if (selectedOverrides.length > 0){ 35 | selectedOverrides.forEach(function(selectedOverride){ 36 | if(selectedOverride.includes('/')){ 37 | var tokens = selectedOverride.split('/') 38 | var element = tokens[tokens.length-1] 39 | var tokensSplit = element.split('_') 40 | var selectedOverrideId = tokensSplit[tokensSplit.length-2] 41 | googleAnalytics(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 42 | pasteSelected(selectedOverrideId, context) 43 | } else { 44 | var tokens = selectedOverride.split('#') 45 | var element = tokens[tokens.length-1] 46 | var tokensSplit = element.split('_') 47 | var selectedOverrideId = tokensSplit[tokensSplit.length-2] 48 | googleAnalytics(context, "Escriba Initiated", "Copy selected", selectedOverrideId); 49 | pasteSelected(selectedOverrideId, context) 50 | } 51 | }) 52 | } else { 53 | UI.message('⚠️ Select one Symbol override to paste ⚠️') 54 | googleAnalytics(context, "Escriba UI", "No override selected to paste"); 55 | } 56 | } -------------------------------------------------------------------------------- /src/settings.js: -------------------------------------------------------------------------------- 1 | import createAlertWindow from './create-alert-window' 2 | import googleAnalytics from './analytics' 3 | var Settings = require('sketch/settings') 4 | 5 | export default function(context){ 6 | googleAnalytics(context, "Escriba settings", "Open") 7 | 8 | // create the alertWindow UI 9 | const alertWindow = createAlertWindow(context); 10 | 11 | // create the radioButtons 12 | // Create inputs 13 | 14 | // Create the main view 15 | var viewWidth = 400; 16 | var viewHeight = 210; 17 | var viewSpacer = 10; 18 | var layerStyleCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 125, viewWidth - viewSpacer, 20)); 19 | var textStyleCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 150, (viewWidth / 2) - viewSpacer, 20)); 20 | var stringValueCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 175, (viewWidth / 2) - viewSpacer, 20)); 21 | var symbolIDCheckbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - 200, (viewWidth / 2) - viewSpacer, 20)); 22 | 23 | var layerStyleSetting = Settings.settingForKey('ValuelayerStyle') 24 | var textStyleSetting = Settings.settingForKey('ValuetextStyle') 25 | var stringValueSetting = Settings.settingForKey('ValuestringValue') 26 | var symbolIDSetting = Settings.settingForKey('ValuesymbolID') 27 | // Configure checkboxes 28 | 29 | layerStyleCheckbox.setButtonType(NSSwitchButton); 30 | layerStyleCheckbox.setBezelStyle(0); 31 | layerStyleCheckbox.setTitle("Layer Style"); 32 | if(layerStyleSetting == 1 || layerStyleSetting == undefined){ 33 | layerStyleCheckbox.setState(NSOnState); 34 | } else { 35 | layerStyleCheckbox.setState(NSOffState); 36 | } 37 | 38 | textStyleCheckbox.setButtonType(NSSwitchButton); 39 | textStyleCheckbox.setBezelStyle(0); 40 | textStyleCheckbox.setTitle("Text Style"); 41 | if(textStyleSetting == 1 || textStyleSetting == undefined){ 42 | textStyleCheckbox.setState(NSOnState); 43 | } else { 44 | textStyleCheckbox.setState(NSOffState); 45 | } 46 | 47 | stringValueCheckbox.setButtonType(NSSwitchButton); 48 | stringValueCheckbox.setBezelStyle(0); 49 | stringValueCheckbox.setTitle("Text content"); 50 | if(stringValueSetting == 1 || stringValueSetting == undefined){ 51 | stringValueCheckbox.setState(NSOnState); 52 | } else { 53 | stringValueCheckbox.setState(NSOffState); 54 | } 55 | 56 | symbolIDCheckbox.setButtonType(NSSwitchButton); 57 | symbolIDCheckbox.setBezelStyle(0); 58 | symbolIDCheckbox.setTitle("Symbol"); 59 | if(symbolIDSetting == 1 || symbolIDSetting == undefined){ 60 | symbolIDCheckbox.setState(NSOnState); 61 | } else { 62 | symbolIDCheckbox.setState(NSOffState); 63 | } 64 | 65 | //Adding inputs to the dialog 66 | alertWindow.addAccessoryView(layerStyleCheckbox); 67 | alertWindow.addAccessoryView(textStyleCheckbox); 68 | alertWindow.addAccessoryView(stringValueCheckbox); 69 | alertWindow.addAccessoryView(symbolIDCheckbox); 70 | 71 | alertWindow.addButtonWithTitle('Save') 72 | alertWindow.addButtonWithTitle('Cancel') 73 | 74 | if (alertWindow.runModal() == NSAlertFirstButtonReturn) { 75 | Settings.setSettingForKey('ValuelayerStyle', layerStyleCheckbox.state()) 76 | Settings.setSettingForKey('ValuetextStyle', textStyleCheckbox.state()) 77 | Settings.setSettingForKey('ValuestringValue', stringValueCheckbox.state()) 78 | Settings.setSettingForKey('ValuesymbolID', symbolIDCheckbox.state()) 79 | googleAnalytics(context, "Escriba settings", "Save") 80 | } 81 | } --------------------------------------------------------------------------------