├── .gitignore ├── LICENSE ├── README.md ├── assets ├── avatar.png └── cover.png ├── figma.d.ts ├── figplug.d.ts ├── manifest.json ├── package-lock.json ├── package.json ├── src ├── canvas.ts ├── colors.ts ├── plugin.ts ├── ui.html ├── ui.ts └── utils.ts ├── tsconfig.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .DS_Store 3 | node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Brian Lovin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Figma Dominant Color Toolkit](./assets/cover.png) 2 | 3 | # Figma Dominant Color Toolkit 🎨 4 | 5 | Generate a palette from an image to magically populate your designs. 6 | 7 | [Install on Figma](https://www.figma.com/c/plugin/744725347356614754/Dominant-Color-Toolkit-%F0%9F%8E%A8) 8 | 9 | ## Usage 10 | 11 | This plugin provides two core functions: 12 | 13 | 1. **Generate utility palette**: extracts the dominant color from an image, suggests high-contrast text colors, and includes additional complementary palette information. 14 | 1. **Smart populate**: takes your selection and intelligently sets layer fills and text colors based on nearby images. 15 | 16 | ### Generating a dominant color palette 17 | 18 | 1. Select one or more layers in Figma that contain image fills. 19 | 1. Run the plugin `Menu > Dominant Color Toolkit 🎨` and your palette will be generated. 20 | 21 | **Note:** To prevent overlapping frames from appearing in your designs, align your images 500px apart. 22 | 23 | ### Smart populate 24 | 25 | 1. Select any frame, component, or instance 26 | 2. Menu > Dominant Color Toolkit 🎨 27 | 3. Command + Shift + P to re-run 28 | 29 | How does Smart Populate work? 30 | - If you selected one or more frames which contain an image, shapes, and text, the plugin will use the first image it finds to automatically fill the shapes with the computed dominant color and set text layers to have a high-contrast fill against that dominant color. 31 | - If you selected an image along with shapes and text layers, the plugin will use the selected image to populate selected shapes with the computed dominant color and set text layers to use the high-contrast fill color. 32 | - If you selected shapes and text, but no image, the plugin will traverse outwards in your frame until it finds an image fill. This image will will then be used to populate the shapes and text with the dominant color and high-contrast text colors. 33 | 34 | **Note:** This plugin supports both image fills and background fills, using the first valid fill it can find. As a result, a frame with a background fill that has children shape and text layers will populate successfully! 35 | 36 | **Secret options:** If you'd like to text layers to the dominant color rather than high-contrast color, simply include the text "dominant" anywhere in the layer name! 37 | 38 | ## Installation and contributing 39 | 40 | 1. Clone the repository: `git clone https://github.com/brianlovin/figma-dominant-color-toolkit.git` 41 | 1. Go to the directory: `cd figma-dominant-color-toolkit` 42 | 1. Install dependencies with `npm install` 43 | 1. Build the plugin: `npm run dev` 44 | 1. Go to the `plugins` directory in Figma 45 | 1. Add a new development plugin 46 | 1. Select the `figma-dominant-color-toolkit/manifest.json` file as the manifest 47 | 48 | 49 | ## Credits 50 | 51 | - [color-thief](https://github.com/lokesh/color-thief) for finding dominant colors and generating palettes -------------------------------------------------------------------------------- /assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianlovin/figma-dominant-color-toolkit/e00073cc5edc753be1c967909fc9eb97205b5ed8/assets/avatar.png -------------------------------------------------------------------------------- /assets/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianlovin/figma-dominant-color-toolkit/e00073cc5edc753be1c967909fc9eb97205b5ed8/assets/cover.png -------------------------------------------------------------------------------- /figma.d.ts: -------------------------------------------------------------------------------- 1 | // Global variable with Figma's plugin API. 2 | declare const figma: PluginAPI 3 | declare const __html__: string 4 | 5 | interface PluginAPI { 6 | readonly apiVersion: "1.0.0" 7 | readonly command: string 8 | readonly root: DocumentNode 9 | readonly viewport: ViewportAPI 10 | closePlugin(message?: string): void 11 | 12 | showUI(html: string, options?: ShowUIOptions): void 13 | readonly ui: UIAPI 14 | 15 | readonly clientStorage: ClientStorageAPI 16 | 17 | getNodeById(id: string): BaseNode | null 18 | getStyleById(id: string): BaseStyle | null 19 | 20 | currentPage: PageNode 21 | 22 | readonly mixed: symbol 23 | 24 | createRectangle(): RectangleNode 25 | createLine(): LineNode 26 | createEllipse(): EllipseNode 27 | createPolygon(): PolygonNode 28 | createStar(): StarNode 29 | createVector(): VectorNode 30 | createText(): TextNode 31 | createBooleanOperation(): BooleanOperationNode 32 | createFrame(): FrameNode 33 | createComponent(): ComponentNode 34 | createPage(): PageNode 35 | createSlice(): SliceNode 36 | 37 | createPaintStyle(): PaintStyle 38 | createTextStyle(): TextStyle 39 | createEffectStyle(): EffectStyle 40 | createGridStyle(): GridStyle 41 | 42 | importComponentByKeyAsync(key: string): Promise 43 | importStyleByKeyAsync(key: string): Promise 44 | 45 | listAvailableFontsAsync(): Promise 46 | loadFontAsync(fontName: FontName): Promise 47 | readonly hasMissingFont: boolean 48 | 49 | createNodeFromSvg(svg: string): FrameNode 50 | 51 | createImage(data: Uint8Array): Image 52 | getImageByHash(hash: string): Image 53 | 54 | group(nodes: ReadonlyArray, parent: BaseNode & ChildrenMixin, index?: number): FrameNode 55 | flatten(nodes: ReadonlyArray, parent?: BaseNode & ChildrenMixin, index?: number): VectorNode 56 | } 57 | 58 | interface ClientStorageAPI { 59 | getAsync(key: string): Promise 60 | setAsync(key: string, value: any): Promise 61 | } 62 | 63 | type ShowUIOptions = { 64 | visible?: boolean, 65 | width?: number, 66 | height?: number, 67 | } 68 | 69 | type UIPostMessageOptions = { 70 | targetOrigin?: string, 71 | } 72 | 73 | type OnMessageProperties = { 74 | sourceOrigin: string, 75 | } 76 | 77 | interface UIAPI { 78 | show(): void 79 | hide(): void 80 | resize(width: number, height: number): void 81 | close(): void 82 | 83 | postMessage(pluginMessage: any, options?: UIPostMessageOptions): void 84 | onmessage: ((pluginMessage: any, props: OnMessageProperties) => void) | undefined 85 | } 86 | 87 | interface ViewportAPI { 88 | center: { x: number, y: number } 89 | zoom: number 90 | scrollAndZoomIntoView(nodes: ReadonlyArray) 91 | } 92 | 93 | //////////////////////////////////////////////////////////////////////////////// 94 | // Datatypes 95 | 96 | type Transform = [ 97 | [number, number, number], 98 | [number, number, number] 99 | ] 100 | 101 | interface Vector { 102 | readonly x: number 103 | readonly y: number 104 | } 105 | 106 | interface RGB { 107 | readonly r: number 108 | readonly g: number 109 | readonly b: number 110 | } 111 | 112 | interface RGBA { 113 | readonly r: number 114 | readonly g: number 115 | readonly b: number 116 | readonly a: number 117 | } 118 | 119 | interface FontName { 120 | readonly family: string 121 | readonly style: string 122 | } 123 | 124 | type TextCase = "ORIGINAL" | "UPPER" | "LOWER" | "TITLE" 125 | 126 | type TextDecoration = "NONE" | "UNDERLINE" | "STRIKETHROUGH" 127 | 128 | interface ArcData { 129 | readonly startingAngle: number 130 | readonly endingAngle: number 131 | readonly innerRadius: number 132 | } 133 | 134 | interface ShadowEffect { 135 | readonly type: "DROP_SHADOW" | "INNER_SHADOW" 136 | readonly color: RGBA 137 | readonly offset: Vector 138 | readonly radius: number 139 | readonly visible: boolean 140 | readonly blendMode: BlendMode 141 | } 142 | 143 | interface BlurEffect { 144 | readonly type: "LAYER_BLUR" | "BACKGROUND_BLUR" 145 | readonly radius: number 146 | readonly visible: boolean 147 | } 148 | 149 | type Effect = ShadowEffect | BlurEffect 150 | 151 | type ConstraintType = "MIN" | "CENTER" | "MAX" | "STRETCH" | "SCALE" 152 | 153 | interface Constraints { 154 | readonly horizontal: ConstraintType 155 | readonly vertical: ConstraintType 156 | } 157 | 158 | interface ColorStop { 159 | readonly position: number 160 | readonly color: RGBA 161 | } 162 | 163 | interface ImageFilters { 164 | exposure?: number 165 | contrast?: number 166 | saturation?: number 167 | temperature?: number 168 | tint?: number 169 | highlights?: number 170 | shadows?: number 171 | } 172 | 173 | interface SolidPaint { 174 | readonly type: "SOLID" 175 | readonly color: RGB 176 | 177 | readonly visible?: boolean 178 | readonly opacity?: number 179 | readonly blendMode?: BlendMode 180 | } 181 | 182 | interface GradientPaint { 183 | readonly type: "GRADIENT_LINEAR" | "GRADIENT_RADIAL" | "GRADIENT_ANGULAR" | "GRADIENT_DIAMOND" 184 | readonly gradientTransform: Transform 185 | readonly gradientStops: ReadonlyArray 186 | 187 | readonly visible?: boolean 188 | readonly opacity?: number 189 | readonly blendMode?: BlendMode 190 | } 191 | 192 | interface ImagePaint { 193 | readonly type: "IMAGE" 194 | readonly scaleMode: "FILL" | "FIT" | "CROP" | "TILE" 195 | readonly imageHash: string | null 196 | readonly imageTransform?: Transform // setting for "CROP" 197 | readonly scalingFactor?: number // setting for "TILE" 198 | readonly filters?: ImageFilters 199 | 200 | readonly visible?: boolean 201 | readonly opacity?: number 202 | readonly blendMode?: BlendMode 203 | } 204 | 205 | type Paint = SolidPaint | GradientPaint | ImagePaint 206 | 207 | interface Guide { 208 | readonly axis: "X" | "Y" 209 | readonly offset: number 210 | } 211 | 212 | interface RowsColsLayoutGrid { 213 | readonly pattern: "ROWS" | "COLUMNS" 214 | readonly alignment: "MIN" | "MAX" | "STRETCH" | "CENTER" 215 | readonly gutterSize: number 216 | 217 | readonly count: number // Infinity when "Auto" is set in the UI 218 | readonly sectionSize?: number // Not set for alignment: "STRETCH" 219 | readonly offset?: number // Not set for alignment: "CENTER" 220 | 221 | readonly visible?: boolean 222 | readonly color?: RGBA 223 | } 224 | 225 | interface GridLayoutGrid { 226 | readonly pattern: "GRID" 227 | readonly sectionSize: number 228 | 229 | readonly visible?: boolean 230 | readonly color?: RGBA 231 | } 232 | 233 | type LayoutGrid = RowsColsLayoutGrid | GridLayoutGrid 234 | 235 | interface ExportSettingsConstraints { 236 | type: "SCALE" | "WIDTH" | "HEIGHT" 237 | value: number 238 | } 239 | 240 | interface ExportSettingsImage { 241 | format: "JPG" | "PNG" 242 | contentsOnly?: boolean // defaults to true 243 | suffix?: string 244 | constraint?: ExportSettingsConstraints 245 | } 246 | 247 | interface ExportSettingsSVG { 248 | format: "SVG" 249 | contentsOnly?: boolean // defaults to true 250 | suffix?: string 251 | svgOutlineText?: boolean // defaults to true 252 | svgIdAttribute?: boolean // defaults to false 253 | svgSimplifyStroke?: boolean // defaults to true 254 | } 255 | 256 | interface ExportSettingsPDF { 257 | format: "PDF" 258 | contentsOnly?: boolean // defaults to true 259 | suffix?: string 260 | } 261 | 262 | type ExportSettings = ExportSettingsImage | ExportSettingsSVG | ExportSettingsPDF 263 | 264 | type WindingRule = "NONZERO" | "EVENODD" 265 | 266 | interface VectorVertex { 267 | readonly x: number 268 | readonly y: number 269 | readonly strokeCap?: StrokeCap 270 | readonly strokeJoin?: StrokeJoin 271 | readonly cornerRadius?: number 272 | readonly handleMirroring?: HandleMirroring 273 | } 274 | 275 | interface VectorSegment { 276 | readonly start: number 277 | readonly end: number 278 | readonly tangentStart?: Vector // Defaults to { x: 0, y: 0 } 279 | readonly tangentEnd?: Vector // Defaults to { x: 0, y: 0 } 280 | } 281 | 282 | interface VectorRegion { 283 | readonly windingRule: WindingRule 284 | readonly loops: ReadonlyArray> 285 | } 286 | 287 | interface VectorNetwork { 288 | readonly vertices: ReadonlyArray 289 | readonly segments: ReadonlyArray 290 | readonly regions?: ReadonlyArray // Defaults to [] 291 | } 292 | 293 | interface VectorPath { 294 | readonly windingRule: WindingRule | "NONE" 295 | readonly data: string 296 | } 297 | 298 | type VectorPaths = ReadonlyArray 299 | 300 | type LetterSpacing = { 301 | readonly value: number 302 | readonly unit: "PIXELS" | "PERCENT" 303 | } 304 | 305 | type LineHeight = { 306 | readonly value: number 307 | readonly unit: "PIXELS" | "PERCENT" 308 | } | { 309 | readonly unit: "AUTO" 310 | } 311 | 312 | type BlendMode = 313 | "PASS_THROUGH" | 314 | "NORMAL" | 315 | "DARKEN" | 316 | "MULTIPLY" | 317 | "LINEAR_BURN" | 318 | "COLOR_BURN" | 319 | "LIGHTEN" | 320 | "SCREEN" | 321 | "LINEAR_DODGE" | 322 | "COLOR_DODGE" | 323 | "OVERLAY" | 324 | "SOFT_LIGHT" | 325 | "HARD_LIGHT" | 326 | "DIFFERENCE" | 327 | "EXCLUSION" | 328 | "HUE" | 329 | "SATURATION" | 330 | "COLOR" | 331 | "LUMINOSITY" 332 | 333 | interface Font { 334 | fontName: FontName 335 | } 336 | 337 | //////////////////////////////////////////////////////////////////////////////// 338 | // Mixins 339 | 340 | interface BaseNodeMixin { 341 | readonly id: string 342 | readonly parent: (BaseNode & ChildrenMixin) | null 343 | name: string // Note: setting this also sets `autoRename` to false on TextNodes 344 | readonly removed: boolean 345 | toString(): string 346 | remove(): void 347 | 348 | getPluginData(key: string): string 349 | setPluginData(key: string, value: string): void 350 | 351 | // Namespace is a string that must be at least 3 alphanumeric characters, and should 352 | // be a name related to your plugin. Other plugins will be able to read this data. 353 | getSharedPluginData(namespace: string, key: string): string 354 | setSharedPluginData(namespace: string, key: string, value: string): void 355 | } 356 | 357 | interface SceneNodeMixin { 358 | visible: boolean 359 | locked: boolean 360 | } 361 | 362 | interface ChildrenMixin { 363 | readonly children: ReadonlyArray 364 | 365 | appendChild(child: BaseNode): void 366 | insertChild(index: number, child: BaseNode): void 367 | 368 | findAll(callback?: (node: BaseNode) => boolean): ReadonlyArray 369 | findOne(callback: (node: BaseNode) => boolean): BaseNode | null 370 | } 371 | 372 | interface ConstraintMixin { 373 | constraints: Constraints 374 | } 375 | 376 | interface LayoutMixin { 377 | readonly absoluteTransform: Transform 378 | relativeTransform: Transform 379 | x: number 380 | y: number 381 | rotation: number // In degrees 382 | 383 | readonly width: number 384 | readonly height: number 385 | 386 | resize(width: number, height: number): void 387 | resizeWithoutConstraints(width: number, height: number): void 388 | } 389 | 390 | interface BlendMixin { 391 | opacity: number 392 | blendMode: BlendMode 393 | isMask: boolean 394 | effects: ReadonlyArray 395 | effectStyleId: string 396 | } 397 | 398 | interface FrameMixin { 399 | backgrounds: ReadonlyArray 400 | layoutGrids: ReadonlyArray 401 | clipsContent: boolean 402 | guides: ReadonlyArray 403 | gridStyleId: string 404 | backgroundStyleId: string 405 | } 406 | 407 | type StrokeCap = "NONE" | "ROUND" | "SQUARE" | "ARROW_LINES" | "ARROW_EQUILATERAL" 408 | type StrokeJoin = "MITER" | "BEVEL" | "ROUND" 409 | type HandleMirroring = "NONE" | "ANGLE" | "ANGLE_AND_LENGTH" 410 | 411 | interface GeometryMixin { 412 | fills: ReadonlyArray | symbol 413 | strokes: ReadonlyArray 414 | strokeWeight: number 415 | strokeAlign: "CENTER" | "INSIDE" | "OUTSIDE" 416 | strokeCap: StrokeCap | symbol 417 | strokeJoin: StrokeJoin | symbol 418 | dashPattern: ReadonlyArray 419 | fillStyleId: string | symbol 420 | strokeStyleId: string 421 | } 422 | 423 | interface CornerMixin { 424 | cornerRadius: number | symbol 425 | cornerSmoothing: number 426 | } 427 | 428 | interface ExportMixin { 429 | exportSettings: ExportSettings[] 430 | exportAsync(settings?: ExportSettings): Promise // Defaults to PNG format 431 | } 432 | 433 | interface DefaultShapeMixin extends 434 | BaseNodeMixin, SceneNodeMixin, 435 | BlendMixin, GeometryMixin, LayoutMixin, ExportMixin { 436 | } 437 | 438 | interface DefaultContainerMixin extends 439 | BaseNodeMixin, SceneNodeMixin, 440 | ChildrenMixin, FrameMixin, 441 | BlendMixin, ConstraintMixin, LayoutMixin, ExportMixin { 442 | } 443 | 444 | //////////////////////////////////////////////////////////////////////////////// 445 | // Nodes 446 | 447 | interface DocumentNode extends BaseNodeMixin, ChildrenMixin { 448 | readonly type: "DOCUMENT" 449 | } 450 | 451 | interface PageNode extends BaseNodeMixin, ChildrenMixin, ExportMixin { 452 | readonly type: "PAGE" 453 | clone(): PageNode 454 | 455 | guides: ReadonlyArray 456 | selection: ReadonlyArray 457 | } 458 | 459 | interface FrameNode extends DefaultContainerMixin { 460 | readonly type: "FRAME" | "GROUP" 461 | clone(): FrameNode 462 | } 463 | 464 | interface SliceNode extends BaseNodeMixin, SceneNodeMixin, LayoutMixin, ExportMixin { 465 | readonly type: "SLICE" 466 | clone(): SliceNode 467 | } 468 | 469 | interface RectangleNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { 470 | readonly type: "RECTANGLE" 471 | clone(): RectangleNode 472 | topLeftRadius: number 473 | topRightRadius: number 474 | bottomLeftRadius: number 475 | bottomRightRadius: number 476 | } 477 | 478 | interface LineNode extends DefaultShapeMixin, ConstraintMixin { 479 | readonly type: "LINE" 480 | clone(): LineNode 481 | } 482 | 483 | interface EllipseNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { 484 | readonly type: "ELLIPSE" 485 | clone(): EllipseNode 486 | arcData: ArcData 487 | } 488 | 489 | interface PolygonNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { 490 | readonly type: "POLYGON" 491 | clone(): PolygonNode 492 | pointCount: number 493 | } 494 | 495 | interface StarNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { 496 | readonly type: "STAR" 497 | clone(): StarNode 498 | pointCount: number 499 | innerRadius: number 500 | } 501 | 502 | interface VectorNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { 503 | readonly type: "VECTOR" 504 | clone(): VectorNode 505 | vectorNetwork: VectorNetwork 506 | vectorPaths: VectorPaths 507 | handleMirroring: HandleMirroring | symbol 508 | } 509 | 510 | interface TextNode extends DefaultShapeMixin, ConstraintMixin { 511 | readonly type: "TEXT" 512 | clone(): TextNode 513 | characters: string 514 | readonly hasMissingFont: boolean 515 | textAlignHorizontal: "LEFT" | "CENTER" | "RIGHT" | "JUSTIFIED" 516 | textAlignVertical: "TOP" | "CENTER" | "BOTTOM" 517 | textAutoResize: "NONE" | "WIDTH_AND_HEIGHT" | "HEIGHT" 518 | paragraphIndent: number 519 | paragraphSpacing: number 520 | autoRename: boolean 521 | 522 | textStyleId: string | symbol 523 | fontSize: number | symbol 524 | fontName: FontName | symbol 525 | textCase: TextCase | symbol 526 | textDecoration: TextDecoration | symbol 527 | letterSpacing: LetterSpacing | symbol 528 | lineHeight: LineHeight | symbol 529 | 530 | getRangeFontSize(start: number, end: number): number | symbol 531 | setRangeFontSize(start: number, end: number, value: number): void 532 | getRangeFontName(start: number, end: number): FontName | symbol 533 | setRangeFontName(start: number, end: number, value: FontName): void 534 | getRangeTextCase(start: number, end: number): TextCase | symbol 535 | setRangeTextCase(start: number, end: number, value: TextCase): void 536 | getRangeTextDecoration(start: number, end: number): TextDecoration | symbol 537 | setRangeTextDecoration(start: number, end: number, value: TextDecoration): void 538 | getRangeLetterSpacing(start: number, end: number): LetterSpacing | symbol 539 | setRangeLetterSpacing(start: number, end: number, value: LetterSpacing): void 540 | getRangeLineHeight(start: number, end: number): LineHeight | symbol 541 | setRangeLineHeight(start: number, end: number, value: LineHeight): void 542 | getRangeFills(start: number, end: number): Paint[] | symbol 543 | setRangeFills(start: number, end: number, value: Paint[]): void 544 | getRangeTextStyleId(start: number, end: number): string | symbol 545 | setRangeTextStyleId(start: number, end: number, value: string): void 546 | getRangeFillStyleId(start: number, end: number): string | symbol 547 | setRangeFillStyleId(start: number, end: number, value: string): void 548 | } 549 | 550 | interface ComponentNode extends DefaultContainerMixin { 551 | readonly type: "COMPONENT" 552 | clone(): ComponentNode 553 | 554 | createInstance(): InstanceNode 555 | description: string 556 | readonly remote: boolean 557 | readonly key: string // The key to use with "importComponentByKeyAsync" 558 | } 559 | 560 | interface InstanceNode extends DefaultContainerMixin { 561 | readonly type: "INSTANCE" 562 | clone(): InstanceNode 563 | masterComponent: ComponentNode 564 | } 565 | 566 | interface BooleanOperationNode extends DefaultShapeMixin, ChildrenMixin, CornerMixin { 567 | readonly type: "BOOLEAN_OPERATION" 568 | clone(): BooleanOperationNode 569 | booleanOperation: "UNION" | "INTERSECT" | "SUBTRACT" | "EXCLUDE" 570 | } 571 | 572 | type BaseNode = 573 | DocumentNode | 574 | PageNode | 575 | SceneNode 576 | 577 | type SceneNode = 578 | SliceNode | 579 | FrameNode | 580 | ComponentNode | 581 | InstanceNode | 582 | BooleanOperationNode | 583 | VectorNode | 584 | StarNode | 585 | LineNode | 586 | EllipseNode | 587 | PolygonNode | 588 | RectangleNode | 589 | TextNode 590 | 591 | type NodeType = 592 | "DOCUMENT" | 593 | "PAGE" | 594 | "SLICE" | 595 | "FRAME" | 596 | "GROUP" | 597 | "COMPONENT" | 598 | "INSTANCE" | 599 | "BOOLEAN_OPERATION" | 600 | "VECTOR" | 601 | "STAR" | 602 | "LINE" | 603 | "ELLIPSE" | 604 | "POLYGON" | 605 | "RECTANGLE" | 606 | "TEXT" 607 | 608 | //////////////////////////////////////////////////////////////////////////////// 609 | // Styles 610 | type StyleType = "PAINT" | "TEXT" | "EFFECT" | "GRID" 611 | 612 | interface BaseStyle { 613 | readonly id: string 614 | readonly type: StyleType 615 | name: string 616 | description: string 617 | remote: boolean 618 | readonly key: string // The key to use with "importStyleByKeyAsync" 619 | remove(): void 620 | } 621 | 622 | interface PaintStyle extends BaseStyle { 623 | type: "PAINT" 624 | paints: ReadonlyArray 625 | } 626 | 627 | interface TextStyle extends BaseStyle { 628 | type: "TEXT" 629 | fontSize: number 630 | textDecoration: TextDecoration 631 | fontName: FontName 632 | letterSpacing: LetterSpacing 633 | lineHeight: LineHeight 634 | paragraphIndent: number 635 | paragraphSpacing: number 636 | textCase: TextCase 637 | } 638 | 639 | interface EffectStyle extends BaseStyle { 640 | type: "EFFECT" 641 | effects: ReadonlyArray 642 | } 643 | 644 | interface GridStyle extends BaseStyle { 645 | type: "GRID" 646 | layoutGrids: ReadonlyArray 647 | } 648 | 649 | //////////////////////////////////////////////////////////////////////////////// 650 | // Other 651 | 652 | interface Image { 653 | readonly hash: string 654 | getBytesAsync(): Promise 655 | } 656 | -------------------------------------------------------------------------------- /figplug.d.ts: -------------------------------------------------------------------------------- 1 | // Helpers provided automatically, as needed, by figplug. 2 | 3 | // symbolic type aliases 4 | type int = number 5 | type float = number 6 | type byte = number 7 | type bool = boolean 8 | 9 | // compile-time constants 10 | declare const DEBUG :boolean 11 | declare const VERSION :string 12 | 13 | // global namespace. Same as `window` in a regular web context. 14 | declare const global :{[k:string]:any} 15 | 16 | // panic prints a message, stack trace and exits the process 17 | // 18 | declare function panic(msg :any, ...v :any[]) :void 19 | 20 | // repr returns a detailed string representation of the input 21 | // 22 | declare function repr(obj :any) :string 23 | 24 | // print works just like console.log 25 | declare function print(msg :any, ...v :any[]) :void 26 | 27 | // dlog works just like console.log but is stripped out from non-debug builds 28 | declare function dlog(msg :any, ...v :any[]) :void 29 | 30 | // assert checks the condition for truth, and if false, prints an optional 31 | // message, stack trace and exits the process. 32 | // assert is removed in release builds 33 | declare var assert :AssertFun 34 | declare var AssertionError :ErrorConstructor 35 | declare interface AssertFun { 36 | (cond :any, msg? :string, cons? :Function) :void 37 | 38 | // throws can be set to true to cause assertions to be thrown as exceptions, 39 | // or set to false to cause the process to exit. 40 | // Only has an effect in Nodejs-like environments. 41 | // false by default. 42 | throws :bool 43 | } 44 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "api": "1.0.0", 3 | "name": "Dominant Color Toolkit 🎨", 4 | "main": "build/code.js", 5 | "ui": "build/ui.html", 6 | "id": "744725347356614754", 7 | "editorType": [ 8 | "figma" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "figma-dominant-color-toolkit", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/runtime": { 8 | "version": "7.12.5", 9 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", 10 | "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", 11 | "requires": { 12 | "regenerator-runtime": "^0.13.4" 13 | } 14 | }, 15 | "@discoveryjs/json-ext": { 16 | "version": "0.5.5", 17 | "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz", 18 | "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==", 19 | "dev": true 20 | }, 21 | "@jimp/bmp": { 22 | "version": "0.16.1", 23 | "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", 24 | "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", 25 | "requires": { 26 | "@babel/runtime": "^7.7.2", 27 | "@jimp/utils": "^0.16.1", 28 | "bmp-js": "^0.1.0" 29 | } 30 | }, 31 | "@jimp/core": { 32 | "version": "0.16.1", 33 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", 34 | "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", 35 | "requires": { 36 | "@babel/runtime": "^7.7.2", 37 | "@jimp/utils": "^0.16.1", 38 | "any-base": "^1.1.0", 39 | "buffer": "^5.2.0", 40 | "exif-parser": "^0.1.12", 41 | "file-type": "^9.0.0", 42 | "load-bmfont": "^1.3.1", 43 | "mkdirp": "^0.5.1", 44 | "phin": "^2.9.1", 45 | "pixelmatch": "^4.0.2", 46 | "tinycolor2": "^1.4.1" 47 | } 48 | }, 49 | "@jimp/custom": { 50 | "version": "0.16.1", 51 | "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", 52 | "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", 53 | "requires": { 54 | "@babel/runtime": "^7.7.2", 55 | "@jimp/core": "^0.16.1" 56 | } 57 | }, 58 | "@jimp/gif": { 59 | "version": "0.16.1", 60 | "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", 61 | "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", 62 | "requires": { 63 | "@babel/runtime": "^7.7.2", 64 | "@jimp/utils": "^0.16.1", 65 | "gifwrap": "^0.9.2", 66 | "omggif": "^1.0.9" 67 | } 68 | }, 69 | "@jimp/jpeg": { 70 | "version": "0.16.1", 71 | "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", 72 | "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", 73 | "requires": { 74 | "@babel/runtime": "^7.7.2", 75 | "@jimp/utils": "^0.16.1", 76 | "jpeg-js": "0.4.2" 77 | }, 78 | "dependencies": { 79 | "jpeg-js": { 80 | "version": "0.4.2", 81 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.2.tgz", 82 | "integrity": "sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw==" 83 | } 84 | } 85 | }, 86 | "@jimp/plugin-resize": { 87 | "version": "0.16.1", 88 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", 89 | "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", 90 | "requires": { 91 | "@babel/runtime": "^7.7.2", 92 | "@jimp/utils": "^0.16.1" 93 | } 94 | }, 95 | "@jimp/png": { 96 | "version": "0.16.1", 97 | "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", 98 | "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", 99 | "requires": { 100 | "@babel/runtime": "^7.7.2", 101 | "@jimp/utils": "^0.16.1", 102 | "pngjs": "^3.3.3" 103 | } 104 | }, 105 | "@jimp/tiff": { 106 | "version": "0.16.1", 107 | "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", 108 | "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", 109 | "requires": { 110 | "@babel/runtime": "^7.7.2", 111 | "utif": "^2.0.1" 112 | } 113 | }, 114 | "@jimp/types": { 115 | "version": "0.16.1", 116 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", 117 | "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", 118 | "requires": { 119 | "@babel/runtime": "^7.7.2", 120 | "@jimp/bmp": "^0.16.1", 121 | "@jimp/gif": "^0.16.1", 122 | "@jimp/jpeg": "^0.16.1", 123 | "@jimp/png": "^0.16.1", 124 | "@jimp/tiff": "^0.16.1", 125 | "timm": "^1.6.1" 126 | } 127 | }, 128 | "@jimp/utils": { 129 | "version": "0.16.1", 130 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", 131 | "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", 132 | "requires": { 133 | "@babel/runtime": "^7.7.2", 134 | "regenerator-runtime": "^0.13.3" 135 | } 136 | }, 137 | "@types/eslint": { 138 | "version": "7.28.1", 139 | "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.1.tgz", 140 | "integrity": "sha512-XhZKznR3i/W5dXqUhgU9fFdJekufbeBd5DALmkuXoeFcjbQcPk+2cL+WLHf6Q81HWAnM2vrslIHpGVyCAviRwg==", 141 | "dev": true, 142 | "requires": { 143 | "@types/estree": "*", 144 | "@types/json-schema": "*" 145 | } 146 | }, 147 | "@types/eslint-scope": { 148 | "version": "3.7.1", 149 | "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", 150 | "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", 151 | "dev": true, 152 | "requires": { 153 | "@types/eslint": "*", 154 | "@types/estree": "*" 155 | } 156 | }, 157 | "@types/estree": { 158 | "version": "0.0.50", 159 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", 160 | "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", 161 | "dev": true 162 | }, 163 | "@types/html-minifier-terser": { 164 | "version": "5.1.1", 165 | "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", 166 | "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==", 167 | "dev": true 168 | }, 169 | "@types/json-schema": { 170 | "version": "7.0.6", 171 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", 172 | "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", 173 | "dev": true 174 | }, 175 | "@types/lodash": { 176 | "version": "4.14.165", 177 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", 178 | "integrity": "sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg==" 179 | }, 180 | "@types/node": { 181 | "version": "10.17.46", 182 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.46.tgz", 183 | "integrity": "sha512-Tice8a+sJtlP9C1EUo0DYyjq52T37b3LexVu3p871+kfIBIN+OQ7PKPei1oF3MgF39olEpUfxaLtD+QFc1k69Q==" 184 | }, 185 | "@webassemblyjs/ast": { 186 | "version": "1.11.1", 187 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", 188 | "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", 189 | "dev": true, 190 | "requires": { 191 | "@webassemblyjs/helper-numbers": "1.11.1", 192 | "@webassemblyjs/helper-wasm-bytecode": "1.11.1" 193 | } 194 | }, 195 | "@webassemblyjs/floating-point-hex-parser": { 196 | "version": "1.11.1", 197 | "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", 198 | "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", 199 | "dev": true 200 | }, 201 | "@webassemblyjs/helper-api-error": { 202 | "version": "1.11.1", 203 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", 204 | "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", 205 | "dev": true 206 | }, 207 | "@webassemblyjs/helper-buffer": { 208 | "version": "1.11.1", 209 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", 210 | "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", 211 | "dev": true 212 | }, 213 | "@webassemblyjs/helper-numbers": { 214 | "version": "1.11.1", 215 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", 216 | "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", 217 | "dev": true, 218 | "requires": { 219 | "@webassemblyjs/floating-point-hex-parser": "1.11.1", 220 | "@webassemblyjs/helper-api-error": "1.11.1", 221 | "@xtuc/long": "4.2.2" 222 | } 223 | }, 224 | "@webassemblyjs/helper-wasm-bytecode": { 225 | "version": "1.11.1", 226 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", 227 | "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", 228 | "dev": true 229 | }, 230 | "@webassemblyjs/helper-wasm-section": { 231 | "version": "1.11.1", 232 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", 233 | "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", 234 | "dev": true, 235 | "requires": { 236 | "@webassemblyjs/ast": "1.11.1", 237 | "@webassemblyjs/helper-buffer": "1.11.1", 238 | "@webassemblyjs/helper-wasm-bytecode": "1.11.1", 239 | "@webassemblyjs/wasm-gen": "1.11.1" 240 | } 241 | }, 242 | "@webassemblyjs/ieee754": { 243 | "version": "1.11.1", 244 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", 245 | "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", 246 | "dev": true, 247 | "requires": { 248 | "@xtuc/ieee754": "^1.2.0" 249 | } 250 | }, 251 | "@webassemblyjs/leb128": { 252 | "version": "1.11.1", 253 | "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", 254 | "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", 255 | "dev": true, 256 | "requires": { 257 | "@xtuc/long": "4.2.2" 258 | } 259 | }, 260 | "@webassemblyjs/utf8": { 261 | "version": "1.11.1", 262 | "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", 263 | "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", 264 | "dev": true 265 | }, 266 | "@webassemblyjs/wasm-edit": { 267 | "version": "1.11.1", 268 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", 269 | "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", 270 | "dev": true, 271 | "requires": { 272 | "@webassemblyjs/ast": "1.11.1", 273 | "@webassemblyjs/helper-buffer": "1.11.1", 274 | "@webassemblyjs/helper-wasm-bytecode": "1.11.1", 275 | "@webassemblyjs/helper-wasm-section": "1.11.1", 276 | "@webassemblyjs/wasm-gen": "1.11.1", 277 | "@webassemblyjs/wasm-opt": "1.11.1", 278 | "@webassemblyjs/wasm-parser": "1.11.1", 279 | "@webassemblyjs/wast-printer": "1.11.1" 280 | } 281 | }, 282 | "@webassemblyjs/wasm-gen": { 283 | "version": "1.11.1", 284 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", 285 | "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", 286 | "dev": true, 287 | "requires": { 288 | "@webassemblyjs/ast": "1.11.1", 289 | "@webassemblyjs/helper-wasm-bytecode": "1.11.1", 290 | "@webassemblyjs/ieee754": "1.11.1", 291 | "@webassemblyjs/leb128": "1.11.1", 292 | "@webassemblyjs/utf8": "1.11.1" 293 | } 294 | }, 295 | "@webassemblyjs/wasm-opt": { 296 | "version": "1.11.1", 297 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", 298 | "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", 299 | "dev": true, 300 | "requires": { 301 | "@webassemblyjs/ast": "1.11.1", 302 | "@webassemblyjs/helper-buffer": "1.11.1", 303 | "@webassemblyjs/wasm-gen": "1.11.1", 304 | "@webassemblyjs/wasm-parser": "1.11.1" 305 | } 306 | }, 307 | "@webassemblyjs/wasm-parser": { 308 | "version": "1.11.1", 309 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", 310 | "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", 311 | "dev": true, 312 | "requires": { 313 | "@webassemblyjs/ast": "1.11.1", 314 | "@webassemblyjs/helper-api-error": "1.11.1", 315 | "@webassemblyjs/helper-wasm-bytecode": "1.11.1", 316 | "@webassemblyjs/ieee754": "1.11.1", 317 | "@webassemblyjs/leb128": "1.11.1", 318 | "@webassemblyjs/utf8": "1.11.1" 319 | } 320 | }, 321 | "@webassemblyjs/wast-printer": { 322 | "version": "1.11.1", 323 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", 324 | "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", 325 | "dev": true, 326 | "requires": { 327 | "@webassemblyjs/ast": "1.11.1", 328 | "@xtuc/long": "4.2.2" 329 | } 330 | }, 331 | "@webpack-cli/configtest": { 332 | "version": "1.1.0", 333 | "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", 334 | "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", 335 | "dev": true 336 | }, 337 | "@webpack-cli/info": { 338 | "version": "1.4.0", 339 | "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", 340 | "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", 341 | "dev": true, 342 | "requires": { 343 | "envinfo": "^7.7.3" 344 | } 345 | }, 346 | "@webpack-cli/serve": { 347 | "version": "1.6.0", 348 | "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", 349 | "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", 350 | "dev": true 351 | }, 352 | "@xtuc/ieee754": { 353 | "version": "1.2.0", 354 | "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", 355 | "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", 356 | "dev": true 357 | }, 358 | "@xtuc/long": { 359 | "version": "4.2.2", 360 | "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", 361 | "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", 362 | "dev": true 363 | }, 364 | "acorn": { 365 | "version": "8.5.0", 366 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", 367 | "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", 368 | "dev": true 369 | }, 370 | "acorn-import-assertions": { 371 | "version": "1.8.0", 372 | "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", 373 | "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", 374 | "dev": true 375 | }, 376 | "ajv": { 377 | "version": "6.12.6", 378 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 379 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 380 | "requires": { 381 | "fast-deep-equal": "^3.1.1", 382 | "fast-json-stable-stringify": "^2.0.0", 383 | "json-schema-traverse": "^0.4.1", 384 | "uri-js": "^4.2.2" 385 | } 386 | }, 387 | "ajv-keywords": { 388 | "version": "3.5.2", 389 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", 390 | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", 391 | "dev": true 392 | }, 393 | "ansi-regex": { 394 | "version": "2.1.1", 395 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 396 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 397 | "dev": true 398 | }, 399 | "ansi-styles": { 400 | "version": "4.3.0", 401 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 402 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 403 | "dev": true, 404 | "requires": { 405 | "color-convert": "^2.0.1" 406 | } 407 | }, 408 | "any-base": { 409 | "version": "1.1.0", 410 | "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", 411 | "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" 412 | }, 413 | "asn1": { 414 | "version": "0.2.4", 415 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 416 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 417 | "requires": { 418 | "safer-buffer": "~2.1.0" 419 | } 420 | }, 421 | "assert-plus": { 422 | "version": "1.0.0", 423 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 424 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 425 | }, 426 | "asynckit": { 427 | "version": "0.4.0", 428 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 429 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 430 | }, 431 | "aws-sign2": { 432 | "version": "0.7.0", 433 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 434 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 435 | }, 436 | "aws4": { 437 | "version": "1.11.0", 438 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", 439 | "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" 440 | }, 441 | "base64-js": { 442 | "version": "1.3.1", 443 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 444 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 445 | }, 446 | "bcrypt-pbkdf": { 447 | "version": "1.0.2", 448 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 449 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 450 | "requires": { 451 | "tweetnacl": "^0.14.3" 452 | } 453 | }, 454 | "big.js": { 455 | "version": "5.2.2", 456 | "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", 457 | "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", 458 | "dev": true 459 | }, 460 | "bmp-js": { 461 | "version": "0.1.0", 462 | "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", 463 | "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" 464 | }, 465 | "boolbase": { 466 | "version": "1.0.0", 467 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 468 | "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", 469 | "dev": true 470 | }, 471 | "braces": { 472 | "version": "3.0.2", 473 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 474 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 475 | "dev": true, 476 | "requires": { 477 | "fill-range": "^7.0.1" 478 | } 479 | }, 480 | "browserslist": { 481 | "version": "4.17.3", 482 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.3.tgz", 483 | "integrity": "sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==", 484 | "dev": true, 485 | "requires": { 486 | "caniuse-lite": "^1.0.30001264", 487 | "electron-to-chromium": "^1.3.857", 488 | "escalade": "^3.1.1", 489 | "node-releases": "^1.1.77", 490 | "picocolors": "^0.2.1" 491 | } 492 | }, 493 | "buffer": { 494 | "version": "5.7.1", 495 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 496 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 497 | "requires": { 498 | "base64-js": "^1.3.1", 499 | "ieee754": "^1.1.13" 500 | } 501 | }, 502 | "buffer-equal": { 503 | "version": "0.0.1", 504 | "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", 505 | "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" 506 | }, 507 | "buffer-from": { 508 | "version": "1.1.1", 509 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 510 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 511 | "dev": true 512 | }, 513 | "camel-case": { 514 | "version": "4.1.2", 515 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", 516 | "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", 517 | "dev": true, 518 | "requires": { 519 | "pascal-case": "^3.1.2", 520 | "tslib": "^2.0.3" 521 | } 522 | }, 523 | "caniuse-lite": { 524 | "version": "1.0.30001265", 525 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz", 526 | "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==", 527 | "dev": true 528 | }, 529 | "caseless": { 530 | "version": "0.12.0", 531 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 532 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 533 | }, 534 | "chalk": { 535 | "version": "4.1.2", 536 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 537 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 538 | "dev": true, 539 | "requires": { 540 | "ansi-styles": "^4.1.0", 541 | "supports-color": "^7.1.0" 542 | } 543 | }, 544 | "chrome-trace-event": { 545 | "version": "1.0.3", 546 | "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", 547 | "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", 548 | "dev": true 549 | }, 550 | "clean-css": { 551 | "version": "4.2.3", 552 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", 553 | "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", 554 | "dev": true, 555 | "requires": { 556 | "source-map": "~0.6.0" 557 | } 558 | }, 559 | "clone-deep": { 560 | "version": "4.0.1", 561 | "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", 562 | "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", 563 | "dev": true, 564 | "requires": { 565 | "is-plain-object": "^2.0.4", 566 | "kind-of": "^6.0.2", 567 | "shallow-clone": "^3.0.0" 568 | } 569 | }, 570 | "color-convert": { 571 | "version": "2.0.1", 572 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 573 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 574 | "dev": true, 575 | "requires": { 576 | "color-name": "~1.1.4" 577 | } 578 | }, 579 | "color-name": { 580 | "version": "1.1.4", 581 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 582 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 583 | "dev": true 584 | }, 585 | "colorette": { 586 | "version": "2.0.16", 587 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", 588 | "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", 589 | "dev": true 590 | }, 591 | "colorthief": { 592 | "version": "2.3.2", 593 | "resolved": "https://registry.npmjs.org/colorthief/-/colorthief-2.3.2.tgz", 594 | "integrity": "sha512-1r4nPW553JviRcFRvN3fS2V9nUSQGjRIws8UfEeFLIxk8j1tvtaX+AAYTkH3A4B5Muiys8SA1WJxf+00xVTXyg==", 595 | "requires": { 596 | "get-pixels": "^3.3.2", 597 | "quantize": "github:lokesh/quantize" 598 | } 599 | }, 600 | "combined-stream": { 601 | "version": "1.0.8", 602 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 603 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 604 | "requires": { 605 | "delayed-stream": "~1.0.0" 606 | } 607 | }, 608 | "commander": { 609 | "version": "4.1.1", 610 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 611 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 612 | "dev": true 613 | }, 614 | "core-util-is": { 615 | "version": "1.0.2", 616 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 617 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 618 | }, 619 | "cross-spawn": { 620 | "version": "7.0.3", 621 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 622 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 623 | "dev": true, 624 | "requires": { 625 | "path-key": "^3.1.0", 626 | "shebang-command": "^2.0.0", 627 | "which": "^2.0.1" 628 | } 629 | }, 630 | "css-loader": { 631 | "version": "6.4.0", 632 | "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.4.0.tgz", 633 | "integrity": "sha512-Dlt6qfsxI/w1vU0r8qDd4BtMPxWqJeY5qQU7SmmZfvbpe6Xl18McO4GhyaMLns24Y2VNPiZwJPQ8JSbg4qvQLw==", 634 | "dev": true, 635 | "requires": { 636 | "icss-utils": "^5.1.0", 637 | "postcss": "^8.2.15", 638 | "postcss-modules-extract-imports": "^3.0.0", 639 | "postcss-modules-local-by-default": "^4.0.0", 640 | "postcss-modules-scope": "^3.0.0", 641 | "postcss-modules-values": "^4.0.0", 642 | "postcss-value-parser": "^4.1.0", 643 | "semver": "^7.3.5" 644 | } 645 | }, 646 | "css-select": { 647 | "version": "4.1.3", 648 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", 649 | "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", 650 | "dev": true, 651 | "requires": { 652 | "boolbase": "^1.0.0", 653 | "css-what": "^5.0.0", 654 | "domhandler": "^4.2.0", 655 | "domutils": "^2.6.0", 656 | "nth-check": "^2.0.0" 657 | } 658 | }, 659 | "css-what": { 660 | "version": "5.0.1", 661 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", 662 | "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", 663 | "dev": true 664 | }, 665 | "cssesc": { 666 | "version": "3.0.0", 667 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 668 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 669 | "dev": true 670 | }, 671 | "cwise-compiler": { 672 | "version": "1.1.3", 673 | "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", 674 | "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", 675 | "requires": { 676 | "uniq": "^1.0.0" 677 | } 678 | }, 679 | "dashdash": { 680 | "version": "1.14.1", 681 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 682 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 683 | "requires": { 684 | "assert-plus": "^1.0.0" 685 | } 686 | }, 687 | "data-uri-to-buffer": { 688 | "version": "0.0.3", 689 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", 690 | "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" 691 | }, 692 | "delayed-stream": { 693 | "version": "1.0.0", 694 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 695 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 696 | }, 697 | "dom-converter": { 698 | "version": "0.2.0", 699 | "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", 700 | "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", 701 | "dev": true, 702 | "requires": { 703 | "utila": "~0.4" 704 | } 705 | }, 706 | "dom-serializer": { 707 | "version": "1.3.2", 708 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", 709 | "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", 710 | "dev": true, 711 | "requires": { 712 | "domelementtype": "^2.0.1", 713 | "domhandler": "^4.2.0", 714 | "entities": "^2.0.0" 715 | } 716 | }, 717 | "dom-walk": { 718 | "version": "0.1.2", 719 | "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", 720 | "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" 721 | }, 722 | "domelementtype": { 723 | "version": "2.2.0", 724 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", 725 | "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", 726 | "dev": true 727 | }, 728 | "domhandler": { 729 | "version": "4.2.0", 730 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", 731 | "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", 732 | "dev": true, 733 | "requires": { 734 | "domelementtype": "^2.2.0" 735 | } 736 | }, 737 | "domutils": { 738 | "version": "2.7.0", 739 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", 740 | "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", 741 | "dev": true, 742 | "requires": { 743 | "dom-serializer": "^1.0.1", 744 | "domelementtype": "^2.2.0", 745 | "domhandler": "^4.2.0" 746 | } 747 | }, 748 | "dot-case": { 749 | "version": "3.0.4", 750 | "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", 751 | "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", 752 | "dev": true, 753 | "requires": { 754 | "no-case": "^3.0.4", 755 | "tslib": "^2.0.3" 756 | } 757 | }, 758 | "ecc-jsbn": { 759 | "version": "0.1.2", 760 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 761 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 762 | "requires": { 763 | "jsbn": "~0.1.0", 764 | "safer-buffer": "^2.1.0" 765 | } 766 | }, 767 | "electron-to-chromium": { 768 | "version": "1.3.867", 769 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.867.tgz", 770 | "integrity": "sha512-WbTXOv7hsLhjJyl7jBfDkioaY++iVVZomZ4dU6TMe/SzucV6mUAs2VZn/AehBwuZMiNEQDaPuTGn22YK5o+aDw==", 771 | "dev": true 772 | }, 773 | "enhanced-resolve": { 774 | "version": "5.8.0", 775 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.0.tgz", 776 | "integrity": "sha512-Sl3KRpJA8OpprrtaIswVki3cWPiPKxXuFxJXBp+zNb6s6VwNWwFRUdtmzd2ReUut8n+sCPx7QCtQ7w5wfJhSgQ==", 777 | "dev": true, 778 | "requires": { 779 | "graceful-fs": "^4.2.4", 780 | "tapable": "^2.2.0" 781 | }, 782 | "dependencies": { 783 | "graceful-fs": { 784 | "version": "4.2.6", 785 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", 786 | "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", 787 | "dev": true 788 | } 789 | } 790 | }, 791 | "entities": { 792 | "version": "2.2.0", 793 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", 794 | "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", 795 | "dev": true 796 | }, 797 | "envinfo": { 798 | "version": "7.8.1", 799 | "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", 800 | "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", 801 | "dev": true 802 | }, 803 | "es-module-lexer": { 804 | "version": "0.9.3", 805 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", 806 | "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", 807 | "dev": true 808 | }, 809 | "escalade": { 810 | "version": "3.1.1", 811 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 812 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 813 | "dev": true 814 | }, 815 | "escape-string-regexp": { 816 | "version": "1.0.5", 817 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 818 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 819 | "dev": true 820 | }, 821 | "eslint-scope": { 822 | "version": "5.1.1", 823 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 824 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 825 | "dev": true, 826 | "requires": { 827 | "esrecurse": "^4.3.0", 828 | "estraverse": "^4.1.1" 829 | } 830 | }, 831 | "esrecurse": { 832 | "version": "4.3.0", 833 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 834 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 835 | "dev": true, 836 | "requires": { 837 | "estraverse": "^5.2.0" 838 | }, 839 | "dependencies": { 840 | "estraverse": { 841 | "version": "5.2.0", 842 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 843 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 844 | "dev": true 845 | } 846 | } 847 | }, 848 | "estraverse": { 849 | "version": "4.3.0", 850 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 851 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 852 | "dev": true 853 | }, 854 | "events": { 855 | "version": "3.3.0", 856 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 857 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 858 | "dev": true 859 | }, 860 | "execa": { 861 | "version": "5.1.1", 862 | "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", 863 | "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", 864 | "dev": true, 865 | "requires": { 866 | "cross-spawn": "^7.0.3", 867 | "get-stream": "^6.0.0", 868 | "human-signals": "^2.1.0", 869 | "is-stream": "^2.0.0", 870 | "merge-stream": "^2.0.0", 871 | "npm-run-path": "^4.0.1", 872 | "onetime": "^5.1.2", 873 | "signal-exit": "^3.0.3", 874 | "strip-final-newline": "^2.0.0" 875 | } 876 | }, 877 | "exif-parser": { 878 | "version": "0.1.12", 879 | "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", 880 | "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" 881 | }, 882 | "extend": { 883 | "version": "3.0.2", 884 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 885 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 886 | }, 887 | "extsprintf": { 888 | "version": "1.3.0", 889 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 890 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 891 | }, 892 | "fast-deep-equal": { 893 | "version": "3.1.3", 894 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 895 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 896 | }, 897 | "fast-json-stable-stringify": { 898 | "version": "2.0.0", 899 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 900 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 901 | }, 902 | "fastest-levenshtein": { 903 | "version": "1.0.12", 904 | "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", 905 | "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", 906 | "dev": true 907 | }, 908 | "file-type": { 909 | "version": "9.0.0", 910 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", 911 | "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" 912 | }, 913 | "fill-range": { 914 | "version": "7.0.1", 915 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 916 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 917 | "dev": true, 918 | "requires": { 919 | "to-regex-range": "^5.0.1" 920 | } 921 | }, 922 | "find-up": { 923 | "version": "4.1.0", 924 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 925 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 926 | "dev": true, 927 | "requires": { 928 | "locate-path": "^5.0.0", 929 | "path-exists": "^4.0.0" 930 | } 931 | }, 932 | "forever-agent": { 933 | "version": "0.6.1", 934 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 935 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 936 | }, 937 | "form-data": { 938 | "version": "2.3.3", 939 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 940 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 941 | "requires": { 942 | "asynckit": "^0.4.0", 943 | "combined-stream": "^1.0.6", 944 | "mime-types": "^2.1.12" 945 | } 946 | }, 947 | "function-bind": { 948 | "version": "1.1.1", 949 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 950 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 951 | "dev": true 952 | }, 953 | "get-pixels": { 954 | "version": "3.3.2", 955 | "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.2.tgz", 956 | "integrity": "sha512-6ar+8yPxRd1pskEcl2GSEu1La0+xYRjjnkby6AYiRDDwZ0tJbPQmHnSeH9fGLskT8kvR0OukVgtZLcsENF9YKQ==", 957 | "requires": { 958 | "data-uri-to-buffer": "0.0.3", 959 | "jpeg-js": "^0.3.2", 960 | "mime-types": "^2.0.1", 961 | "ndarray": "^1.0.13", 962 | "ndarray-pack": "^1.1.1", 963 | "node-bitmap": "0.0.1", 964 | "omggif": "^1.0.5", 965 | "parse-data-uri": "^0.2.0", 966 | "pngjs": "^3.3.3", 967 | "request": "^2.44.0", 968 | "through": "^2.3.4" 969 | } 970 | }, 971 | "get-stream": { 972 | "version": "6.0.1", 973 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", 974 | "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", 975 | "dev": true 976 | }, 977 | "getpass": { 978 | "version": "0.1.7", 979 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 980 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 981 | "requires": { 982 | "assert-plus": "^1.0.0" 983 | } 984 | }, 985 | "gifwrap": { 986 | "version": "0.9.2", 987 | "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", 988 | "integrity": "sha512-fcIswrPaiCDAyO8xnWvHSZdWChjKXUanKKpAiWWJ/UTkEi/aYKn5+90e7DE820zbEaVR9CE2y4z9bzhQijZ0BA==", 989 | "requires": { 990 | "image-q": "^1.1.1", 991 | "omggif": "^1.0.10" 992 | } 993 | }, 994 | "glob-to-regexp": { 995 | "version": "0.4.1", 996 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 997 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 998 | "dev": true 999 | }, 1000 | "global": { 1001 | "version": "4.3.2", 1002 | "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", 1003 | "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", 1004 | "requires": { 1005 | "min-document": "^2.19.0", 1006 | "process": "~0.5.1" 1007 | } 1008 | }, 1009 | "graceful-fs": { 1010 | "version": "4.2.8", 1011 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", 1012 | "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", 1013 | "dev": true 1014 | }, 1015 | "har-schema": { 1016 | "version": "2.0.0", 1017 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 1018 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 1019 | }, 1020 | "har-validator": { 1021 | "version": "5.1.5", 1022 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 1023 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 1024 | "requires": { 1025 | "ajv": "^6.12.3", 1026 | "har-schema": "^2.0.0" 1027 | } 1028 | }, 1029 | "has": { 1030 | "version": "1.0.3", 1031 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1032 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1033 | "dev": true, 1034 | "requires": { 1035 | "function-bind": "^1.1.1" 1036 | } 1037 | }, 1038 | "has-flag": { 1039 | "version": "4.0.0", 1040 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1041 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1042 | "dev": true 1043 | }, 1044 | "he": { 1045 | "version": "1.2.0", 1046 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 1047 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 1048 | "dev": true 1049 | }, 1050 | "html-minifier-terser": { 1051 | "version": "5.1.1", 1052 | "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", 1053 | "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", 1054 | "dev": true, 1055 | "requires": { 1056 | "camel-case": "^4.1.1", 1057 | "clean-css": "^4.2.3", 1058 | "commander": "^4.1.1", 1059 | "he": "^1.2.0", 1060 | "param-case": "^3.0.3", 1061 | "relateurl": "^0.2.7", 1062 | "terser": "^4.6.3" 1063 | } 1064 | }, 1065 | "html-webpack-inline-source-plugin": { 1066 | "version": "0.0.10", 1067 | "resolved": "https://registry.npmjs.org/html-webpack-inline-source-plugin/-/html-webpack-inline-source-plugin-0.0.10.tgz", 1068 | "integrity": "sha512-0ZNU57u7283vrXSF5a4VDnVOMWiSwypKIp1z/XfXWoVHLA1r3Xmyxx5+Lz+mnthz/UvxL1OAf41w5UIF68Jngw==", 1069 | "dev": true, 1070 | "requires": { 1071 | "escape-string-regexp": "^1.0.5", 1072 | "slash": "^1.0.0", 1073 | "source-map-url": "^0.4.0" 1074 | } 1075 | }, 1076 | "html-webpack-plugin": { 1077 | "version": "5.3.2", 1078 | "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.3.2.tgz", 1079 | "integrity": "sha512-HvB33boVNCz2lTyBsSiMffsJ+m0YLIQ+pskblXgN9fnjS1BgEcuAfdInfXfGrkdXV406k9FiDi86eVCDBgJOyQ==", 1080 | "dev": true, 1081 | "requires": { 1082 | "@types/html-minifier-terser": "^5.0.0", 1083 | "html-minifier-terser": "^5.0.1", 1084 | "lodash": "^4.17.21", 1085 | "pretty-error": "^3.0.4", 1086 | "tapable": "^2.0.0" 1087 | } 1088 | }, 1089 | "htmlparser2": { 1090 | "version": "6.1.0", 1091 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", 1092 | "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", 1093 | "dev": true, 1094 | "requires": { 1095 | "domelementtype": "^2.0.1", 1096 | "domhandler": "^4.0.0", 1097 | "domutils": "^2.5.2", 1098 | "entities": "^2.0.0" 1099 | } 1100 | }, 1101 | "http-signature": { 1102 | "version": "1.2.0", 1103 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 1104 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 1105 | "requires": { 1106 | "assert-plus": "^1.0.0", 1107 | "jsprim": "^1.2.2", 1108 | "sshpk": "^1.7.0" 1109 | } 1110 | }, 1111 | "human-signals": { 1112 | "version": "2.1.0", 1113 | "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", 1114 | "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", 1115 | "dev": true 1116 | }, 1117 | "icss-utils": { 1118 | "version": "5.1.0", 1119 | "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", 1120 | "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", 1121 | "dev": true 1122 | }, 1123 | "ieee754": { 1124 | "version": "1.1.13", 1125 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 1126 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 1127 | }, 1128 | "image-q": { 1129 | "version": "1.1.1", 1130 | "resolved": "https://registry.npmjs.org/image-q/-/image-q-1.1.1.tgz", 1131 | "integrity": "sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=" 1132 | }, 1133 | "import-local": { 1134 | "version": "3.0.3", 1135 | "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", 1136 | "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", 1137 | "dev": true, 1138 | "requires": { 1139 | "pkg-dir": "^4.2.0", 1140 | "resolve-cwd": "^3.0.0" 1141 | } 1142 | }, 1143 | "interpret": { 1144 | "version": "2.2.0", 1145 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", 1146 | "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", 1147 | "dev": true 1148 | }, 1149 | "iota-array": { 1150 | "version": "1.0.0", 1151 | "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", 1152 | "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" 1153 | }, 1154 | "is-buffer": { 1155 | "version": "1.1.6", 1156 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1157 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 1158 | }, 1159 | "is-core-module": { 1160 | "version": "2.7.0", 1161 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", 1162 | "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", 1163 | "dev": true, 1164 | "requires": { 1165 | "has": "^1.0.3" 1166 | } 1167 | }, 1168 | "is-function": { 1169 | "version": "1.0.2", 1170 | "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", 1171 | "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" 1172 | }, 1173 | "is-number": { 1174 | "version": "7.0.0", 1175 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1176 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1177 | "dev": true 1178 | }, 1179 | "is-plain-object": { 1180 | "version": "2.0.4", 1181 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1182 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1183 | "dev": true, 1184 | "requires": { 1185 | "isobject": "^3.0.1" 1186 | } 1187 | }, 1188 | "is-stream": { 1189 | "version": "2.0.1", 1190 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 1191 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 1192 | "dev": true 1193 | }, 1194 | "is-typedarray": { 1195 | "version": "1.0.0", 1196 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1197 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 1198 | }, 1199 | "isexe": { 1200 | "version": "2.0.0", 1201 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1202 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1203 | "dev": true 1204 | }, 1205 | "isobject": { 1206 | "version": "3.0.1", 1207 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1208 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", 1209 | "dev": true 1210 | }, 1211 | "isstream": { 1212 | "version": "0.1.2", 1213 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 1214 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 1215 | }, 1216 | "jest-worker": { 1217 | "version": "27.2.5", 1218 | "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", 1219 | "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", 1220 | "dev": true, 1221 | "requires": { 1222 | "@types/node": "*", 1223 | "merge-stream": "^2.0.0", 1224 | "supports-color": "^8.0.0" 1225 | }, 1226 | "dependencies": { 1227 | "supports-color": { 1228 | "version": "8.1.1", 1229 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1230 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1231 | "dev": true, 1232 | "requires": { 1233 | "has-flag": "^4.0.0" 1234 | } 1235 | } 1236 | } 1237 | }, 1238 | "jpeg-js": { 1239 | "version": "0.3.7", 1240 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", 1241 | "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" 1242 | }, 1243 | "jsbn": { 1244 | "version": "0.1.1", 1245 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1246 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 1247 | }, 1248 | "json-parse-better-errors": { 1249 | "version": "1.0.2", 1250 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 1251 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", 1252 | "dev": true 1253 | }, 1254 | "json-schema": { 1255 | "version": "0.2.3", 1256 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 1257 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 1258 | }, 1259 | "json-schema-traverse": { 1260 | "version": "0.4.1", 1261 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1262 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 1263 | }, 1264 | "json-stringify-safe": { 1265 | "version": "5.0.1", 1266 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1267 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 1268 | }, 1269 | "jsprim": { 1270 | "version": "1.4.1", 1271 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 1272 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 1273 | "requires": { 1274 | "assert-plus": "1.0.0", 1275 | "extsprintf": "1.3.0", 1276 | "json-schema": "0.2.3", 1277 | "verror": "1.10.0" 1278 | } 1279 | }, 1280 | "kind-of": { 1281 | "version": "6.0.3", 1282 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", 1283 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", 1284 | "dev": true 1285 | }, 1286 | "load-bmfont": { 1287 | "version": "1.4.1", 1288 | "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", 1289 | "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", 1290 | "requires": { 1291 | "buffer-equal": "0.0.1", 1292 | "mime": "^1.3.4", 1293 | "parse-bmfont-ascii": "^1.0.3", 1294 | "parse-bmfont-binary": "^1.0.5", 1295 | "parse-bmfont-xml": "^1.1.4", 1296 | "phin": "^2.9.1", 1297 | "xhr": "^2.0.1", 1298 | "xtend": "^4.0.0" 1299 | } 1300 | }, 1301 | "loader-runner": { 1302 | "version": "4.2.0", 1303 | "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", 1304 | "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", 1305 | "dev": true 1306 | }, 1307 | "locate-path": { 1308 | "version": "5.0.0", 1309 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1310 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1311 | "dev": true, 1312 | "requires": { 1313 | "p-locate": "^4.1.0" 1314 | } 1315 | }, 1316 | "lodash": { 1317 | "version": "4.17.21", 1318 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1319 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 1320 | }, 1321 | "lower-case": { 1322 | "version": "2.0.2", 1323 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", 1324 | "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", 1325 | "dev": true, 1326 | "requires": { 1327 | "tslib": "^2.0.3" 1328 | } 1329 | }, 1330 | "lru-cache": { 1331 | "version": "6.0.0", 1332 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1333 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1334 | "dev": true, 1335 | "requires": { 1336 | "yallist": "^4.0.0" 1337 | } 1338 | }, 1339 | "merge-stream": { 1340 | "version": "2.0.0", 1341 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 1342 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", 1343 | "dev": true 1344 | }, 1345 | "micromatch": { 1346 | "version": "4.0.4", 1347 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 1348 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 1349 | "dev": true, 1350 | "requires": { 1351 | "braces": "^3.0.1", 1352 | "picomatch": "^2.2.3" 1353 | } 1354 | }, 1355 | "mime": { 1356 | "version": "1.6.0", 1357 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1358 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1359 | }, 1360 | "mime-db": { 1361 | "version": "1.44.0", 1362 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 1363 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 1364 | }, 1365 | "mime-types": { 1366 | "version": "2.1.27", 1367 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 1368 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 1369 | "requires": { 1370 | "mime-db": "1.44.0" 1371 | } 1372 | }, 1373 | "mimic-fn": { 1374 | "version": "2.1.0", 1375 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 1376 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 1377 | "dev": true 1378 | }, 1379 | "min-document": { 1380 | "version": "2.19.0", 1381 | "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", 1382 | "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", 1383 | "requires": { 1384 | "dom-walk": "^0.1.0" 1385 | } 1386 | }, 1387 | "minimist": { 1388 | "version": "0.0.8", 1389 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1390 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1391 | }, 1392 | "mkdirp": { 1393 | "version": "0.5.1", 1394 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1395 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1396 | "requires": { 1397 | "minimist": "0.0.8" 1398 | } 1399 | }, 1400 | "nanoid": { 1401 | "version": "3.1.29", 1402 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz", 1403 | "integrity": "sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==", 1404 | "dev": true 1405 | }, 1406 | "ndarray": { 1407 | "version": "1.0.19", 1408 | "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz", 1409 | "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==", 1410 | "requires": { 1411 | "iota-array": "^1.0.0", 1412 | "is-buffer": "^1.0.2" 1413 | } 1414 | }, 1415 | "ndarray-pack": { 1416 | "version": "1.2.1", 1417 | "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", 1418 | "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", 1419 | "requires": { 1420 | "cwise-compiler": "^1.1.2", 1421 | "ndarray": "^1.0.13" 1422 | } 1423 | }, 1424 | "neo-async": { 1425 | "version": "2.6.2", 1426 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 1427 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 1428 | "dev": true 1429 | }, 1430 | "no-case": { 1431 | "version": "3.0.4", 1432 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", 1433 | "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", 1434 | "dev": true, 1435 | "requires": { 1436 | "lower-case": "^2.0.2", 1437 | "tslib": "^2.0.3" 1438 | } 1439 | }, 1440 | "node-bitmap": { 1441 | "version": "0.0.1", 1442 | "resolved": "https://registry.npmjs.org/node-bitmap/-/node-bitmap-0.0.1.tgz", 1443 | "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=" 1444 | }, 1445 | "node-releases": { 1446 | "version": "1.1.77", 1447 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", 1448 | "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", 1449 | "dev": true 1450 | }, 1451 | "node-vibrant": { 1452 | "version": "3.1.6", 1453 | "resolved": "https://registry.npmjs.org/node-vibrant/-/node-vibrant-3.1.6.tgz", 1454 | "integrity": "sha512-Wlc/hQmBMOu6xon12ZJHS2N3M+I6J8DhrD3Yo6m5175v8sFkVIN+UjhKVRcO+fqvre89ASTpmiFEP3nPO13SwA==", 1455 | "requires": { 1456 | "@jimp/custom": "^0.16.1", 1457 | "@jimp/plugin-resize": "^0.16.1", 1458 | "@jimp/types": "^0.16.1", 1459 | "@types/lodash": "^4.14.53", 1460 | "@types/node": "^10.11.7", 1461 | "lodash": "^4.17.20", 1462 | "url": "^0.11.0" 1463 | } 1464 | }, 1465 | "npm-run-path": { 1466 | "version": "4.0.1", 1467 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", 1468 | "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", 1469 | "dev": true, 1470 | "requires": { 1471 | "path-key": "^3.0.0" 1472 | } 1473 | }, 1474 | "nth-check": { 1475 | "version": "2.0.1", 1476 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", 1477 | "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", 1478 | "dev": true, 1479 | "requires": { 1480 | "boolbase": "^1.0.0" 1481 | } 1482 | }, 1483 | "oauth-sign": { 1484 | "version": "0.9.0", 1485 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1486 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 1487 | }, 1488 | "omggif": { 1489 | "version": "1.0.10", 1490 | "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", 1491 | "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" 1492 | }, 1493 | "onetime": { 1494 | "version": "5.1.2", 1495 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 1496 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 1497 | "dev": true, 1498 | "requires": { 1499 | "mimic-fn": "^2.1.0" 1500 | } 1501 | }, 1502 | "p-limit": { 1503 | "version": "2.3.0", 1504 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1505 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1506 | "dev": true, 1507 | "requires": { 1508 | "p-try": "^2.0.0" 1509 | } 1510 | }, 1511 | "p-locate": { 1512 | "version": "4.1.0", 1513 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1514 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1515 | "dev": true, 1516 | "requires": { 1517 | "p-limit": "^2.2.0" 1518 | } 1519 | }, 1520 | "p-try": { 1521 | "version": "2.2.0", 1522 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1523 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1524 | "dev": true 1525 | }, 1526 | "pako": { 1527 | "version": "1.0.10", 1528 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", 1529 | "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" 1530 | }, 1531 | "param-case": { 1532 | "version": "3.0.4", 1533 | "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", 1534 | "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", 1535 | "dev": true, 1536 | "requires": { 1537 | "dot-case": "^3.0.4", 1538 | "tslib": "^2.0.3" 1539 | } 1540 | }, 1541 | "parse-bmfont-ascii": { 1542 | "version": "1.0.6", 1543 | "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", 1544 | "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" 1545 | }, 1546 | "parse-bmfont-binary": { 1547 | "version": "1.0.6", 1548 | "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", 1549 | "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" 1550 | }, 1551 | "parse-bmfont-xml": { 1552 | "version": "1.1.4", 1553 | "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", 1554 | "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", 1555 | "requires": { 1556 | "xml-parse-from-string": "^1.0.0", 1557 | "xml2js": "^0.4.5" 1558 | } 1559 | }, 1560 | "parse-data-uri": { 1561 | "version": "0.2.0", 1562 | "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", 1563 | "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", 1564 | "requires": { 1565 | "data-uri-to-buffer": "0.0.3" 1566 | } 1567 | }, 1568 | "parse-headers": { 1569 | "version": "2.0.3", 1570 | "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", 1571 | "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" 1572 | }, 1573 | "pascal-case": { 1574 | "version": "3.1.2", 1575 | "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", 1576 | "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", 1577 | "dev": true, 1578 | "requires": { 1579 | "no-case": "^3.0.4", 1580 | "tslib": "^2.0.3" 1581 | } 1582 | }, 1583 | "path-exists": { 1584 | "version": "4.0.0", 1585 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1586 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1587 | "dev": true 1588 | }, 1589 | "path-key": { 1590 | "version": "3.1.1", 1591 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1592 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1593 | "dev": true 1594 | }, 1595 | "path-parse": { 1596 | "version": "1.0.7", 1597 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1598 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1599 | "dev": true 1600 | }, 1601 | "performance-now": { 1602 | "version": "2.1.0", 1603 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1604 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1605 | }, 1606 | "phin": { 1607 | "version": "2.9.3", 1608 | "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", 1609 | "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" 1610 | }, 1611 | "picocolors": { 1612 | "version": "0.2.1", 1613 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", 1614 | "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", 1615 | "dev": true 1616 | }, 1617 | "picomatch": { 1618 | "version": "2.3.0", 1619 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1620 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1621 | "dev": true 1622 | }, 1623 | "pixelmatch": { 1624 | "version": "4.0.2", 1625 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", 1626 | "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", 1627 | "requires": { 1628 | "pngjs": "^3.0.0" 1629 | } 1630 | }, 1631 | "pkg-dir": { 1632 | "version": "4.2.0", 1633 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 1634 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 1635 | "dev": true, 1636 | "requires": { 1637 | "find-up": "^4.0.0" 1638 | } 1639 | }, 1640 | "pngjs": { 1641 | "version": "3.4.0", 1642 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", 1643 | "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" 1644 | }, 1645 | "postcss": { 1646 | "version": "8.3.9", 1647 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.9.tgz", 1648 | "integrity": "sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw==", 1649 | "dev": true, 1650 | "requires": { 1651 | "nanoid": "^3.1.28", 1652 | "picocolors": "^0.2.1", 1653 | "source-map-js": "^0.6.2" 1654 | } 1655 | }, 1656 | "postcss-modules-extract-imports": { 1657 | "version": "3.0.0", 1658 | "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", 1659 | "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", 1660 | "dev": true 1661 | }, 1662 | "postcss-modules-local-by-default": { 1663 | "version": "4.0.0", 1664 | "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", 1665 | "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", 1666 | "dev": true, 1667 | "requires": { 1668 | "icss-utils": "^5.0.0", 1669 | "postcss-selector-parser": "^6.0.2", 1670 | "postcss-value-parser": "^4.1.0" 1671 | } 1672 | }, 1673 | "postcss-modules-scope": { 1674 | "version": "3.0.0", 1675 | "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", 1676 | "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", 1677 | "dev": true, 1678 | "requires": { 1679 | "postcss-selector-parser": "^6.0.4" 1680 | } 1681 | }, 1682 | "postcss-modules-values": { 1683 | "version": "4.0.0", 1684 | "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", 1685 | "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", 1686 | "dev": true, 1687 | "requires": { 1688 | "icss-utils": "^5.0.0" 1689 | } 1690 | }, 1691 | "postcss-selector-parser": { 1692 | "version": "6.0.6", 1693 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", 1694 | "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", 1695 | "dev": true, 1696 | "requires": { 1697 | "cssesc": "^3.0.0", 1698 | "util-deprecate": "^1.0.2" 1699 | } 1700 | }, 1701 | "postcss-value-parser": { 1702 | "version": "4.1.0", 1703 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", 1704 | "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", 1705 | "dev": true 1706 | }, 1707 | "pretty-error": { 1708 | "version": "3.0.4", 1709 | "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.4.tgz", 1710 | "integrity": "sha512-ytLFLfv1So4AO1UkoBF6GXQgJRaKbiSiGFICaOPNwQ3CMvBvXpLRubeQWyPGnsbV/t9ml9qto6IeCsho0aEvwQ==", 1711 | "dev": true, 1712 | "requires": { 1713 | "lodash": "^4.17.20", 1714 | "renderkid": "^2.0.6" 1715 | } 1716 | }, 1717 | "process": { 1718 | "version": "0.5.2", 1719 | "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", 1720 | "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" 1721 | }, 1722 | "psl": { 1723 | "version": "1.8.0", 1724 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 1725 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 1726 | }, 1727 | "punycode": { 1728 | "version": "2.1.1", 1729 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1730 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 1731 | }, 1732 | "qs": { 1733 | "version": "6.5.2", 1734 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1735 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 1736 | }, 1737 | "quantize": { 1738 | "version": "github:lokesh/quantize#f572abd2646b5944852535c8a26fdb958a5d7c4b", 1739 | "from": "github:lokesh/quantize" 1740 | }, 1741 | "querystring": { 1742 | "version": "0.2.0", 1743 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1744 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1745 | }, 1746 | "randombytes": { 1747 | "version": "2.1.0", 1748 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1749 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1750 | "dev": true, 1751 | "requires": { 1752 | "safe-buffer": "^5.1.0" 1753 | } 1754 | }, 1755 | "rechoir": { 1756 | "version": "0.7.1", 1757 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", 1758 | "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", 1759 | "dev": true, 1760 | "requires": { 1761 | "resolve": "^1.9.0" 1762 | } 1763 | }, 1764 | "regenerator-runtime": { 1765 | "version": "0.13.7", 1766 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", 1767 | "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" 1768 | }, 1769 | "relateurl": { 1770 | "version": "0.2.7", 1771 | "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", 1772 | "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", 1773 | "dev": true 1774 | }, 1775 | "renderkid": { 1776 | "version": "2.0.7", 1777 | "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", 1778 | "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", 1779 | "dev": true, 1780 | "requires": { 1781 | "css-select": "^4.1.3", 1782 | "dom-converter": "^0.2.0", 1783 | "htmlparser2": "^6.1.0", 1784 | "lodash": "^4.17.21", 1785 | "strip-ansi": "^3.0.1" 1786 | } 1787 | }, 1788 | "request": { 1789 | "version": "2.88.2", 1790 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1791 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1792 | "requires": { 1793 | "aws-sign2": "~0.7.0", 1794 | "aws4": "^1.8.0", 1795 | "caseless": "~0.12.0", 1796 | "combined-stream": "~1.0.6", 1797 | "extend": "~3.0.2", 1798 | "forever-agent": "~0.6.1", 1799 | "form-data": "~2.3.2", 1800 | "har-validator": "~5.1.3", 1801 | "http-signature": "~1.2.0", 1802 | "is-typedarray": "~1.0.0", 1803 | "isstream": "~0.1.2", 1804 | "json-stringify-safe": "~5.0.1", 1805 | "mime-types": "~2.1.19", 1806 | "oauth-sign": "~0.9.0", 1807 | "performance-now": "^2.1.0", 1808 | "qs": "~6.5.2", 1809 | "safe-buffer": "^5.1.2", 1810 | "tough-cookie": "~2.5.0", 1811 | "tunnel-agent": "^0.6.0", 1812 | "uuid": "^3.3.2" 1813 | } 1814 | }, 1815 | "resolve": { 1816 | "version": "1.20.0", 1817 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 1818 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 1819 | "dev": true, 1820 | "requires": { 1821 | "is-core-module": "^2.2.0", 1822 | "path-parse": "^1.0.6" 1823 | } 1824 | }, 1825 | "resolve-cwd": { 1826 | "version": "3.0.0", 1827 | "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", 1828 | "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", 1829 | "dev": true, 1830 | "requires": { 1831 | "resolve-from": "^5.0.0" 1832 | } 1833 | }, 1834 | "resolve-from": { 1835 | "version": "5.0.0", 1836 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 1837 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 1838 | "dev": true 1839 | }, 1840 | "safe-buffer": { 1841 | "version": "5.2.0", 1842 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 1843 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 1844 | }, 1845 | "safer-buffer": { 1846 | "version": "2.1.2", 1847 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1848 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1849 | }, 1850 | "sax": { 1851 | "version": "1.2.4", 1852 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1853 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1854 | }, 1855 | "schema-utils": { 1856 | "version": "3.0.0", 1857 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", 1858 | "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", 1859 | "dev": true, 1860 | "requires": { 1861 | "@types/json-schema": "^7.0.6", 1862 | "ajv": "^6.12.5", 1863 | "ajv-keywords": "^3.5.2" 1864 | }, 1865 | "dependencies": { 1866 | "ajv": { 1867 | "version": "6.12.6", 1868 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 1869 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 1870 | "dev": true, 1871 | "requires": { 1872 | "fast-deep-equal": "^3.1.1", 1873 | "fast-json-stable-stringify": "^2.0.0", 1874 | "json-schema-traverse": "^0.4.1", 1875 | "uri-js": "^4.2.2" 1876 | } 1877 | }, 1878 | "ajv-keywords": { 1879 | "version": "3.5.2", 1880 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", 1881 | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", 1882 | "dev": true 1883 | }, 1884 | "fast-deep-equal": { 1885 | "version": "3.1.3", 1886 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1887 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1888 | "dev": true 1889 | } 1890 | } 1891 | }, 1892 | "semver": { 1893 | "version": "7.3.5", 1894 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1895 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1896 | "dev": true, 1897 | "requires": { 1898 | "lru-cache": "^6.0.0" 1899 | } 1900 | }, 1901 | "serialize-javascript": { 1902 | "version": "6.0.0", 1903 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 1904 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 1905 | "dev": true, 1906 | "requires": { 1907 | "randombytes": "^2.1.0" 1908 | } 1909 | }, 1910 | "shallow-clone": { 1911 | "version": "3.0.1", 1912 | "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", 1913 | "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", 1914 | "dev": true, 1915 | "requires": { 1916 | "kind-of": "^6.0.2" 1917 | } 1918 | }, 1919 | "shebang-command": { 1920 | "version": "2.0.0", 1921 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1922 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1923 | "dev": true, 1924 | "requires": { 1925 | "shebang-regex": "^3.0.0" 1926 | } 1927 | }, 1928 | "shebang-regex": { 1929 | "version": "3.0.0", 1930 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1931 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1932 | "dev": true 1933 | }, 1934 | "signal-exit": { 1935 | "version": "3.0.5", 1936 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", 1937 | "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", 1938 | "dev": true 1939 | }, 1940 | "slash": { 1941 | "version": "1.0.0", 1942 | "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", 1943 | "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", 1944 | "dev": true 1945 | }, 1946 | "source-map": { 1947 | "version": "0.6.1", 1948 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1949 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1950 | "dev": true 1951 | }, 1952 | "source-map-js": { 1953 | "version": "0.6.2", 1954 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", 1955 | "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", 1956 | "dev": true 1957 | }, 1958 | "source-map-support": { 1959 | "version": "0.5.19", 1960 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 1961 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 1962 | "dev": true, 1963 | "requires": { 1964 | "buffer-from": "^1.0.0", 1965 | "source-map": "^0.6.0" 1966 | } 1967 | }, 1968 | "source-map-url": { 1969 | "version": "0.4.0", 1970 | "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", 1971 | "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", 1972 | "dev": true 1973 | }, 1974 | "sshpk": { 1975 | "version": "1.16.1", 1976 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1977 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1978 | "requires": { 1979 | "asn1": "~0.2.3", 1980 | "assert-plus": "^1.0.0", 1981 | "bcrypt-pbkdf": "^1.0.0", 1982 | "dashdash": "^1.12.0", 1983 | "ecc-jsbn": "~0.1.1", 1984 | "getpass": "^0.1.1", 1985 | "jsbn": "~0.1.0", 1986 | "safer-buffer": "^2.0.2", 1987 | "tweetnacl": "~0.14.0" 1988 | } 1989 | }, 1990 | "strip-ansi": { 1991 | "version": "3.0.1", 1992 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1993 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1994 | "dev": true, 1995 | "requires": { 1996 | "ansi-regex": "^2.0.0" 1997 | } 1998 | }, 1999 | "strip-final-newline": { 2000 | "version": "2.0.0", 2001 | "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", 2002 | "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", 2003 | "dev": true 2004 | }, 2005 | "style-loader": { 2006 | "version": "3.3.0", 2007 | "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.0.tgz", 2008 | "integrity": "sha512-szANub7ksJtQioJYtpbWwh1hUl99uK15n5HDlikeCRil/zYMZgSxucHddyF/4A3qJMUiAjPhFowrrQuNMA7jwQ==", 2009 | "dev": true 2010 | }, 2011 | "supports-color": { 2012 | "version": "7.2.0", 2013 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2014 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2015 | "dev": true, 2016 | "requires": { 2017 | "has-flag": "^4.0.0" 2018 | } 2019 | }, 2020 | "tapable": { 2021 | "version": "2.2.0", 2022 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", 2023 | "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", 2024 | "dev": true 2025 | }, 2026 | "terser": { 2027 | "version": "4.8.0", 2028 | "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", 2029 | "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", 2030 | "dev": true, 2031 | "requires": { 2032 | "commander": "^2.20.0", 2033 | "source-map": "~0.6.1", 2034 | "source-map-support": "~0.5.12" 2035 | }, 2036 | "dependencies": { 2037 | "commander": { 2038 | "version": "2.20.3", 2039 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 2040 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 2041 | "dev": true 2042 | } 2043 | } 2044 | }, 2045 | "terser-webpack-plugin": { 2046 | "version": "5.2.4", 2047 | "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz", 2048 | "integrity": "sha512-E2CkNMN+1cho04YpdANyRrn8CyN4yMy+WdFKZIySFZrGXZxJwJP6PMNGGc/Mcr6qygQHUUqRxnAPmi0M9f00XA==", 2049 | "dev": true, 2050 | "requires": { 2051 | "jest-worker": "^27.0.6", 2052 | "p-limit": "^3.1.0", 2053 | "schema-utils": "^3.1.1", 2054 | "serialize-javascript": "^6.0.0", 2055 | "source-map": "^0.6.1", 2056 | "terser": "^5.7.2" 2057 | }, 2058 | "dependencies": { 2059 | "@types/json-schema": { 2060 | "version": "7.0.9", 2061 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", 2062 | "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", 2063 | "dev": true 2064 | }, 2065 | "commander": { 2066 | "version": "2.20.3", 2067 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 2068 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 2069 | "dev": true 2070 | }, 2071 | "p-limit": { 2072 | "version": "3.1.0", 2073 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 2074 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 2075 | "dev": true, 2076 | "requires": { 2077 | "yocto-queue": "^0.1.0" 2078 | } 2079 | }, 2080 | "schema-utils": { 2081 | "version": "3.1.1", 2082 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", 2083 | "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", 2084 | "dev": true, 2085 | "requires": { 2086 | "@types/json-schema": "^7.0.8", 2087 | "ajv": "^6.12.5", 2088 | "ajv-keywords": "^3.5.2" 2089 | } 2090 | }, 2091 | "source-map-support": { 2092 | "version": "0.5.20", 2093 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", 2094 | "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", 2095 | "dev": true, 2096 | "requires": { 2097 | "buffer-from": "^1.0.0", 2098 | "source-map": "^0.6.0" 2099 | } 2100 | }, 2101 | "terser": { 2102 | "version": "5.9.0", 2103 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", 2104 | "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", 2105 | "dev": true, 2106 | "requires": { 2107 | "commander": "^2.20.0", 2108 | "source-map": "~0.7.2", 2109 | "source-map-support": "~0.5.20" 2110 | }, 2111 | "dependencies": { 2112 | "source-map": { 2113 | "version": "0.7.3", 2114 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", 2115 | "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", 2116 | "dev": true 2117 | } 2118 | } 2119 | } 2120 | } 2121 | }, 2122 | "through": { 2123 | "version": "2.3.8", 2124 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2125 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 2126 | }, 2127 | "timm": { 2128 | "version": "1.7.1", 2129 | "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", 2130 | "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" 2131 | }, 2132 | "tinycolor2": { 2133 | "version": "1.4.2", 2134 | "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", 2135 | "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" 2136 | }, 2137 | "to-regex-range": { 2138 | "version": "5.0.1", 2139 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2140 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2141 | "dev": true, 2142 | "requires": { 2143 | "is-number": "^7.0.0" 2144 | } 2145 | }, 2146 | "tough-cookie": { 2147 | "version": "2.5.0", 2148 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 2149 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 2150 | "requires": { 2151 | "psl": "^1.1.28", 2152 | "punycode": "^2.1.1" 2153 | } 2154 | }, 2155 | "ts-loader": { 2156 | "version": "9.2.6", 2157 | "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.6.tgz", 2158 | "integrity": "sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw==", 2159 | "dev": true, 2160 | "requires": { 2161 | "chalk": "^4.1.0", 2162 | "enhanced-resolve": "^5.0.0", 2163 | "micromatch": "^4.0.0", 2164 | "semver": "^7.3.4" 2165 | } 2166 | }, 2167 | "tslib": { 2168 | "version": "2.3.0", 2169 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", 2170 | "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", 2171 | "dev": true 2172 | }, 2173 | "tunnel-agent": { 2174 | "version": "0.6.0", 2175 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 2176 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 2177 | "requires": { 2178 | "safe-buffer": "^5.0.1" 2179 | } 2180 | }, 2181 | "tweetnacl": { 2182 | "version": "0.14.5", 2183 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 2184 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 2185 | }, 2186 | "typescript": { 2187 | "version": "4.4.4", 2188 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", 2189 | "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", 2190 | "dev": true 2191 | }, 2192 | "uniq": { 2193 | "version": "1.0.1", 2194 | "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", 2195 | "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" 2196 | }, 2197 | "uri-js": { 2198 | "version": "4.2.2", 2199 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 2200 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 2201 | "requires": { 2202 | "punycode": "^2.1.0" 2203 | } 2204 | }, 2205 | "url": { 2206 | "version": "0.11.0", 2207 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 2208 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 2209 | "requires": { 2210 | "punycode": "1.3.2", 2211 | "querystring": "0.2.0" 2212 | }, 2213 | "dependencies": { 2214 | "punycode": { 2215 | "version": "1.3.2", 2216 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 2217 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 2218 | } 2219 | } 2220 | }, 2221 | "url-loader": { 2222 | "version": "4.1.1", 2223 | "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", 2224 | "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", 2225 | "dev": true, 2226 | "requires": { 2227 | "loader-utils": "^2.0.0", 2228 | "mime-types": "^2.1.27", 2229 | "schema-utils": "^3.0.0" 2230 | }, 2231 | "dependencies": { 2232 | "emojis-list": { 2233 | "version": "3.0.0", 2234 | "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", 2235 | "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", 2236 | "dev": true 2237 | }, 2238 | "json5": { 2239 | "version": "2.1.3", 2240 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", 2241 | "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", 2242 | "dev": true, 2243 | "requires": { 2244 | "minimist": "^1.2.5" 2245 | } 2246 | }, 2247 | "loader-utils": { 2248 | "version": "2.0.0", 2249 | "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", 2250 | "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", 2251 | "dev": true, 2252 | "requires": { 2253 | "big.js": "^5.2.2", 2254 | "emojis-list": "^3.0.0", 2255 | "json5": "^2.1.2" 2256 | } 2257 | }, 2258 | "mime-db": { 2259 | "version": "1.44.0", 2260 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 2261 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", 2262 | "dev": true 2263 | }, 2264 | "mime-types": { 2265 | "version": "2.1.27", 2266 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 2267 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 2268 | "dev": true, 2269 | "requires": { 2270 | "mime-db": "1.44.0" 2271 | } 2272 | }, 2273 | "minimist": { 2274 | "version": "1.2.5", 2275 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 2276 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 2277 | "dev": true 2278 | } 2279 | } 2280 | }, 2281 | "utif": { 2282 | "version": "2.0.1", 2283 | "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", 2284 | "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", 2285 | "requires": { 2286 | "pako": "^1.0.5" 2287 | } 2288 | }, 2289 | "util-deprecate": { 2290 | "version": "1.0.2", 2291 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2292 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 2293 | "dev": true 2294 | }, 2295 | "utila": { 2296 | "version": "0.4.0", 2297 | "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", 2298 | "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", 2299 | "dev": true 2300 | }, 2301 | "uuid": { 2302 | "version": "3.4.0", 2303 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 2304 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 2305 | }, 2306 | "v8-compile-cache": { 2307 | "version": "2.3.0", 2308 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2309 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2310 | "dev": true 2311 | }, 2312 | "verror": { 2313 | "version": "1.10.0", 2314 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 2315 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 2316 | "requires": { 2317 | "assert-plus": "^1.0.0", 2318 | "core-util-is": "1.0.2", 2319 | "extsprintf": "^1.2.0" 2320 | } 2321 | }, 2322 | "watchpack": { 2323 | "version": "2.2.0", 2324 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", 2325 | "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", 2326 | "dev": true, 2327 | "requires": { 2328 | "glob-to-regexp": "^0.4.1", 2329 | "graceful-fs": "^4.1.2" 2330 | } 2331 | }, 2332 | "webpack": { 2333 | "version": "5.58.2", 2334 | "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", 2335 | "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", 2336 | "dev": true, 2337 | "requires": { 2338 | "@types/eslint-scope": "^3.7.0", 2339 | "@types/estree": "^0.0.50", 2340 | "@webassemblyjs/ast": "1.11.1", 2341 | "@webassemblyjs/wasm-edit": "1.11.1", 2342 | "@webassemblyjs/wasm-parser": "1.11.1", 2343 | "acorn": "^8.4.1", 2344 | "acorn-import-assertions": "^1.7.6", 2345 | "browserslist": "^4.14.5", 2346 | "chrome-trace-event": "^1.0.2", 2347 | "enhanced-resolve": "^5.8.3", 2348 | "es-module-lexer": "^0.9.0", 2349 | "eslint-scope": "5.1.1", 2350 | "events": "^3.2.0", 2351 | "glob-to-regexp": "^0.4.1", 2352 | "graceful-fs": "^4.2.4", 2353 | "json-parse-better-errors": "^1.0.2", 2354 | "loader-runner": "^4.2.0", 2355 | "mime-types": "^2.1.27", 2356 | "neo-async": "^2.6.2", 2357 | "schema-utils": "^3.1.0", 2358 | "tapable": "^2.1.1", 2359 | "terser-webpack-plugin": "^5.1.3", 2360 | "watchpack": "^2.2.0", 2361 | "webpack-sources": "^3.2.0" 2362 | }, 2363 | "dependencies": { 2364 | "@types/json-schema": { 2365 | "version": "7.0.9", 2366 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", 2367 | "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", 2368 | "dev": true 2369 | }, 2370 | "enhanced-resolve": { 2371 | "version": "5.8.3", 2372 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", 2373 | "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", 2374 | "dev": true, 2375 | "requires": { 2376 | "graceful-fs": "^4.2.4", 2377 | "tapable": "^2.2.0" 2378 | } 2379 | }, 2380 | "schema-utils": { 2381 | "version": "3.1.1", 2382 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", 2383 | "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", 2384 | "dev": true, 2385 | "requires": { 2386 | "@types/json-schema": "^7.0.8", 2387 | "ajv": "^6.12.5", 2388 | "ajv-keywords": "^3.5.2" 2389 | } 2390 | } 2391 | } 2392 | }, 2393 | "webpack-cli": { 2394 | "version": "4.9.0", 2395 | "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz", 2396 | "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==", 2397 | "dev": true, 2398 | "requires": { 2399 | "@discoveryjs/json-ext": "^0.5.0", 2400 | "@webpack-cli/configtest": "^1.1.0", 2401 | "@webpack-cli/info": "^1.4.0", 2402 | "@webpack-cli/serve": "^1.6.0", 2403 | "colorette": "^2.0.14", 2404 | "commander": "^7.0.0", 2405 | "execa": "^5.0.0", 2406 | "fastest-levenshtein": "^1.0.12", 2407 | "import-local": "^3.0.2", 2408 | "interpret": "^2.2.0", 2409 | "rechoir": "^0.7.0", 2410 | "v8-compile-cache": "^2.2.0", 2411 | "webpack-merge": "^5.7.3" 2412 | }, 2413 | "dependencies": { 2414 | "commander": { 2415 | "version": "7.2.0", 2416 | "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 2417 | "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", 2418 | "dev": true 2419 | } 2420 | } 2421 | }, 2422 | "webpack-merge": { 2423 | "version": "5.8.0", 2424 | "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", 2425 | "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", 2426 | "dev": true, 2427 | "requires": { 2428 | "clone-deep": "^4.0.1", 2429 | "wildcard": "^2.0.0" 2430 | } 2431 | }, 2432 | "webpack-sources": { 2433 | "version": "3.2.1", 2434 | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.1.tgz", 2435 | "integrity": "sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA==", 2436 | "dev": true 2437 | }, 2438 | "which": { 2439 | "version": "2.0.2", 2440 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2441 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2442 | "dev": true, 2443 | "requires": { 2444 | "isexe": "^2.0.0" 2445 | } 2446 | }, 2447 | "wildcard": { 2448 | "version": "2.0.0", 2449 | "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", 2450 | "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", 2451 | "dev": true 2452 | }, 2453 | "xhr": { 2454 | "version": "2.5.0", 2455 | "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", 2456 | "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", 2457 | "requires": { 2458 | "global": "~4.3.0", 2459 | "is-function": "^1.0.1", 2460 | "parse-headers": "^2.0.0", 2461 | "xtend": "^4.0.0" 2462 | } 2463 | }, 2464 | "xml-parse-from-string": { 2465 | "version": "1.0.1", 2466 | "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", 2467 | "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" 2468 | }, 2469 | "xml2js": { 2470 | "version": "0.4.23", 2471 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 2472 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 2473 | "requires": { 2474 | "sax": ">=0.6.0", 2475 | "xmlbuilder": "~11.0.0" 2476 | } 2477 | }, 2478 | "xmlbuilder": { 2479 | "version": "11.0.1", 2480 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 2481 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 2482 | }, 2483 | "xtend": { 2484 | "version": "4.0.2", 2485 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2486 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 2487 | }, 2488 | "yallist": { 2489 | "version": "4.0.0", 2490 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2491 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2492 | "dev": true 2493 | }, 2494 | "yocto-queue": { 2495 | "version": "0.1.0", 2496 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2497 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2498 | "dev": true 2499 | } 2500 | } 2501 | } 2502 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "figma-dominant-color-toolkit", 3 | "version": "1.0.0", 4 | "description": "Generate a palette from an image to magically populate your designs.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "npx webpack --mode=development --watch", 9 | "build": "npx webpack --mode=production" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "css-loader": "^6.4.0", 16 | "html-webpack-inline-source-plugin": "^1.0.0-beta.2", 17 | "html-webpack-plugin": "^5.3.2", 18 | "style-loader": "^3.3.0", 19 | "ts-loader": "^9.2.6", 20 | "typescript": "^4.4.4", 21 | "url-loader": "^4.1.1", 22 | "webpack-cli": "^4.9.0", 23 | "webpack": "^5.58.2" 24 | }, 25 | "dependencies": { 26 | "colorthief": "^2.3.2", 27 | "node-vibrant": "^3.1.6" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/canvas.ts: -------------------------------------------------------------------------------- 1 | import { getFirstImagePaintFromNode, UIColorData } from "./utils"; 2 | 3 | export async function generateColorGuideFrame(node, data: UIColorData): Promise { 4 | const { dominantColor, palette, suggestedTextColors } = data 5 | 6 | const swatchSize = 44 7 | const labelTopMargin = 24 8 | const labelHeight = 12 9 | const labelBottomMargin = 8 + labelHeight 10 | const swatchGap = 12 11 | const maxWidth = 300 12 | const maxImagePreviewHeight = 300 13 | const leftMargin = 16 14 | const black = { r: 0, g: 0, b: 0 } 15 | const white = { r: 1, g: 1, b: 1 } 16 | const paletteCornerRadius = 6 17 | 18 | const imagePreviewInset = 16 19 | const imageBoundsHeight = node.height > maxImagePreviewHeight 20 | ? maxImagePreviewHeight 21 | : node.height + (imagePreviewInset * 2) > maxImagePreviewHeight 22 | ? maxImagePreviewHeight 23 | : node.height + (imagePreviewInset * 2) 24 | 25 | const contentStartY = imageBoundsHeight + labelTopMargin 26 | const totalHeight = imageBoundsHeight + ((labelTopMargin + labelBottomMargin + swatchSize) * 3) + leftMargin 27 | 28 | const sf = { family: 'SF Pro Text', style: 'Bold'} 29 | const roboto = { family: 'Roboto', style: 'Bold' } 30 | const fonts = await figma.listAvailableFontsAsync() 31 | const hasSf = fonts.find(({ fontName}) => fontName.family === sf.family && fontName.style === sf.style) 32 | hasSf ? await figma.loadFontAsync(sf) : await figma.loadFontAsync(roboto) 33 | 34 | const frame = figma.createFrame() 35 | frame.resize(maxWidth, totalHeight) 36 | frame.x = node.x + node.width + 100 37 | frame.y = node.y 38 | frame.backgrounds = [] 39 | frame.effects = [] 40 | frame.name = "Palette" 41 | frame.clipsContent = false 42 | const background = figma.createRectangle() 43 | frame.appendChild(background) 44 | background.x = 0 45 | background.y = 0 46 | background.resize(maxWidth, totalHeight) 47 | background.cornerRadius = paletteCornerRadius 48 | background.fills = [{ color: white, type: 'SOLID' }] 49 | background.effects = [{ type: 'DROP_SHADOW', visible: true, blendMode: "NORMAL", radius: 12, offset: { x: 0, y: 2 }, color: { ...black, a: 0.16 }}] 50 | 51 | const imageBackground = figma.createRectangle() 52 | imageBackground.y = 0 53 | imageBackground.topLeftRadius = paletteCornerRadius 54 | imageBackground.topRightRadius = paletteCornerRadius 55 | imageBackground.resize(maxWidth, imageBoundsHeight) 56 | imageBackground.fills = [{ type: 'SOLID', color: dominantColor, opacity: 0.08 }] 57 | imageBackground.effects = [{ type: 'INNER_SHADOW', visible: true, blendMode: "NORMAL", radius: 0, offset: { x: 0, y: -1 }, color: { ...black, a: 0.08 }}] 58 | 59 | const imageBounds = figma.createRectangle() 60 | imageBounds.name = "Source image" 61 | 62 | frame.appendChild(imageBackground) 63 | frame.appendChild(imageBounds) 64 | 65 | const paint = getFirstImagePaintFromNode(node) 66 | imageBounds.fills = [ paint] 67 | imageBounds.cornerRadius = node.cornerRadius 68 | imageBounds.resize(node.width >= maxWidth ? maxWidth : node.width, node.height <= maxImagePreviewHeight ? node.height : maxImagePreviewHeight) 69 | imageBounds.y = node.height >= maxImagePreviewHeight 70 | ? 0 71 | : node.height + imagePreviewInset >= maxImagePreviewHeight 72 | ? (maxImagePreviewHeight - node.height) / 2 73 | : imagePreviewInset 74 | imageBounds.x = node.width >= maxWidth 75 | ? 0 76 | : (maxWidth - node.width) / 2 77 | 78 | 79 | const label = figma.createText() 80 | label.name = "Label" 81 | label.fontName = hasSf ? sf : roboto 82 | label.fills = [{ type: 'SOLID', color: black }] 83 | label.fontSize = 10 84 | 85 | const dominantLabel = label 86 | dominantLabel.characters = "DOMINANT COLOR" 87 | dominantLabel.y = contentStartY 88 | dominantLabel.x = leftMargin 89 | 90 | const recommendedTextLabel = dominantLabel.clone() 91 | recommendedTextLabel.characters = "RECOMMENDED TEXT COLOR" 92 | recommendedTextLabel.y = dominantLabel.y + labelBottomMargin + swatchSize + labelTopMargin 93 | 94 | const paletteLabel = recommendedTextLabel.clone() 95 | paletteLabel.characters = "PALETTE" 96 | paletteLabel.y = recommendedTextLabel.y + labelBottomMargin + swatchSize + labelTopMargin 97 | 98 | frame.appendChild(dominantLabel) 99 | frame.appendChild(recommendedTextLabel) 100 | frame.appendChild(paletteLabel) 101 | 102 | const swatch = figma.createRectangle() 103 | swatch.name = "Swatch" 104 | swatch.cornerRadius = 2 105 | swatch.resize(swatchSize, swatchSize) 106 | swatch.x = leftMargin 107 | swatch.y = dominantLabel.y + labelBottomMargin 108 | const dominantSwatch = swatch 109 | dominantSwatch.fills = [{ type: 'SOLID', color: dominantColor }] 110 | frame.appendChild(dominantSwatch) 111 | 112 | for (let [index, color] of suggestedTextColors.entries()) { 113 | let paletteSwatch = dominantSwatch.clone() 114 | paletteSwatch.x = leftMargin + (index * (swatchSize + swatchGap)) 115 | paletteSwatch.y = recommendedTextLabel.y + labelBottomMargin 116 | paletteSwatch.fills = [{ type: 'SOLID', color }] 117 | // hacky way to determine if the swatch is white 118 | const { r, g, b } = color 119 | if (r === 1 && g === 1 && b === 1) { 120 | paletteSwatch.strokeAlign = "INSIDE" 121 | paletteSwatch.strokes = [{ type: 'SOLID', color: black, opacity: 0.08 }] 122 | } 123 | frame.appendChild(paletteSwatch) 124 | } 125 | 126 | 127 | for (let [index, color] of palette.entries()) { 128 | let paletteSwatch = dominantSwatch.clone() 129 | paletteSwatch.x = leftMargin + (index * (swatchSize + swatchGap)) 130 | paletteSwatch.y = paletteLabel.y + labelBottomMargin 131 | paletteSwatch.fills = [{ type: 'SOLID', color }] 132 | // hacky way to determine if the swatch is white 133 | const { r, g, b } = color 134 | if (r === 1 && g === 1 && b === 1) { 135 | paletteSwatch.strokeAlign = "INSIDE" 136 | paletteSwatch.strokes = [{ type: 'SOLID', color: black, opacity: 0.08 }] 137 | } 138 | frame.appendChild(paletteSwatch) 139 | } 140 | 141 | return Promise.resolve(frame) 142 | } -------------------------------------------------------------------------------- /src/colors.ts: -------------------------------------------------------------------------------- 1 | const black = { r: 0, b: 0, g: 0 } 2 | const white = { r: 1, b: 1, g: 1 } 3 | 4 | export interface RGB { 5 | r: number; 6 | g: number; 7 | b: number; 8 | } 9 | 10 | interface Tint { 11 | rgb: RGB, 12 | amount: number 13 | } 14 | 15 | function tintRGB(props: Tint): RGB { 16 | let { amount, rgb: { r, g, b }} = props 17 | 18 | const getColorTransformation = (number: number): number => (number * (100 + amount)) / 100 19 | 20 | r = getColorTransformation(r); 21 | g = getColorTransformation(g); 22 | b = getColorTransformation(b); 23 | 24 | // dont exceed black or white on the hex scale 25 | r = r < 1 ? r : 1; 26 | g = g < 1 ? g : 1; 27 | b = b < 1 ? b : 1; 28 | 29 | return { r, g, b} 30 | } 31 | 32 | export function getTextColorsFromRGB(props: RGB): RGB[] { 33 | const { r, g, b} = props 34 | 35 | let C, L; 36 | C = [r, g, b]; 37 | C = C.map(i => { 38 | if (i <= 0.03928) { 39 | return i / 12.92; 40 | } else { 41 | return Math.pow((i + 0.055) / 1.055, 2.4); 42 | } 43 | }); 44 | 45 | L = 0.2126 * C[0] + 0.7152 * C[1] + 0.0722 * C[2]; 46 | 47 | if (L > 0.179) { 48 | return [ tintRGB({ rgb: props, amount: -80 }) ]; 49 | } else { 50 | return [ white ]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/plugin.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isFrametypeNode, 3 | nodeIsSourceImage, 4 | getTextNodesFromShallowSelection, 5 | getShapeNodesFromShallowSelection, 6 | getTextNodesFromDeepSelection, 7 | getShapeNodesFromDeepSelection, 8 | hasValidSelection, 9 | selectedSingleImage, 10 | selectedFrameContainsImageAndFillables, 11 | selectedImageAndFillables, 12 | seletedFillablesWithoutImage, 13 | getSourceImageNodeFromNodes, 14 | getDataForUIFromNode, 15 | getSourceImageNodeFromParentsOfNodes, 16 | applyTransformationsToNodes, 17 | } from './utils' 18 | import { generateColorGuideFrame } from './canvas' 19 | 20 | figma.showUI(__html__, { visible: false }) 21 | function populateUI(data) { 22 | figma.ui.postMessage(data) 23 | } 24 | 25 | async function main(nodes) { 26 | if (!hasValidSelection(nodes)) return figma.closePlugin('Invalid selection') 27 | 28 | if (nodes.length > 1 && nodes.every(isFrametypeNode)) { 29 | console.info({ 1: nodes }) 30 | for (let frame of nodes) { 31 | await main([frame]) 32 | } 33 | 34 | return Promise.resolve() 35 | } 36 | 37 | if (nodes.length > 1 && nodes.every(nodeIsSourceImage)) { 38 | console.info({ 2: nodes }) 39 | for (let image of nodes) { 40 | await main([ image ]) 41 | } 42 | 43 | return Promise.resolve() 44 | } 45 | 46 | if (selectedSingleImage(nodes)) { 47 | console.info({ 3: nodes }) 48 | 49 | const node = nodes[0] 50 | const data = await getDataForUIFromNode(node) 51 | populateUI(data) 52 | 53 | return new Promise(res => { 54 | figma.ui.onmessage = async data => { 55 | await generateColorGuideFrame(node, data).then(node => { 56 | figma.currentPage.selection = [] 57 | res() 58 | }) 59 | } 60 | 61 | return Promise.resolve() 62 | }) 63 | } 64 | 65 | if (selectedFrameContainsImageAndFillables(nodes)) { 66 | console.info({ 4: nodes }) 67 | 68 | // open the modal with the selected image 69 | const node = getSourceImageNodeFromNodes(nodes) 70 | const data = await getDataForUIFromNode(node) 71 | populateUI(data) 72 | 73 | const selectedNode = nodes[0] 74 | const textNodes = getTextNodesFromDeepSelection(selectedNode) 75 | const shapeNodes = getShapeNodesFromDeepSelection(selectedNode) 76 | const transformable = [...textNodes, ...shapeNodes] 77 | 78 | return new Promise(res => { 79 | figma.ui.onmessage = async data => { 80 | await applyTransformationsToNodes(transformable, data).then(() => res()) 81 | } 82 | 83 | return Promise.resolve() 84 | }) 85 | } 86 | 87 | if (selectedImageAndFillables(nodes)) { 88 | console.info({ 5: nodes }) 89 | 90 | const node = getSourceImageNodeFromNodes(nodes) 91 | const data = await getDataForUIFromNode(node) 92 | populateUI(data) 93 | 94 | const textNodes = getTextNodesFromShallowSelection(nodes) 95 | const shapeNodes = getShapeNodesFromShallowSelection(nodes) 96 | const transformable = [...textNodes, ...shapeNodes] 97 | 98 | return new Promise(res => { 99 | figma.ui.onmessage = async data => { 100 | await applyTransformationsToNodes(transformable, data).then(() => res()) 101 | } 102 | }) 103 | } 104 | 105 | if (seletedFillablesWithoutImage(nodes)) { 106 | console.info({ 6: nodes }) 107 | 108 | const node = getSourceImageNodeFromParentsOfNodes(nodes) 109 | if (!node) return Promise.resolve('Couldn’t find an image to sample from, try a new selection!') 110 | const data = await getDataForUIFromNode(node) 111 | populateUI(data) 112 | 113 | return new Promise(res => { 114 | figma.ui.onmessage = async data => { 115 | await applyTransformationsToNodes(nodes, data).then(() => res()) 116 | } 117 | 118 | return Promise.resolve() 119 | }) 120 | } 121 | 122 | figma.closePlugin("Couldn't process your selection. Please try again") 123 | } 124 | 125 | const selection = figma.currentPage.selection 126 | main(selection).then((msg?: string) => figma.closePlugin(msg || 'Colors generated ✨')) -------------------------------------------------------------------------------- /src/ui.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianlovin/figma-dominant-color-toolkit/e00073cc5edc753be1c967909fc9eb97205b5ed8/src/ui.html -------------------------------------------------------------------------------- /src/ui.ts: -------------------------------------------------------------------------------- 1 | import Colorthief from '../node_modules/colorthief/dist/color-thief.umd.js' 2 | import { getTextColorsFromRGB } from './colors' 3 | 4 | interface ImageProps { 5 | img: HTMLElement; 6 | dominantColor: RGB; 7 | palette: RGB[][]; 8 | } 9 | 10 | function getImageColors(bytes): Promise { 11 | const img = document.createElement('img') 12 | const blob = new Blob( [ bytes ], { type: "image/jpeg" }); 13 | const urlCreator = window.URL 14 | const imageUrl = urlCreator.createObjectURL(blob) 15 | img.setAttribute('src', imageUrl) 16 | return new Promise(res => { 17 | img.onload = function() { 18 | const thief = new Colorthief() 19 | 20 | const rawDominantColor = thief.getColor(img, 1) 21 | const dominantColor = { r: rawDominantColor[0] / 255, g: rawDominantColor[1] / 255, b: rawDominantColor[2] / 255 } 22 | 23 | const rawPalette = thief.getPalette(img, 5, 1) 24 | const palette = rawPalette.map(arr => ({ r: arr[0] / 255, g: arr[1] / 255, b: arr[2] / 255 })) 25 | 26 | res({ img, dominantColor, palette }) 27 | } 28 | }) 29 | } 30 | 31 | window.onmessage = async (event) => { 32 | const { data } = event 33 | const { pluginMessage } = data 34 | const { imageBytes, width, height } = pluginMessage 35 | const { img, dominantColor, palette } = await getImageColors(imageBytes) 36 | img.setAttribute('width', width) 37 | img.setAttribute('height', height) 38 | const suggestedTextColors = getTextColorsFromRGB(dominantColor) 39 | window.parent.postMessage({ pluginMessage: { dominantColor, suggestedTextColors, palette } }, '*') 40 | } -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { RGB } from './colors' 2 | import { isArray } from 'util'; 3 | 4 | function isTextNode(node): boolean { 5 | return node.type === "TEXT" 6 | } 7 | 8 | const validShapeTypes = ["RECTANGLE", "ELLIPSE", "POLYGON", "STAR", "VECTOR"] 9 | function isShapeNode(node): boolean { 10 | return validShapeTypes.indexOf(node.type) >= 0 11 | } 12 | 13 | const validFrameTypes = ["COMPONENT", "INSTANCE", "FRAME"] 14 | export function isFrametypeNode(node): boolean { 15 | return validFrameTypes.indexOf(node.type) >= 0 16 | } 17 | 18 | // doesnt traverse into any children 19 | export function getTextNodesFromShallowSelection(nodes) { 20 | return nodes.filter(isTextNode) 21 | } 22 | 23 | // doesnt traverse into any children 24 | export function getShapeNodesFromShallowSelection(nodes) { 25 | return nodes.filter(isShapeNode) 26 | } 27 | 28 | // gets all nodes regardless of how deep the selection goes 29 | export function getTextNodesFromDeepSelection(node) { 30 | let filtered = [] 31 | 32 | if (isTextNode(node)) { 33 | filtered.push(node) 34 | } 35 | 36 | if (isFrametypeNode(node)) { 37 | if (node.children.length > 0) { 38 | filtered.push(...node.children.map(getTextNodesFromDeepSelection).filter(Boolean)) 39 | } 40 | } 41 | 42 | return [].concat.apply([], filtered) 43 | } 44 | 45 | // gets all nodes regardless of how deep the selection goes 46 | export function getShapeNodesFromDeepSelection(node) { 47 | let filtered = [] 48 | 49 | if (isShapeNode(node)) { 50 | if (!nodeIsSourceImage(node)) filtered.push(node) 51 | } 52 | 53 | if (isFrametypeNode(node)) { 54 | if (node.children.length > 0) { 55 | filtered.push(...node.children.map(getShapeNodesFromDeepSelection).filter(Boolean)) 56 | } 57 | } 58 | 59 | return [].concat.apply([], filtered) 60 | } 61 | 62 | function paintIsImage(paint): boolean { 63 | return paint.type === "IMAGE" 64 | } 65 | 66 | function nodeFillsContainsImagePaint(node): boolean { 67 | if (node.fills) { 68 | if (node.fills.length === 0) return false 69 | if (!Array.isArray(node.fills)) return false 70 | return node.fills.some(paintIsImage) 71 | } 72 | 73 | if (node.backgrounds) { 74 | if (node.backgrounds.length === 0) return false 75 | if (!Array.isArray(node.backgrounds)) return false 76 | return node.backgrounds.some(paintIsImage) 77 | } 78 | 79 | return false 80 | } 81 | 82 | function nodesContainFillable(nodes): boolean { 83 | if (nodes.length === 0) return false 84 | 85 | return nodes.some(node => { 86 | if (node.children) return nodesContainFillable(node.children) 87 | return isShapeNode(node) || isTextNode(node) 88 | }) 89 | } 90 | 91 | function nodeContainsSourceImage(node): boolean { 92 | if (isShapeNode(node)) return nodeFillsContainsImagePaint(node) 93 | if (isFrametypeNode(node)) { 94 | const frameIsSourceImage = nodeFillsContainsImagePaint(node) 95 | const frameContainsChildrenWithSourceImage = nodesContainSourceImage(node.children) 96 | return frameIsSourceImage || frameContainsChildrenWithSourceImage 97 | } 98 | } 99 | 100 | function nodesContainSourceImage(nodes): boolean { 101 | if (nodes.length === 0) return false 102 | return nodes.some(nodeContainsSourceImage) 103 | } 104 | 105 | export function getFirstImagePaintFromNode(node) { 106 | if (node.fills) return node.fills.find(paintIsImage) 107 | if (node.backgrounds) return node.backgrounds.find(paintIsImage) 108 | } 109 | 110 | export function hasValidSelection(nodes): boolean { 111 | return nodes.length > 0 112 | } 113 | 114 | export function selectedSingleImage(nodes) { 115 | const singleSelectedNode = nodes.length === 1 116 | if (!singleSelectedNode) return false 117 | 118 | const selectedNode = nodes[0] 119 | const isShape = isShapeNode(selectedNode) 120 | const isFrame = isFrametypeNode(selectedNode) 121 | if (!isShape && !isFrame) return false 122 | 123 | const hasChildren = isFrame && selectedNode.children.length > 0 124 | if (hasChildren) return false 125 | 126 | return nodeFillsContainsImagePaint(selectedNode) 127 | } 128 | 129 | export function selectedFrameContainsImageAndFillables(nodes): boolean { 130 | const singleSelectedNode = nodes.length === 1 131 | if (!singleSelectedNode) return false 132 | 133 | const selectedNode = nodes[0] 134 | const isFrame = isFrametypeNode(selectedNode) 135 | if (!isFrame) return false 136 | 137 | // does the frame itself contain a valid paint? 138 | if (nodeFillsContainsImagePaint(selectedNode)) { 139 | // see if fillables exist within the frame 140 | return nodesContainFillable(selectedNode.children) 141 | } else { 142 | // otherwise find a source image from the node's children 143 | return nodesContainSourceImage(selectedNode.children) 144 | } 145 | } 146 | 147 | export function selectedImageAndFillables(nodes): boolean { 148 | const singleSelectedNode = nodes.length === 1 149 | if (singleSelectedNode) return false 150 | 151 | const hasSourceImage = nodesContainSourceImage(nodes) 152 | const hasFillables = nodesContainFillable(nodes) 153 | return hasSourceImage && hasFillables 154 | } 155 | 156 | function parentTreeOfNodesHasSourceImage(nodes): boolean { 157 | for (let node of nodes) { 158 | // we've gone too far 159 | if (node.type === "PAGE") return false 160 | 161 | if (nodeIsSourceImage(node)) return true 162 | if (nodeContainsSourceImage(node)) return true 163 | 164 | const parentContainsSource = nodesContainSourceImage(node.parent.children) 165 | const parentIsSource = nodeIsSourceImage(node.parent) 166 | if (parentContainsSource || parentIsSource) return true 167 | 168 | return parentTreeOfNodesHasSourceImage(node.parent.parent.children) 169 | } 170 | } 171 | 172 | export function seletedFillablesWithoutImage(nodes) { 173 | const hasFillables = nodesContainFillable(nodes) 174 | if (!hasFillables) return false 175 | 176 | const hasSourceImage = nodesContainSourceImage(nodes) 177 | if (hasSourceImage) return false 178 | 179 | return parentTreeOfNodesHasSourceImage(nodes) 180 | } 181 | 182 | export function nodeIsSourceImage(node): boolean { 183 | return nodeFillsContainsImagePaint(node) 184 | } 185 | 186 | export function getSourceImageNodeFromParentsOfNodes(nodes) { 187 | for (let node of nodes) { 188 | if (node.type === "PAGE") return null 189 | if (node.parent.type === "PAGE") { 190 | if (!nodeIsSourceImage(node)) return null 191 | } 192 | 193 | if (nodeIsSourceImage(node)) return node 194 | if (nodeIsSourceImage(node.parent)) return node.parent 195 | 196 | const siblingIsSourceImage = node.parent.children.find(nodeIsSourceImage) 197 | if (siblingIsSourceImage) return siblingIsSourceImage 198 | 199 | if (parentTreeOfNodesHasSourceImage(nodes)) return getSourceImageNodeFromParentsOfNodes(node.parent.parent.children) 200 | return null 201 | } 202 | } 203 | 204 | export function getSourceImageNodeFromNodes(nodes) { 205 | for (let node of nodes) { 206 | if (nodeIsSourceImage(node)) return node 207 | if (node.children) return getSourceImageNodeFromNodes(node.children) 208 | } 209 | } 210 | 211 | 212 | export async function getDataForUIFromNode(node) { 213 | const paint = getFirstImagePaintFromNode(node) 214 | const hash = figma.getImageByHash(paint.imageHash) 215 | const imageBytes = await hash.getBytesAsync() 216 | const { width, height, name } = node 217 | return { imageBytes, width, height, name } 218 | } 219 | 220 | 221 | export interface UIColorData { 222 | dominantColor: RGB; 223 | suggestedTextColors: RGB[]; 224 | palette: RGB[] 225 | } 226 | 227 | function setNodeFillFromRGB(node, color: RGB, options = {}) { 228 | // only override the color and optional properties, but retain all 229 | // existing properties like fill opacity 230 | const gradientFillTypes = [ "GRADIENT_LINEAR", "GRADIENT_RADIAL", "GRADIENT_ANGULAR", "GRADIENT_DIAMOND"] 231 | const solidFill = (fill) => ({ ...fill, color, ...options }) 232 | const gradientFill = (fill) => ({ 233 | ...fill, 234 | gradientStops: fill.gradientStops.map(gs => ({ ...gs, color: { ...gs.color, ...color }})), 235 | ...options 236 | }) 237 | 238 | if (!Array.isArray(node.fills)) return 239 | 240 | const copies = node.fills.slice().map(fill => { 241 | if (fill.type === "IMAGE") return fill 242 | if (fill.type === 'SOLID') return solidFill(fill) 243 | if (gradientFillTypes.indexOf(fill.type) >= 0) return gradientFill(fill) 244 | return fill 245 | }) 246 | 247 | return node.fills = copies 248 | } 249 | 250 | export async function applyTransformationsToNodes(nodes, data: UIColorData) { 251 | const { dominantColor, suggestedTextColors } = data 252 | 253 | for (let node of nodes) { 254 | if (isTextNode(node)) { 255 | const textColor = node.name.includes('dominant') 256 | ? dominantColor 257 | : suggestedTextColors[0] 258 | setNodeFillFromRGB(node, textColor, { opacity: 0.9 }) 259 | } 260 | 261 | if (isShapeNode(node)) { 262 | if (!nodeFillsContainsImagePaint(node)) setNodeFillFromRGB(node, dominantColor) 263 | } 264 | 265 | if (isFrametypeNode(node)) { 266 | return applyTransformationsToNodes(node.children, data) 267 | } 268 | } 269 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "lib": [ 5 | "es2017", 6 | "dom" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin') 2 | const HtmlWebpackPlugin = require('html-webpack-plugin') 3 | const path = require('path') 4 | 5 | module.exports = (env, argv) => ({ 6 | mode: argv.mode === 'production' ? 'production' : 'development', 7 | 8 | // This is necessary because Figma's 'eval' works differently than normal eval 9 | devtool: argv.mode === 'production' ? false : 'inline-source-map', 10 | 11 | entry: { 12 | ui: './src/ui.ts', // The entry point for your UI code 13 | code: './src/plugin.ts', // The entry point for your plugin code 14 | }, 15 | 16 | module: { 17 | rules: [ 18 | // Converts TypeScript code to JavaScript 19 | { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }, 20 | 21 | // Enables including CSS by doing "import './file.css'" in your TypeScript code 22 | { test: /\.css$/, use: ['style-loader', { loader: 'css-loader' }] }, 23 | 24 | // Allows you to use "<%= require('./file.svg') %>" in your HTML code to get a data URI 25 | { test: /\.(png|jpg|gif|webp|svg)$/, loader: 'url-loader' }, 26 | ], 27 | }, 28 | 29 | // Webpack tries these extensions for you if you omit the extension like "import './file'" 30 | resolve: { extensions: ['.tsx', '.ts', '.jsx', '.js'] }, 31 | 32 | output: { 33 | publicPath: '/', 34 | filename: '[name].js', 35 | path: path.resolve(__dirname, 'build'), // Compile into a folder called "build" 36 | }, 37 | 38 | // Tells Webpack to generate "ui.html" and to inline "ui.ts" into it 39 | plugins: [ 40 | new HtmlWebpackPlugin({ 41 | template: './src/ui.html', 42 | filename: 'ui.html', 43 | inlineSource: '.(js)$', 44 | chunks: ['ui'], 45 | }), 46 | new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin), 47 | ], 48 | }) --------------------------------------------------------------------------------