├── .appcast.xml ├── .gitignore ├── LICENSE ├── README.md ├── assets └── icon.png ├── design-token-exporter.sketchplugin └── Contents │ ├── Resources │ └── icon.png │ └── Sketch │ ├── __colorTokens.js │ ├── __colorTokens.js.map │ ├── __exportTokens.js │ ├── __exportTokens.js.map │ ├── __spacingTokens.js │ ├── __spacingTokens.js.map │ ├── __textObjects.js │ ├── __textObjects.js.map │ ├── __textTokens.js │ ├── __textTokens.js.map │ ├── colorTokens.js │ ├── colorTokens.js.map │ ├── exportTokens.js │ ├── exportTokens.js.map │ ├── manifest.json │ ├── spacingTokens.js │ ├── spacingTokens.js.map │ ├── textObjects.js │ ├── textObjects.js.map │ ├── textTokens.js │ └── textTokens.js.map ├── images ├── colors.gif ├── exportTokens.gif ├── fontsize.gif ├── gitcover.jpg ├── spacing.gif └── textstyles.gif ├── package-lock.json ├── package.json └── src ├── colorTokens.js ├── exportTokens.js ├── lib ├── dialogFields.js ├── formatObject.js ├── hexAToRGBA.js ├── tokenValue.js ├── values.js └── varNaming.js ├── manifest.json ├── spacingTokens.js ├── textObjects.js └── textTokens.js /.appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build artifacts 2 | # design-token-exporter.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 | 15 | # sketch 16 | # sketch-assets -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Herkko Huttunen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![alt text](images/gitcover.jpg) 2 | 3 | # This project is not maintained anymore 4 | 5 | ## Design Token Exporter 6 | 7 | **Export Design Tokens from your Sketch project.** 8 | 9 | - You can export Design Token file either JSON or YAML format. Token file follow Salesforce [Theo](https://github.com/salesforce-ux/theo) spec. 10 | - Layers naming format is type/category/tokenname (e.g. color/background-color/bg-light) 11 | 12 | **Available categories:** 13 | 14 | | Category | Sketch Layer type | Value | 15 | | --------------------------- | ------------------------------ | --------------------------------------------------------- | 16 | | `spacing`/`space`/`spacer` | Shape Layer | Layer height | 17 | | `sizing`/`size` | Shape Layer | Layer height | 18 | | `font` | Text Layer | Font weight (type=number) / Font Family (type=...) | 19 | | `font-style` | Text Layer | Font style | 20 | | `font-weight` | Text Layer | Font weight | 21 | | `font-size` | Text Layer | Font Size | 22 | | `line-height` | Text Layer | Line height | 23 | | `font-family` | Text Layer | Font Family | 24 | | `border-style` | Shape Layer | Border style | 25 | | `border-color` | Shape Layer | Border style or Fill color | 26 | | `radius` | Shape Layer | Radius | 27 | | `border-radius` | Shape Layer | Radius | 28 | | `hr-color` | Shape Layer | Fill color | 29 | | `background-color` | Shape Layer | Fill color | 30 | | `gradient` | Shape Layer | Fill gradient | 31 | | `background-gradient` | Shape Layer | Fill gradient | 32 | | `drop-shadow` | Shape Layer | Shadows | 33 | | `box-shadow` | Shape Layer | Shadows | 34 | | `inner-shadow` | Shape Layer | Inner Shadows | 35 | | `text-color` | Shape Layer or Text Layer | Text color or Fill color | 36 | | `text-shadow` | Shape Layer or Text Layer | Layer shadow | 37 | | `time` | Text Layer | Text layer value | 38 | | `media-query` | Text Layer | Text layer value | 39 | | `z-index` | Text Layer | Text layer value | 40 | | `any` | Shape Layer | Fill color (type=color) | 41 | 42 | 43 | **Export variables from your Sketch project. You can export colors, text, spacing variables and text styles.** 44 | 45 | - You can choose file format: SCSS, CSS, LESS, JSON, JavaScript (Object/Variables) 46 | - You can choose color format: HEX or RGBA 47 | - You can choose text value: font family, font size, font weight, line height or letter spacing 48 | - You can choose units: Absolute (px) or Relative (rem) 49 | - You can choose naming (kebab-case, camelCase or part of layer name) 50 | 51 | ## Features 52 | 53 | 1. Export Tokens 54 | 2. Export Color Variables 55 | 3. Export Text Variables 56 | 4. Export Spacing Variables 57 | 5. Export Text Styles 58 | 59 | ### 1. Export Tokens 60 | 61 | Select layers or one artboard and go to `Plugins -> Design Token Exporter -> Export Tokens` 62 | 63 | ![alt text](images/exportTokens.gif) 64 | 65 | **Example output - tokens.yml** 66 | 67 | ```yml 68 | props: 69 | gray_1: 70 | value: "#fafaf9" 71 | type: "color" 72 | category: "gray" 73 | gradient_background: 74 | value: "linear-gradient(180deg, #FAFAF9 0%, #F3F2F2 100%)" 75 | type: "..." 76 | category: "gradient" 77 | spacing_m: 78 | value: "16px" 79 | type: "number" 80 | category: "spacing" 81 | font_size_l: 82 | value: "24px" 83 | type: "number" 84 | category: "font-size" 85 | ``` 86 | 87 | ### 2. Export Color Variables 88 | 89 | Select layers and go to `Plugins -> Design Token Exporter -> Export Color Variables` 90 | 91 | ![alt text](images/colors.gif) 92 | 93 | **Example output - colors.scss (SCSS, HEX)** 94 | 95 | ```scss 96 | $primary1: #b39ddb; 97 | $primary2: #673ab7; 98 | $primary3: #512da8; 99 | $primary4: #311b92; 100 | $secondary1: #b2dfdb; 101 | $secondary2: #4db6ac; 102 | $secondary3: #009688; 103 | $secondary4: #00796b; 104 | $grey1: #cfd8dc; 105 | $grey2: #90a4ae; 106 | $grey3: #607d8b; 107 | $grey4: #37474f; 108 | ``` 109 | 110 | ### 3. Export Text Variables 111 | 112 | Select layers and go to `Plugins -> Design Token Exporter -> Export Text Variables` 113 | 114 | ![alt text](images/fontsize.gif) 115 | 116 | **Example output - fontsize.json (JSON, Font size, Absolute(px))** 117 | 118 | ```json 119 | { 120 | "fontSize": { 121 | "xxl": "64px", 122 | "xl": "48px", 123 | "l": "32px", 124 | "m": "24px", 125 | "s": "20px", 126 | "xs": "16px", 127 | "xxs": "12px" 128 | } 129 | } 130 | ``` 131 | 132 | ### 4. Export Spacing Variables 133 | 134 | Select layers and go to `Plugins -> Design Token Exporter -> Export Spacing Variables` 135 | 136 | ![alt text](images/spacing.gif) 137 | 138 | **Example output - spacing.css (CSS, Relative(rem))** 139 | 140 | ```css 141 | :root { 142 | --spacing-xxs: 0.25rem; 143 | --spacing-xs: 0.5rem; 144 | --spacing-s: 1rem; 145 | --spacing-m: 1.5rem; 146 | --spacing-l: 3rem; 147 | --spacing-xl: 4rem; 148 | --spacing-xxl: 8rem; 149 | } 150 | ``` 151 | 152 | ### 5. Export Text Styles 153 | 154 | Select layers and go to `Plugins -> Design Token Exporter -> Export Text Styles` 155 | 156 | ![alt text](images/textstyles.gif) 157 | 158 | **Example output - textstyles.js (JavaScript Object, Absolute(px))** 159 | 160 | ```js 161 | const textStyles = { 162 | h1: { 163 | fontFamily: "Museo Sans", 164 | fontSize: "64px", 165 | fontWeight: 300, 166 | lineHeight: "64px", 167 | letterSpacing: "normal", 168 | textTransform: "none", 169 | }, 170 | h2: { 171 | fontFamily: "Museo Sans", 172 | fontSize: "48px", 173 | fontWeight: 300, 174 | lineHeight: "48px", 175 | letterSpacing: "normal", 176 | textTransform: "none", 177 | }, 178 | h3: { 179 | fontFamily: "Museo Sans", 180 | fontSize: "32px", 181 | fontWeight: 300, 182 | lineHeight: "48px", 183 | letterSpacing: "normal", 184 | textTransform: "none", 185 | }, 186 | h4: { 187 | fontFamily: "Museo Sans", 188 | fontSize: "24px", 189 | fontWeight: 500, 190 | lineHeight: "36px", 191 | letterSpacing: "normal", 192 | textTransform: "none", 193 | }, 194 | title: { 195 | fontFamily: "Museo Sans", 196 | fontSize: "20px", 197 | fontWeight: 700, 198 | lineHeight: "36px", 199 | letterSpacing: "1.5px", 200 | textTransform: "uppercase", 201 | }, 202 | body: { 203 | fontFamily: "Museo Sans", 204 | fontSize: "16px", 205 | fontWeight: 500, 206 | lineHeight: "24px", 207 | letterSpacing: "normal", 208 | textTransform: "none", 209 | }, 210 | caption: { 211 | fontFamily: "Museo Sans", 212 | fontSize: "12px", 213 | fontWeight: 500, 214 | lineHeight: "18px", 215 | letterSpacing: "normal", 216 | textTransform: "none", 217 | }, 218 | } 219 | ``` 220 | 221 | 222 | ## License 223 | 224 | This project is licensed under the terms of the MIT license. 225 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/assets/icon.png -------------------------------------------------------------------------------- /design-token-exporter.sketchplugin/Contents/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/design-token-exporter.sketchplugin/Contents/Resources/icon.png -------------------------------------------------------------------------------- /design-token-exporter.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Design Token Exporter", 3 | "identifier": "fi.erhe.design-token-exporter", 4 | "description": "Simple Design Token Exporter", 5 | "homepage": "https://github.com/here-erhe/Design-Token-Exporter", 6 | "author": "Herkko Huttunen", 7 | "icon": "icon.png", 8 | "compatibleVersion": "54.0", 9 | "commands": [ 10 | { 11 | "name": "Export Tokens", 12 | "identifier": "tokens.tokens", 13 | "script": "__exportTokens.js", 14 | "description": "Export multiple multiple layers or one artboard" 15 | }, 16 | { 17 | "name": "Export Colors Variables", 18 | "identifier": "tokens.colors", 19 | "script": "__colorTokens.js", 20 | "description": "Export selected layers" 21 | }, 22 | { 23 | "name": "Export Text Variables", 24 | "identifier": "tokens.text", 25 | "script": "__textTokens.js", 26 | "description": "Export selected layers" 27 | }, 28 | { 29 | "name": "Export Spacing Variables", 30 | "identifier": "tokens.spacing", 31 | "script": "__spacingTokens.js", 32 | "description": "Export selected layers" 33 | }, 34 | { 35 | "name": "Export Text Styles", 36 | "identifier": "tokens.styles", 37 | "script": "__textObjects.js", 38 | "description": "Export selected layers" 39 | } 40 | ], 41 | "menu": { 42 | "title": "Design Token Exporter", 43 | "items": [ 44 | "tokens.tokens", 45 | "-", 46 | "tokens.colors", 47 | "tokens.text", 48 | "tokens.spacing", 49 | "-", 50 | "tokens.styles" 51 | ] 52 | }, 53 | "version": "1.0.0", 54 | "disableCocoaScriptPreprocessor": true, 55 | "appcast": "https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/master/.appcast.xml" 56 | } -------------------------------------------------------------------------------- /design-token-exporter.sketchplugin/Contents/Sketch/spacingTokens.js: -------------------------------------------------------------------------------- 1 | var globalThis=this;function __skpm_run(n,t){globalThis.context=t;var r=function(n){var t={};function r(e){if(t[e])return t[e].exports;var u=t[e]={i:e,l:!1,exports:{}};return n[e].call(u.exports,u,u.exports,r),u.l=!0,u.exports}return r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},r.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},r.t=function(n,t){if(1&t&&(n=r(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(r.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var u in n)r.d(e,u,function(t){return n[t]}.bind(null,u));return e},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=7)}([function(n,t,r){(function(n,e){var u;(function(){var i,o=200,a="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",f="Expected a function",c="__lodash_hash_undefined__",l=500,s="__lodash_placeholder__",p=1,h=2,v=4,_=1,g=2,y=1,d=2,b=4,w=8,m=16,x=32,S=64,j=128,A=256,O=512,k=30,E="...",I=800,R=16,C=1,z=2,W=1/0,L=9007199254740991,T=17976931348623157e292,N=NaN,B=4294967295,U=B-1,M=B>>>1,F=[["ary",j],["bind",y],["bindKey",d],["curry",w],["curryRight",m],["flip",O],["partial",x],["partialRight",S],["rearg",A]],P="[object Arguments]",$="[object Array]",D="[object AsyncFunction]",q="[object Boolean]",V="[object Date]",J="[object DOMException]",Z="[object Error]",K="[object Function]",Y="[object GeneratorFunction]",G="[object Map]",H="[object Number]",Q="[object Null]",X="[object Object]",nn="[object Proxy]",tn="[object RegExp]",rn="[object Set]",en="[object String]",un="[object Symbol]",on="[object Undefined]",an="[object WeakMap]",fn="[object WeakSet]",cn="[object ArrayBuffer]",ln="[object DataView]",sn="[object Float32Array]",pn="[object Float64Array]",hn="[object Int8Array]",vn="[object Int16Array]",_n="[object Int32Array]",gn="[object Uint8Array]",yn="[object Uint8ClampedArray]",dn="[object Uint16Array]",bn="[object Uint32Array]",wn=/\b__p \+= '';/g,mn=/\b(__p \+=) '' \+/g,xn=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Sn=/&(?:amp|lt|gt|quot|#39);/g,jn=/[&<>"']/g,An=RegExp(Sn.source),On=RegExp(jn.source),kn=/<%-([\s\S]+?)%>/g,En=/<%([\s\S]+?)%>/g,In=/<%=([\s\S]+?)%>/g,Rn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Cn=/^\w*$/,zn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Wn=/[\\^$.*+?()[\]{}|]/g,Ln=RegExp(Wn.source),Tn=/^\s+|\s+$/g,Nn=/^\s+/,Bn=/\s+$/,Un=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Mn=/\{\n\/\* \[wrapped with (.+)\] \*/,Fn=/,? & /,Pn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,$n=/\\(\\)?/g,Dn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,qn=/\w*$/,Vn=/^[-+]0x[0-9a-f]+$/i,Jn=/^0b[01]+$/i,Zn=/^\[object .+?Constructor\]$/,Kn=/^0o[0-7]+$/i,Yn=/^(?:0|[1-9]\d*)$/,Gn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Hn=/($^)/,Qn=/['\n\r\u2028\u2029\\]/g,Xn="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",nt="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",tt="[\\ud800-\\udfff]",rt="["+nt+"]",et="["+Xn+"]",ut="\\d+",it="[\\u2700-\\u27bf]",ot="[a-z\\xdf-\\xf6\\xf8-\\xff]",at="[^\\ud800-\\udfff"+nt+ut+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",ft="\\ud83c[\\udffb-\\udfff]",ct="[^\\ud800-\\udfff]",lt="(?:\\ud83c[\\udde6-\\uddff]){2}",st="[\\ud800-\\udbff][\\udc00-\\udfff]",pt="[A-Z\\xc0-\\xd6\\xd8-\\xde]",ht="(?:"+ot+"|"+at+")",vt="(?:"+pt+"|"+at+")",_t="(?:"+et+"|"+ft+")"+"?",gt="[\\ufe0e\\ufe0f]?"+_t+("(?:\\u200d(?:"+[ct,lt,st].join("|")+")[\\ufe0e\\ufe0f]?"+_t+")*"),yt="(?:"+[it,lt,st].join("|")+")"+gt,dt="(?:"+[ct+et+"?",et,lt,st,tt].join("|")+")",bt=RegExp("['’]","g"),wt=RegExp(et,"g"),mt=RegExp(ft+"(?="+ft+")|"+dt+gt,"g"),xt=RegExp([pt+"?"+ot+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[rt,pt,"$"].join("|")+")",vt+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[rt,pt+ht,"$"].join("|")+")",pt+"?"+ht+"+(?:['’](?:d|ll|m|re|s|t|ve))?",pt+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ut,yt].join("|"),"g"),St=RegExp("[\\u200d\\ud800-\\udfff"+Xn+"\\ufe0e\\ufe0f]"),jt=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,At=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Ot=-1,kt={};kt[sn]=kt[pn]=kt[hn]=kt[vn]=kt[_n]=kt[gn]=kt[yn]=kt[dn]=kt[bn]=!0,kt[P]=kt[$]=kt[cn]=kt[q]=kt[ln]=kt[V]=kt[Z]=kt[K]=kt[G]=kt[H]=kt[X]=kt[tn]=kt[rn]=kt[en]=kt[an]=!1;var Et={};Et[P]=Et[$]=Et[cn]=Et[ln]=Et[q]=Et[V]=Et[sn]=Et[pn]=Et[hn]=Et[vn]=Et[_n]=Et[G]=Et[H]=Et[X]=Et[tn]=Et[rn]=Et[en]=Et[un]=Et[gn]=Et[yn]=Et[dn]=Et[bn]=!0,Et[Z]=Et[K]=Et[an]=!1;var It={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Rt=parseFloat,Ct=parseInt,zt="object"==typeof n&&n&&n.Object===Object&&n,Wt="object"==typeof self&&self&&self.Object===Object&&self,Lt=zt||Wt||Function("return this")(),Tt=t&&!t.nodeType&&t,Nt=Tt&&"object"==typeof e&&e&&!e.nodeType&&e,Bt=Nt&&Nt.exports===Tt,Ut=Bt&&zt.process,Mt=function(){try{var n=Nt&&Nt.require&&Nt.require("util").types;return n||Ut&&Ut.binding&&Ut.binding("util")}catch(t){}}(),Ft=Mt&&Mt.isArrayBuffer,Pt=Mt&&Mt.isDate,$t=Mt&&Mt.isMap,Dt=Mt&&Mt.isRegExp,qt=Mt&&Mt.isSet,Vt=Mt&&Mt.isTypedArray;function Jt(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function Zt(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function Xt(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function mr(n,t){for(var r=n.length;r--&&fr(t,n[r],0)>-1;);return r}var xr=hr({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),Sr=hr({"&":"&","<":"<",">":">",'"':""","'":"'"});function jr(n){return"\\"+It[n]}function Ar(n){return St.test(n)}function Or(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function kr(n,t){return function(r){return n(t(r))}}function Er(n,t){for(var r=-1,e=n.length,u=0,i=[];++r",""":'"',"'":"'"});var Lr=function n(t){var r,e=(t=null==t?Lt:Lr.defaults(Lt.Object(),t,Lr.pick(Lt,At))).Array,u=t.Date,Xn=t.Error,nt=t.Function,tt=t.Math,rt=t.Object,et=t.RegExp,ut=t.String,it=t.TypeError,ot=e.prototype,at=nt.prototype,ft=rt.prototype,ct=t["__core-js_shared__"],lt=at.toString,st=ft.hasOwnProperty,pt=0,ht=(r=/[^.]+$/.exec(ct&&ct.keys&&ct.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"",vt=ft.toString,_t=lt.call(rt),gt=Lt._,yt=et("^"+lt.call(st).replace(Wn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),dt=Bt?t.Buffer:i,mt=t.Symbol,St=t.Uint8Array,It=dt?dt.allocUnsafe:i,zt=kr(rt.getPrototypeOf,rt),Wt=rt.create,Tt=ft.propertyIsEnumerable,Nt=ot.splice,Ut=mt?mt.isConcatSpreadable:i,Mt=mt?mt.iterator:i,ir=mt?mt.toStringTag:i,hr=function(){try{var n=Ui(rt,"defineProperty");return n({},"",{}),n}catch(t){}}(),Tr=t.clearTimeout!==Lt.clearTimeout&&t.clearTimeout,Nr=u&&u.now!==Lt.Date.now&&u.now,Br=t.setTimeout!==Lt.setTimeout&&t.setTimeout,Ur=tt.ceil,Mr=tt.floor,Fr=rt.getOwnPropertySymbols,Pr=dt?dt.isBuffer:i,$r=t.isFinite,Dr=ot.join,qr=kr(rt.keys,rt),Vr=tt.max,Jr=tt.min,Zr=u.now,Kr=t.parseInt,Yr=tt.random,Gr=ot.reverse,Hr=Ui(t,"DataView"),Qr=Ui(t,"Map"),Xr=Ui(t,"Promise"),ne=Ui(t,"Set"),te=Ui(t,"WeakMap"),re=Ui(rt,"create"),ee=te&&new te,ue={},ie=lo(Hr),oe=lo(Qr),ae=lo(Xr),fe=lo(ne),ce=lo(te),le=mt?mt.prototype:i,se=le?le.valueOf:i,pe=le?le.toString:i;function he(n){if(Ea(n)&&!ya(n)&&!(n instanceof ye)){if(n instanceof ge)return n;if(st.call(n,"__wrapped__"))return so(n)}return new ge(n)}var ve=function(){function n(){}return function(t){if(!ka(t))return{};if(Wt)return Wt(t);n.prototype=t;var r=new n;return n.prototype=i,r}}();function _e(){}function ge(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=i}function ye(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=B,this.__views__=[]}function de(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function Te(n,t,r,e,u,o){var a,f=t&p,c=t&h,l=t&v;if(r&&(a=u?r(n,e,u,o):r(n)),a!==i)return a;if(!ka(n))return n;var s=ya(n);if(s){if(a=function(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&st.call(n,"index")&&(r.index=n.index,r.input=n.input),r}(n),!f)return ri(n,a)}else{var _=Pi(n),g=_==K||_==Y;if(ma(n))return Gu(n,f);if(_==X||_==P||g&&!u){if(a=c||g?{}:Di(n),!f)return c?function(n,t){return ei(n,Fi(n),t)}(n,function(n,t){return n&&ei(t,of(t),n)}(a,n)):function(n,t){return ei(n,Mi(n),t)}(n,Ce(a,n))}else{if(!Et[_])return u?n:{};a=function(n,t,r){var e,u=n.constructor;switch(t){case cn:return Hu(n);case q:case V:return new u(+n);case ln:return function(n,t){var r=t?Hu(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}(n,r);case sn:case pn:case hn:case vn:case _n:case gn:case yn:case dn:case bn:return Qu(n,r);case G:return new u;case H:case en:return new u(n);case tn:return function(n){var t=new n.constructor(n.source,qn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case rn:return new u;case un:return e=n,se?rt(se.call(e)):{}}}(n,_,f)}}o||(o=new xe);var y=o.get(n);if(y)return y;o.set(n,a),Wa(n)?n.forEach(function(e){a.add(Te(e,t,r,e,n,o))}):Ia(n)&&n.forEach(function(e,u){a.set(u,Te(e,t,r,u,n,o))});var d=s?i:(l?c?Ci:Ri:c?of:uf)(n);return Kt(d||n,function(e,u){d&&(e=n[u=e]),Ee(a,u,Te(e,t,r,u,n,o))}),a}function Ne(n,t,r){var e=r.length;if(null==n)return!e;for(n=rt(n);e--;){var u=r[e],o=t[u],a=n[u];if(a===i&&!(u in n)||!o(a))return!1}return!0}function Be(n,t,r){if("function"!=typeof n)throw new it(f);return eo(function(){n.apply(i,r)},t)}function Ue(n,t,r,e){var u=-1,i=Qt,a=!0,f=n.length,c=[],l=t.length;if(!f)return c;r&&(t=nr(t,yr(r))),e?(i=Xt,a=!1):t.length>=o&&(i=br,a=!1,t=new me(t));n:for(;++u-1},be.prototype.set=function(n,t){var r=this.__data__,e=Ie(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},we.prototype.clear=function(){this.size=0,this.__data__={hash:new de,map:new(Qr||be),string:new de}},we.prototype.delete=function(n){var t=Ni(this,n).delete(n);return this.size-=t?1:0,t},we.prototype.get=function(n){return Ni(this,n).get(n)},we.prototype.has=function(n){return Ni(this,n).has(n)},we.prototype.set=function(n,t){var r=Ni(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},me.prototype.add=me.prototype.push=function(n){return this.__data__.set(n,c),this},me.prototype.has=function(n){return this.__data__.has(n)},xe.prototype.clear=function(){this.__data__=new be,this.size=0},xe.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},xe.prototype.get=function(n){return this.__data__.get(n)},xe.prototype.has=function(n){return this.__data__.has(n)},xe.prototype.set=function(n,t){var r=this.__data__;if(r instanceof be){var e=r.__data__;if(!Qr||e.length0&&r(a)?t>1?qe(a,t-1,r,e,u):tr(u,a):e||(u[u.length]=a)}return u}var Ve=ai(),Je=ai(!0);function Ze(n,t){return n&&Ve(n,t,uf)}function Ke(n,t){return n&&Je(n,t,uf)}function Ye(n,t){return Ht(t,function(t){return ja(n[t])})}function Ge(n,t){for(var r=0,e=(t=Ju(t,n)).length;null!=n&&rt}function nu(n,t){return null!=n&&st.call(n,t)}function tu(n,t){return null!=n&&t in rt(n)}function ru(n,t,r){for(var u=r?Xt:Qt,o=n[0].length,a=n.length,f=a,c=e(a),l=1/0,s=[];f--;){var p=n[f];f&&t&&(p=nr(p,yr(t))),l=Jr(p.length,l),c[f]=!r&&(t||o>=120&&p.length>=120)?new me(f&&p):i}p=n[0];var h=-1,v=c[0];n:for(;++h=a)return f;var c=r[e];return f*("desc"==c?-1:1)}}return n.index-t.index}(n,t,r)})}function du(n,t,r){for(var e=-1,u=t.length,i={};++e-1;)a!==n&&Nt.call(a,f,1),Nt.call(n,f,1);return n}function wu(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Vi(u)?Nt.call(n,u,1):Uu(n,u)}}return n}function mu(n,t){return n+Mr(Yr()*(t-n+1))}function xu(n,t){var r="";if(!n||t<1||t>L)return r;do{t%2&&(r+=n),(t=Mr(t/2))&&(n+=n)}while(t);return r}function Su(n,t){return uo(Xi(n,t,Cf),n+"")}function ju(n){return je(vf(n))}function Au(n,t){var r=vf(n);return ao(r,Le(t,0,r.length))}function Ou(n,t,r,e){if(!ka(n))return n;for(var u=-1,o=(t=Ju(t,n)).length,a=o-1,f=n;null!=f&&++ui?0:i+t),(r=r>i?i:r)<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=e(i);++u>>1,o=n[i];null!==o&&!Ta(o)&&(r?o<=t:o=o){var l=t?null:xi(n);if(l)return Ir(l);a=!1,u=br,c=new me}else c=t?[]:f;n:for(;++e=e?n:Ru(n,t,r)}var Yu=Tr||function(n){return Lt.clearTimeout(n)};function Gu(n,t){if(t)return n.slice();var r=n.length,e=It?It(r):new n.constructor(r);return n.copy(e),e}function Hu(n){var t=new n.constructor(n.byteLength);return new St(t).set(new St(n)),t}function Qu(n,t){var r=t?Hu(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function Xu(n,t){if(n!==t){var r=n!==i,e=null===n,u=n==n,o=Ta(n),a=t!==i,f=null===t,c=t==t,l=Ta(t);if(!f&&!l&&!o&&n>t||o&&a&&c&&!f&&!l||e&&a&&c||!r&&c||!u)return 1;if(!e&&!o&&!l&&n1?r[u-1]:i,a=u>2?r[2]:i;for(o=n.length>3&&"function"==typeof o?(u--,o):i,a&&Ji(r[0],r[1],a)&&(o=u<3?i:o,u=1),t=rt(t);++e-1?u[o?t[a]:a]:i}}function pi(n){return Ii(function(t){var r=t.length,e=r,u=ge.prototype.thru;for(n&&t.reverse();e--;){var o=t[e];if("function"!=typeof o)throw new it(f);if(u&&!a&&"wrapper"==Wi(o))var a=new ge([],!0)}for(e=a?e:r;++e1&&w.reverse(),p&&lf))return!1;var l=o.get(n);if(l&&o.get(t))return l==t;var s=-1,p=!0,h=r&g?new me:i;for(o.set(n,t),o.set(t,n);++s-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(Un,"{\n/* [wrapped with "+t+"] */\n")}(e,function(n,t){return Kt(F,function(r){var e="_."+r[0];t&r[1]&&!Qt(n,e)&&n.push(e)}),n.sort()}(function(n){var t=n.match(Mn);return t?t[1].split(Fn):[]}(e),r)))}function oo(n){var t=0,r=0;return function(){var e=Zr(),u=R-(e-r);if(r=e,u>0){if(++t>=I)return arguments[0]}else t=0;return n.apply(i,arguments)}}function ao(n,t){var r=-1,e=n.length,u=e-1;for(t=t===i?e:t;++r1?n[t-1]:i;return r="function"==typeof r?(n.pop(),r):i,zo(n,r)});function Mo(n){var t=he(n);return t.__chain__=!0,t}function Fo(n,t){return t(n)}var Po=Ii(function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return We(t,n)};return!(t>1||this.__actions__.length)&&e instanceof ye&&Vi(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:Fo,args:[u],thisArg:i}),new ge(e,this.__chain__).thru(function(n){return t&&!n.length&&n.push(i),n})):this.thru(u)});var $o=ui(function(n,t,r){st.call(n,r)?++n[r]:ze(n,r,1)});var Do=si(_o),qo=si(go);function Vo(n,t){return(ya(n)?Kt:Me)(n,Ti(t,3))}function Jo(n,t){return(ya(n)?Yt:Fe)(n,Ti(t,3))}var Zo=ui(function(n,t,r){st.call(n,r)?n[r].push(t):ze(n,r,[t])});var Ko=Su(function(n,t,r){var u=-1,i="function"==typeof t,o=ba(n)?e(n.length):[];return Me(n,function(n){o[++u]=i?Jt(t,n,r):eu(n,t,r)}),o}),Yo=ui(function(n,t,r){ze(n,r,t)});function Go(n,t){return(ya(n)?nr:pu)(n,Ti(t,3))}var Ho=ui(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]});var Qo=Su(function(n,t){if(null==n)return[];var r=t.length;return r>1&&Ji(n,t[0],t[1])?t=[]:r>2&&Ji(t[0],t[1],t[2])&&(t=[t[0]]),yu(n,qe(t,1),[])}),Xo=Nr||function(){return Lt.Date.now()};function na(n,t,r){return t=r?i:t,t=n&&null==t?n.length:t,ji(n,j,i,i,i,i,t)}function ta(n,t){var r;if("function"!=typeof t)throw new it(f);return n=Pa(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=i),r}}var ra=Su(function(n,t,r){var e=y;if(r.length){var u=Er(r,Li(ra));e|=x}return ji(n,e,t,r,u)}),ea=Su(function(n,t,r){var e=y|d;if(r.length){var u=Er(r,Li(ea));e|=x}return ji(t,e,n,r,u)});function ua(n,t,r){var e,u,o,a,c,l,s=0,p=!1,h=!1,v=!0;if("function"!=typeof n)throw new it(f);function _(t){var r=e,o=u;return e=u=i,s=t,a=n.apply(o,r)}function g(n){var r=n-l;return l===i||r>=t||r<0||h&&n-s>=o}function y(){var n=Xo();if(g(n))return d(n);c=eo(y,function(n){var r=t-(n-l);return h?Jr(r,o-(n-s)):r}(n))}function d(n){return c=i,v&&e?_(n):(e=u=i,a)}function b(){var n=Xo(),r=g(n);if(e=arguments,u=this,l=n,r){if(c===i)return function(n){return s=n,c=eo(y,t),p?_(n):a}(l);if(h)return Yu(c),c=eo(y,t),_(l)}return c===i&&(c=eo(y,t)),a}return t=Da(t)||0,ka(r)&&(p=!!r.leading,o=(h="maxWait"in r)?Vr(Da(r.maxWait)||0,t):o,v="trailing"in r?!!r.trailing:v),b.cancel=function(){c!==i&&Yu(c),s=0,e=l=u=c=i},b.flush=function(){return c===i?a:d(Xo())},b}var ia=Su(function(n,t){return Be(n,1,t)}),oa=Su(function(n,t,r){return Be(n,Da(t)||0,r)});function aa(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new it(f);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(aa.Cache||we),r}function fa(n){if("function"!=typeof n)throw new it(f);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}aa.Cache=we;var ca=Zu(function(n,t){var r=(t=1==t.length&&ya(t[0])?nr(t[0],yr(Ti())):nr(qe(t,1),yr(Ti()))).length;return Su(function(e){for(var u=-1,i=Jr(e.length,r);++u=t}),ga=uu(function(){return arguments}())?uu:function(n){return Ea(n)&&st.call(n,"callee")&&!Tt.call(n,"callee")},ya=e.isArray,da=Ft?yr(Ft):function(n){return Ea(n)&&Qe(n)==cn};function ba(n){return null!=n&&Oa(n.length)&&!ja(n)}function wa(n){return Ea(n)&&ba(n)}var ma=Pr||qf,xa=Pt?yr(Pt):function(n){return Ea(n)&&Qe(n)==V};function Sa(n){if(!Ea(n))return!1;var t=Qe(n);return t==Z||t==J||"string"==typeof n.message&&"string"==typeof n.name&&!Ca(n)}function ja(n){if(!ka(n))return!1;var t=Qe(n);return t==K||t==Y||t==D||t==nn}function Aa(n){return"number"==typeof n&&n==Pa(n)}function Oa(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=L}function ka(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function Ea(n){return null!=n&&"object"==typeof n}var Ia=$t?yr($t):function(n){return Ea(n)&&Pi(n)==G};function Ra(n){return"number"==typeof n||Ea(n)&&Qe(n)==H}function Ca(n){if(!Ea(n)||Qe(n)!=X)return!1;var t=zt(n);if(null===t)return!0;var r=st.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&<.call(r)==_t}var za=Dt?yr(Dt):function(n){return Ea(n)&&Qe(n)==tn};var Wa=qt?yr(qt):function(n){return Ea(n)&&Pi(n)==rn};function La(n){return"string"==typeof n||!ya(n)&&Ea(n)&&Qe(n)==en}function Ta(n){return"symbol"==typeof n||Ea(n)&&Qe(n)==un}var Na=Vt?yr(Vt):function(n){return Ea(n)&&Oa(n.length)&&!!kt[Qe(n)]};var Ba=bi(su),Ua=bi(function(n,t){return n<=t});function Ma(n){if(!n)return[];if(ba(n))return La(n)?zr(n):ri(n);if(Mt&&n[Mt])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Mt]());var t=Pi(n);return(t==G?Or:t==rn?Ir:vf)(n)}function Fa(n){return n?(n=Da(n))===W||n===-W?(n<0?-1:1)*T:n==n?n:0:0===n?n:0}function Pa(n){var t=Fa(n),r=t%1;return t==t?r?t-r:t:0}function $a(n){return n?Le(Pa(n),0,B):0}function Da(n){if("number"==typeof n)return n;if(Ta(n))return N;if(ka(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=ka(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=n.replace(Tn,"");var r=Jn.test(n);return r||Kn.test(n)?Ct(n.slice(2),r?2:8):Vn.test(n)?N:+n}function qa(n){return ei(n,of(n))}function Va(n){return null==n?"":Nu(n)}var Ja=ii(function(n,t){if(Gi(t)||ba(t))ei(t,uf(t),n);else for(var r in t)st.call(t,r)&&Ee(n,r,t[r])}),Za=ii(function(n,t){ei(t,of(t),n)}),Ka=ii(function(n,t,r,e){ei(t,of(t),n,e)}),Ya=ii(function(n,t,r,e){ei(t,uf(t),n,e)}),Ga=Ii(We);var Ha=Su(function(n,t){n=rt(n);var r=-1,e=t.length,u=e>2?t[2]:i;for(u&&Ji(t[0],t[1],u)&&(e=1);++r1),t}),ei(n,Ci(n),r),e&&(r=Te(r,p|h|v,ki));for(var u=t.length;u--;)Uu(r,t[u]);return r});var lf=Ii(function(n,t){return null==n?{}:function(n,t){return du(n,t,function(t,r){return nf(n,r)})}(n,t)});function sf(n,t){if(null==n)return{};var r=nr(Ci(n),function(n){return[n]});return t=Ti(t),du(n,r,function(n,r){return t(n,r[0])})}var pf=Si(uf),hf=Si(of);function vf(n){return null==n?[]:dr(n,uf(n))}var _f=ci(function(n,t,r){return t=t.toLowerCase(),n+(r?gf(t):t)});function gf(n){return jf(Va(n).toLowerCase())}function yf(n){return(n=Va(n))&&n.replace(Gn,xr).replace(wt,"")}var df=ci(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),bf=ci(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),wf=fi("toLowerCase");var mf=ci(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()});var xf=ci(function(n,t,r){return n+(r?" ":"")+jf(t)});var Sf=ci(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),jf=fi("toUpperCase");function Af(n,t,r){return n=Va(n),(t=r?i:t)===i?function(n){return jt.test(n)}(n)?function(n){return n.match(xt)||[]}(n):function(n){return n.match(Pn)||[]}(n):n.match(t)||[]}var Of=Su(function(n,t){try{return Jt(n,i,t)}catch(r){return Sa(r)?r:new Xn(r)}}),kf=Ii(function(n,t){return Kt(t,function(t){t=co(t),ze(n,t,ra(n[t],n))}),n});function Ef(n){return function(){return n}}var If=pi(),Rf=pi(!0);function Cf(n){return n}function zf(n){return fu("function"==typeof n?n:Te(n,p))}var Wf=Su(function(n,t){return function(r){return eu(r,n,t)}}),Lf=Su(function(n,t){return function(r){return eu(n,r,t)}});function Tf(n,t,r){var e=uf(t),u=Ye(t,e);null!=r||ka(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=Ye(t,uf(t)));var i=!(ka(r)&&"chain"in r&&!r.chain),o=ja(n);return Kt(u,function(r){var e=t[r];n[r]=e,o&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__),u=r.__actions__=ri(this.__actions__);return u.push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,tr([this.value()],arguments))})}),n}function Nf(){}var Bf=gi(nr),Uf=gi(Gt),Mf=gi(ur);function Ff(n){return Zi(n)?pr(co(n)):function(n){return function(t){return Ge(t,n)}}(n)}var Pf=di(),$f=di(!0);function Df(){return[]}function qf(){return!1}var Vf=_i(function(n,t){return n+t},0),Jf=mi("ceil"),Zf=_i(function(n,t){return n/t},1),Kf=mi("floor");var Yf,Gf=_i(function(n,t){return n*t},1),Hf=mi("round"),Qf=_i(function(n,t){return n-t},0);return he.after=function(n,t){if("function"!=typeof t)throw new it(f);return n=Pa(n),function(){if(--n<1)return t.apply(this,arguments)}},he.ary=na,he.assign=Ja,he.assignIn=Za,he.assignInWith=Ka,he.assignWith=Ya,he.at=Ga,he.before=ta,he.bind=ra,he.bindAll=kf,he.bindKey=ea,he.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return ya(n)?n:[n]},he.chain=Mo,he.chunk=function(n,t,r){t=(r?Ji(n,t,r):t===i)?1:Vr(Pa(t),0);var u=null==n?0:n.length;if(!u||t<1)return[];for(var o=0,a=0,f=e(Ur(u/t));ou?0:u+r),(e=e===i||e>u?u:Pa(e))<0&&(e+=u),e=r>e?0:$a(e);r>>0)?(n=Va(n))&&("string"==typeof t||null!=t&&!za(t))&&!(t=Nu(t))&&Ar(n)?Ku(zr(n),0,r):n.split(t,r):[]},he.spread=function(n,t){if("function"!=typeof n)throw new it(f);return t=null==t?0:Vr(Pa(t),0),Su(function(r){var e=r[t],u=Ku(r,0,t);return e&&tr(u,e),Jt(n,this,u)})},he.tail=function(n){var t=null==n?0:n.length;return t?Ru(n,1,t):[]},he.take=function(n,t,r){return n&&n.length?Ru(n,0,(t=r||t===i?1:Pa(t))<0?0:t):[]},he.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?Ru(n,(t=e-(t=r||t===i?1:Pa(t)))<0?0:t,e):[]},he.takeRightWhile=function(n,t){return n&&n.length?Fu(n,Ti(t,3),!1,!0):[]},he.takeWhile=function(n,t){return n&&n.length?Fu(n,Ti(t,3)):[]},he.tap=function(n,t){return t(n),n},he.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new it(f);return ka(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ua(n,t,{leading:e,maxWait:t,trailing:u})},he.thru=Fo,he.toArray=Ma,he.toPairs=pf,he.toPairsIn=hf,he.toPath=function(n){return ya(n)?nr(n,co):Ta(n)?[n]:ri(fo(Va(n)))},he.toPlainObject=qa,he.transform=function(n,t,r){var e=ya(n),u=e||ma(n)||Na(n);if(t=Ti(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:ka(n)&&ja(i)?ve(zt(n)):{}}return(u?Kt:Ze)(n,function(n,e,u){return t(r,n,e,u)}),r},he.unary=function(n){return na(n,1)},he.union=Eo,he.unionBy=Io,he.unionWith=Ro,he.uniq=function(n){return n&&n.length?Bu(n):[]},he.uniqBy=function(n,t){return n&&n.length?Bu(n,Ti(t,2)):[]},he.uniqWith=function(n,t){return t="function"==typeof t?t:i,n&&n.length?Bu(n,i,t):[]},he.unset=function(n,t){return null==n||Uu(n,t)},he.unzip=Co,he.unzipWith=zo,he.update=function(n,t,r){return null==n?n:Mu(n,t,Vu(r))},he.updateWith=function(n,t,r,e){return e="function"==typeof e?e:i,null==n?n:Mu(n,t,Vu(r),e)},he.values=vf,he.valuesIn=function(n){return null==n?[]:dr(n,of(n))},he.without=Wo,he.words=Af,he.wrap=function(n,t){return la(Vu(t),n)},he.xor=Lo,he.xorBy=To,he.xorWith=No,he.zip=Bo,he.zipObject=function(n,t){return Du(n||[],t||[],Ee)},he.zipObjectDeep=function(n,t){return Du(n||[],t||[],Ou)},he.zipWith=Uo,he.entries=pf,he.entriesIn=hf,he.extend=Za,he.extendWith=Ka,Tf(he,he),he.add=Vf,he.attempt=Of,he.camelCase=_f,he.capitalize=gf,he.ceil=Jf,he.clamp=function(n,t,r){return r===i&&(r=t,t=i),r!==i&&(r=(r=Da(r))==r?r:0),t!==i&&(t=(t=Da(t))==t?t:0),Le(Da(n),t,r)},he.clone=function(n){return Te(n,v)},he.cloneDeep=function(n){return Te(n,p|v)},he.cloneDeepWith=function(n,t){return Te(n,p|v,t="function"==typeof t?t:i)},he.cloneWith=function(n,t){return Te(n,v,t="function"==typeof t?t:i)},he.conformsTo=function(n,t){return null==t||Ne(n,t,uf(t))},he.deburr=yf,he.defaultTo=function(n,t){return null==n||n!=n?t:n},he.divide=Zf,he.endsWith=function(n,t,r){n=Va(n),t=Nu(t);var e=n.length,u=r=r===i?e:Le(Pa(r),0,e);return(r-=t.length)>=0&&n.slice(r,u)==t},he.eq=ha,he.escape=function(n){return(n=Va(n))&&On.test(n)?n.replace(jn,Sr):n},he.escapeRegExp=function(n){return(n=Va(n))&&Ln.test(n)?n.replace(Wn,"\\$&"):n},he.every=function(n,t,r){var e=ya(n)?Gt:Pe;return r&&Ji(n,t,r)&&(t=i),e(n,Ti(t,3))},he.find=Do,he.findIndex=_o,he.findKey=function(n,t){return or(n,Ti(t,3),Ze)},he.findLast=qo,he.findLastIndex=go,he.findLastKey=function(n,t){return or(n,Ti(t,3),Ke)},he.floor=Kf,he.forEach=Vo,he.forEachRight=Jo,he.forIn=function(n,t){return null==n?n:Ve(n,Ti(t,3),of)},he.forInRight=function(n,t){return null==n?n:Je(n,Ti(t,3),of)},he.forOwn=function(n,t){return n&&Ze(n,Ti(t,3))},he.forOwnRight=function(n,t){return n&&Ke(n,Ti(t,3))},he.get=Xa,he.gt=va,he.gte=_a,he.has=function(n,t){return null!=n&&$i(n,t,nu)},he.hasIn=nf,he.head=bo,he.identity=Cf,he.includes=function(n,t,r,e){n=ba(n)?n:vf(n),r=r&&!e?Pa(r):0;var u=n.length;return r<0&&(r=Vr(u+r,0)),La(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&fr(n,t,r)>-1},he.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:Pa(r);return u<0&&(u=Vr(e+u,0)),fr(n,t,u)},he.inRange=function(n,t,r){return t=Fa(t),r===i?(r=t,t=0):r=Fa(r),function(n,t,r){return n>=Jr(t,r)&&n=-L&&n<=L},he.isSet=Wa,he.isString=La,he.isSymbol=Ta,he.isTypedArray=Na,he.isUndefined=function(n){return n===i},he.isWeakMap=function(n){return Ea(n)&&Pi(n)==an},he.isWeakSet=function(n){return Ea(n)&&Qe(n)==fn},he.join=function(n,t){return null==n?"":Dr.call(n,t)},he.kebabCase=df,he.last=So,he.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;return r!==i&&(u=(u=Pa(r))<0?Vr(e+u,0):Jr(u,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,u):ar(n,lr,u,!0)},he.lowerCase=bf,he.lowerFirst=wf,he.lt=Ba,he.lte=Ua,he.max=function(n){return n&&n.length?$e(n,Cf,Xe):i},he.maxBy=function(n,t){return n&&n.length?$e(n,Ti(t,2),Xe):i},he.mean=function(n){return sr(n,Cf)},he.meanBy=function(n,t){return sr(n,Ti(t,2))},he.min=function(n){return n&&n.length?$e(n,Cf,su):i},he.minBy=function(n,t){return n&&n.length?$e(n,Ti(t,2),su):i},he.stubArray=Df,he.stubFalse=qf,he.stubObject=function(){return{}},he.stubString=function(){return""},he.stubTrue=function(){return!0},he.multiply=Gf,he.nth=function(n,t){return n&&n.length?gu(n,Pa(t)):i},he.noConflict=function(){return Lt._===this&&(Lt._=gt),this},he.noop=Nf,he.now=Xo,he.pad=function(n,t,r){n=Va(n);var e=(t=Pa(t))?Cr(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return yi(Mr(u),r)+n+yi(Ur(u),r)},he.padEnd=function(n,t,r){n=Va(n);var e=(t=Pa(t))?Cr(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var u=Yr();return Jr(n+u*(t-n+Rt("1e-"+((u+"").length-1))),t)}return mu(n,t)},he.reduce=function(n,t,r){var e=ya(n)?rr:vr,u=arguments.length<3;return e(n,Ti(t,4),r,u,Me)},he.reduceRight=function(n,t,r){var e=ya(n)?er:vr,u=arguments.length<3;return e(n,Ti(t,4),r,u,Fe)},he.repeat=function(n,t,r){return t=(r?Ji(n,t,r):t===i)?1:Pa(t),xu(Va(n),t)},he.replace=function(){var n=arguments,t=Va(n[0]);return n.length<3?t:t.replace(n[1],n[2])},he.result=function(n,t,r){var e=-1,u=(t=Ju(t,n)).length;for(u||(u=1,n=i);++eL)return[];var r=B,e=Jr(n,B);t=Ti(t),n-=B;for(var u=gr(e,t);++r=o)return n;var f=r-Cr(e);if(f<1)return e;var c=a?Ku(a,0,f).join(""):n.slice(0,f);if(u===i)return c+e;if(a&&(f+=c.length-f),za(u)){if(n.slice(f).search(u)){var l,s=c;for(u.global||(u=et(u.source,Va(qn.exec(u))+"g")),u.lastIndex=0;l=u.exec(s);)var p=l.index;c=c.slice(0,p===i?f:p)}}else if(n.indexOf(Nu(u),f)!=f){var h=c.lastIndexOf(u);h>-1&&(c=c.slice(0,h))}return c+e},he.unescape=function(n){return(n=Va(n))&&An.test(n)?n.replace(Sn,Wr):n},he.uniqueId=function(n){var t=++pt;return Va(n)+t},he.upperCase=Sf,he.upperFirst=jf,he.each=Vo,he.eachRight=Jo,he.first=bo,Tf(he,(Yf={},Ze(he,function(n,t){st.call(he.prototype,t)||(Yf[t]=n)}),Yf),{chain:!1}),he.VERSION="4.17.14",Kt(["bind","bindKey","curry","curryRight","partial","partialRight"],function(n){he[n].placeholder=he}),Kt(["drop","take"],function(n,t){ye.prototype[n]=function(r){r=r===i?1:Vr(Pa(r),0);var e=this.__filtered__&&!t?new ye(this):this.clone();return e.__filtered__?e.__takeCount__=Jr(r,e.__takeCount__):e.__views__.push({size:Jr(r,B),type:n+(e.__dir__<0?"Right":"")}),e},ye.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),Kt(["filter","map","takeWhile"],function(n,t){var r=t+1,e=r==C||3==r;ye.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:Ti(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),Kt(["head","last"],function(n,t){var r="take"+(t?"Right":"");ye.prototype[n]=function(){return this[r](1).value()[0]}}),Kt(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");ye.prototype[n]=function(){return this.__filtered__?new ye(this):this[r](1)}}),ye.prototype.compact=function(){return this.filter(Cf)},ye.prototype.find=function(n){return this.filter(n).head()},ye.prototype.findLast=function(n){return this.reverse().find(n)},ye.prototype.invokeMap=Su(function(n,t){return"function"==typeof n?new ye(this):this.map(function(r){return eu(r,n,t)})}),ye.prototype.reject=function(n){return this.filter(fa(Ti(n)))},ye.prototype.slice=function(n,t){n=Pa(n);var r=this;return r.__filtered__&&(n>0||t<0)?new ye(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==i&&(r=(t=Pa(t))<0?r.dropRight(-t):r.take(t-n)),r)},ye.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},ye.prototype.toArray=function(){return this.take(B)},Ze(ye.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=he[e?"take"+("last"==t?"Right":""):t],o=e||/^find/.test(t);u&&(he.prototype[t]=function(){var t=this.__wrapped__,a=e?[1]:arguments,f=t instanceof ye,c=a[0],l=f||ya(t),s=function(n){var t=u.apply(he,tr([n],a));return e&&p?t[0]:t};l&&r&&"function"==typeof c&&1!=c.length&&(f=l=!1);var p=this.__chain__,h=!!this.__actions__.length,v=o&&!p,_=f&&!h;if(!o&&l){t=_?t:new ye(this);var g=n.apply(t,a);return g.__actions__.push({func:Fo,args:[s],thisArg:i}),new ge(g,p)}return v&&_?n.apply(this,a):(g=this.thru(s),v?e?g.value()[0]:g.value():g)})}),Kt(["pop","push","shift","sort","splice","unshift"],function(n){var t=ot[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);he.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(ya(u)?u:[],n)}return this[r](function(r){return t.apply(ya(r)?r:[],n)})}}),Ze(ye.prototype,function(n,t){var r=he[t];if(r){var e=r.name+"";st.call(ue,e)||(ue[e]=[]),ue[e].push({name:t,func:r})}}),ue[hi(i,d).name]=[{name:"wrapper",func:i}],ye.prototype.clone=function(){var n=new ye(this.__wrapped__);return n.__actions__=ri(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=ri(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=ri(this.__views__),n},ye.prototype.reverse=function(){if(this.__filtered__){var n=new ye(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},ye.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=ya(n),e=t<0,u=r?n.length:0,i=function(n,t,r){for(var e=-1,u=r.length;++e=this.__values__.length;return{done:n,value:n?i:this.__values__[this.__index__++]}},he.prototype.plant=function(n){for(var t,r=this;r instanceof _e;){var e=so(r);e.__index__=0,e.__values__=i,t?u.__wrapped__=e:t=e;var u=e;r=r.__wrapped__}return u.__wrapped__=n,t},he.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof ye){var t=n;return this.__actions__.length&&(t=new ye(this)),(t=t.reverse()).__actions__.push({func:Fo,args:[ko],thisArg:i}),new ge(t,this.__chain__)}return this.thru(ko)},he.prototype.toJSON=he.prototype.valueOf=he.prototype.value=function(){return Pu(this.__wrapped__,this.__actions__)},he.prototype.first=he.prototype.head,Mt&&(he.prototype[Mt]=function(){return this}),he}();Lt._=Lr,(u=function(){return Lr}.call(t,r,t,e))===i||(e.exports=u)}).call(this)}).call(this,r(3),r(4)(n))},function(n,t){n.exports=require("sketch")},function(n,t,r){!function(){"use strict";var t=r(5).typeOf,e=r(6);n.exports.stringify=function(n){var r,u="";return e((r={undefined:function(){return"null"},null:function(){return"null"},number:function(n){return n},boolean:function(n){return n?"true":"false"},string:function(n){return JSON.stringify(n)},array:function(n){var e="";return 0===n.length?e+="[]":(u=u.replace(/$/," "),n.forEach(function(n,i){var o=r[t(n)];if(!o)throw new Error("what the crap: "+t(n));e+="\n"+u+"- "+o(n,!0)}),u=u.replace(/ /,""),e)},object:function(n,e,i){var o="";return 0===Object.keys(n).length?o+="{}":(i||(u=u.replace(/$/," ")),Object.keys(n).forEach(function(i,a){var f=n[i],c=r[t(f)];if(void 0!==f){if(!c)throw new Error("what the crap: "+t(f));e&&0===a||(o+="\n"+u),o+=i+": "+c(f)}}),u=u.replace(/ /,""),o)},function:function(){return"[object Function]"}})[t(n)](n,!0,!0)+"\n")}}()},function(n,t){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(e){"object"==typeof window&&(r=window)}n.exports=r},function(n,t){n.exports=function(n){return n.webpackPolyfill||(n.deprecate=function(){},n.paths=[],n.children||(n.children=[]),Object.defineProperty(n,"loaded",{enumerable:!0,get:function(){return n.l}}),Object.defineProperty(n,"id",{enumerable:!0,get:function(){return n.i}}),n.webpackPolyfill=1),n}},function(n,t){!function(){"use strict";var t,r,e=Function("return this")(),u="Boolean Number String Function Array Date RegExp Object".split(" "),i={};for(t in u)u.hasOwnProperty(t)&&(r=u[t],i["[object "+r+"]"]=r.toLowerCase());function o(n){return null==n?String(n):i[Object.prototype.toString.call(n)]||"object"}function a(n){var t,r;if("object"===o(n))for(t in n)if(void 0!==(r=n[t])&&"function"!==o(r))return!1;return!0}String.prototype.entityify||(String.prototype.entityify=function(){return this.replace(/&/g,"&").replace(//g,">")}),String.prototype.quote||(String.prototype.quote=function(){var n,t,r=this.length,e='"';for(t=0;t=" ")"\\"!==n&&'"'!==n||(e+="\\"),e+=n;else switch(n){case"\b":e+="\\b";break;case"\f":e+="\\f";break;case"\n":e+="\\n";break;case"\r":e+="\\r";break;case"\t":e+="\\t";break;default:n=n.charCodeAt(),e+="\\u00"+Math.floor(n/16).toString(16)+(n%16).toString(16)}return e+'"'}),String.prototype.supplant||(String.prototype.supplant=function(n){return this.replace(/{([^{}]*)}/g,function(t,r){var e=n[r];return"string"==typeof e||"number"==typeof e?e:t})}),String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/,"$1")}),n.exports={typeOf:o,isEmpty:a},e.typeOf=e.typeOf||o,e.isEmpty=e.isEmpty||a}()},function(n,t,r){"use strict";n.exports=function(n){return n.split("\n").map(function(n){return n.trimRight()}).join("\n")}},function(n,r,e){"use strict";e.r(r);var u,i,o,a,f=e(1),c=e.n(f),l=e(0),s=e.n(l),p={"JavaScript Object":{lineStart:"",prefix:" '",diviner:"': '",postfix:"',\n",lineEnd:"}",filetype:"js"},"JavaScript Variables":{lineStart:"",prefix:"const ",diviner:" = '",postfix:"';\n",lineEnd:"",filetype:"js"},SCSS:{lineStart:"",prefix:"$",diviner:": ",postfix:";\n",lineEnd:"",filetype:"scss"},Less:{lineStart:"",prefix:"@",diviner:": ",postfix:";\n",lineEnd:"",filetype:"less"},CSS:{lineStart:":root {\n",prefix:" --",diviner:": ",postfix:";\n",lineEnd:"}",filetype:"css"},JSON:{lineStart:{},prefix:"",diviner:"",postfix:"",lineEnd:"",filetype:"json"},YAML:{lineStart:{},prefix:"",diviner:"",postfix:"",lineEnd:"",filetype:"yml"}},h=e(2),v=e.n(h),_=function(n,t,r){var e="";if("JSON"==t){var u={};u[s.a.camelCase(r)]=n,e=JSON.stringify(u,null,"\t")}else if("YAML"==t){var i={};i[s.a.camelCase(r)]=n,e=v.a.stringify(i)}else e=(e=(e="JavaScript Object"==t?"const "+s.a.camelCase(r)+" = {\n":p[t].lineStart).concat(s.a.join(s.a.map(n,function(n,r){return p[t].prefix+r+p[t].diviner+n+p[t].postfix}),""))).concat(p[t].lineEnd);return e},g=function(n,t){var r=n.name.split("/"),e="";if(0==t)e=s.a.kebabCase(r);else if(1==t)e=s.a.camelCase(s.a.join(r,"-"));else{var u=t-2;e=r.length4&&void 0!==arguments[4]&&arguments[4],i=NSPopUpButton.alloc().initWithFrame(NSMakeRect(0,e-n,r,22));if(u){var o=t.map(function(n){return n.name}),a=o[0].split("/"),f=s.a.kebabCase(a),c=s.a.camelCase(s.a.join(a,"-"));i.addItemWithTitle(f),i.addItemWithTitle(c),a.length>1&&s.a.forEach(a,function(n){i.addItemWithTitle(n.toLowerCase().replace(/ /g,""))})}else s.a.forEach(t,function(n){i.addItemWithTitle(n)});return i.selectItemAtIndex(0),i},b=function(n){var r=function(n){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Choose variables format.",e=COSAlertWindow.new();return e.setIcon(NSImage.alloc().initByReferencingFile(t.plugin.urlForResourceNamed("icon.png").path())),e.setMessageText(n),e.setInformativeText(r),e.addButtonWithTitle("Ok"),e.addButtonWithTitle("Cancel"),e}("Export Spacing Variables"),e=NSView.alloc().initWithFrame(NSMakeRect(0,0,300,225));r.addAccessoryView(e),e.addSubview(y(35,"File format:",300,225));u=d(45,["SCSS","Less","CSS","JSON","JavaScript Object","JavaScript Variables"],300,225),e.addSubview(u),e.addSubview(y(90,"Dimension:",300,225));i=d(100,["Width","Height"],300,225),e.addSubview(i),e.addSubview(y(145,"Units:",300,225));return a=d(155,["Absolute (px)","Relative (rem)"],300,225),e.addSubview(a),e.addSubview(y(200,"Naming:",300,225)),o=d(210,n,300,225,!0),e.addSubview(o),r.runModal()};r.default=function(){var n=c.a.getSelectedDocument().selectedLayers.layers,t=s.a.filter(s.a.reverse(n),["type","ShapePath"]);if(0!==s.a.size(t)){var r=b(t),e=u.titleOfSelectedItem(),f=i.titleOfSelectedItem(),l=o.indexOfSelectedItem(),h=a.titleOfSelectedItem();"1000"==r&&function(n,t,r,e,u){var i=n.length,o=NSArray.arrayWithArray([p[t].filetype,nil]),a=NSSavePanel.savePanel();if(a.setAllowedFileTypes(o),a.setNameFieldStringValue("spacing."+p[t].filetype),a.setPrompt("Save Spacing Variables"),a.runModal()&&0!==i){var f={};s.a.forEach(n,function(n){var t=g(n,e),i="Width"==r?n.frame.width:n.frame.height,o="Absolute (px)"==u?i+"px":i/16+"rem";f[t]=o});var l=NSString.stringWithString(_(f,t,"spacing")),h=a.URL().path();l.writeToFile_atomically_encoding_error(h,!0,NSUTF8StringEncoding,null),c.a.UI.message("Spacing Variables Exported!")}}(t,e,f,l,h)}else c.a.UI.alert("Select layers","Please select shape layers first.")}}]);if("default"===n&&"function"==typeof r)r(t);else{if("function"!=typeof r[n])throw new Error('Missing export named "'+n+'". Your command should contain something like `export function " + key +"() {}`.');r[n](t)}}globalThis.onRun=__skpm_run.bind(this,"default"); -------------------------------------------------------------------------------- /design-token-exporter.sketchplugin/Contents/Sketch/textObjects.js: -------------------------------------------------------------------------------- 1 | var globalThis=this;function __skpm_run(n,t){globalThis.context=t;var r=function(n){var t={};function r(e){if(t[e])return t[e].exports;var u=t[e]={i:e,l:!1,exports:{}};return n[e].call(u.exports,u,u.exports,r),u.l=!0,u.exports}return r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},r.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},r.t=function(n,t){if(1&t&&(n=r(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(r.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var u in n)r.d(e,u,function(t){return n[t]}.bind(null,u));return e},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=4)}([function(n,t,r){(function(n,e){var u;(function(){var i,o=200,a="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",f="Expected a function",c="__lodash_hash_undefined__",l=500,s="__lodash_placeholder__",h=1,p=2,v=4,_=1,g=2,d=1,y=2,b=4,w=8,m=16,x=32,S=64,j=128,A=256,O=512,k=30,E="...",I=800,z=16,R=1,T=2,W=1/0,C=9007199254740991,L=17976931348623157e292,N=NaN,B=4294967295,F=B-1,U=B>>>1,M=[["ary",j],["bind",d],["bindKey",y],["curry",w],["curryRight",m],["flip",O],["partial",x],["partialRight",S],["rearg",A]],V="[object Arguments]",P="[object Array]",$="[object AsyncFunction]",D="[object Boolean]",q="[object Date]",J="[object DOMException]",Z="[object Error]",H="[object Function]",K="[object GeneratorFunction]",G="[object Map]",Y="[object Number]",Q="[object Null]",X="[object Object]",nn="[object Proxy]",tn="[object RegExp]",rn="[object Set]",en="[object String]",un="[object Symbol]",on="[object Undefined]",an="[object WeakMap]",fn="[object WeakSet]",cn="[object ArrayBuffer]",ln="[object DataView]",sn="[object Float32Array]",hn="[object Float64Array]",pn="[object Int8Array]",vn="[object Int16Array]",_n="[object Int32Array]",gn="[object Uint8Array]",dn="[object Uint8ClampedArray]",yn="[object Uint16Array]",bn="[object Uint32Array]",wn=/\b__p \+= '';/g,mn=/\b(__p \+=) '' \+/g,xn=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Sn=/&(?:amp|lt|gt|quot|#39);/g,jn=/[&<>"']/g,An=RegExp(Sn.source),On=RegExp(jn.source),kn=/<%-([\s\S]+?)%>/g,En=/<%([\s\S]+?)%>/g,In=/<%=([\s\S]+?)%>/g,zn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Rn=/^\w*$/,Tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Wn=/[\\^$.*+?()[\]{}|]/g,Cn=RegExp(Wn.source),Ln=/^\s+|\s+$/g,Nn=/^\s+/,Bn=/\s+$/,Fn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Un=/\{\n\/\* \[wrapped with (.+)\] \*/,Mn=/,? & /,Vn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Pn=/\\(\\)?/g,$n=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Dn=/\w*$/,qn=/^[-+]0x[0-9a-f]+$/i,Jn=/^0b[01]+$/i,Zn=/^\[object .+?Constructor\]$/,Hn=/^0o[0-7]+$/i,Kn=/^(?:0|[1-9]\d*)$/,Gn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Yn=/($^)/,Qn=/['\n\r\u2028\u2029\\]/g,Xn="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",nt="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",tt="[\\ud800-\\udfff]",rt="["+nt+"]",et="["+Xn+"]",ut="\\d+",it="[\\u2700-\\u27bf]",ot="[a-z\\xdf-\\xf6\\xf8-\\xff]",at="[^\\ud800-\\udfff"+nt+ut+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",ft="\\ud83c[\\udffb-\\udfff]",ct="[^\\ud800-\\udfff]",lt="(?:\\ud83c[\\udde6-\\uddff]){2}",st="[\\ud800-\\udbff][\\udc00-\\udfff]",ht="[A-Z\\xc0-\\xd6\\xd8-\\xde]",pt="(?:"+ot+"|"+at+")",vt="(?:"+ht+"|"+at+")",_t="(?:"+et+"|"+ft+")"+"?",gt="[\\ufe0e\\ufe0f]?"+_t+("(?:\\u200d(?:"+[ct,lt,st].join("|")+")[\\ufe0e\\ufe0f]?"+_t+")*"),dt="(?:"+[it,lt,st].join("|")+")"+gt,yt="(?:"+[ct+et+"?",et,lt,st,tt].join("|")+")",bt=RegExp("['’]","g"),wt=RegExp(et,"g"),mt=RegExp(ft+"(?="+ft+")|"+yt+gt,"g"),xt=RegExp([ht+"?"+ot+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[rt,ht,"$"].join("|")+")",vt+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[rt,ht+pt,"$"].join("|")+")",ht+"?"+pt+"+(?:['’](?:d|ll|m|re|s|t|ve))?",ht+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ut,dt].join("|"),"g"),St=RegExp("[\\u200d\\ud800-\\udfff"+Xn+"\\ufe0e\\ufe0f]"),jt=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,At=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Ot=-1,kt={};kt[sn]=kt[hn]=kt[pn]=kt[vn]=kt[_n]=kt[gn]=kt[dn]=kt[yn]=kt[bn]=!0,kt[V]=kt[P]=kt[cn]=kt[D]=kt[ln]=kt[q]=kt[Z]=kt[H]=kt[G]=kt[Y]=kt[X]=kt[tn]=kt[rn]=kt[en]=kt[an]=!1;var Et={};Et[V]=Et[P]=Et[cn]=Et[ln]=Et[D]=Et[q]=Et[sn]=Et[hn]=Et[pn]=Et[vn]=Et[_n]=Et[G]=Et[Y]=Et[X]=Et[tn]=Et[rn]=Et[en]=Et[un]=Et[gn]=Et[dn]=Et[yn]=Et[bn]=!0,Et[Z]=Et[H]=Et[an]=!1;var It={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},zt=parseFloat,Rt=parseInt,Tt="object"==typeof n&&n&&n.Object===Object&&n,Wt="object"==typeof self&&self&&self.Object===Object&&self,Ct=Tt||Wt||Function("return this")(),Lt=t&&!t.nodeType&&t,Nt=Lt&&"object"==typeof e&&e&&!e.nodeType&&e,Bt=Nt&&Nt.exports===Lt,Ft=Bt&&Tt.process,Ut=function(){try{var n=Nt&&Nt.require&&Nt.require("util").types;return n||Ft&&Ft.binding&&Ft.binding("util")}catch(t){}}(),Mt=Ut&&Ut.isArrayBuffer,Vt=Ut&&Ut.isDate,Pt=Ut&&Ut.isMap,$t=Ut&&Ut.isRegExp,Dt=Ut&&Ut.isSet,qt=Ut&&Ut.isTypedArray;function Jt(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function Zt(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function Xt(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function mr(n,t){for(var r=n.length;r--&&fr(t,n[r],0)>-1;);return r}var xr=pr({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),Sr=pr({"&":"&","<":"<",">":">",'"':""","'":"'"});function jr(n){return"\\"+It[n]}function Ar(n){return St.test(n)}function Or(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function kr(n,t){return function(r){return n(t(r))}}function Er(n,t){for(var r=-1,e=n.length,u=0,i=[];++r",""":'"',"'":"'"});var Cr=function n(t){var r,e=(t=null==t?Ct:Cr.defaults(Ct.Object(),t,Cr.pick(Ct,At))).Array,u=t.Date,Xn=t.Error,nt=t.Function,tt=t.Math,rt=t.Object,et=t.RegExp,ut=t.String,it=t.TypeError,ot=e.prototype,at=nt.prototype,ft=rt.prototype,ct=t["__core-js_shared__"],lt=at.toString,st=ft.hasOwnProperty,ht=0,pt=(r=/[^.]+$/.exec(ct&&ct.keys&&ct.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"",vt=ft.toString,_t=lt.call(rt),gt=Ct._,dt=et("^"+lt.call(st).replace(Wn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),yt=Bt?t.Buffer:i,mt=t.Symbol,St=t.Uint8Array,It=yt?yt.allocUnsafe:i,Tt=kr(rt.getPrototypeOf,rt),Wt=rt.create,Lt=ft.propertyIsEnumerable,Nt=ot.splice,Ft=mt?mt.isConcatSpreadable:i,Ut=mt?mt.iterator:i,ir=mt?mt.toStringTag:i,pr=function(){try{var n=Fi(rt,"defineProperty");return n({},"",{}),n}catch(t){}}(),Lr=t.clearTimeout!==Ct.clearTimeout&&t.clearTimeout,Nr=u&&u.now!==Ct.Date.now&&u.now,Br=t.setTimeout!==Ct.setTimeout&&t.setTimeout,Fr=tt.ceil,Ur=tt.floor,Mr=rt.getOwnPropertySymbols,Vr=yt?yt.isBuffer:i,Pr=t.isFinite,$r=ot.join,Dr=kr(rt.keys,rt),qr=tt.max,Jr=tt.min,Zr=u.now,Hr=t.parseInt,Kr=tt.random,Gr=ot.reverse,Yr=Fi(t,"DataView"),Qr=Fi(t,"Map"),Xr=Fi(t,"Promise"),ne=Fi(t,"Set"),te=Fi(t,"WeakMap"),re=Fi(rt,"create"),ee=te&&new te,ue={},ie=lo(Yr),oe=lo(Qr),ae=lo(Xr),fe=lo(ne),ce=lo(te),le=mt?mt.prototype:i,se=le?le.valueOf:i,he=le?le.toString:i;function pe(n){if(Ea(n)&&!da(n)&&!(n instanceof de)){if(n instanceof ge)return n;if(st.call(n,"__wrapped__"))return so(n)}return new ge(n)}var ve=function(){function n(){}return function(t){if(!ka(t))return{};if(Wt)return Wt(t);n.prototype=t;var r=new n;return n.prototype=i,r}}();function _e(){}function ge(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=i}function de(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=B,this.__views__=[]}function ye(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function Le(n,t,r,e,u,o){var a,f=t&h,c=t&p,l=t&v;if(r&&(a=u?r(n,e,u,o):r(n)),a!==i)return a;if(!ka(n))return n;var s=da(n);if(s){if(a=function(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&st.call(n,"index")&&(r.index=n.index,r.input=n.input),r}(n),!f)return ri(n,a)}else{var _=Vi(n),g=_==H||_==K;if(ma(n))return Gu(n,f);if(_==X||_==V||g&&!u){if(a=c||g?{}:$i(n),!f)return c?function(n,t){return ei(n,Mi(n),t)}(n,function(n,t){return n&&ei(t,of(t),n)}(a,n)):function(n,t){return ei(n,Ui(n),t)}(n,Re(a,n))}else{if(!Et[_])return u?n:{};a=function(n,t,r){var e,u=n.constructor;switch(t){case cn:return Yu(n);case D:case q:return new u(+n);case ln:return function(n,t){var r=t?Yu(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}(n,r);case sn:case hn:case pn:case vn:case _n:case gn:case dn:case yn:case bn:return Qu(n,r);case G:return new u;case Y:case en:return new u(n);case tn:return function(n){var t=new n.constructor(n.source,Dn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case rn:return new u;case un:return e=n,se?rt(se.call(e)):{}}}(n,_,f)}}o||(o=new xe);var d=o.get(n);if(d)return d;o.set(n,a),Wa(n)?n.forEach(function(e){a.add(Le(e,t,r,e,n,o))}):Ia(n)&&n.forEach(function(e,u){a.set(u,Le(e,t,r,u,n,o))});var y=s?i:(l?c?Ri:zi:c?of:uf)(n);return Ht(y||n,function(e,u){y&&(e=n[u=e]),Ee(a,u,Le(e,t,r,u,n,o))}),a}function Ne(n,t,r){var e=r.length;if(null==n)return!e;for(n=rt(n);e--;){var u=r[e],o=t[u],a=n[u];if(a===i&&!(u in n)||!o(a))return!1}return!0}function Be(n,t,r){if("function"!=typeof n)throw new it(f);return eo(function(){n.apply(i,r)},t)}function Fe(n,t,r,e){var u=-1,i=Qt,a=!0,f=n.length,c=[],l=t.length;if(!f)return c;r&&(t=nr(t,dr(r))),e?(i=Xt,a=!1):t.length>=o&&(i=br,a=!1,t=new me(t));n:for(;++u-1},be.prototype.set=function(n,t){var r=this.__data__,e=Ie(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},we.prototype.clear=function(){this.size=0,this.__data__={hash:new ye,map:new(Qr||be),string:new ye}},we.prototype.delete=function(n){var t=Ni(this,n).delete(n);return this.size-=t?1:0,t},we.prototype.get=function(n){return Ni(this,n).get(n)},we.prototype.has=function(n){return Ni(this,n).has(n)},we.prototype.set=function(n,t){var r=Ni(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},me.prototype.add=me.prototype.push=function(n){return this.__data__.set(n,c),this},me.prototype.has=function(n){return this.__data__.has(n)},xe.prototype.clear=function(){this.__data__=new be,this.size=0},xe.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},xe.prototype.get=function(n){return this.__data__.get(n)},xe.prototype.has=function(n){return this.__data__.has(n)},xe.prototype.set=function(n,t){var r=this.__data__;if(r instanceof be){var e=r.__data__;if(!Qr||e.length0&&r(a)?t>1?De(a,t-1,r,e,u):tr(u,a):e||(u[u.length]=a)}return u}var qe=ai(),Je=ai(!0);function Ze(n,t){return n&&qe(n,t,uf)}function He(n,t){return n&&Je(n,t,uf)}function Ke(n,t){return Yt(t,function(t){return ja(n[t])})}function Ge(n,t){for(var r=0,e=(t=Ju(t,n)).length;null!=n&&rt}function nu(n,t){return null!=n&&st.call(n,t)}function tu(n,t){return null!=n&&t in rt(n)}function ru(n,t,r){for(var u=r?Xt:Qt,o=n[0].length,a=n.length,f=a,c=e(a),l=1/0,s=[];f--;){var h=n[f];f&&t&&(h=nr(h,dr(t))),l=Jr(h.length,l),c[f]=!r&&(t||o>=120&&h.length>=120)?new me(f&&h):i}h=n[0];var p=-1,v=c[0];n:for(;++p=a)return f;var c=r[e];return f*("desc"==c?-1:1)}}return n.index-t.index}(n,t,r)})}function yu(n,t,r){for(var e=-1,u=t.length,i={};++e-1;)a!==n&&Nt.call(a,f,1),Nt.call(n,f,1);return n}function wu(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;qi(u)?Nt.call(n,u,1):Fu(n,u)}}return n}function mu(n,t){return n+Ur(Kr()*(t-n+1))}function xu(n,t){var r="";if(!n||t<1||t>C)return r;do{t%2&&(r+=n),(t=Ur(t/2))&&(n+=n)}while(t);return r}function Su(n,t){return uo(Xi(n,t,Rf),n+"")}function ju(n){return je(vf(n))}function Au(n,t){var r=vf(n);return ao(r,Ce(t,0,r.length))}function Ou(n,t,r,e){if(!ka(n))return n;for(var u=-1,o=(t=Ju(t,n)).length,a=o-1,f=n;null!=f&&++ui?0:i+t),(r=r>i?i:r)<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=e(i);++u>>1,o=n[i];null!==o&&!La(o)&&(r?o<=t:o=o){var l=t?null:xi(n);if(l)return Ir(l);a=!1,u=br,c=new me}else c=t?[]:f;n:for(;++e=e?n:zu(n,t,r)}var Ku=Lr||function(n){return Ct.clearTimeout(n)};function Gu(n,t){if(t)return n.slice();var r=n.length,e=It?It(r):new n.constructor(r);return n.copy(e),e}function Yu(n){var t=new n.constructor(n.byteLength);return new St(t).set(new St(n)),t}function Qu(n,t){var r=t?Yu(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function Xu(n,t){if(n!==t){var r=n!==i,e=null===n,u=n==n,o=La(n),a=t!==i,f=null===t,c=t==t,l=La(t);if(!f&&!l&&!o&&n>t||o&&a&&c&&!f&&!l||e&&a&&c||!r&&c||!u)return 1;if(!e&&!o&&!l&&n1?r[u-1]:i,a=u>2?r[2]:i;for(o=n.length>3&&"function"==typeof o?(u--,o):i,a&&Ji(r[0],r[1],a)&&(o=u<3?i:o,u=1),t=rt(t);++e-1?u[o?t[a]:a]:i}}function hi(n){return Ii(function(t){var r=t.length,e=r,u=ge.prototype.thru;for(n&&t.reverse();e--;){var o=t[e];if("function"!=typeof o)throw new it(f);if(u&&!a&&"wrapper"==Wi(o))var a=new ge([],!0)}for(e=a?e:r;++e1&&w.reverse(),h&&lf))return!1;var l=o.get(n);if(l&&o.get(t))return l==t;var s=-1,h=!0,p=r&g?new me:i;for(o.set(n,t),o.set(t,n);++s-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(Fn,"{\n/* [wrapped with "+t+"] */\n")}(e,function(n,t){return Ht(M,function(r){var e="_."+r[0];t&r[1]&&!Qt(n,e)&&n.push(e)}),n.sort()}(function(n){var t=n.match(Un);return t?t[1].split(Mn):[]}(e),r)))}function oo(n){var t=0,r=0;return function(){var e=Zr(),u=z-(e-r);if(r=e,u>0){if(++t>=I)return arguments[0]}else t=0;return n.apply(i,arguments)}}function ao(n,t){var r=-1,e=n.length,u=e-1;for(t=t===i?e:t;++r1?n[t-1]:i;return r="function"==typeof r?(n.pop(),r):i,To(n,r)});function Uo(n){var t=pe(n);return t.__chain__=!0,t}function Mo(n,t){return t(n)}var Vo=Ii(function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return We(t,n)};return!(t>1||this.__actions__.length)&&e instanceof de&&qi(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:Mo,args:[u],thisArg:i}),new ge(e,this.__chain__).thru(function(n){return t&&!n.length&&n.push(i),n})):this.thru(u)});var Po=ui(function(n,t,r){st.call(n,r)?++n[r]:Te(n,r,1)});var $o=si(_o),Do=si(go);function qo(n,t){return(da(n)?Ht:Ue)(n,Li(t,3))}function Jo(n,t){return(da(n)?Kt:Me)(n,Li(t,3))}var Zo=ui(function(n,t,r){st.call(n,r)?n[r].push(t):Te(n,r,[t])});var Ho=Su(function(n,t,r){var u=-1,i="function"==typeof t,o=ba(n)?e(n.length):[];return Ue(n,function(n){o[++u]=i?Jt(t,n,r):eu(n,t,r)}),o}),Ko=ui(function(n,t,r){Te(n,r,t)});function Go(n,t){return(da(n)?nr:hu)(n,Li(t,3))}var Yo=ui(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]});var Qo=Su(function(n,t){if(null==n)return[];var r=t.length;return r>1&&Ji(n,t[0],t[1])?t=[]:r>2&&Ji(t[0],t[1],t[2])&&(t=[t[0]]),du(n,De(t,1),[])}),Xo=Nr||function(){return Ct.Date.now()};function na(n,t,r){return t=r?i:t,t=n&&null==t?n.length:t,ji(n,j,i,i,i,i,t)}function ta(n,t){var r;if("function"!=typeof t)throw new it(f);return n=Va(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=i),r}}var ra=Su(function(n,t,r){var e=d;if(r.length){var u=Er(r,Ci(ra));e|=x}return ji(n,e,t,r,u)}),ea=Su(function(n,t,r){var e=d|y;if(r.length){var u=Er(r,Ci(ea));e|=x}return ji(t,e,n,r,u)});function ua(n,t,r){var e,u,o,a,c,l,s=0,h=!1,p=!1,v=!0;if("function"!=typeof n)throw new it(f);function _(t){var r=e,o=u;return e=u=i,s=t,a=n.apply(o,r)}function g(n){var r=n-l;return l===i||r>=t||r<0||p&&n-s>=o}function d(){var n=Xo();if(g(n))return y(n);c=eo(d,function(n){var r=t-(n-l);return p?Jr(r,o-(n-s)):r}(n))}function y(n){return c=i,v&&e?_(n):(e=u=i,a)}function b(){var n=Xo(),r=g(n);if(e=arguments,u=this,l=n,r){if(c===i)return function(n){return s=n,c=eo(d,t),h?_(n):a}(l);if(p)return Ku(c),c=eo(d,t),_(l)}return c===i&&(c=eo(d,t)),a}return t=$a(t)||0,ka(r)&&(h=!!r.leading,o=(p="maxWait"in r)?qr($a(r.maxWait)||0,t):o,v="trailing"in r?!!r.trailing:v),b.cancel=function(){c!==i&&Ku(c),s=0,e=l=u=c=i},b.flush=function(){return c===i?a:y(Xo())},b}var ia=Su(function(n,t){return Be(n,1,t)}),oa=Su(function(n,t,r){return Be(n,$a(t)||0,r)});function aa(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new it(f);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(aa.Cache||we),r}function fa(n){if("function"!=typeof n)throw new it(f);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}aa.Cache=we;var ca=Zu(function(n,t){var r=(t=1==t.length&&da(t[0])?nr(t[0],dr(Li())):nr(De(t,1),dr(Li()))).length;return Su(function(e){for(var u=-1,i=Jr(e.length,r);++u=t}),ga=uu(function(){return arguments}())?uu:function(n){return Ea(n)&&st.call(n,"callee")&&!Lt.call(n,"callee")},da=e.isArray,ya=Mt?dr(Mt):function(n){return Ea(n)&&Qe(n)==cn};function ba(n){return null!=n&&Oa(n.length)&&!ja(n)}function wa(n){return Ea(n)&&ba(n)}var ma=Vr||Df,xa=Vt?dr(Vt):function(n){return Ea(n)&&Qe(n)==q};function Sa(n){if(!Ea(n))return!1;var t=Qe(n);return t==Z||t==J||"string"==typeof n.message&&"string"==typeof n.name&&!Ra(n)}function ja(n){if(!ka(n))return!1;var t=Qe(n);return t==H||t==K||t==$||t==nn}function Aa(n){return"number"==typeof n&&n==Va(n)}function Oa(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=C}function ka(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function Ea(n){return null!=n&&"object"==typeof n}var Ia=Pt?dr(Pt):function(n){return Ea(n)&&Vi(n)==G};function za(n){return"number"==typeof n||Ea(n)&&Qe(n)==Y}function Ra(n){if(!Ea(n)||Qe(n)!=X)return!1;var t=Tt(n);if(null===t)return!0;var r=st.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&<.call(r)==_t}var Ta=$t?dr($t):function(n){return Ea(n)&&Qe(n)==tn};var Wa=Dt?dr(Dt):function(n){return Ea(n)&&Vi(n)==rn};function Ca(n){return"string"==typeof n||!da(n)&&Ea(n)&&Qe(n)==en}function La(n){return"symbol"==typeof n||Ea(n)&&Qe(n)==un}var Na=qt?dr(qt):function(n){return Ea(n)&&Oa(n.length)&&!!kt[Qe(n)]};var Ba=bi(su),Fa=bi(function(n,t){return n<=t});function Ua(n){if(!n)return[];if(ba(n))return Ca(n)?Tr(n):ri(n);if(Ut&&n[Ut])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Ut]());var t=Vi(n);return(t==G?Or:t==rn?Ir:vf)(n)}function Ma(n){return n?(n=$a(n))===W||n===-W?(n<0?-1:1)*L:n==n?n:0:0===n?n:0}function Va(n){var t=Ma(n),r=t%1;return t==t?r?t-r:t:0}function Pa(n){return n?Ce(Va(n),0,B):0}function $a(n){if("number"==typeof n)return n;if(La(n))return N;if(ka(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=ka(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=n.replace(Ln,"");var r=Jn.test(n);return r||Hn.test(n)?Rt(n.slice(2),r?2:8):qn.test(n)?N:+n}function Da(n){return ei(n,of(n))}function qa(n){return null==n?"":Nu(n)}var Ja=ii(function(n,t){if(Gi(t)||ba(t))ei(t,uf(t),n);else for(var r in t)st.call(t,r)&&Ee(n,r,t[r])}),Za=ii(function(n,t){ei(t,of(t),n)}),Ha=ii(function(n,t,r,e){ei(t,of(t),n,e)}),Ka=ii(function(n,t,r,e){ei(t,uf(t),n,e)}),Ga=Ii(We);var Ya=Su(function(n,t){n=rt(n);var r=-1,e=t.length,u=e>2?t[2]:i;for(u&&Ji(t[0],t[1],u)&&(e=1);++r1),t}),ei(n,Ri(n),r),e&&(r=Le(r,h|p|v,ki));for(var u=t.length;u--;)Fu(r,t[u]);return r});var lf=Ii(function(n,t){return null==n?{}:function(n,t){return yu(n,t,function(t,r){return nf(n,r)})}(n,t)});function sf(n,t){if(null==n)return{};var r=nr(Ri(n),function(n){return[n]});return t=Li(t),yu(n,r,function(n,r){return t(n,r[0])})}var hf=Si(uf),pf=Si(of);function vf(n){return null==n?[]:yr(n,uf(n))}var _f=ci(function(n,t,r){return t=t.toLowerCase(),n+(r?gf(t):t)});function gf(n){return jf(qa(n).toLowerCase())}function df(n){return(n=qa(n))&&n.replace(Gn,xr).replace(wt,"")}var yf=ci(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),bf=ci(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),wf=fi("toLowerCase");var mf=ci(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()});var xf=ci(function(n,t,r){return n+(r?" ":"")+jf(t)});var Sf=ci(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),jf=fi("toUpperCase");function Af(n,t,r){return n=qa(n),(t=r?i:t)===i?function(n){return jt.test(n)}(n)?function(n){return n.match(xt)||[]}(n):function(n){return n.match(Vn)||[]}(n):n.match(t)||[]}var Of=Su(function(n,t){try{return Jt(n,i,t)}catch(r){return Sa(r)?r:new Xn(r)}}),kf=Ii(function(n,t){return Ht(t,function(t){t=co(t),Te(n,t,ra(n[t],n))}),n});function Ef(n){return function(){return n}}var If=hi(),zf=hi(!0);function Rf(n){return n}function Tf(n){return fu("function"==typeof n?n:Le(n,h))}var Wf=Su(function(n,t){return function(r){return eu(r,n,t)}}),Cf=Su(function(n,t){return function(r){return eu(n,r,t)}});function Lf(n,t,r){var e=uf(t),u=Ke(t,e);null!=r||ka(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=Ke(t,uf(t)));var i=!(ka(r)&&"chain"in r&&!r.chain),o=ja(n);return Ht(u,function(r){var e=t[r];n[r]=e,o&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__),u=r.__actions__=ri(this.__actions__);return u.push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,tr([this.value()],arguments))})}),n}function Nf(){}var Bf=gi(nr),Ff=gi(Gt),Uf=gi(ur);function Mf(n){return Zi(n)?hr(co(n)):function(n){return function(t){return Ge(t,n)}}(n)}var Vf=yi(),Pf=yi(!0);function $f(){return[]}function Df(){return!1}var qf=_i(function(n,t){return n+t},0),Jf=mi("ceil"),Zf=_i(function(n,t){return n/t},1),Hf=mi("floor");var Kf,Gf=_i(function(n,t){return n*t},1),Yf=mi("round"),Qf=_i(function(n,t){return n-t},0);return pe.after=function(n,t){if("function"!=typeof t)throw new it(f);return n=Va(n),function(){if(--n<1)return t.apply(this,arguments)}},pe.ary=na,pe.assign=Ja,pe.assignIn=Za,pe.assignInWith=Ha,pe.assignWith=Ka,pe.at=Ga,pe.before=ta,pe.bind=ra,pe.bindAll=kf,pe.bindKey=ea,pe.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return da(n)?n:[n]},pe.chain=Uo,pe.chunk=function(n,t,r){t=(r?Ji(n,t,r):t===i)?1:qr(Va(t),0);var u=null==n?0:n.length;if(!u||t<1)return[];for(var o=0,a=0,f=e(Fr(u/t));ou?0:u+r),(e=e===i||e>u?u:Va(e))<0&&(e+=u),e=r>e?0:Pa(e);r>>0)?(n=qa(n))&&("string"==typeof t||null!=t&&!Ta(t))&&!(t=Nu(t))&&Ar(n)?Hu(Tr(n),0,r):n.split(t,r):[]},pe.spread=function(n,t){if("function"!=typeof n)throw new it(f);return t=null==t?0:qr(Va(t),0),Su(function(r){var e=r[t],u=Hu(r,0,t);return e&&tr(u,e),Jt(n,this,u)})},pe.tail=function(n){var t=null==n?0:n.length;return t?zu(n,1,t):[]},pe.take=function(n,t,r){return n&&n.length?zu(n,0,(t=r||t===i?1:Va(t))<0?0:t):[]},pe.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?zu(n,(t=e-(t=r||t===i?1:Va(t)))<0?0:t,e):[]},pe.takeRightWhile=function(n,t){return n&&n.length?Mu(n,Li(t,3),!1,!0):[]},pe.takeWhile=function(n,t){return n&&n.length?Mu(n,Li(t,3)):[]},pe.tap=function(n,t){return t(n),n},pe.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new it(f);return ka(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ua(n,t,{leading:e,maxWait:t,trailing:u})},pe.thru=Mo,pe.toArray=Ua,pe.toPairs=hf,pe.toPairsIn=pf,pe.toPath=function(n){return da(n)?nr(n,co):La(n)?[n]:ri(fo(qa(n)))},pe.toPlainObject=Da,pe.transform=function(n,t,r){var e=da(n),u=e||ma(n)||Na(n);if(t=Li(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:ka(n)&&ja(i)?ve(Tt(n)):{}}return(u?Ht:Ze)(n,function(n,e,u){return t(r,n,e,u)}),r},pe.unary=function(n){return na(n,1)},pe.union=Eo,pe.unionBy=Io,pe.unionWith=zo,pe.uniq=function(n){return n&&n.length?Bu(n):[]},pe.uniqBy=function(n,t){return n&&n.length?Bu(n,Li(t,2)):[]},pe.uniqWith=function(n,t){return t="function"==typeof t?t:i,n&&n.length?Bu(n,i,t):[]},pe.unset=function(n,t){return null==n||Fu(n,t)},pe.unzip=Ro,pe.unzipWith=To,pe.update=function(n,t,r){return null==n?n:Uu(n,t,qu(r))},pe.updateWith=function(n,t,r,e){return e="function"==typeof e?e:i,null==n?n:Uu(n,t,qu(r),e)},pe.values=vf,pe.valuesIn=function(n){return null==n?[]:yr(n,of(n))},pe.without=Wo,pe.words=Af,pe.wrap=function(n,t){return la(qu(t),n)},pe.xor=Co,pe.xorBy=Lo,pe.xorWith=No,pe.zip=Bo,pe.zipObject=function(n,t){return $u(n||[],t||[],Ee)},pe.zipObjectDeep=function(n,t){return $u(n||[],t||[],Ou)},pe.zipWith=Fo,pe.entries=hf,pe.entriesIn=pf,pe.extend=Za,pe.extendWith=Ha,Lf(pe,pe),pe.add=qf,pe.attempt=Of,pe.camelCase=_f,pe.capitalize=gf,pe.ceil=Jf,pe.clamp=function(n,t,r){return r===i&&(r=t,t=i),r!==i&&(r=(r=$a(r))==r?r:0),t!==i&&(t=(t=$a(t))==t?t:0),Ce($a(n),t,r)},pe.clone=function(n){return Le(n,v)},pe.cloneDeep=function(n){return Le(n,h|v)},pe.cloneDeepWith=function(n,t){return Le(n,h|v,t="function"==typeof t?t:i)},pe.cloneWith=function(n,t){return Le(n,v,t="function"==typeof t?t:i)},pe.conformsTo=function(n,t){return null==t||Ne(n,t,uf(t))},pe.deburr=df,pe.defaultTo=function(n,t){return null==n||n!=n?t:n},pe.divide=Zf,pe.endsWith=function(n,t,r){n=qa(n),t=Nu(t);var e=n.length,u=r=r===i?e:Ce(Va(r),0,e);return(r-=t.length)>=0&&n.slice(r,u)==t},pe.eq=pa,pe.escape=function(n){return(n=qa(n))&&On.test(n)?n.replace(jn,Sr):n},pe.escapeRegExp=function(n){return(n=qa(n))&&Cn.test(n)?n.replace(Wn,"\\$&"):n},pe.every=function(n,t,r){var e=da(n)?Gt:Ve;return r&&Ji(n,t,r)&&(t=i),e(n,Li(t,3))},pe.find=$o,pe.findIndex=_o,pe.findKey=function(n,t){return or(n,Li(t,3),Ze)},pe.findLast=Do,pe.findLastIndex=go,pe.findLastKey=function(n,t){return or(n,Li(t,3),He)},pe.floor=Hf,pe.forEach=qo,pe.forEachRight=Jo,pe.forIn=function(n,t){return null==n?n:qe(n,Li(t,3),of)},pe.forInRight=function(n,t){return null==n?n:Je(n,Li(t,3),of)},pe.forOwn=function(n,t){return n&&Ze(n,Li(t,3))},pe.forOwnRight=function(n,t){return n&&He(n,Li(t,3))},pe.get=Xa,pe.gt=va,pe.gte=_a,pe.has=function(n,t){return null!=n&&Pi(n,t,nu)},pe.hasIn=nf,pe.head=bo,pe.identity=Rf,pe.includes=function(n,t,r,e){n=ba(n)?n:vf(n),r=r&&!e?Va(r):0;var u=n.length;return r<0&&(r=qr(u+r,0)),Ca(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&fr(n,t,r)>-1},pe.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:Va(r);return u<0&&(u=qr(e+u,0)),fr(n,t,u)},pe.inRange=function(n,t,r){return t=Ma(t),r===i?(r=t,t=0):r=Ma(r),function(n,t,r){return n>=Jr(t,r)&&n=-C&&n<=C},pe.isSet=Wa,pe.isString=Ca,pe.isSymbol=La,pe.isTypedArray=Na,pe.isUndefined=function(n){return n===i},pe.isWeakMap=function(n){return Ea(n)&&Vi(n)==an},pe.isWeakSet=function(n){return Ea(n)&&Qe(n)==fn},pe.join=function(n,t){return null==n?"":$r.call(n,t)},pe.kebabCase=yf,pe.last=So,pe.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;return r!==i&&(u=(u=Va(r))<0?qr(e+u,0):Jr(u,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,u):ar(n,lr,u,!0)},pe.lowerCase=bf,pe.lowerFirst=wf,pe.lt=Ba,pe.lte=Fa,pe.max=function(n){return n&&n.length?Pe(n,Rf,Xe):i},pe.maxBy=function(n,t){return n&&n.length?Pe(n,Li(t,2),Xe):i},pe.mean=function(n){return sr(n,Rf)},pe.meanBy=function(n,t){return sr(n,Li(t,2))},pe.min=function(n){return n&&n.length?Pe(n,Rf,su):i},pe.minBy=function(n,t){return n&&n.length?Pe(n,Li(t,2),su):i},pe.stubArray=$f,pe.stubFalse=Df,pe.stubObject=function(){return{}},pe.stubString=function(){return""},pe.stubTrue=function(){return!0},pe.multiply=Gf,pe.nth=function(n,t){return n&&n.length?gu(n,Va(t)):i},pe.noConflict=function(){return Ct._===this&&(Ct._=gt),this},pe.noop=Nf,pe.now=Xo,pe.pad=function(n,t,r){n=qa(n);var e=(t=Va(t))?Rr(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return di(Ur(u),r)+n+di(Fr(u),r)},pe.padEnd=function(n,t,r){n=qa(n);var e=(t=Va(t))?Rr(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var u=Kr();return Jr(n+u*(t-n+zt("1e-"+((u+"").length-1))),t)}return mu(n,t)},pe.reduce=function(n,t,r){var e=da(n)?rr:vr,u=arguments.length<3;return e(n,Li(t,4),r,u,Ue)},pe.reduceRight=function(n,t,r){var e=da(n)?er:vr,u=arguments.length<3;return e(n,Li(t,4),r,u,Me)},pe.repeat=function(n,t,r){return t=(r?Ji(n,t,r):t===i)?1:Va(t),xu(qa(n),t)},pe.replace=function(){var n=arguments,t=qa(n[0]);return n.length<3?t:t.replace(n[1],n[2])},pe.result=function(n,t,r){var e=-1,u=(t=Ju(t,n)).length;for(u||(u=1,n=i);++eC)return[];var r=B,e=Jr(n,B);t=Li(t),n-=B;for(var u=gr(e,t);++r=o)return n;var f=r-Rr(e);if(f<1)return e;var c=a?Hu(a,0,f).join(""):n.slice(0,f);if(u===i)return c+e;if(a&&(f+=c.length-f),Ta(u)){if(n.slice(f).search(u)){var l,s=c;for(u.global||(u=et(u.source,qa(Dn.exec(u))+"g")),u.lastIndex=0;l=u.exec(s);)var h=l.index;c=c.slice(0,h===i?f:h)}}else if(n.indexOf(Nu(u),f)!=f){var p=c.lastIndexOf(u);p>-1&&(c=c.slice(0,p))}return c+e},pe.unescape=function(n){return(n=qa(n))&&An.test(n)?n.replace(Sn,Wr):n},pe.uniqueId=function(n){var t=++ht;return qa(n)+t},pe.upperCase=Sf,pe.upperFirst=jf,pe.each=qo,pe.eachRight=Jo,pe.first=bo,Lf(pe,(Kf={},Ze(pe,function(n,t){st.call(pe.prototype,t)||(Kf[t]=n)}),Kf),{chain:!1}),pe.VERSION="4.17.14",Ht(["bind","bindKey","curry","curryRight","partial","partialRight"],function(n){pe[n].placeholder=pe}),Ht(["drop","take"],function(n,t){de.prototype[n]=function(r){r=r===i?1:qr(Va(r),0);var e=this.__filtered__&&!t?new de(this):this.clone();return e.__filtered__?e.__takeCount__=Jr(r,e.__takeCount__):e.__views__.push({size:Jr(r,B),type:n+(e.__dir__<0?"Right":"")}),e},de.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),Ht(["filter","map","takeWhile"],function(n,t){var r=t+1,e=r==R||3==r;de.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:Li(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),Ht(["head","last"],function(n,t){var r="take"+(t?"Right":"");de.prototype[n]=function(){return this[r](1).value()[0]}}),Ht(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");de.prototype[n]=function(){return this.__filtered__?new de(this):this[r](1)}}),de.prototype.compact=function(){return this.filter(Rf)},de.prototype.find=function(n){return this.filter(n).head()},de.prototype.findLast=function(n){return this.reverse().find(n)},de.prototype.invokeMap=Su(function(n,t){return"function"==typeof n?new de(this):this.map(function(r){return eu(r,n,t)})}),de.prototype.reject=function(n){return this.filter(fa(Li(n)))},de.prototype.slice=function(n,t){n=Va(n);var r=this;return r.__filtered__&&(n>0||t<0)?new de(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==i&&(r=(t=Va(t))<0?r.dropRight(-t):r.take(t-n)),r)},de.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},de.prototype.toArray=function(){return this.take(B)},Ze(de.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=pe[e?"take"+("last"==t?"Right":""):t],o=e||/^find/.test(t);u&&(pe.prototype[t]=function(){var t=this.__wrapped__,a=e?[1]:arguments,f=t instanceof de,c=a[0],l=f||da(t),s=function(n){var t=u.apply(pe,tr([n],a));return e&&h?t[0]:t};l&&r&&"function"==typeof c&&1!=c.length&&(f=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,_=f&&!p;if(!o&&l){t=_?t:new de(this);var g=n.apply(t,a);return g.__actions__.push({func:Mo,args:[s],thisArg:i}),new ge(g,h)}return v&&_?n.apply(this,a):(g=this.thru(s),v?e?g.value()[0]:g.value():g)})}),Ht(["pop","push","shift","sort","splice","unshift"],function(n){var t=ot[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);pe.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(da(u)?u:[],n)}return this[r](function(r){return t.apply(da(r)?r:[],n)})}}),Ze(de.prototype,function(n,t){var r=pe[t];if(r){var e=r.name+"";st.call(ue,e)||(ue[e]=[]),ue[e].push({name:t,func:r})}}),ue[pi(i,y).name]=[{name:"wrapper",func:i}],de.prototype.clone=function(){var n=new de(this.__wrapped__);return n.__actions__=ri(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=ri(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=ri(this.__views__),n},de.prototype.reverse=function(){if(this.__filtered__){var n=new de(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},de.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=da(n),e=t<0,u=r?n.length:0,i=function(n,t,r){for(var e=-1,u=r.length;++e=this.__values__.length;return{done:n,value:n?i:this.__values__[this.__index__++]}},pe.prototype.plant=function(n){for(var t,r=this;r instanceof _e;){var e=so(r);e.__index__=0,e.__values__=i,t?u.__wrapped__=e:t=e;var u=e;r=r.__wrapped__}return u.__wrapped__=n,t},pe.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof de){var t=n;return this.__actions__.length&&(t=new de(this)),(t=t.reverse()).__actions__.push({func:Mo,args:[ko],thisArg:i}),new ge(t,this.__chain__)}return this.thru(ko)},pe.prototype.toJSON=pe.prototype.valueOf=pe.prototype.value=function(){return Vu(this.__wrapped__,this.__actions__)},pe.prototype.first=pe.prototype.head,Ut&&(pe.prototype[Ut]=function(){return this}),pe}();Ct._=Cr,(u=function(){return Cr}.call(t,r,t,e))===i||(e.exports=u)}).call(this)}).call(this,r(2),r(3)(n))},function(n,t){n.exports=require("sketch")},function(n,t){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(e){"object"==typeof window&&(r=window)}n.exports=r},function(n,t){n.exports=function(n){return n.webpackPolyfill||(n.deprecate=function(){},n.paths=[],n.children||(n.children=[]),Object.defineProperty(n,"loaded",{enumerable:!0,get:function(){return n.l}}),Object.defineProperty(n,"id",{enumerable:!0,get:function(){return n.i}}),n.webpackPolyfill=1),n}},function(n,r,e){"use strict";e.r(r);var u,i,o,a,f,c,l,s,h,p,v=e(1),_=e.n(v),g=e(0),d=e.n(g),y={"JavaScript Object":{lineStart:"",prefix:" '",diviner:"': '",postfix:"',\n",lineEnd:"}",filetype:"js"},"JavaScript Variables":{lineStart:"",prefix:"const ",diviner:" = '",postfix:"';\n",lineEnd:"",filetype:"js"},SCSS:{lineStart:"",prefix:"$",diviner:": ",postfix:";\n",lineEnd:"",filetype:"scss"},Less:{lineStart:"",prefix:"@",diviner:": ",postfix:";\n",lineEnd:"",filetype:"less"},CSS:{lineStart:":root {\n",prefix:" --",diviner:": ",postfix:";\n",lineEnd:"}",filetype:"css"},JSON:{lineStart:{},prefix:"",diviner:"",postfix:"",lineEnd:"",filetype:"json"},YAML:{lineStart:{},prefix:"",diviner:"",postfix:"",lineEnd:"",filetype:"yml"}},b=function(n,t){var r=n.name.split("/"),e="";if(0==t)e=d.a.kebabCase(r);else if(1==t)e=d.a.camelCase(d.a.join(r,"-"));else{var u=t-2;e=r.length4&&void 0!==arguments[4]&&arguments[4],i=NSPopUpButton.alloc().initWithFrame(NSMakeRect(0,e-n,r,22));if(u){var o=t.map(function(n){return n.name}),a=o[0].split("/"),f=d.a.kebabCase(a),c=d.a.camelCase(d.a.join(a,"-"));i.addItemWithTitle(f),i.addItemWithTitle(c),a.length>1&&d.a.forEach(a,function(n){i.addItemWithTitle(n.toLowerCase().replace(/ /g,""))})}else d.a.forEach(t,function(n){i.addItemWithTitle(n)});return i.selectItemAtIndex(0),i},x=function(n,t,r,e){var u=arguments.length>4&&void 0!==arguments[4]&&arguments[4],i=NSButton.alloc().initWithFrame(NSMakeRect(0,e-n,r,20)),o=u?NSOnState:NSOffState;return i.setButtonType(NSSwitchButton),i.setBezelStyle(0),i.setTitle(t),i.setState(o),i},S=function(n){var r=function(n){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Choose variables format.",e=COSAlertWindow.new();return e.setIcon(NSImage.alloc().initByReferencingFile(t.plugin.urlForResourceNamed("icon.png").path())),e.setMessageText(n),e.setInformativeText(r),e.addButtonWithTitle("Ok"),e.addButtonWithTitle("Cancel"),e}("Export Text Styles"),e=NSView.alloc().initWithFrame(NSMakeRect(0,0,300,340));r.addAccessoryView(e),e.addSubview(w(35,"File format:",300,340));u=m(45,["CSS","JSON","JavaScript Object"],300,340),e.addSubview(u),e.addSubview(w(90,"Units:",300,340));return i=m(100,["Absolute (px)","Relative (em/rem)"],300,340),e.addSubview(i),e.addSubview(w(145,"Naming:",300,340)),o=m(155,n,300,340,!0),e.addSubview(o),e.addSubview(w(200,"Export selected values:",300,340)),a=x(210,"Font Family",300,340),e.addSubview(a),f=x(230,"Font Size",300,340,!0),e.addSubview(f),c=x(250,"Font Weight",300,340,!0),e.addSubview(c),l=x(270,"Line Height",300,340,!0),e.addSubview(l),s=x(290,"Letter Spacing",300,340,!0),e.addSubview(s),h=x(310,"Text Transform",300,340,!0),e.addSubview(h),p=x(330,"Color",300,340),e.addSubview(p),r.runModal()};r.default=function(){var n=_.a.getSelectedDocument().selectedLayers.layers,t=d.a.filter(d.a.reverse(n),["type","Text"]);if(0!==d.a.size(t)){var r=S(t),e=u.titleOfSelectedItem(),v=i.titleOfSelectedItem(),g=o.indexOfSelectedItem();"1000"==r&&function(n,t,r,e){var u=n.length,i=NSArray.arrayWithArray([y[t].filetype,nil]),o=NSSavePanel.savePanel();if(o.setAllowedFileTypes(i),o.setNameFieldStringValue("textstyles."+y[t].filetype),o.setPrompt("Save Text Styles"),o.runModal()&&0!==u){var v="";v="JSON"==t?{}:"JavaScript Object"==t?"const textStyles = {\n":"",d.a.forEach(n,function(n){var u=b(n,e),i=n.style.fontFamily,o="Absolute (px)"==r?n.style.fontSize+"px":n.style.fontSize/16+"rem",_=100*n.style.fontWeight,g="Absolute (px)"==r?d.a.round(n.style.lineHeight,2)+"px":d.a.round(n.style.lineHeight/n.style.fontSize,2),y=null==n.style.kerning?"normal":"Absolute (px)"==r?d.a.round(n.style.kerning,2)+"px":d.a.round(n.style.kerning/n.style.fontSize,2)+"em",w=n.style.textTransform,m=n.style.textColor.substr(0,7);"JSON"==t?(v[u]={},1==a.stringValue()&&(v[u].fontFamily=i),1==f.stringValue()&&(v[u].fontSize=o),1==c.stringValue()&&(v[u].fontWeight=_),1==l.stringValue()&&(v[u].lineHeight=g),1==s.stringValue()&&(v[u].letterSpacing=y),1==h.stringValue()&&(v[u].textTransform=w),1==p.stringValue()&&(v[u].color=m)):"JavaScript Object"==t?(v=v.concat('\t"'+u+'": {\n'),1==a.stringValue()&&(v=v.concat('\t\tfontFamily: "'+i+'",\n')),1==f.stringValue()&&(v=v.concat('\t\tfontSize: "'+o+'",\n')),1==c.stringValue()&&(v=v.concat("\t\tfontWeight: "+_+",\n")),1==l.stringValue()&&(v=v.concat('\t\tlineHeight: "'+g+'",\n')),1==s.stringValue()&&(v=v.concat('\t\tletterSpacing: "'+y+'",\n')),1==h.stringValue()&&(v=v.concat('\t\ttextTransform: "'+w+'",\n')),1==p.stringValue()&&(v=v.concat('\t\tcolor: "'+m+'",\n')),v=v.concat("\t},\n")):"CSS"==t&&(v=v.concat("."+u+"{\n"),1==a.stringValue()&&(v=v.concat('\tfont-family: "'+i+'";\n')),1==f.stringValue()&&(v=v.concat("\tfont-size: "+o+";\n")),1==c.stringValue()&&(v=v.concat("\tfont-weight: "+_+";\n")),1==l.stringValue()&&(v=v.concat("\tline-height: "+g+";\n")),1==s.stringValue()&&(v=v.concat("\tletter-spacing: "+y+";\n")),1==h.stringValue()&&(v=v.concat("\ttext-transform: "+w+";\n")),1==p.stringValue()&&(v=v.concat("\tcolor: "+m+";\n")),v=v.concat("}\n"))});var g="";if("JSON"==t){var w={textstyles:v};g=NSString.stringWithString(JSON.stringify(w,null,"\t"))}else"JavaScript Object"==t?(v=v.concat("}"),g=NSString.stringWithString(v)):g=NSString.stringWithString(v);var m=o.URL().path();g.writeToFile_atomically_encoding_error(m,!0,NSUTF8StringEncoding,null),_.a.UI.message("Text Styles Exported!")}}(t,e,v,g)}else _.a.UI.alert("Select layers","Please select text layers first.")}}]);if("default"===n&&"function"==typeof r)r(t);else{if("function"!=typeof r[n])throw new Error('Missing export named "'+n+'". Your command should contain something like `export function " + key +"() {}`.');r[n](t)}}globalThis.onRun=__skpm_run.bind(this,"default"); -------------------------------------------------------------------------------- /images/colors.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/images/colors.gif -------------------------------------------------------------------------------- /images/exportTokens.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/images/exportTokens.gif -------------------------------------------------------------------------------- /images/fontsize.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/images/fontsize.gif -------------------------------------------------------------------------------- /images/gitcover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/images/gitcover.jpg -------------------------------------------------------------------------------- /images/spacing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/images/spacing.gif -------------------------------------------------------------------------------- /images/textstyles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/here-erhe/Design-Token-Exporter/876d92c845a4500a8babf68e4a63ca56f43e3951/images/textstyles.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "design-token-exporter", 3 | "description": "Simple Design Token Exporter", 4 | "author": "Herkko Huttunen", 5 | "version": "1.0.1", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/here-erhe/Design-Token-Exporter" 10 | }, 11 | "engines": { 12 | "sketch": ">=51.0" 13 | }, 14 | "skpm": { 15 | "name": "Design Token Exporter", 16 | "manifest": "src/manifest.json", 17 | "main": "design-token-exporter.sketchplugin", 18 | "assets": [ 19 | "assets/**/*" 20 | ] 21 | }, 22 | "scripts": { 23 | "build": "skpm-build", 24 | "watch": "skpm-build --watch", 25 | "start": "skpm-build --watch --run", 26 | "postinstall": "npm run build && skpm-link" 27 | }, 28 | "devDependencies": { 29 | "@skpm/builder": "^0.7.5" 30 | }, 31 | "dependencies": { 32 | "json-to-pretty-yaml": "^1.2.2", 33 | "lodash": "^4.17.15" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/colorTokens.js: -------------------------------------------------------------------------------- 1 | import sketch from 'sketch' 2 | import _ from 'lodash' 3 | 4 | import values from './lib/values' 5 | import hexAToRGBA from './lib/hexAToRGBA' 6 | import formatObject from './lib/formatObject' 7 | import varNaming from './lib/varNaming' 8 | 9 | import {dialogAlert,fieldLabel, fieldSelect} from './lib/dialogFields' 10 | 11 | 12 | let dropdownFileType; 13 | let dropdownFormat; 14 | let dropdownNames; 15 | 16 | /** 17 | * 18 | * Dialog 19 | * 20 | */ 21 | const dialogBox = (selectedLayers) => { 22 | 23 | let alert = dialogAlert("Export Color Variables"); 24 | 25 | // Creating the view 26 | 27 | let viewWidth = 300; 28 | let viewHeight = 180; 29 | 30 | 31 | let view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, viewWidth, viewHeight)); 32 | alert.addAccessoryView(view); 33 | 34 | //Dropdown: File format 35 | 36 | view.addSubview(fieldLabel(35, 'File format:', viewWidth, viewHeight)); 37 | 38 | let names = ["SCSS","Less","CSS","JSON","JavaScript Object","JavaScript Variables"]; 39 | dropdownFileType = fieldSelect(45, names, viewWidth, viewHeight) 40 | 41 | view.addSubview(dropdownFileType); 42 | 43 | //Dropdown: Color value 44 | 45 | view.addSubview(fieldLabel(90, 'Color value:', viewWidth, viewHeight)); 46 | 47 | let types = ["HEX", "RGBA"]; 48 | dropdownFormat = fieldSelect(100, types, viewWidth, viewHeight) 49 | view.addSubview(dropdownFormat); 50 | 51 | //Dropdown: Naming 52 | 53 | view.addSubview(fieldLabel(145, 'Naming:', viewWidth, viewHeight)); 54 | 55 | dropdownNames = fieldSelect(155, selectedLayers, viewWidth, viewHeight, true) 56 | view.addSubview(dropdownNames); 57 | 58 | 59 | return alert.runModal(); 60 | 61 | } 62 | 63 | /** 64 | * 65 | * Export exportColors 66 | * 67 | */ 68 | const exportColors = (selectedLayers, type, format, naming) => { 69 | 70 | 71 | const selectedCount = selectedLayers.length; 72 | 73 | if (selectedCount !== 0) { 74 | 75 | let variables = {} 76 | 77 | _.forEach(selectedLayers, function (layer) { 78 | 79 | let fillArray = layer.style.fills; 80 | 81 | if(_.size(fillArray) != 0 && _.last(fillArray).fillType == 'Color' && _.last(fillArray).enabled){ 82 | 83 | let colorName = varNaming(layer, naming); 84 | let colorFill = format == 'HEX' ? _.last(fillArray).color.substr(0, 7) : hexAToRGBA(_.last(fillArray).color); 85 | variables[colorName] = colorFill 86 | 87 | } 88 | 89 | }) 90 | 91 | if(_.size(variables) == 0){ 92 | sketch.UI.alert('Select layers','Select shape layers with solid fill color'); 93 | }else{ 94 | 95 | 96 | let fileTypes = NSArray.arrayWithArray([values[type].filetype, nil]); 97 | let savePanel = NSSavePanel.savePanel() 98 | 99 | 100 | //savePanel.setCanChooseDirectories(false); 101 | //savePanel.setCanCreateDirectories(false); 102 | savePanel.setAllowedFileTypes(fileTypes) 103 | 104 | 105 | savePanel.setNameFieldStringValue('colors.' + values[type].filetype) 106 | savePanel.setPrompt("Save Color Variables"); 107 | 108 | savePanel.runModal(); 109 | 110 | 111 | let file = NSString.stringWithString(formatObject(variables, type, 'colors')); 112 | let file_path = savePanel.URL().path(); 113 | file.writeToFile_atomically_encoding_error(file_path, true, NSUTF8StringEncoding, null); 114 | 115 | sketch.UI.message('Color Variables Exported!'); 116 | } 117 | 118 | 119 | } 120 | 121 | } 122 | 123 | /** 124 | * 125 | * Main 126 | * 127 | */ 128 | export default () => { 129 | 130 | const doc = sketch.getSelectedDocument(); 131 | const selected = doc.selectedLayers.layers; 132 | 133 | // Only ShapePath layers - no text layers 134 | const selectedLayers = _.filter(_.reverse(selected), ['type', 'ShapePath']); 135 | const selectedCount = _.size(selectedLayers); 136 | 137 | if (selectedCount !== 0) { 138 | 139 | const dialog = dialogBox(selectedLayers); 140 | const exportType = dropdownFileType.titleOfSelectedItem(); 141 | const exportFormat = dropdownFormat.titleOfSelectedItem(); 142 | const exportNaming = dropdownNames.indexOfSelectedItem(); 143 | 144 | 145 | if(dialog == "1000"){ 146 | exportColors(selectedLayers, exportType, exportFormat, exportNaming); 147 | } 148 | 149 | }else{ 150 | sketch.UI.alert('Select layers','Please select shape layers first.'); 151 | } 152 | 153 | } -------------------------------------------------------------------------------- /src/exportTokens.js: -------------------------------------------------------------------------------- 1 | import sketch from 'sketch' 2 | import _ from 'lodash' 3 | 4 | import values from './lib/values' 5 | import formatObject from './lib/formatObject' 6 | 7 | import tokenValue from './lib/tokenValue' 8 | 9 | import {dialogAlert,fieldLabel, fieldSelect} from './lib/dialogFields' 10 | 11 | 12 | let dropdownFileType; 13 | 14 | /** 15 | * 16 | * Dialog 17 | * 18 | */ 19 | const dialogBox = (selectedLayers) => { 20 | 21 | let alert = dialogAlert( 22 | "Export Design Tokens", 23 | "Choose tokens file format. Layers naming format is type/category/name (e.g. Color/Background-Color/Primary-red)." 24 | ); 25 | 26 | // Creating the view 27 | 28 | let viewWidth = 300; 29 | let viewHeight = 60; 30 | 31 | 32 | let view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, viewWidth, viewHeight)); 33 | alert.addAccessoryView(view); 34 | 35 | //Dropdown: File format 36 | 37 | view.addSubview(fieldLabel(35, 'File format:', viewWidth, viewHeight)); 38 | 39 | let names = ["YAML","JSON"]; 40 | dropdownFileType = fieldSelect(45, names, viewWidth, viewHeight) 41 | 42 | view.addSubview(dropdownFileType); 43 | 44 | 45 | return alert.runModal(); 46 | 47 | } 48 | 49 | /** 50 | * 51 | * Export exportColors 52 | * 53 | */ 54 | const exportTokens = (selectedLayers, type) => { 55 | 56 | 57 | const selectedCount = selectedLayers.length; 58 | 59 | if (selectedCount !== 0) { 60 | 61 | let variables = {} 62 | 63 | _.forEach(selectedLayers, function (layer) { 64 | 65 | let layerNameArr = layer.name.split('/'); 66 | 67 | 68 | if(_.size(layerNameArr) > 2){ 69 | // Notice layer if it contains type/category/name 70 | 71 | let value = tokenValue(layer); 72 | 73 | if(value !== ""){ 74 | 75 | let tokenType = layerNameArr[0]; 76 | let tokenCategory = _.kebabCase(layerNameArr[1]); 77 | let tokenName = _.snakeCase(layerNameArr[2]); 78 | 79 | let newObj = { 80 | "value" : value, 81 | "type" : tokenType, 82 | "category" : tokenCategory 83 | }; 84 | 85 | variables[tokenName] = newObj; 86 | 87 | } 88 | } 89 | 90 | 91 | 92 | }) 93 | 94 | if(_.size(variables) == 0){ 95 | sketch.UI.alert('Select layers or artboard','Select one artboard or multiple layers'); 96 | }else{ 97 | 98 | 99 | let fileTypes = NSArray.arrayWithArray([values[type].filetype, nil]); 100 | let savePanel = NSSavePanel.savePanel() 101 | 102 | savePanel.setAllowedFileTypes(fileTypes) 103 | 104 | savePanel.setNameFieldStringValue('tokens.' + values[type].filetype) 105 | savePanel.setPrompt("Save Tokens"); 106 | 107 | savePanel.runModal(); 108 | 109 | 110 | let file = NSString.stringWithString(formatObject(variables, type, 'props')); 111 | let file_path = savePanel.URL().path(); 112 | file.writeToFile_atomically_encoding_error(file_path, true, NSUTF8StringEncoding, null); 113 | 114 | sketch.UI.message('Design Tokens Exported!'); 115 | } 116 | 117 | 118 | } 119 | 120 | } 121 | 122 | /** 123 | * 124 | * Main 125 | * 126 | */ 127 | export default () => { 128 | 129 | const doc = sketch.getSelectedDocument(); 130 | 131 | let selected = []; 132 | 133 | selected = doc.selectedLayers.layers; 134 | 135 | const selectedCount = _.size(selected); 136 | 137 | if (selectedCount !== 0) { 138 | 139 | if(selected[0].type === "Artboard"){ 140 | // Select artboard layers 141 | selected = selected[0].layers; 142 | } 143 | 144 | const selectedLayers = _.reverse(selected); 145 | 146 | const dialog = dialogBox(selectedLayers); 147 | const exportType = dropdownFileType.titleOfSelectedItem(); 148 | 149 | 150 | 151 | if(dialog == "1000"){ 152 | exportTokens(selectedLayers, exportType); 153 | } 154 | 155 | }else{ 156 | sketch.UI.alert('Select tokens','Please select layers or artboard first.'); 157 | } 158 | 159 | } -------------------------------------------------------------------------------- /src/lib/dialogFields.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | 3 | export const dialogAlert = (title, desc = "Choose variables format.") => { 4 | 5 | let alert = COSAlertWindow.new(); 6 | 7 | alert.setIcon(NSImage.alloc().initByReferencingFile(context.plugin.urlForResourceNamed("icon.png").path())); 8 | alert.setMessageText(title); 9 | alert.setInformativeText(desc); 10 | alert.addButtonWithTitle("Ok"); 11 | alert.addButtonWithTitle("Cancel"); 12 | 13 | return alert; 14 | 15 | } 16 | 17 | export const fieldLabel = (pos, title, viewWidth, viewHeight) => { 18 | 19 | let label = NSTextField.alloc().initWithFrame(NSMakeRect(0,viewHeight - pos,viewWidth,35)); 20 | label.setBezeled(false); 21 | label.setDrawsBackground(false); 22 | label.setEditable(false); 23 | label.setSelectable(false); 24 | label.setStringValue(title); 25 | 26 | return label; 27 | 28 | } 29 | 30 | export const fieldSelect = (pos, values, viewWidth, viewHeight, namingSelect = false) => { 31 | 32 | let select = NSPopUpButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - pos, viewWidth, 22)); 33 | 34 | if(namingSelect){ 35 | 36 | const layerNames = values.map(layer => layer.name); 37 | const sliceArr = layerNames[0].split('/'); 38 | 39 | let kebabCase = _.kebabCase(sliceArr); 40 | let camelCase = _.camelCase(_.join(sliceArr, '-')); 41 | 42 | select.addItemWithTitle(kebabCase); 43 | select.addItemWithTitle(camelCase); 44 | 45 | if(sliceArr.length > 1){ 46 | 47 | _.forEach(sliceArr,function (slice) { 48 | select.addItemWithTitle(slice.toLowerCase().replace(/ /g, '')); 49 | }); 50 | 51 | } 52 | 53 | }else{ 54 | 55 | _.forEach(values, function(value) { 56 | select.addItemWithTitle(value); 57 | }); 58 | 59 | } 60 | 61 | 62 | select.selectItemAtIndex(0); 63 | 64 | return select; 65 | 66 | } 67 | 68 | 69 | export const fieldCheckbox = (pos, label, viewWidth, viewHeight, state = false) => { 70 | 71 | let checkbox = NSButton.alloc().initWithFrame(NSMakeRect(0, viewHeight - pos, viewWidth, 20)); 72 | 73 | let initState = state ? NSOnState : NSOffState; 74 | 75 | checkbox.setButtonType(NSSwitchButton); 76 | checkbox.setBezelStyle(0); 77 | checkbox.setTitle(label); 78 | checkbox.setState(initState); 79 | 80 | return checkbox; 81 | 82 | } -------------------------------------------------------------------------------- /src/lib/formatObject.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | import values from './values' 3 | import YAML from 'json-to-pretty-yaml'; 4 | 5 | const formatObject = (obj, type, jsonTitle) => { 6 | 7 | let string = ''; 8 | 9 | if(type == 'JSON'){ 10 | 11 | let jsonObj = {}; 12 | jsonObj[_.camelCase(jsonTitle)] = obj; 13 | 14 | string = JSON.stringify(jsonObj, null, "\t"); 15 | 16 | }else if(type == 'YAML'){ 17 | 18 | let jsonObj = {}; 19 | jsonObj[_.camelCase(jsonTitle)] = obj; 20 | 21 | string = YAML.stringify(jsonObj); 22 | 23 | }else{ 24 | 25 | if(type == 'JavaScript Object'){ 26 | string = "const " + _.camelCase(jsonTitle) + " = {\n"; 27 | }else{ 28 | string = values[type].lineStart; 29 | } 30 | 31 | 32 | string = string.concat( 33 | _.join( 34 | _.map(obj, (value, key) => values[type].prefix + key + values[type].diviner + value + values[type].postfix), 35 | '' 36 | )); 37 | 38 | string = string.concat(values[type].lineEnd); 39 | } 40 | 41 | return string; 42 | 43 | } 44 | 45 | export default formatObject; 46 | -------------------------------------------------------------------------------- /src/lib/hexAToRGBA.js: -------------------------------------------------------------------------------- 1 | const hexAToRGBA = (h) => { 2 | let r = 0, g = 0, b = 0, a = 1; 3 | 4 | if (h.length == 5) { 5 | r = "0x" + h[1] + h[1]; 6 | g = "0x" + h[2] + h[2]; 7 | b = "0x" + h[3] + h[3]; 8 | a = "0x" + h[4] + h[4]; 9 | 10 | } else if (h.length == 9) { 11 | r = "0x" + h[1] + h[2]; 12 | g = "0x" + h[3] + h[4]; 13 | b = "0x" + h[5] + h[6]; 14 | a = "0x" + h[7] + h[8]; 15 | } 16 | a = +(a / 255).toFixed(2); 17 | 18 | return "rgba(" + +r + "," + +g + "," + +b + "," + a + ")"; 19 | } 20 | 21 | export default hexAToRGBA; 22 | -------------------------------------------------------------------------------- /src/lib/tokenValue.js: -------------------------------------------------------------------------------- 1 | import hexAToRGBA from './hexAToRGBA' 2 | 3 | 4 | const tokenValue = (layer) => { 5 | 6 | let value = ''; 7 | 8 | let layerType = layer.type; 9 | 10 | let layerNameArr = layer.name.split('/'); 11 | let tokenType = layerNameArr[0]; 12 | let tokenCategory = _.kebabCase(layerNameArr[1]); 13 | 14 | 15 | if(layerType === "ShapePath"){ 16 | 17 | // ShapeLayers + Category match 18 | 19 | if(_.indexOf(['spacing','space','spacer','sizing','size'], tokenCategory) !== -1){ 20 | // Get spacing 21 | value = _.round(layer.frame.height,0) + 'px'; 22 | }else if(_.indexOf(['hr-color','background-color','text-color','color'], tokenCategory) !== -1){ 23 | 24 | // Get color 25 | let color = _.last(layer.style.fills).color; 26 | value = color.slice(-2) === "ff" ? color.substr(0, 7) : hexAToRGBA(color); 27 | 28 | }else if(tokenCategory === 'border-color'){ 29 | // Get border color 30 | 31 | if(_.size(layer.style.borders) !== 0){ 32 | let border = _.last(layer.style.borders); 33 | value = border.color.substr(0, 7); 34 | }else{ 35 | let fillArray = layer.style.fills; 36 | value = _.last(fillArray).color.substr(0, 7); 37 | } 38 | 39 | }else if(_.indexOf(['radius','border-radius'], tokenCategory) !== -1){ 40 | 41 | // Get color 42 | 43 | let points = _.map(layer.points, 'cornerRadius'); 44 | 45 | if(_.size(_.uniq(points)) === 1){ 46 | 47 | if(layer.frame.width / 2 === points[1] || layer.frame.height / 2 === points[1]){ 48 | value = '50%'; 49 | }else{ 50 | value = points[1] + 'px'; 51 | } 52 | 53 | }else{ 54 | value = _.join(points, 'px ') + 'px'; 55 | } 56 | 57 | 58 | }else if(_.indexOf(['drop-shadow','box-shadow','text-shadow','shadow'], tokenCategory) !== -1){ 59 | 60 | // Get shadow 61 | let shadowArr = _.last(layer.style.shadows); 62 | let x = shadowArr.x == 0 ? 0 : shadowArr.x + "px"; 63 | let y = shadowArr.y == 0 ? 0 : shadowArr.y + "px"; 64 | let blur = shadowArr.blur == 0 ? 0 : shadowArr.blur + "px"; 65 | let spread = shadowArr.spread == 0 ? 0 : shadowArr.spread + "px"; 66 | let color = shadowArr.color.slice(-2) === "ff" ? shadowArr.color.substr(0, 7) : hexAToRGBA(shadowArr.color); 67 | 68 | value = x + " " + y + " " + blur + " " + spread + " " + color; 69 | 70 | }else if(tokenCategory === 'inner-shadow'){ 71 | // Get innershadow 72 | let shadowArr = _.last(layer.style.innerShadows); 73 | let x = shadowArr.x == 0 ? 0 : shadowArr.x + "px"; 74 | let y = shadowArr.y == 0 ? 0 : shadowArr.y + "px"; 75 | let blur = shadowArr.blur == 0 ? 0 : shadowArr.blur + "px"; 76 | let spread = shadowArr.spread == 0 ? 0 : shadowArr.spread + "px"; 77 | let color = shadowArr.color.slice(-2) === "ff" ? shadowArr.color.substr(0, 7) : hexAToRGBA(shadowArr.color); 78 | 79 | 80 | value = "inset " + x + " " + y + " " + blur + " " + spread + " " + color; 81 | 82 | }else if(_.indexOf(['background-gradient','gradient'], tokenCategory) !== -1){ 83 | 84 | // Get gradient 85 | var gradient = layer.style.fills[0].gradient; 86 | 87 | if(gradient.gradientType === "Radial"){ 88 | value = "radial-gradient(" + gradient.sketchObject.gradientStringWithMasterAlpha(1) + ")"; 89 | }else if(gradient.gradientType === "Linear"){ 90 | value = "linear-gradient(" + gradient.sketchObject.gradientStringWithMasterAlpha(1) + ")"; 91 | } 92 | 93 | 94 | }else if(tokenCategory === 'border-style'){ 95 | // Get border style 96 | let border = _.last(layer.style.borders); 97 | let borderColor = border.color.substr(0, 7); 98 | let borderThickness = border.thickness + "px"; 99 | 100 | let borderStyle = _.isEmpty(layer.style.borderOptions.dashPattern) ? "solid" : "dashed"; 101 | 102 | value = borderThickness + " " + borderStyle + " " + borderColor; 103 | 104 | 105 | }else if(['opacity'].indexOf(tokenCategory) !== -1){ 106 | 107 | // Get opacity 108 | value = _.round(layer.style.opacity,2); 109 | 110 | }else if(tokenType === 'color'){ 111 | 112 | // Token type color 113 | let color = _.last(layer.style.fills).color; 114 | let colorFormat = color.slice(-2) === "ff" ? color.substr(0, 7) : hexAToRGBA(color); 115 | 116 | value = colorFormat; 117 | 118 | } 119 | 120 | }else if(layerType === "Text"){ 121 | 122 | // ShapeLayers + Category match 123 | 124 | if(tokenCategory === 'font-style'){ 125 | 126 | value = layer.style.fontStyle; 127 | 128 | }else if(tokenCategory === 'font'){ 129 | 130 | 131 | if(tokenType === "..."){ 132 | value = layer.style.fontFamily; 133 | }else if(tokenType === "number"){ 134 | value = layer.style.fontWeight * 100; 135 | } 136 | 137 | 138 | }else if(tokenCategory === 'font-weight'){ 139 | 140 | value = layer.style.fontWeight * 100; 141 | 142 | }else if(tokenCategory === 'font-size'){ 143 | 144 | value = layer.style.fontSize + 'px'; 145 | 146 | }else if(tokenCategory === 'line-height'){ 147 | 148 | value = _.round(layer.style.lineHeight / layer.style.fontSize, 2); 149 | 150 | }else if(tokenCategory === 'font-family'){ 151 | 152 | value = layer.style.fontFamily; 153 | 154 | }else if(tokenCategory === 'text-color'){ 155 | 156 | var color = layer.style.textColor; 157 | value = color.slice(-2) === "ff" ? color.substr(0, 7) : hexAToRGBA(color); 158 | 159 | 160 | }else if(tokenCategory === 'text-shadow'){ 161 | 162 | let shadowArr = layer.style.shadows[0]; 163 | let x = shadowArr.x == 0 ? 0 : shadowArr.x + "px"; 164 | let y = shadowArr.y == 0 ? 0 : shadowArr.y + "px"; 165 | let blur = shadowArr.blur == 0 ? 0 : shadowArr.blur + "px"; 166 | let spread = shadowArr.spread == 0 ? 0 : shadowArr.spread + "px"; 167 | let color = shadowArr.color.slice(-2) === "ff" ? shadowArr.color.substr(0, 7) : hexAToRGBA(shadowArr.color); 168 | 169 | 170 | value = x + " " + y + " " + blur + " " + spread + " " + color; 171 | 172 | }else if(_.indexOf(['z-index','time','media-query'], tokenCategory) !== -1){ 173 | 174 | value = layer.text; 175 | 176 | } 177 | 178 | } 179 | 180 | return value; 181 | } 182 | 183 | export default tokenValue; -------------------------------------------------------------------------------- /src/lib/values.js: -------------------------------------------------------------------------------- 1 | const values = { 2 | 'JavaScript Object': { 3 | lineStart: "", 4 | prefix: " '", 5 | diviner: "': '", 6 | postfix: "',\n", 7 | lineEnd: "}", 8 | filetype: "js", 9 | }, 10 | 'JavaScript Variables': { 11 | lineStart: "", 12 | prefix: "const ", 13 | diviner: " = '", 14 | postfix: "';\n", 15 | lineEnd: "", 16 | filetype: "js" 17 | }, 18 | 'SCSS': { 19 | lineStart: "", 20 | prefix: "$", 21 | diviner: ": ", 22 | postfix: ";\n", 23 | lineEnd: "", 24 | filetype: "scss" 25 | }, 26 | 'Less': { 27 | lineStart: "", 28 | prefix: "@", 29 | diviner: ": ", 30 | postfix: ";\n", 31 | lineEnd: "", 32 | filetype: "less" 33 | }, 34 | 'CSS': { 35 | lineStart: ":root {\n", 36 | prefix: " --", 37 | diviner: ": ", 38 | postfix: ";\n", 39 | lineEnd: "}", 40 | filetype: "css" 41 | }, 42 | 'JSON': { 43 | lineStart: {}, 44 | prefix: "", 45 | diviner: "", 46 | postfix: "", 47 | lineEnd: "", 48 | filetype: "json" 49 | }, 50 | 'YAML': { 51 | lineStart: {}, 52 | prefix: "", 53 | diviner: "", 54 | postfix: "", 55 | lineEnd: "", 56 | filetype: "yml" 57 | }, 58 | } 59 | 60 | export default values; -------------------------------------------------------------------------------- /src/lib/varNaming.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | const varNaming = (layer, naming) => { 4 | 5 | let layerNameArr = layer.name.split('/'); 6 | let layerName = ''; 7 | 8 | if(naming == 0){ 9 | layerName = _.kebabCase(layerNameArr); 10 | }else if(naming == 1){ 11 | layerName = _.camelCase(_.join(layerNameArr, '-')); 12 | }else{ 13 | 14 | let stringPosition = naming-2; 15 | 16 | if(layerNameArr.length < stringPosition+1){ 17 | layerName = layerNameArr[0].toLowerCase().replace(/ /g, ''); 18 | }else{ 19 | layerName = layerNameArr[stringPosition].toLowerCase().replace(/ /g, ''); 20 | } 21 | } 22 | 23 | return layerName; 24 | 25 | } 26 | 27 | export default varNaming; 28 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Design Token Exporter", 3 | "identifier": "fi.erhe.design-token-exporter", 4 | "description": "Simple Design Token Exporter", 5 | "homepage": "https://github.com/here-erhe/Design-Token-Exporter", 6 | "author": "Herkko Huttunen", 7 | "icon": "icon.png", 8 | "compatibleVersion": "54.0", 9 | "commands": [ 10 | { 11 | "name": "Export Tokens", 12 | "identifier": "tokens.tokens", 13 | "script": "./exportTokens.js", 14 | "description": "Export multiple multiple layers or one artboard" 15 | }, 16 | { 17 | "name": "Export Colors Variables", 18 | "identifier": "tokens.colors", 19 | "script": "./colorTokens.js", 20 | "description": "Export selected layers" 21 | }, 22 | { 23 | "name": "Export Text Variables", 24 | "identifier": "tokens.text", 25 | "script": "./textTokens.js", 26 | "description": "Export selected layers" 27 | }, 28 | { 29 | "name": "Export Spacing Variables", 30 | "identifier": "tokens.spacing", 31 | "script": "./spacingTokens.js", 32 | "description": "Export selected layers" 33 | }, 34 | { 35 | "name": "Export Text Styles", 36 | "identifier": "tokens.styles", 37 | "script": "./textObjects.js", 38 | "description": "Export selected layers" 39 | } 40 | ], 41 | "menu": { 42 | "title": "Design Token Exporter", 43 | "items": [ 44 | "tokens.tokens", 45 | "-", 46 | "tokens.colors", 47 | "tokens.text", 48 | "tokens.spacing", 49 | "-", 50 | "tokens.styles" 51 | ] 52 | } 53 | } -------------------------------------------------------------------------------- /src/spacingTokens.js: -------------------------------------------------------------------------------- 1 | import sketch from 'sketch' 2 | import _ from 'lodash' 3 | 4 | import values from './lib/values' 5 | import formatObject from './lib/formatObject' 6 | import varNaming from './lib/varNaming' 7 | 8 | import {dialogAlert,fieldLabel, fieldSelect} from './lib/dialogFields' 9 | 10 | let dropdownFileType; 11 | let dropdownFormat; 12 | let dropdownNames; 13 | let dropdownUnits; 14 | 15 | /** 16 | * 17 | * Dialog 18 | * 19 | */ 20 | const dialogBox = (selectedLayers) => { 21 | 22 | let alert = dialogAlert("Export Spacing Variables"); 23 | 24 | // Creating the view 25 | let viewWidth = 300; 26 | let viewHeight = 225; 27 | 28 | let view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, viewWidth, viewHeight)); 29 | alert.addAccessoryView(view); 30 | 31 | //Dropdown: File format 32 | 33 | view.addSubview(fieldLabel(35, 'File format:', viewWidth, viewHeight)); 34 | 35 | let names = ["SCSS","Less","CSS","JSON","JavaScript Object","JavaScript Variables"]; 36 | dropdownFileType = fieldSelect(45, names, viewWidth, viewHeight) 37 | 38 | view.addSubview(dropdownFileType); 39 | 40 | //Dropdown: Dimension 41 | 42 | view.addSubview(fieldLabel(90, 'Dimension:', viewWidth, viewHeight)); 43 | 44 | let types = [ "Width", "Height"]; 45 | dropdownFormat = fieldSelect(100, types, viewWidth, viewHeight) 46 | view.addSubview(dropdownFormat); 47 | 48 | //Dropdown: Units 49 | 50 | view.addSubview(fieldLabel(145, 'Units:', viewWidth, viewHeight)); 51 | 52 | let units = [ "Absolute (px)", "Relative (rem)"]; 53 | dropdownUnits = fieldSelect(155, units, viewWidth, viewHeight) 54 | view.addSubview(dropdownUnits); 55 | 56 | //Dropdown: Naming 57 | 58 | view.addSubview(fieldLabel(200, 'Naming:', viewWidth, viewHeight)); 59 | 60 | dropdownNames = fieldSelect(210, selectedLayers, viewWidth, viewHeight, true) 61 | view.addSubview(dropdownNames); 62 | 63 | 64 | return alert.runModal(); 65 | 66 | } 67 | 68 | /** 69 | * 70 | * Export exportTextstyles 71 | * 72 | */ 73 | const exportTextstyles = (selectedLayers, type, format, naming, units) => { 74 | 75 | const selectedCount = selectedLayers.length; 76 | 77 | let fileTypes = NSArray.arrayWithArray([values[type].filetype, nil]); 78 | 79 | let savePanel = NSSavePanel.savePanel() 80 | //savePanel.setCanChooseDirectories(true) 81 | //savePanel.setCanCreateDirectories(true) 82 | savePanel.setAllowedFileTypes(fileTypes) 83 | 84 | savePanel.setNameFieldStringValue('spacing.' + values[type].filetype) 85 | savePanel.setPrompt("Save Spacing Variables"); 86 | 87 | if (savePanel.runModal() && selectedCount !== 0) { 88 | 89 | let variables = {} 90 | 91 | _.forEach(selectedLayers, function (layer) { 92 | 93 | 94 | let layerName = varNaming(layer, naming); 95 | 96 | let side = format == 'Width' ? layer.frame.width : layer.frame.height; 97 | let space = units == 'Absolute (px)' ? side + 'px' : side / 16 + 'rem'; 98 | 99 | variables[layerName] = space; 100 | 101 | 102 | }) 103 | 104 | let file = NSString.stringWithString(formatObject(variables, type, 'spacing')); 105 | let file_path = savePanel.URL().path(); 106 | file.writeToFile_atomically_encoding_error(file_path, true, NSUTF8StringEncoding, null); 107 | 108 | sketch.UI.message('Spacing Variables Exported!'); 109 | 110 | } 111 | 112 | } 113 | 114 | /** 115 | * 116 | * Main 117 | * 118 | */ 119 | export default () => { 120 | 121 | const doc = sketch.getSelectedDocument(); 122 | const selected = doc.selectedLayers.layers; 123 | 124 | // Only ShapePath layers - no text layers 125 | const selectedLayers = _.filter(_.reverse(selected), ['type', 'ShapePath']); 126 | const selectedCount = _.size(selectedLayers); 127 | 128 | if (selectedCount !== 0) { 129 | 130 | const dialog = dialogBox(selectedLayers); 131 | const exportType = dropdownFileType.titleOfSelectedItem(); 132 | const exportFormat = dropdownFormat.titleOfSelectedItem(); 133 | const exportNaming = dropdownNames.indexOfSelectedItem(); 134 | const exportUnits = dropdownUnits.titleOfSelectedItem(); 135 | 136 | 137 | 138 | if(dialog == "1000"){ 139 | exportTextstyles(selectedLayers, exportType, exportFormat, exportNaming, exportUnits); 140 | } 141 | 142 | }else{ 143 | sketch.UI.alert('Select layers','Please select shape layers first.'); 144 | } 145 | 146 | } -------------------------------------------------------------------------------- /src/textObjects.js: -------------------------------------------------------------------------------- 1 | import sketch from 'sketch' 2 | import _ from 'lodash' 3 | 4 | import values from './lib/values' 5 | import varNaming from './lib/varNaming' 6 | 7 | import {dialogAlert,fieldLabel, fieldSelect, fieldCheckbox} from './lib/dialogFields' 8 | 9 | let dropdownFileType; 10 | let dropdownUnits; 11 | let dropdownNames; 12 | 13 | let checkFontFamily; 14 | let checkFontSize; 15 | let checkFontWeight; 16 | let checkLineHeight; 17 | let checkLetterSpacing; 18 | let checkTextTransform; 19 | let checkColor; 20 | 21 | 22 | /** 23 | * 24 | * Dialog 25 | * 26 | */ 27 | const dialogBox = (selectedLayers) => { 28 | 29 | let alert = dialogAlert("Export Text Styles"); 30 | 31 | // Creating the view 32 | let viewWidth = 300; 33 | let viewHeight = 340; 34 | 35 | let view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, viewWidth, viewHeight)); 36 | alert.addAccessoryView(view); 37 | 38 | //Dropdown: File format 39 | 40 | view.addSubview(fieldLabel(35, 'File format:', viewWidth, viewHeight)); 41 | 42 | let names = ["CSS","JSON","JavaScript Object"]; 43 | dropdownFileType = fieldSelect(45, names, viewWidth, viewHeight) 44 | 45 | view.addSubview(dropdownFileType); 46 | 47 | //Dropdown: Select units 48 | 49 | view.addSubview(fieldLabel(90, 'Units:', viewWidth, viewHeight)); 50 | 51 | let units = [ "Absolute (px)", "Relative (em/rem)"]; 52 | dropdownUnits = fieldSelect(100, units, viewWidth, viewHeight) 53 | view.addSubview(dropdownUnits); 54 | 55 | //Dropdown: Naming 56 | 57 | view.addSubview(fieldLabel(145, 'Naming:', viewWidth, viewHeight)); 58 | 59 | dropdownNames = fieldSelect(155, selectedLayers, viewWidth, viewHeight, true) 60 | view.addSubview(dropdownNames); 61 | 62 | //Checkbox: Select values 63 | 64 | view.addSubview(fieldLabel(200, 'Export selected values:', viewWidth, viewHeight)); 65 | 66 | checkFontFamily = fieldCheckbox(210, 'Font Family', viewWidth, viewHeight) 67 | view.addSubview(checkFontFamily); 68 | 69 | checkFontSize = fieldCheckbox(230, 'Font Size', viewWidth, viewHeight, true) 70 | view.addSubview(checkFontSize); 71 | 72 | checkFontWeight = fieldCheckbox(250, 'Font Weight', viewWidth, viewHeight, true) 73 | view.addSubview(checkFontWeight); 74 | 75 | checkLineHeight = fieldCheckbox(270, 'Line Height', viewWidth, viewHeight, true) 76 | view.addSubview(checkLineHeight); 77 | 78 | checkLetterSpacing = fieldCheckbox(290, 'Letter Spacing', viewWidth, viewHeight, true) 79 | view.addSubview(checkLetterSpacing); 80 | 81 | checkTextTransform = fieldCheckbox(310, 'Text Transform', viewWidth, viewHeight, true) 82 | view.addSubview(checkTextTransform); 83 | 84 | checkColor = fieldCheckbox(330, 'Color', viewWidth, viewHeight) 85 | view.addSubview(checkColor); 86 | 87 | 88 | 89 | return alert.runModal(); 90 | 91 | } 92 | 93 | /** 94 | * 95 | * Export exportTextstyles 96 | * 97 | */ 98 | const exportTextstyles = (selectedLayers, type, units, naming) => { 99 | 100 | 101 | const selectedCount = selectedLayers.length; 102 | 103 | let fileTypes = NSArray.arrayWithArray([values[type].filetype, nil]); 104 | 105 | let savePanel = NSSavePanel.savePanel() 106 | //savePanel.setCanChooseDirectories(true) 107 | //savePanel.setCanCreateDirectories(true) 108 | savePanel.setAllowedFileTypes(fileTypes) 109 | 110 | savePanel.setNameFieldStringValue('textstyles.' + values[type].filetype) 111 | savePanel.setPrompt("Save Text Styles"); 112 | 113 | if (savePanel.runModal() && selectedCount !== 0) { 114 | 115 | 116 | let texts = ''; 117 | 118 | if(type == 'JSON'){ 119 | texts = {} 120 | }else if(type == 'JavaScript Object'){ 121 | texts = 'const textStyles = {\n'; 122 | }else{ 123 | texts = ''; 124 | } 125 | 126 | _.forEach(selectedLayers, function (layer) { 127 | 128 | 129 | let layerName = varNaming(layer, naming); 130 | 131 | let fontFamily = layer.style.fontFamily; 132 | let fontSize = units == 'Absolute (px)' ? layer.style.fontSize + 'px' : layer.style.fontSize / 16 + 'rem'; 133 | let fontWeight = layer.style.fontWeight * 100; 134 | let lineHeight = units == 'Absolute (px)' ? _.round(layer.style.lineHeight, 2) + 'px' : _.round(layer.style.lineHeight / layer.style.fontSize, 2); 135 | let letterSpacing = layer.style.kerning == null ? 'normal' : units == 'Absolute (px)' ? _.round(layer.style.kerning, 2) + 'px' : _.round(layer.style.kerning / layer.style.fontSize, 2) + 'em'; 136 | let textTransform = layer.style.textTransform; 137 | 138 | let textColor = layer.style.textColor.substr(0, 7); 139 | 140 | 141 | 142 | 143 | // JSON 144 | if(type == 'JSON'){ 145 | 146 | texts[layerName] = {}; 147 | 148 | if(checkFontFamily.stringValue() == 1) texts[layerName]['fontFamily'] = fontFamily; 149 | if(checkFontSize.stringValue() == 1) texts[layerName]['fontSize'] = fontSize; 150 | if(checkFontWeight.stringValue() == 1) texts[layerName]['fontWeight'] = fontWeight; 151 | if(checkLineHeight.stringValue() == 1) texts[layerName]['lineHeight'] = lineHeight; 152 | if(checkLetterSpacing.stringValue() == 1) texts[layerName]['letterSpacing'] = letterSpacing; 153 | if(checkTextTransform.stringValue() == 1) texts[layerName]['textTransform'] = textTransform; 154 | if(checkColor.stringValue() == 1) texts[layerName]['color'] = textColor; 155 | 156 | 157 | }else if(type == 'JavaScript Object'){ 158 | // JS Object 159 | texts = texts.concat('\t"' + layerName + '": {\n'); 160 | if(checkFontFamily.stringValue() == 1) texts = texts.concat('\t\tfontFamily: "' + fontFamily +'",\n'); 161 | if(checkFontSize.stringValue() == 1) texts = texts.concat('\t\tfontSize: "' + fontSize +'",\n'); 162 | if(checkFontWeight.stringValue() == 1) texts = texts.concat('\t\tfontWeight: ' + fontWeight +',\n'); 163 | if(checkLineHeight.stringValue() == 1) texts = texts.concat('\t\tlineHeight: "' + lineHeight + '",\n'); 164 | if(checkLetterSpacing.stringValue() == 1) texts = texts.concat('\t\tletterSpacing: "' + letterSpacing + '",\n'); 165 | if(checkTextTransform.stringValue() == 1) texts = texts.concat('\t\ttextTransform: "' + textTransform + '",\n'); 166 | if(checkColor.stringValue() == 1) texts = texts.concat('\t\tcolor: "' + textColor + '",\n'); 167 | 168 | texts = texts.concat( '\t},\n'); 169 | 170 | }else if(type == 'CSS'){ 171 | // CSS 172 | texts = texts.concat('.' + layerName + '{\n'); 173 | if(checkFontFamily.stringValue() == 1) texts = texts.concat('\tfont-family: "' + fontFamily +'";\n'); 174 | if(checkFontSize.stringValue() == 1) texts = texts.concat('\tfont-size: ' + fontSize +';\n'); 175 | if(checkFontWeight.stringValue() == 1) texts = texts.concat('\tfont-weight: ' + fontWeight +';\n'); 176 | if(checkLineHeight.stringValue() == 1) texts = texts.concat('\tline-height: ' + lineHeight + ';\n'); 177 | if(checkLetterSpacing.stringValue() == 1) texts = texts.concat('\tletter-spacing: ' + letterSpacing + ';\n'); 178 | if(checkTextTransform.stringValue() == 1) texts = texts.concat('\ttext-transform: ' + textTransform + ';\n'); 179 | if(checkColor.stringValue() == 1) texts = texts.concat('\tcolor: ' + textColor + ';\n'); 180 | texts = texts.concat( '}\n'); 181 | 182 | } 183 | 184 | }) 185 | 186 | let file = ''; 187 | 188 | if(type == 'JSON'){ 189 | let jsonObj = { "textstyles": texts }; 190 | file = NSString.stringWithString(JSON.stringify(jsonObj, null, "\t")); 191 | }else if(type == 'JavaScript Object'){ 192 | texts = texts.concat('}'); 193 | file = NSString.stringWithString(texts); 194 | }else{ 195 | file = NSString.stringWithString(texts); 196 | } 197 | 198 | let file_path = savePanel.URL().path(); 199 | file.writeToFile_atomically_encoding_error(file_path, true, NSUTF8StringEncoding, null); 200 | 201 | sketch.UI.message('Text Styles Exported!'); 202 | } 203 | 204 | } 205 | 206 | /** 207 | * 208 | * Main 209 | * 210 | */ 211 | export default () => { 212 | 213 | const doc = sketch.getSelectedDocument(); 214 | const selected = doc.selectedLayers.layers; 215 | 216 | // Only Text layers - no shape layers 217 | const selectedLayers = _.filter(_.reverse(selected), ['type', 'Text']); 218 | const selectedCount = _.size(selectedLayers); 219 | 220 | if (selectedCount !== 0) { 221 | 222 | const dialog = dialogBox(selectedLayers); 223 | const exportType = dropdownFileType.titleOfSelectedItem(); 224 | const exportUnits = dropdownUnits.titleOfSelectedItem(); 225 | const exportNaming = dropdownNames.indexOfSelectedItem(); 226 | 227 | 228 | if(dialog == "1000"){ 229 | exportTextstyles(selectedLayers, exportType, exportUnits, exportNaming); 230 | } 231 | 232 | }else{ 233 | sketch.UI.alert('Select layers','Please select text layers first.'); 234 | } 235 | 236 | } -------------------------------------------------------------------------------- /src/textTokens.js: -------------------------------------------------------------------------------- 1 | import sketch from 'sketch' 2 | import _ from 'lodash' 3 | 4 | import values from './lib/values' 5 | import formatObject from './lib/formatObject' 6 | import varNaming from './lib/varNaming' 7 | 8 | let dropdownFileType; 9 | let dropdownFormat; 10 | let dropdownNames; 11 | let dropdownUnits; 12 | 13 | import {dialogAlert,fieldLabel, fieldSelect} from './lib/dialogFields' 14 | 15 | 16 | /** 17 | * 18 | * Dialog 19 | * 20 | */ 21 | const dialogBox = (selectedLayers) => { 22 | 23 | let alert = dialogAlert("Export Text Variables"); 24 | 25 | // Creating the view 26 | let viewWidth = 300; 27 | let viewHeight = 225; 28 | 29 | let view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, viewWidth, viewHeight)); 30 | alert.addAccessoryView(view); 31 | 32 | //Dropdown: File format 33 | 34 | view.addSubview(fieldLabel(35, 'File format:', viewWidth, viewHeight)); 35 | 36 | let names = ["SCSS","Less","CSS","JSON","JavaScript Object","JavaScript Variables"]; 37 | dropdownFileType = fieldSelect(45, names, viewWidth, viewHeight) 38 | 39 | view.addSubview(dropdownFileType); 40 | 41 | //Dropdown: Select text tokens 42 | 43 | view.addSubview(fieldLabel(90, 'Select values:', viewWidth, viewHeight)); 44 | 45 | let types = [ "Font Size", "Font Weight", "Font Family", "Line Height", "Letter Spacing"]; 46 | dropdownFormat = fieldSelect(100, types, viewWidth, viewHeight) 47 | view.addSubview(dropdownFormat); 48 | 49 | //Dropdown: Select units 50 | 51 | view.addSubview(fieldLabel(145, 'Units:', viewWidth, viewHeight)); 52 | 53 | let units = [ "Absolute (px)", "Relative (em/rem)"]; 54 | dropdownUnits = fieldSelect(155, units, viewWidth, viewHeight) 55 | view.addSubview(dropdownUnits); 56 | 57 | //Dropdown: Naming 58 | 59 | view.addSubview(fieldLabel(200, 'Naming:', viewWidth, viewHeight)); 60 | 61 | dropdownNames = fieldSelect(210, selectedLayers, viewWidth, viewHeight, true) 62 | view.addSubview(dropdownNames); 63 | 64 | 65 | return alert.runModal(); 66 | 67 | } 68 | 69 | /** 70 | * 71 | * Export exportTextstyles 72 | * 73 | */ 74 | const exportTextstyles = (selectedLayers, type, format, naming, units) => { 75 | 76 | const selectedCount = selectedLayers.length; 77 | 78 | let fileTypes = NSArray.arrayWithArray([values[type].filetype, nil]); 79 | 80 | let savePanel = NSSavePanel.savePanel() 81 | //savePanel.setCanChooseDirectories(true) 82 | //savePanel.setCanCreateDirectories(true) 83 | savePanel.setAllowedFileTypes(fileTypes) 84 | 85 | savePanel.setNameFieldStringValue(_.camelCase(format) + '.' + values[type].filetype) 86 | savePanel.setPrompt("Save Text Tokens"); 87 | 88 | if (savePanel.runModal() && selectedCount !== 0) { 89 | 90 | let variables = {} 91 | 92 | _.forEach(selectedLayers, function (layer) { 93 | 94 | 95 | let layerName = varNaming(layer, naming); 96 | 97 | let fontFamily = layer.style.fontFamily; 98 | let fontSize = units == 'Absolute (px)' ? layer.style.fontSize + 'px' : layer.style.fontSize / 16 + 'rem'; 99 | let fontWeight = layer.style.fontWeight * 100; 100 | let lineHeight = units == 'Absolute (px)' ? _.round(layer.style.lineHeight, 2) + 'px' : _.round(layer.style.lineHeight / layer.style.fontSize, 2); 101 | let letterSpacing = layer.style.kerning == null ? 'normal' : units == 'Absolute (px)' ? _.round(layer.style.kerning, 2) + 'px' : _.round(layer.style.kerning / layer.style.fontSize, 2) + 'em'; 102 | 103 | if(format == 'Font Family') variables[layerName] = fontFamily 104 | if(format == 'Font Size') variables[layerName] = fontSize 105 | if(format == 'Font Weight') variables[layerName] = fontWeight 106 | if(format == 'Line Height') variables[layerName] = lineHeight 107 | if(format == 'Letter Spacing') variables[layerName] = letterSpacing 108 | 109 | }) 110 | 111 | let file = NSString.stringWithString(formatObject(variables, type, format)); 112 | let file_path = savePanel.URL().path(); 113 | file.writeToFile_atomically_encoding_error(file_path, true, NSUTF8StringEncoding, null); 114 | 115 | sketch.UI.message('Text Variables Exported!'); 116 | 117 | } 118 | 119 | } 120 | 121 | /** 122 | * 123 | * Main 124 | * 125 | */ 126 | export default () => { 127 | 128 | const doc = sketch.getSelectedDocument(); 129 | const selected = doc.selectedLayers.layers; 130 | 131 | // Only Text layers - no shape layers 132 | const selectedLayers = _.filter(_.reverse(selected), ['type', 'Text']); 133 | const selectedCount = _.size(selectedLayers); 134 | 135 | if (selectedCount !== 0) { 136 | 137 | const dialog = dialogBox(selectedLayers); 138 | const exportType = dropdownFileType.titleOfSelectedItem(); 139 | const exportFormat = dropdownFormat.titleOfSelectedItem(); 140 | const exportNaming = dropdownNames.indexOfSelectedItem(); 141 | const exportUnits = dropdownUnits.titleOfSelectedItem(); 142 | 143 | 144 | 145 | if(dialog == "1000"){ 146 | exportTextstyles(selectedLayers, exportType, exportFormat, exportNaming, exportUnits); 147 | } 148 | 149 | }else{ 150 | sketch.UI.alert('Select layers','Please select text layers first.'); 151 | } 152 | 153 | } --------------------------------------------------------------------------------