├── .gitignore ├── LICENSE ├── dist └── FigmaConsoleKit.js ├── esbuild.js ├── package-lock.json ├── package.json ├── readme.md ├── shot └── shot.gif ├── src ├── index.js └── lib │ ├── active.js │ ├── color.js │ ├── export.js │ ├── get.js │ ├── json.js │ ├── text.js │ └── tidy.js └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Moonvy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /esbuild.js: -------------------------------------------------------------------------------- 1 | let package = require("./package.json") 2 | 3 | require("esbuild") 4 | .build({ 5 | entryPoints: ["./src/index.js"], 6 | bundle: true, 7 | minify: true, 8 | outfile: "./dist/FigmaConsoleKit.js", 9 | define: { 10 | VERSION: `"${package.version}"`, 11 | }, 12 | }) 13 | .catch(() => process.exit(1)) 14 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FigmaConsoleKit", 3 | "version": "1.2.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "FigmaConsoleKit", 9 | "version": "1.2.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "axios": "^0.21.1", 13 | "client-zip": "^1.5.1", 14 | "color": "^4.2.0", 15 | "esbuild": "^0.12.8", 16 | "font-color-contrast": "^10.1.0", 17 | "loadsh": "^0.0.4", 18 | "mathjs": "^9.4.2" 19 | }, 20 | "devDependencies": { 21 | "@figma/plugin-typings": "^1.19.2" 22 | } 23 | }, 24 | "node_modules/@babel/runtime": { 25 | "version": "7.16.7", 26 | "resolved": "https://registry.npmmirror.com/@babel/runtime/download/@babel/runtime-7.16.7.tgz", 27 | "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", 28 | "dependencies": { 29 | "regenerator-runtime": "^0.13.4" 30 | }, 31 | "engines": { 32 | "node": ">=6.9.0" 33 | } 34 | }, 35 | "node_modules/@figma/plugin-typings": { 36 | "version": "1.40.0", 37 | "resolved": "https://registry.npmmirror.com/@figma/plugin-typings/download/@figma/plugin-typings-1.40.0.tgz", 38 | "integrity": "sha512-PA73qVIn6KFVpnJkt2xNbCpaxx04pXs9eu22JH2123O7Mu17ARLDlXE+tt1ikACfsS6aEGsStI3IFPks+yomVA==", 39 | "dev": true 40 | }, 41 | "node_modules/axios": { 42 | "version": "0.21.4", 43 | "resolved": "https://registry.npmmirror.com/axios/download/axios-0.21.4.tgz", 44 | "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", 45 | "dependencies": { 46 | "follow-redirects": "^1.14.0" 47 | } 48 | }, 49 | "node_modules/client-zip": { 50 | "version": "1.5.1", 51 | "resolved": "https://registry.npmmirror.com/client-zip/-/client-zip-1.5.1.tgz", 52 | "integrity": "sha512-uuEGhjC4rHej0Ho0h+DbCsngfwPAQGjh2GNzI/Qd5D/4162EJQq0ZsE1GTUDaFjQp8Pt2FR97itJNXPsNHjowA==" 53 | }, 54 | "node_modules/color": { 55 | "version": "4.2.0", 56 | "resolved": "https://registry.npmmirror.com/color/download/color-4.2.0.tgz", 57 | "integrity": "sha512-hHTcrbvEnGjC7WBMk6ibQWFVDgEFTVmjrz2Q5HlU6ltwxv0JJN2Z8I7uRbWeQLF04dikxs8zgyZkazRJvSMtyQ==", 58 | "dependencies": { 59 | "color-convert": "^2.0.1", 60 | "color-string": "^1.9.0" 61 | } 62 | }, 63 | "node_modules/color-convert": { 64 | "version": "2.0.1", 65 | "resolved": "https://registry.npmmirror.com/color-convert/download/color-convert-2.0.1.tgz", 66 | "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", 67 | "dependencies": { 68 | "color-name": "~1.1.4" 69 | }, 70 | "engines": { 71 | "node": ">=7.0.0" 72 | } 73 | }, 74 | "node_modules/color-name": { 75 | "version": "1.1.4", 76 | "resolved": "https://registry.npmmirror.com/color-name/download/color-name-1.1.4.tgz", 77 | "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=" 78 | }, 79 | "node_modules/color-string": { 80 | "version": "1.9.0", 81 | "resolved": "https://registry.npmmirror.com/color-string/download/color-string-1.9.0.tgz", 82 | "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", 83 | "dependencies": { 84 | "color-name": "^1.0.0", 85 | "simple-swizzle": "^0.2.2" 86 | } 87 | }, 88 | "node_modules/complex.js": { 89 | "version": "2.0.15", 90 | "resolved": "https://registry.npmmirror.com/complex.js/download/complex.js-2.0.15.tgz", 91 | "integrity": "sha1-et1oSLTB0SqpJi99+SXr56UadAY=", 92 | "engines": { 93 | "node": "*" 94 | } 95 | }, 96 | "node_modules/decimal.js": { 97 | "version": "10.3.1", 98 | "resolved": "https://registry.npmmirror.com/decimal.js/download/decimal.js-10.3.1.tgz", 99 | "integrity": "sha1-2MOkRKnGd0umDKatcmHDqU/V54M=" 100 | }, 101 | "node_modules/esbuild": { 102 | "version": "0.12.29", 103 | "resolved": "https://registry.npmmirror.com/esbuild/download/esbuild-0.12.29.tgz", 104 | "integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==", 105 | "hasInstallScript": true, 106 | "bin": { 107 | "esbuild": "bin/esbuild" 108 | } 109 | }, 110 | "node_modules/escape-latex": { 111 | "version": "1.2.0", 112 | "resolved": "https://registry.npmmirror.com/escape-latex/download/escape-latex-1.2.0.tgz", 113 | "integrity": "sha1-B8A4GM99rCUMzlF/T9obAB7yvKE=" 114 | }, 115 | "node_modules/follow-redirects": { 116 | "version": "1.14.7", 117 | "resolved": "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.7.tgz", 118 | "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", 119 | "engines": { 120 | "node": ">=4.0" 121 | }, 122 | "peerDependenciesMeta": { 123 | "debug": { 124 | "optional": true 125 | } 126 | } 127 | }, 128 | "node_modules/font-color-contrast": { 129 | "version": "10.1.0", 130 | "resolved": "https://registry.npmmirror.com/font-color-contrast/download/font-color-contrast-10.1.0.tgz", 131 | "integrity": "sha1-/LxAp58Z9WIVpMA84mH4glMyQQ8=", 132 | "license": "MIT" 133 | }, 134 | "node_modules/fraction.js": { 135 | "version": "4.1.2", 136 | "resolved": "https://registry.npmmirror.com/fraction.js/download/fraction.js-4.1.2.tgz?cache=0&sync_timestamp=1636701944838&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ffraction.js%2Fdownload%2Ffraction.js-4.1.2.tgz", 137 | "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", 138 | "engines": { 139 | "node": "*" 140 | }, 141 | "funding": { 142 | "type": "patreon", 143 | "url": "https://www.patreon.com/infusion" 144 | } 145 | }, 146 | "node_modules/is-arrayish": { 147 | "version": "0.3.2", 148 | "resolved": "https://registry.npmmirror.com/is-arrayish/download/is-arrayish-0.3.2.tgz", 149 | "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=" 150 | }, 151 | "node_modules/javascript-natural-sort": { 152 | "version": "0.7.1", 153 | "resolved": "https://registry.npmmirror.com/javascript-natural-sort/download/javascript-natural-sort-0.7.1.tgz", 154 | "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" 155 | }, 156 | "node_modules/loadsh": { 157 | "version": "0.0.4", 158 | "resolved": "https://registry.npmmirror.com/loadsh/download/loadsh-0.0.4.tgz", 159 | "integrity": "sha512-U+wLL8InpfRalWrr+0SuhWgGt10M4OyAk6G8xCYo2rwpiHtxZkWiFpjei0vO463ghW8LPCdhqQxXlMy2qicAEw==", 160 | "deprecated": "This is a typosquat on the popular Lodash package. This is not maintained nor is the original Lodash package." 161 | }, 162 | "node_modules/mathjs": { 163 | "version": "9.5.2", 164 | "resolved": "https://registry.npmmirror.com/mathjs/download/mathjs-9.5.2.tgz", 165 | "integrity": "sha1-4PMnkyDcb0nkXZnE/N2LUiMfBGI=", 166 | "license": "Apache-2.0", 167 | "dependencies": { 168 | "@babel/runtime": "^7.15.4", 169 | "complex.js": "^2.0.15", 170 | "decimal.js": "^10.3.1", 171 | "escape-latex": "^1.2.0", 172 | "fraction.js": "^4.1.1", 173 | "javascript-natural-sort": "^0.7.1", 174 | "seedrandom": "^3.0.5", 175 | "tiny-emitter": "^2.1.0", 176 | "typed-function": "^2.0.0" 177 | }, 178 | "bin": { 179 | "mathjs": "bin/cli.js" 180 | }, 181 | "engines": { 182 | "node": ">= 12" 183 | } 184 | }, 185 | "node_modules/regenerator-runtime": { 186 | "version": "0.13.9", 187 | "resolved": "https://registry.npmmirror.com/regenerator-runtime/download/regenerator-runtime-0.13.9.tgz", 188 | "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" 189 | }, 190 | "node_modules/seedrandom": { 191 | "version": "3.0.5", 192 | "resolved": "https://registry.npmmirror.com/seedrandom/download/seedrandom-3.0.5.tgz", 193 | "integrity": "sha1-VO3IXJUiJSWwx6b2s1Q9jgs6oKc=" 194 | }, 195 | "node_modules/simple-swizzle": { 196 | "version": "0.2.2", 197 | "resolved": "https://registry.npmmirror.com/simple-swizzle/download/simple-swizzle-0.2.2.tgz", 198 | "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", 199 | "dependencies": { 200 | "is-arrayish": "^0.3.1" 201 | } 202 | }, 203 | "node_modules/tiny-emitter": { 204 | "version": "2.1.0", 205 | "resolved": "https://registry.npmmirror.com/tiny-emitter/download/tiny-emitter-2.1.0.tgz", 206 | "integrity": "sha1-HRpW7fxRxD6GPLtTgqcjMONVVCM=" 207 | }, 208 | "node_modules/typed-function": { 209 | "version": "2.0.0", 210 | "resolved": "https://registry.npmmirror.com/typed-function/download/typed-function-2.0.0.tgz", 211 | "integrity": "sha1-Fas4JYRROKixETvYnmDNakNXOeg=", 212 | "engines": { 213 | "node": ">= 8" 214 | } 215 | } 216 | }, 217 | "dependencies": { 218 | "@babel/runtime": { 219 | "version": "7.16.7", 220 | "resolved": "https://registry.npmmirror.com/@babel/runtime/download/@babel/runtime-7.16.7.tgz", 221 | "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", 222 | "requires": { 223 | "regenerator-runtime": "^0.13.4" 224 | } 225 | }, 226 | "@figma/plugin-typings": { 227 | "version": "1.40.0", 228 | "resolved": "https://registry.npmmirror.com/@figma/plugin-typings/download/@figma/plugin-typings-1.40.0.tgz", 229 | "integrity": "sha512-PA73qVIn6KFVpnJkt2xNbCpaxx04pXs9eu22JH2123O7Mu17ARLDlXE+tt1ikACfsS6aEGsStI3IFPks+yomVA==", 230 | "dev": true 231 | }, 232 | "axios": { 233 | "version": "0.21.4", 234 | "resolved": "https://registry.npmmirror.com/axios/download/axios-0.21.4.tgz", 235 | "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", 236 | "requires": { 237 | "follow-redirects": "^1.14.0" 238 | } 239 | }, 240 | "client-zip": { 241 | "version": "1.5.1", 242 | "resolved": "https://registry.npmmirror.com/client-zip/-/client-zip-1.5.1.tgz", 243 | "integrity": "sha512-uuEGhjC4rHej0Ho0h+DbCsngfwPAQGjh2GNzI/Qd5D/4162EJQq0ZsE1GTUDaFjQp8Pt2FR97itJNXPsNHjowA==" 244 | }, 245 | "color": { 246 | "version": "4.2.0", 247 | "resolved": "https://registry.npmmirror.com/color/download/color-4.2.0.tgz", 248 | "integrity": "sha512-hHTcrbvEnGjC7WBMk6ibQWFVDgEFTVmjrz2Q5HlU6ltwxv0JJN2Z8I7uRbWeQLF04dikxs8zgyZkazRJvSMtyQ==", 249 | "requires": { 250 | "color-convert": "^2.0.1", 251 | "color-string": "^1.9.0" 252 | } 253 | }, 254 | "color-convert": { 255 | "version": "2.0.1", 256 | "resolved": "https://registry.npmmirror.com/color-convert/download/color-convert-2.0.1.tgz", 257 | "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", 258 | "requires": { 259 | "color-name": "~1.1.4" 260 | } 261 | }, 262 | "color-name": { 263 | "version": "1.1.4", 264 | "resolved": "https://registry.npmmirror.com/color-name/download/color-name-1.1.4.tgz", 265 | "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=" 266 | }, 267 | "color-string": { 268 | "version": "1.9.0", 269 | "resolved": "https://registry.npmmirror.com/color-string/download/color-string-1.9.0.tgz", 270 | "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", 271 | "requires": { 272 | "color-name": "^1.0.0", 273 | "simple-swizzle": "^0.2.2" 274 | } 275 | }, 276 | "complex.js": { 277 | "version": "2.0.15", 278 | "resolved": "https://registry.npmmirror.com/complex.js/download/complex.js-2.0.15.tgz", 279 | "integrity": "sha1-et1oSLTB0SqpJi99+SXr56UadAY=" 280 | }, 281 | "decimal.js": { 282 | "version": "10.3.1", 283 | "resolved": "https://registry.npmmirror.com/decimal.js/download/decimal.js-10.3.1.tgz", 284 | "integrity": "sha1-2MOkRKnGd0umDKatcmHDqU/V54M=" 285 | }, 286 | "esbuild": { 287 | "version": "0.12.29", 288 | "resolved": "https://registry.npmmirror.com/esbuild/download/esbuild-0.12.29.tgz", 289 | "integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==" 290 | }, 291 | "escape-latex": { 292 | "version": "1.2.0", 293 | "resolved": "https://registry.npmmirror.com/escape-latex/download/escape-latex-1.2.0.tgz", 294 | "integrity": "sha1-B8A4GM99rCUMzlF/T9obAB7yvKE=" 295 | }, 296 | "follow-redirects": { 297 | "version": "1.14.7", 298 | "resolved": "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.7.tgz", 299 | "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" 300 | }, 301 | "font-color-contrast": { 302 | "version": "10.1.0", 303 | "resolved": "https://registry.npmmirror.com/font-color-contrast/download/font-color-contrast-10.1.0.tgz", 304 | "integrity": "sha1-/LxAp58Z9WIVpMA84mH4glMyQQ8=" 305 | }, 306 | "fraction.js": { 307 | "version": "4.1.2", 308 | "resolved": "https://registry.npmmirror.com/fraction.js/download/fraction.js-4.1.2.tgz?cache=0&sync_timestamp=1636701944838&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ffraction.js%2Fdownload%2Ffraction.js-4.1.2.tgz", 309 | "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==" 310 | }, 311 | "is-arrayish": { 312 | "version": "0.3.2", 313 | "resolved": "https://registry.npmmirror.com/is-arrayish/download/is-arrayish-0.3.2.tgz", 314 | "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=" 315 | }, 316 | "javascript-natural-sort": { 317 | "version": "0.7.1", 318 | "resolved": "https://registry.npmmirror.com/javascript-natural-sort/download/javascript-natural-sort-0.7.1.tgz", 319 | "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" 320 | }, 321 | "loadsh": { 322 | "version": "0.0.4", 323 | "resolved": "https://registry.npmmirror.com/loadsh/download/loadsh-0.0.4.tgz", 324 | "integrity": "sha512-U+wLL8InpfRalWrr+0SuhWgGt10M4OyAk6G8xCYo2rwpiHtxZkWiFpjei0vO463ghW8LPCdhqQxXlMy2qicAEw==" 325 | }, 326 | "mathjs": { 327 | "version": "9.5.2", 328 | "resolved": "https://registry.npmmirror.com/mathjs/download/mathjs-9.5.2.tgz", 329 | "integrity": "sha1-4PMnkyDcb0nkXZnE/N2LUiMfBGI=", 330 | "requires": { 331 | "@babel/runtime": "^7.15.4", 332 | "complex.js": "^2.0.15", 333 | "decimal.js": "^10.3.1", 334 | "escape-latex": "^1.2.0", 335 | "fraction.js": "^4.1.1", 336 | "javascript-natural-sort": "^0.7.1", 337 | "seedrandom": "^3.0.5", 338 | "tiny-emitter": "^2.1.0", 339 | "typed-function": "^2.0.0" 340 | } 341 | }, 342 | "regenerator-runtime": { 343 | "version": "0.13.9", 344 | "resolved": "https://registry.npmmirror.com/regenerator-runtime/download/regenerator-runtime-0.13.9.tgz", 345 | "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" 346 | }, 347 | "seedrandom": { 348 | "version": "3.0.5", 349 | "resolved": "https://registry.npmmirror.com/seedrandom/download/seedrandom-3.0.5.tgz", 350 | "integrity": "sha1-VO3IXJUiJSWwx6b2s1Q9jgs6oKc=" 351 | }, 352 | "simple-swizzle": { 353 | "version": "0.2.2", 354 | "resolved": "https://registry.npmmirror.com/simple-swizzle/download/simple-swizzle-0.2.2.tgz", 355 | "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", 356 | "requires": { 357 | "is-arrayish": "^0.3.1" 358 | } 359 | }, 360 | "tiny-emitter": { 361 | "version": "2.1.0", 362 | "resolved": "https://registry.npmmirror.com/tiny-emitter/download/tiny-emitter-2.1.0.tgz", 363 | "integrity": "sha1-HRpW7fxRxD6GPLtTgqcjMONVVCM=" 364 | }, 365 | "typed-function": { 366 | "version": "2.0.0", 367 | "resolved": "https://registry.npmmirror.com/typed-function/download/typed-function-2.0.0.tgz", 368 | "integrity": "sha1-Fas4JYRROKixETvYnmDNakNXOeg=" 369 | } 370 | } 371 | } 372 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FigmaConsoleKit", 3 | "version": "1.5.0", 4 | "scripts": { 5 | "build": "node ./esbuild.js" 6 | }, 7 | "main": "./dist/FigmaConsoleKit.js", 8 | "module": "./src/index.js", 9 | "author": "yArna@me.moonvy.com", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@figma/plugin-typings": "^1.19.2" 13 | }, 14 | "dependencies": { 15 | "axios": "^0.21.1", 16 | "client-zip": "^1.5.1", 17 | "color": "^4.2.0", 18 | "esbuild": "^0.12.8", 19 | "font-color-contrast": "^10.1.0", 20 | "loadsh": "^0.0.4", 21 | "mathjs": "^9.4.2" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 🏂 FigmaConsoleKit 2 | 3 | Browser Devtool console is Figma's best scripting tool, FigmaConsoleKit can make it better, add a debugging-friendly API, most commonly used libraries(`axios`,`lodash`,`mathjs`,`Color`,`font-color-contrast`). 4 | 5 | 6 | 7 | ## Usege 8 | 9 | - paste code into figma console 10 | 11 | ```js 12 | fetch( 13 | "https://raw.githubusercontent.com/Moonvy/FigmaConsoleKit/master/dist/FigmaConsoleKit.js?v1.5.0" 14 | ).then((r) => r.text().then((c) => eval(c))); 15 | ``` 16 | 17 | or 18 | 19 | - create a browser bookmark and add the code as address 20 | 21 | ```js 22 | javascript:(function()%7Bfetch(%22https%3A%2F%2Fraw.githubusercontent.com%2FMoonvy%2FFigmaConsoleKit%2Fmaster%2Fdist%2FFigmaConsoleKit.js%3Fv1.5.0%22).then((r)%20%3D%3E%20r.text().then((c)%20%3D%3E%20eval(c)))%7D)() 23 | ``` 24 | 25 | or 26 | 27 | - paste [the code](dist/FigmaConsoleKit.js) into console 28 | 29 | ### Access 30 | 31 | - 🔥 `activeNodes` currently selected layers (multiple) 32 | - 🔥 `activeNode` currently selected layer (only one is fetched) 33 | - `getChildrenByName(node)` get multiple sublayers by layer name 34 | - `getClidByName(node)` get a sublayer by layer name 35 | - `getNodes(node, eachFunc)` get nodes from all children by eachFunc. 36 | - `getNodesByName(node, name)` get nodes with the specified name from all children 37 | - `getNodesByType(node, type)` get nodes with the specified type from all children 38 | - `getNodesByTypeName(node, type, name)` get nodes with the specified type and name from all children 39 | 40 | ![](./shot/shot.gif) 41 | 42 | ### Print 43 | 44 | - `show(node)` Show layer information 45 | - `json(node)` converts the layer information into a JSON string 46 | 47 | ### Color 48 | 49 | - `toFloatColor(intColor)` [255,255,255] => {r:1.0, g:1.0, b:1.0} 50 | - `toIntColor(floatColor)` {r:1.0, g:1.0, b:1.0} => [255,255,255] 51 | 52 | ### Text 53 | 54 | - `loadNodeFonts(node)` prepare the font used for a layer 55 | - `setNodeText(node, text)` set the text content of the text layer 56 | 57 | ### Tidy 58 | 59 | - `tidyX(nodes, cols, gap)` rearrange layers by number of columns 60 | 61 | ### Export 62 | 63 | - `download([{name, input}])` download multiple Unit8Array as zip file ([client-zip](https://www.npmjs.com/package/client-zip)). 64 | - `downloadZip()` ([client-zip](https://www.npmjs.com/package/client-zip)). 65 | 66 | ### Utils 67 | 68 | - [`axios`](https://github.com/axios/axios) best JavaScript HTTP client. 69 | - [`font-color-contrast`](https://github.com/russoedu/font-color-contrast#readme) use black or white font according to the given background color. 70 | - [`lodash`](https://github.com/lodash/lodash) a modern JavaScript utility library delivering modularity, performance & extras. 71 | - [`mathjs`](https://mathjs.org/) an extensive math library. 72 | - [`client-zip`](https://www.npmjs.com/package/client-zip) download all the files in one click. 73 | - [`Color`](https://github.com/Qix-/color#readme) immutable color conversion and manipulation with support for CSS color strings. 74 | -------------------------------------------------------------------------------- /shot/shot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Moonvy/FigmaConsoleKit/1c26e16fa97532f0ae7a6b8f3ccd3f1fb75355e2/shot/shot.gif -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | getActiveNode, 3 | getActiveNodes, 4 | setActiveNode, 5 | setActiveNodes, 6 | } from "./lib/active"; 7 | import { toFloatColor, toIntColor } from "./lib/color"; 8 | import { 9 | getChildrenByName, 10 | getClidByName, 11 | getNodesByName, 12 | getNodes, 13 | getNodesByType, 14 | getNodesByTypeName, 15 | } from "./lib/get"; 16 | import { tidyX } from "./lib/tidy"; 17 | import { show, json } from "./lib/json"; 18 | import { loadNodeFonts, setNodeText } from "./lib/text"; 19 | import { download } from "./lib/export"; 20 | 21 | import lodash from "loadsh"; 22 | import axios from "axios"; 23 | import fontColorContrast from "font-color-contrast"; 24 | import Color from "color"; 25 | import * as mathjs from "mathjs"; 26 | import { downloadZip } from "client-zip"; 27 | 28 | console.log( 29 | `%c[FimgaConsoleKit] v${VERSION} Landed!`, 30 | `border: 2px solid rgba(65, 40, 190, 0.09); background: #4128BE; color:#fff; border-radius: 4px; padding: 2px 4px;`, 31 | `https://github.com/Moonvy/FigmaConsoleKit` 32 | ); 33 | 34 | let fkit = { 35 | fontColorContrast, 36 | axios, 37 | mathjs, 38 | lodash, 39 | Color, 40 | // ---- 41 | loadNodeFonts, 42 | setNodeText, 43 | getChildrenByName, 44 | getClidByName, 45 | getNodesByName, 46 | getNodes, 47 | getNodesByType, 48 | getNodesByTypeName, 49 | toFloatColor, 50 | toIntColor, 51 | download, 52 | downloadZip, 53 | tidyX, 54 | show, 55 | json, 56 | }; 57 | 58 | Object.assign(window, fkit); 59 | window._ = lodash; 60 | window.fkit = fkit; 61 | 62 | Object.defineProperty(window, "activeNode", { 63 | configurable: true, 64 | get: getActiveNode, 65 | set: setActiveNode, 66 | }); 67 | 68 | Object.defineProperty(window, "activeNodes", { 69 | configurable: true, 70 | get: getActiveNodes, 71 | set: setActiveNodes, 72 | }); 73 | -------------------------------------------------------------------------------- /src/lib/active.js: -------------------------------------------------------------------------------- 1 | export function getActiveNodes() { 2 | return figma.currentPage.selection 3 | } 4 | 5 | export function getActiveNode() { 6 | return getActiveNodes()[0] 7 | } 8 | 9 | export function setActiveNode(node) { 10 | return (figma.currentPage.selection = [node]) 11 | } 12 | 13 | export function setActiveNodes(nodes) { 14 | return (figma.currentPage.selection = nodes) 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/color.js: -------------------------------------------------------------------------------- 1 | /** [255,255,255] => {r:1.0, g:1.0, b:1.0} */ 2 | export function toFloatColor(color) { 3 | return { r: color[0] / 255, g: color[1] / 255, b: color[2] / 255 }; 4 | } 5 | 6 | /** {r:1.0, g:1.0, b:1.0} => [255,255,255] */ 7 | export function toIntColor(color) { 8 | return [color.r * 255, color.g * 255, color.b * 255]; 9 | } 10 | -------------------------------------------------------------------------------- /src/lib/export.js: -------------------------------------------------------------------------------- 1 | import { downloadZip } from "client-zip"; 2 | 3 | /** 4 | * 下载文件 5 | * @param {[name:string, input: Unit8Array]} files 6 | */ 7 | export async function download(files, zipName) { 8 | const blob = await downloadZip(files).blob(); 9 | const link = document.createElement("a"); 10 | link.href = URL.createObjectURL(blob); 11 | link.download = zipName ?? "donwload.zip"; 12 | link.click(); 13 | link.remove(); 14 | } 15 | -------------------------------------------------------------------------------- /src/lib/get.js: -------------------------------------------------------------------------------- 1 | /** 按图层名称获取子节点(多个) */ 2 | export function getChildrenByName(node, name) { 3 | return node.children.filter((child) => child.name == name); 4 | } 5 | 6 | /** 按图层名称获取子节点 */ 7 | export function getClidByName(node, name) { 8 | return node.children.find((child) => child.name == name); 9 | } 10 | 11 | /** 在全部子级中挑选节点 */ 12 | export function getNodes(node, eachFunc) { 13 | let nodes = []; 14 | if (eachFunc(node)) { 15 | nodes.push(node); 16 | } 17 | if (node.children) { 18 | node.children.forEach((child) => { 19 | nodes = nodes.concat(getNodes(child)); 20 | }); 21 | } 22 | return nodes; 23 | } 24 | 25 | /** 在全部子级中挑选指定名称的节点 */ 26 | export function getNodesByName(node, name) { 27 | return getNodes(node, (node) => node.name == name); 28 | } 29 | 30 | /** 在全部子级中挑选指定类型的节点 */ 31 | export function getNodesByType(node, type) { 32 | return getNodes(node, (node) => node.type == type); 33 | } 34 | 35 | /** 在全部子级中挑选指定类型与名称的节点 */ 36 | export function getNodesByTypeName(node, type, name) { 37 | return getNodes(node, (node) => node.name == name && node.type == type); 38 | } 39 | -------------------------------------------------------------------------------- /src/lib/json.js: -------------------------------------------------------------------------------- 1 | export function show(data) { 2 | let ob = {} 3 | for (let key in data) { 4 | // 跳过一些 key 5 | if (["horizontalPadding", "verticalPadding"].includes(key)) { 6 | continue 7 | } 8 | 9 | let val 10 | try { 11 | val = data[key] 12 | } catch (e) { 13 | console.error("err get:" + key, e) 14 | } 15 | // 去掉 Symbol 16 | if (typeof val == "symbol") { 17 | val = val.description 18 | } 19 | ob[key] = val 20 | } 21 | return ob 22 | } 23 | 24 | export function json(data) { 25 | return JSON.stringify(show(data)) 26 | } 27 | -------------------------------------------------------------------------------- /src/lib/text.js: -------------------------------------------------------------------------------- 1 | /** 编辑文本前要先载入字体 */ 2 | export async function loadNodeFonts(node) { 3 | try { 4 | const fonts = node.getRangeAllFontNames(0, node.characters.length); 5 | for (const font of fonts) { 6 | await figma.loadFontAsync(font); 7 | } 8 | } catch (e) { 9 | console.error(e); 10 | } 11 | } 12 | 13 | /** 设置节点文本 */ 14 | export async function setNodeText(node, text) { 15 | try { 16 | node.characters = text; 17 | } catch (e) { 18 | await loadNodeFonts(node); 19 | node.characters = text; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/lib/tidy.js: -------------------------------------------------------------------------------- 1 | /** 排列图层 2 | * @param {number} xLen 列数 3 | * @param {number} gap 间距 4 | */ 5 | export function tidyX(nodes, xLen, gap) { 6 | let lastX, lastY; 7 | let startX, startY; 8 | let H = 0; 9 | 10 | let l = 0; 11 | for (let i = 0; i < nodes.length; i++) { 12 | let node = nodes[i]; 13 | if (lastX === undefined) { 14 | lastX = node.x; 15 | startX = lastX; 16 | } 17 | if (lastY === undefined) { 18 | lastY = node.y; 19 | startY = lastY; 20 | } 21 | 22 | if (H < node.height) { 23 | H = node.height; 24 | } 25 | 26 | node.x = lastX; 27 | node.y = lastY; 28 | lastX += node.width + gap; 29 | 30 | l++; 31 | if (l >= xLen) { 32 | l = 0; 33 | lastX = startX; 34 | lastY = lastY + H + gap; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "moduleResolution": "node", 5 | "allowSyntheticDefaultImports": true, 6 | "experimentalDecorators": true, 7 | "skipLibCheck": true, 8 | "allowJs": true, 9 | "strict": true, 10 | "lib": ["es2017", "dom"], 11 | "outDir": "dist", 12 | "typeRoots": [ 13 | "../../node_modules/@figma", 14 | "../../node_modules/@types", 15 | ] 16 | }, 17 | "include": ["src"], 18 | "exclude": ["node_modules"] 19 | } 20 | --------------------------------------------------------------------------------